Supported LLM Providers in ChatMCP and How to Configure API Keys
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):FoundryClientwith custom user-defined endpoints - Claude Code (
claude-code):ClaudeCodeClientusing 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.
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.
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:
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 bylib/provider/settings_provider.dart. - API keys are stored in SharedPreferences under
apiSettings_v6as part ofLLMProviderSettingobjects. - 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():
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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →