主题
MCP 客户端
MCP 客户端是实现 Model Context Protocol 的应用程序,能够连接到 MCP 服务器并利用其提供的工具、资源和提示词。本页面介绍各种可用的 MCP 客户端以及如何使用它们。
官方客户端
🤖 Claude Desktop
Claude Desktop 是 Anthropic 开发的桌面应用程序,内置了对 MCP 的原生支持。
特性
- 原生 MCP 支持 - 无需额外配置即可使用 MCP 服务器
- 可视化配置 - 图形界面管理 MCP 连接
- 实时同步 - 与 Claude 网页版同步对话历史
- 本地处理 - 支持本地 MCP 服务器连接
安装和配置
下载安装
bash
# macOS
brew install --cask claude
# Windows
# 从官网下载 .exe 安装包
# https://claude.ai/download
# Linux
# 下载 .AppImage 文件
wget https://claude.ai/download/linux/claude.AppImage
chmod +x claude.AppImage
./claude.AppImage
配置 MCP 服务器
- 打开 Claude Desktop
- 进入 设置 > MCP 服务器
- 添加新的服务器配置:
json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"]
},
"postgres": {
"command": "python",
"args": ["-m", "mcp_server_postgres"],
"env": {
"POSTGRES_CONNECTION_STRING": "postgresql://user:password@localhost:5432/database"
}
}
}
}
使用示例
用户: 请帮我分析 /data/sales.csv 文件中的销售数据
Claude: 我来帮你分析销售数据。首先让我读取文件内容。
[调用 filesystem 服务器的 read_file 工具]
根据文件内容,我发现以下销售趋势:
1. Q4 销售额比 Q3 增长了 23%
2. 产品 A 是最畅销的产品
3. 北美地区贡献了 45% 的总销售额
需要我进行更详细的分析吗?
🔧 MCP CLI 客户端
官方命令行客户端,适合开发者和自动化场景。
安装
bash
npm install -g @modelcontextprotocol/cli
基本用法
连接服务器
bash
# 连接本地服务器
mcp connect --command "python server.py"
# 连接远程服务器
mcp connect --url "https://api.example.com/mcp"
# 使用配置文件
mcp connect --config config.json
交互模式
bash
mcp> tools list
Available tools:
- get_weather: Get weather information
- calculate: Perform calculations
- search_web: Search the internet
mcp> tools call get_weather --location "San Francisco"
{
"content": [
{
"type": "text",
"text": "Weather in San Francisco: Sunny, 72°F"
}
]
}
mcp> resources list
Available resources:
- file://config.json
- https://api.example.com/data
mcp> resources read file://config.json
{
"contents": [
{
"uri": "file://config.json",
"mimeType": "application/json",
"text": "{\n \"api_key\": \"...\"\n}"
}
]
}
脚本模式
bash
# 执行单个命令
mcp exec --command "python server.py" --tool get_weather --args '{"location": "Tokyo"}'
# 批量执行
mcp batch --config servers.json --script commands.txt
第三方客户端
🌐 Web 客户端
MCP Web Client
基于浏览器的 MCP 客户端,支持 WebSocket 和 SSE 连接。
javascript
// 安装
npm install @mcp-community/web-client
// 使用
import { MCPWebClient } from '@mcp-community/web-client';
const client = new MCPWebClient({
transport: 'websocket',
url: 'wss://api.example.com/mcp'
});
await client.connect();
const tools = await client.listTools();
console.log('Available tools:', tools);
React MCP Hook
React 应用的 MCP 集成钩子。
jsx
import { useMCP } from '@mcp-community/react-hooks';
function MyComponent() {
const { client, tools, isConnected } = useMCP({
serverUrl: 'wss://api.example.com/mcp'
});
const handleToolCall = async (toolName, args) => {
const result = await client.callTool(toolName, args);
console.log('Tool result:', result);
};
return (
<div>
<h2>MCP Tools</h2>
{isConnected ? (
<ul>
{tools.map(tool => (
<li key={tool.name}>
<button onClick={() => handleToolCall(tool.name, {})}>
{tool.name}
</button>
</li>
))}
</ul>
) : (
<p>Connecting...</p>
)}
</div>
);
}
📱 移动客户端
MCP Mobile (iOS/Android)
跨平台移动应用,使用 React Native 构建。
bash
# 安装
npm install -g @mcp-community/mobile-cli
# 创建新项目
mcp-mobile init MyMCPApp
cd MyMCPApp
# 运行
npm run ios # iOS
npm run android # Android
Flutter MCP Plugin
Flutter 应用的 MCP 插件。
dart
// pubspec.yaml
dependencies:
mcp_flutter: ^1.0.0
// main.dart
import 'package:mcp_flutter/mcp_flutter.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MCPProvider(
serverUrl: 'wss://api.example.com/mcp',
child: MaterialApp(
home: MCPToolsPage(),
),
);
}
}
🖥️ 桌面客户端
Electron MCP Client
基于 Electron 的跨平台桌面客户端。
bash
# 下载预构建版本
# GitHub: https://github.com/mcp-community/electron-client
# 或从源码构建
git clone https://github.com/mcp-community/electron-client.git
cd electron-client
npm install
npm run build
npm run dist
Tauri MCP Client
使用 Rust + Web 技术构建的轻量级桌面客户端。
bash
# 安装 Tauri CLI
cargo install tauri-cli
# 克隆项目
git clone https://github.com/mcp-community/tauri-client.git
cd tauri-client
# 开发模式
cargo tauri dev
# 构建发布版
cargo tauri build
IDE 集成
🔧 VS Code 扩展
MCP for VS Code
官方 VS Code 扩展,提供 MCP 服务器的集成支持。
安装
bash
# 从 VS Code Marketplace 安装
code --install-extension modelcontextprotocol.mcp-vscode
# 或从 VSIX 文件安装
code --install-extension mcp-vscode-1.0.0.vsix
配置
json
// settings.json
{
"mcp.servers": [
{
"name": "filesystem",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "${workspaceFolder}"]
},
{
"name": "git",
"command": "python",
"args": ["-m", "mcp_server_git"],
"cwd": "${workspaceFolder}"
}
],
"mcp.autoConnect": true,
"mcp.showStatusBar": true
}
功能特性
- 自动连接 - 打开项目时自动连接 MCP 服务器
- 工具面板 - 侧边栏显示可用工具和资源
- 命令面板 - 通过命令面板调用 MCP 功能
- 状态栏 - 显示连接状态和服务器信息
使用示例
typescript
// 在 VS Code 中使用 MCP 工具
// 1. 打开命令面板 (Ctrl+Shift+P)
// 2. 输入 "MCP: Call Tool"
// 3. 选择工具和参数
// 4. 查看结果
// 或使用代码片段
const result = await vscode.commands.executeCommand(
'mcp.callTool',
'get_weather',
{ location: 'New York' }
);
🧠 IntelliJ IDEA 插件
MCP Plugin for IntelliJ
JetBrains IDE 系列的 MCP 支持插件。
安装
- 打开 IntelliJ IDEA
- 进入 File > Settings > Plugins
- 搜索 "Model Context Protocol"
- 安装并重启 IDE
配置
xml
<!-- .idea/mcp-config.xml -->
<mcp-configuration>
<servers>
<server name="database" command="python" args="-m mcp_server_postgres">
<env name="DB_URL" value="postgresql://localhost:5432/mydb"/>
</server>
<server name="filesystem" command="npx" args="-y @modelcontextprotocol/server-filesystem ${PROJECT_DIR}"/>
</servers>
</mcp-configuration>
📝 Vim/Neovim 插件
mcp.nvim
Neovim 的 MCP 集成插件。
lua
-- init.lua
require('mcp').setup({
servers = {
{
name = 'filesystem',
command = 'npx',
args = {'-y', '@modelcontextprotocol/server-filesystem', vim.fn.getcwd()}
}
},
auto_connect = true,
keymaps = {
call_tool = '<leader>mt',
list_tools = '<leader>ml',
read_resource = '<leader>mr'
}
})
自定义客户端开发
🛠️ 客户端 SDK
Python SDK
python
from mcp import Client, StdioTransport
# 创建客户端
transport = StdioTransport(['python', 'server.py'])
client = Client(transport)
# 连接和初始化
await client.connect()
await client.initialize()
# 使用工具
result = await client.call_tool('get_weather', {'location': 'Paris'})
print(result.content[0].text)
# 读取资源
resource = await client.read_resource('file://data.json')
print(resource.contents[0].text)
# 断开连接
await client.disconnect()
TypeScript SDK
typescript
import { Client, StdioTransport } from '@modelcontextprotocol/sdk/client/index.js';
// 创建客户端
const transport = new StdioTransport({
command: 'python',
args: ['server.py']
});
const client = new Client({
name: 'my-client',
version: '1.0.0'
}, {
capabilities: {
roots: { listChanged: true }
}
});
// 连接
await client.connect(transport);
// 列出工具
const tools = await client.listTools();
console.log('Available tools:', tools.tools);
// 调用工具
const result = await client.callTool({
name: 'calculate',
arguments: { expression: '2 + 2' }
});
console.log('Result:', result.content);
Go SDK
go
package main
import (
"context"
"fmt"
"github.com/modelcontextprotocol/go-sdk/client"
"github.com/modelcontextprotocol/go-sdk/transport"
)
func main() {
// 创建传输层
transport := transport.NewStdioTransport("python", []string{"server.py"})
// 创建客户端
client := client.New(client.Config{
Name: "go-client",
Version: "1.0.0",
})
// 连接
ctx := context.Background()
if err := client.Connect(ctx, transport); err != nil {
panic(err)
}
defer client.Disconnect()
// 调用工具
result, err := client.CallTool(ctx, "get_weather", map[string]interface{}{
"location": "Tokyo",
})
if err != nil {
panic(err)
}
fmt.Printf("Weather: %s\n", result.Content[0].Text)
}
🔌 传输层实现
WebSocket 客户端
javascript
class WebSocketMCPClient {
constructor(url) {
this.url = url;
this.ws = null;
this.requestId = 0;
this.pendingRequests = new Map();
}
async connect() {
this.ws = new WebSocket(this.url);
return new Promise((resolve, reject) => {
this.ws.onopen = () => {
this.setupMessageHandler();
resolve();
};
this.ws.onerror = reject;
});
}
setupMessageHandler() {
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.id && this.pendingRequests.has(message.id)) {
const { resolve, reject } = this.pendingRequests.get(message.id);
this.pendingRequests.delete(message.id);
if (message.error) {
reject(new Error(message.error.message));
} else {
resolve(message.result);
}
}
};
}
async sendRequest(method, params = {}) {
const id = ++this.requestId;
const message = {
jsonrpc: '2.0',
method,
params,
id
};
return new Promise((resolve, reject) => {
this.pendingRequests.set(id, { resolve, reject });
this.ws.send(JSON.stringify(message));
// 超时处理
setTimeout(() => {
if (this.pendingRequests.has(id)) {
this.pendingRequests.delete(id);
reject(new Error('Request timeout'));
}
}, 30000);
});
}
async callTool(name, arguments) {
return await this.sendRequest('tools/call', { name, arguments });
}
}
SSE 客户端
javascript
class SSEMCPClient {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.eventSource = null;
this.sessionId = null;
}
async initialize() {
// 初始化会话
const response = await fetch(`${this.baseUrl}/initialize`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
protocolVersion: '2025-06-18',
capabilities: { roots: { listChanged: true } },
clientInfo: { name: 'SSE Client', version: '1.0.0' }
})
});
const data = await response.json();
this.sessionId = data.sessionId;
// 建立 SSE 连接
this.eventSource = new EventSource(
`${this.baseUrl}/events/${this.sessionId}`
);
this.eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
this.handleServerEvent(data);
};
}
async callTool(name, arguments) {
const response = await fetch(`${this.baseUrl}/tools/call`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Session-ID': this.sessionId
},
body: JSON.stringify({ name, arguments })
});
return await response.json();
}
handleServerEvent(data) {
switch (data.type) {
case 'resource_updated':
this.onResourceUpdated(data.resource);
break;
case 'tool_list_changed':
this.onToolListChanged();
break;
}
}
}
客户端配置
📋 配置文件格式
JSON 配置
json
{
"client": {
"name": "my-mcp-client",
"version": "1.0.0",
"capabilities": {
"roots": { "listChanged": true },
"sampling": {}
}
},
"servers": [
{
"name": "filesystem",
"transport": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"]
},
"settings": {
"timeout": 30000,
"retries": 3
}
},
{
"name": "database",
"transport": {
"type": "websocket",
"url": "wss://db.example.com/mcp"
},
"auth": {
"type": "bearer",
"token": "${DB_TOKEN}"
}
}
],
"logging": {
"level": "info",
"file": "mcp-client.log"
}
}
YAML 配置
yaml
client:
name: my-mcp-client
version: 1.0.0
capabilities:
roots:
listChanged: true
sampling: {}
servers:
- name: filesystem
transport:
type: stdio
command: npx
args:
- "-y"
- "@modelcontextprotocol/server-filesystem"
- "/allowed/path"
settings:
timeout: 30000
retries: 3
- name: api-server
transport:
type: sse
url: https://api.example.com/mcp/sse
auth:
type: api-key
key: "${API_KEY}"
logging:
level: info
file: mcp-client.log
🔐 认证配置
API 密钥认证
json
{
"auth": {
"type": "api-key",
"key": "${API_KEY}",
"header": "X-API-Key"
}
}
Bearer Token 认证
json
{
"auth": {
"type": "bearer",
"token": "${ACCESS_TOKEN}"
}
}
OAuth 2.0 认证
json
{
"auth": {
"type": "oauth2",
"clientId": "${OAUTH_CLIENT_ID}",
"clientSecret": "${OAUTH_CLIENT_SECRET}",
"tokenUrl": "https://auth.example.com/token",
"scopes": ["mcp:read", "mcp:write"]
}
}
最佳实践
🚀 性能优化
连接池管理
javascript
class MCPConnectionPool {
constructor(config) {
this.config = config;
this.connections = new Map();
this.maxConnections = config.maxConnections || 10;
}
async getConnection(serverName) {
if (this.connections.has(serverName)) {
return this.connections.get(serverName);
}
if (this.connections.size >= this.maxConnections) {
// 移除最久未使用的连接
const oldestKey = this.connections.keys().next().value;
const oldestConnection = this.connections.get(oldestKey);
await oldestConnection.disconnect();
this.connections.delete(oldestKey);
}
const connection = await this.createConnection(serverName);
this.connections.set(serverName, connection);
return connection;
}
async createConnection(serverName) {
const serverConfig = this.config.servers[serverName];
const client = new MCPClient(serverConfig);
await client.connect();
return client;
}
}
请求缓存
javascript
class CachedMCPClient {
constructor(client, cacheConfig = {}) {
this.client = client;
this.cache = new Map();
this.cacheTTL = cacheConfig.ttl || 300000; // 5分钟
}
async callTool(name, arguments) {
const cacheKey = `${name}:${JSON.stringify(arguments)}`;
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < this.cacheTTL) {
return cached.result;
}
const result = await this.client.callTool(name, arguments);
this.cache.set(cacheKey, {
result,
timestamp: Date.now()
});
return result;
}
}
🛡️ 错误处理
重试机制
javascript
class ResilientMCPClient {
constructor(client, retryConfig = {}) {
this.client = client;
this.maxRetries = retryConfig.maxRetries || 3;
this.retryDelay = retryConfig.retryDelay || 1000;
}
async callToolWithRetry(name, arguments) {
let lastError;
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
try {
return await this.client.callTool(name, arguments);
} catch (error) {
lastError = error;
if (attempt < this.maxRetries) {
const delay = this.retryDelay * Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError;
}
}
断路器模式
javascript
class CircuitBreakerMCPClient {
constructor(client, config = {}) {
this.client = client;
this.failureThreshold = config.failureThreshold || 5;
this.resetTimeout = config.resetTimeout || 60000;
this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
this.failureCount = 0;
this.lastFailureTime = null;
}
async callTool(name, arguments) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailureTime > this.resetTimeout) {
this.state = 'HALF_OPEN';
} else {
throw new Error('Circuit breaker is OPEN');
}
}
try {
const result = await this.client.callTool(name, arguments);
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failureCount = 0;
this.state = 'CLOSED';
}
onFailure() {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.failureThreshold) {
this.state = 'OPEN';
}
}
}
相关资源
- MCP 协议规范 - 了解协议详细信息
- 构建 MCP 服务器 - 服务器开发指南
- MCP Inspector - 调试和测试工具
- 社区项目 - 社区贡献的客户端项目