# Supported LLM Providers in ChatMCP and How to Configure API Keys

> Discover supported LLM providers in ChatMCP like OpenAI, Claude, and Gemini. Learn how to easily configure API keys securely using SharedPreferences for seamless integration.

- Repository: [刀刀/chatmcp](https://github.com/daodao97/chatmcp)
- Tags: supported-llms-and-configuration
- Published: 2026-02-28

---

**ChatMCP supports eight LLM providers including OpenAI, Claude, Ollama, DeepSeek, Gemini, Azure AI Foundry, Claude Code, and GitHub Copilot, with API keys stored in SharedPreferences via the SettingsProvider class.**

ChatMCP is an open-source Flutter application that unifies multiple large language model backends through a single abstraction layer. Understanding which providers are supported and how to configure their API keys is essential for customizing your chat experience. This guide breaks down the provider architecture in the `daodao97/chatmcp` repository and explains the exact steps to securely store and retrieve credentials.

## Supported LLM Providers in ChatMCP

The framework defines supported backends through the `LLMProvider` enum in `lib/llm/llm_factory.dart`【/cache/repos/github.com/daodao97/chatmcp/main/lib/llm/llm_factory.dart#L15-L16】. The `LLMFactoryHelper.providerMap` translates provider ID strings into enum values at runtime【/cache/repos/github.com/daodao97/chatmcp/main/lib/llm/llm_factory.dart#L47-L55】.

Each provider maps to a concrete client implementation:

- **OpenAI** (`openai`): `OpenAIClient` → `https://api.openai.com/v1`
- **Claude** (`claude`): `ClaudeClient` → `https://api.anthropic.com`
- **Ollama** (`ollama`): `OllamaClient` → `http://localhost:11434` (local)
- **DeepSeek** (`deepseek`): `DeepSeekClient` → `https://api.deepseek.com`
- **Gemini** (`gemini`): `GeminiClient` → `https://generativelanguage.googleapis.com/v1beta`
- **Azure AI Foundry** (`foundry`): `FoundryClient` with custom user-defined endpoints
- **Claude Code** (`claude-code`): `ClaudeCodeClient` using the Claude Code SDK (no HTTP endpoint)
- **GitHub Copilot** (`copilot`): `CopilotClient` → `https://api.githubcopilot.com`

## How ChatMCP Stores API Keys

All credentials persist in **SharedPreferences** under the key `apiSettings_v6`. The `SettingsProvider` class in `lib/provider/settings_provider.dart` manages this storage, maintaining a list of `LLMProviderSetting` objects that contain the `apiKey` and `apiEndpoint` fields【/cache/repos/github.com/daodao97/chatmcp/main/lib/provider/settings_provider.dart#L188-L274】.

When the application starts, the `loadSettings` method merges saved preferences with default configurations, ensuring every supported provider appears in the settings list【/cache/repos/github.com/daodao97/chatmcp/main/lib/provider/settings_provider.dart#L50-L73】.

## Configuring API Keys Programmatically

While users typically interact with the settings UI, you can programmatically update credentials using `SettingsProvider.updateApiSettings`. This requires constructing a new `LLMProviderSetting` instance and merging it with existing configurations.

```dart
import 'package:chatmcp/provider/provider_manager.dart';
import 'package:chatmcp/provider/settings_provider.dart';

Future<void> configureOpenAiKey(String apiKey) async {
  final currentSettings = ProviderManager.settingsProvider.apiSettings;
  
  final updatedSettings = [
    ...currentSettings,
    LLMProviderSetting(
      apiKey: apiKey,
      apiEndpoint: 'https://api.openai.com/v1',
      providerId: 'openai',
      providerName: 'OpenAI',
      icon: 'openai',
      custom: false,
    ),
  ];

  await ProviderManager.settingsProvider.updateApiSettings(
    apiSettings: updatedSettings,
  );
}

```

## Runtime Provider Selection and Key Injection

When initiating a chat session, `LLMFactoryHelper.createFromModel` retrieves the appropriate `LLMProviderSetting` for the selected model, extracts the `apiKey` and `apiEndpoint`, and instantiates the corresponding client【/cache/repos/github.com/daodao97/chatmcp/main/lib/llm/llm_factory.dart#L69-L92】. The factory masks the key in logs for security while passing the full credential to the HTTP client.

```dart
final model = llm_model.Model(
  name: 'gpt-4o-mini',
  providerId: 'openai',
);

final client = LLMFactoryHelper.createFromModel(model);
// Returns an OpenAIClient configured with the stored API key

```

## Adding Custom LLM Providers

You can extend ChatMCP to support additional providers like OpenRouter by specifying an `apiStyle` of `openai` to reuse the existing OpenAI-compatible client logic:

```dart
Future<void> addOpenRouterProvider() async {
  final openRouter = LLMProviderSetting(
    apiKey: 'YOUR_OPENROUTER_KEY',
    apiEndpoint: 'https://openrouter.ai/api/v1',
    providerId: 'openrouter',
    providerName: 'OpenRouter',
    apiStyle: 'openai',
    icon: 'openrouter',
    custom: false,
  );

  final settings = [
    ...ProviderManager.settingsProvider.apiSettings,
    openRouter,
  ];

  await ProviderManager.settingsProvider.updateApiSettings(apiSettings: settings);
}

```

## Summary

- ChatMCP supports **eight built-in providers**: OpenAI, Claude, Ollama, DeepSeek, Gemini, Azure AI Foundry, Claude Code, and GitHub Copilot.
- Provider definitions live in `lib/llm/llm_factory.dart`, while credentials are managed by `lib/provider/settings_provider.dart`.
- API keys are stored in **SharedPreferences** under `apiSettings_v6` as part of `LLMProviderSetting` objects.
- Use `ProviderManager.settingsProvider.updateApiSettings()` to programmatically configure keys or add custom providers.

## Frequently Asked Questions

### How do I retrieve the currently configured API key for a specific provider?

Access the provider setting through `ProviderManager.settingsProvider.getProviderSetting()`:

```dart
final setting = ProviderManager.settingsProvider.getProviderSetting('openai');
print('Endpoint: ${setting.apiEndpoint}');
print('Key: ${setting.apiKey.substring(0, 4)}...');

```

### Can I use local LLMs with ChatMCP?

Yes. The **Ollama** provider (`ollama`) connects to `http://localhost:11434` by default via `OllamaClient`, enabling entirely local inference without external API keys.

### What happens if I don't configure an API key for a provider?

The `loadSettings` method initializes all providers with empty placeholder strings【/cache/repos/github.com/daodao97/chatmcp/main/lib/provider/settings_provider.dart#L50-L73】. Attempting to use an unconfigured provider will result in authentication errors when the client attempts to communicate with the LLM endpoint.

### Is there a way to mask or secure API keys in the UI?

The application automatically masks keys in debug logs within `LLMFactoryHelper.createFromModel`【/cache/repos/github.com/daodao97/chatmcp/main/lib/llm/llm_factory.dart#L69-L92】. For UI display, implement similar substring masking (showing only the first 4 characters) when rendering the `apiKey` field from `LLMProviderSetting`.