How Cherry Studio MCP Server Integration Works: A Complete Technical Guide
Cherry Studio's MCP server integration enables AI assistants to invoke external tools via the Model Context Protocol through a layered architecture involving Redux state management, prompt generation, and provider-agnostic runtime dispatch.
Cherry Studio, an open-source AI client from the cherryhq/cherry-studio repository, implements the Model Context Protocol (MCP) to extend LLM capabilities beyond text generation. The Cherry Studio MCP server integration transforms external HTTP services into callable functions that large language models can invoke during conversations, creating a seamless bridge between AI reasoning and real-world tool execution.
Architectural Layers of Cherry Studio MCP Integration
The integration follows a strict separation of concerns across seven distinct layers, each handling specific responsibilities from type validation to HTTP dispatch.
Type Definitions and Validation
The foundation resides in src/renderer/src/types/mcp.ts, where Zod schemas define the shape of MCP servers and their install sources:
export const MCPServerInstallSourceSchema = z.enum(['builtin','manual','protocol','unknown']).default('unknown')
export type MCPServerInstallSource = z.infer<typeof MCPServerInstallSourceSchema>
export interface MCPServer {
id: string
name: string
type: 'inMemory' | 'http'
installSource?: MCPServerInstallSource
isTrusted?: boolean
}
Built-in servers are identified via isBuiltinMCPServerName in src/renderer/src/types/index.ts, distinguishing system tools like memory and mcpAutoInstall from user-added servers.
State Management with Redux
The Redux slice in src/renderer/src/store/mcp.ts manages the lifecycle of MCP servers:
export const builtinMCPServers = [
{ name: BuiltinMCPServerNames.mcpAutoInstall, … },
{ name: BuiltinMCPServerNames.memory, … }
]
export const mcpSlice = createSlice({
name: 'mcp',
initialState: { mcpServers: [] as MCPServer[] },
reducers: {
setMCPServers(state, action) { state.mcpServers = action.payload },
addMCPServer(state, action) { state.mcpServers.push(action.payload) }
}
})
The initializeMCPServers function injects built-in servers at startup if they are missing from persisted state, ensuring core tools like the hub server are always available.
Prompt Generation for LLM Tool Awareness
Before sending context to the LLM, src/renderer/src/utils/prompt.ts serializes available tools into the system prompt:
export const AvailableTools = (tools: MCPTool[]) => {
return tools.map(t => ({
name: t.id,
description: t.description,
parameters: processSchemaForO3(t.inputSchema)
}))
}
The buildSystemPromptWithTools function appends this JSON-encoded list to the system prompt, enabling function calling capabilities in the model.
Provider-Agnostic Tool Mapping
src/renderer/src/utils/mcp-tools.ts contains adapter functions that convert MCP tool definitions to provider-specific formats:
- OpenAI:
mcpToolsToOpenAIResponseToolsandmcpToolsToOpenAIChatToolscreatefunction-type tools - Anthropic:
mcpToolsToAnthropicToolsbuildsToolobjects - Google Gemini:
mcpToolsToGeminiTools - AWS Bedrock:
mcpToolsToAwsBedrockTools
All mapping functions utilize processSchemaForO3 from src/renderer/src/utils/mcp-schema.ts to ensure strict O3 schema compliance required by OpenAI's API.
Runtime Dispatch and HTTP Execution
The callMCPTool function in src/renderer/src/utils/mcp-tools.ts serves as the runtime dispatcher:
export async function callMCPTool(toolResponse: MCPToolResponse): Promise<MCPCallToolResponse> {
const server = getMcpServerByTool(toolResponse.tool)
if (!server) throw new Error(`Server not found: ${toolResponse.tool.serverName}`)
// Short-circuit for built-in tools
if (toolResponse.tool.serverName === BuiltinMCPServerNames.mcpAutoInstall) {
// Auto-install logic
}
// Generic HTTP execution
const resp = await fetch(`${server.baseUrl}/${toolResponse.tool.name}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(toolResponse.arguments)
})
const data = await resp.json()
return { toolResponse, result: data }
}
The function logs execution via loggerService and surfaces errors as toast notifications in the UI.
Assistant-Level Server Resolution
src/renderer/src/services/ApiService.ts determines which MCP servers are active for a specific assistant:
export function getMcpServersForAssistant(assistant: Assistant): MCPServer[] {
const enabledMCPs = assistant.enabledMCPs?.length
? assistant.enabledMCPs
: [hubMCPServer]
return enabledMCPs
}
If no specific servers are configured, the assistant falls back to the hub server, ensuring baseline MCP functionality.
The Complete MCP Tool Call Flow
Understanding the Cherry Studio MCP server integration requires following the complete lifecycle of a tool invocation:
-
Assistant Configuration –
enabledMCPsis stored in the Redux state viaassistantSliceduring assistant creation or editing. -
Prompt Generation –
buildSystemPromptWithToolsinjects tool schemas from enabled servers into the system prompt sent to the LLM. -
LLM Decision – The model returns a function call object (e.g.,
{"name":"fetch","arguments":{"url":"https://api.example.com"}}). -
Tool Resolution –
openAIToolsToMcpTool(or Anthropic/Gemini equivalents) maps the call name to anMCPToolobject. -
Dispatch Execution –
callMCPToolreceives theMCPToolResponse:- Built-in tools route through
callBuiltInTool - External servers resolve via
getMcpServerByTooland execute via HTTP POST to${server.baseUrl}/${tool.name}
- Built-in tools route through
-
Result Handling – The response normalizes to
MCPCallToolResponseformat and streams back to the chat interface as tool output.
Practical Implementation Examples
Registering a Custom MCP Server
Add external MCP servers to the Redux store using the addMCPServer action:
import { addMCPServer } from '@renderer/store/mcp'
const myServer = {
id: 'custom-mcp-1',
name: 'MyRemoteMCP',
type: 'http',
baseUrl: 'https://my-mcp.example.com/api',
installSource: 'manual',
isTrusted: true,
isActive: true
}
store.dispatch(addMCPServer(myServer))
This persists the server configuration in src/renderer/src/store/mcp.ts and makes it available for assistant configuration.
Invoking Tools from LLM Responses
Handle tool calls programmatically using the runtime dispatcher:
import { callMCPTool } from '@renderer/utils/mcp-tools'
async function handleToolInvocation(toolResponse) {
try {
const result = await callMCPTool(toolResponse)
// Result conforms to MCPCallToolResponse interface
return result.result
} catch (error) {
console.error('Tool execution failed:', error)
throw error
}
}
The callMCPTool function in src/renderer/src/utils/mcp-tools.ts handles both built-in and external server execution.
Adding Built-in Tools
Built-in tools like think and memory bypass HTTP calls. They are identified by isBuiltIn in src/renderer/src/types/tool.ts and handled in callBuiltInTool:
// Excerpt from callBuiltInTool implementation
if (toolResponse.tool.name === 'think' && typeof toolResponse.arguments === 'object') {
const thought = toolResponse.arguments.thought
// Process internal thought for chain-of-th reasoning
return { content: [{ type: 'text', text: `Thought: ${thought}` }] }
}
These tools provide core functionality without external dependencies.
Generating System Prompts with Tools
Construct LLM prompts that include available tools:
import { buildSystemPromptWithTools } from '@renderer/utils/prompt'
import { getMcpServersForAssistant } from '@renderer/services/ApiService'
const assistant = /* retrieve from Redux store */
const servers = getMcpServersForAssistant(assistant)
const tools = servers.flatMap(s => s.tools ?? [])
const systemPrompt = buildSystemPromptWithTools(
'You are a helpful assistant with access to external tools.',
tools
)
The buildSystemPromptWithTools function in src/renderer/src/utils/prompt.ts serializes tool schemas for LLM consumption.
Key Source Files Reference
| File | Role | Location |
|---|---|---|
src/renderer/src/types/mcp.ts |
MCP server and schema type definitions | View on GitHub |
src/renderer/src/store/mcp.ts |
Redux state management for servers | View on GitHub |
src/renderer/src/utils/mcp-tools.ts |
Provider mapping and runtime dispatch | View on GitHub |
src/renderer/src/utils/prompt.ts |
System prompt construction with tools | View on GitHub |
src/renderer/src/services/ApiService.ts |
Assistant-level server resolution | View on GitHub |
src/renderer/src/utils/mcp-schema.ts |
Schema processing for O3 compliance | View on GitHub |
src/renderer/src/types/tool.ts |
Tool interface including isBuiltIn flag |
View on GitHub |
Summary
Cherry Studio MCP server integration operates through a sophisticated multi-layered architecture:
- Type-safe configuration via Zod schemas in
src/renderer/src/types/mcp.tsvalidates both built-in and custom servers - Centralized state management through Redux in
src/renderer/src/store/mcp.tspersists server configurations and handles built-in injection at startup - Dynamic prompt generation in
src/renderer/src/utils/prompt.tsserializes tool schemas into LLM system prompts - Provider abstraction via
src/renderer/src/utils/mcp-tools.tsconverts MCP definitions to OpenAI, Anthropic, Gemini, and Bedrock formats - Unified runtime dispatch through
callMCPToolhandles both built-in implementations and external HTTP requests to MCP servers
This design enables seamless extension of AI assistant capabilities while maintaining strict type safety and provider compatibility.
Frequently Asked Questions
What is the Model Context Protocol (MCP) in Cherry Studio?
The Model Context Protocol (MCP) is an open standard that Cherry Studio implements to allow AI assistants to discover and invoke external tools. In Cherry Studio, MCP servers are HTTP services that expose functions—such as web fetching, memory storage, or custom business logic—that the LLM can call during conversations to retrieve real-time data or perform actions.
How does Cherry Studio handle different LLM providers for MCP tools?
Cherry Studio uses provider-specific adapter functions in src/renderer/src/utils/mcp-tools.ts to translate MCP tool definitions into formats required by each LLM API. The codebase includes mcpToolsToOpenAIResponseTools and mcpToolsToOpenAIChatTools for OpenAI, mcpToolsToAnthropicTools for Claude, mcpToolsToGeminiTools for Google, and mcpToolsToAwsBedrockTools for AWS. All adapters process schemas through processSchemaForO3 to ensure compatibility.
Can I add my own custom MCP servers to Cherry Studio?
Yes, you can register custom MCP servers through the Redux store using the addMCPServer action in src/renderer/src/store/mcp.ts. You must provide a unique ID, server name, type (typically 'http'), base URL, and installation source. Once registered, the server appears in the MCP settings UI at src/renderer/src/pages/settings/MCPSettings/* where you can activate it for specific assistants.
What built-in MCP tools does Cherry Studio provide?
Cherry Studio includes several built-in MCP servers that operate without external HTTP calls. These include the hub server (default fallback for assistants), mcpAutoInstall (handles automatic tool installation), and memory (provides persistent storage across conversations). Built-in tools are identified by the isBuiltIn flag in src/renderer/src/types/tool.ts and are executed through callBuiltInTool in src/renderer/src/utils/mcp-tools.ts rather than being dispatched to external endpoints.
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 →