Pixiv · 緋雪插画
2050 字
10 分钟
MCP 完整研究指南
研究时间:2026-03-10
本文档整理了 MCP 配置文件位置、连接原理以及自定义 MCP 服务器的部署方法。
目录
1. 概述
MCP (Model Context Protocol) 是 Anthropic 推出的开放协议,用于连接 AI 助手与外部工具和数据源。
核心概念
| 概念 | 说明 |
|---|---|
| Tools | 可调用的函数,AI 可以执行操作 |
| Resources | 可读取的数据源,类似文件系统 |
| Prompts | 预定义的提示模板 |
| Transport | 通信层,支持 stdio 或 HTTP |
当前已连接的 MCP
| MCP 名称 | 用途 |
|---|---|
websearch | Exa 网络搜索 |
context7 | 技术文档查询 |
grep_app | GitHub 代码搜索 |
2. 配置文件位置
2.1 OpenCode 配置目录
~/.config/opencode/├── opencode.json # OpenCode 主配置(AI Provider 设置)├── oh-my-opencode.json # 插件配置(Agent 模型映射)├── skills/│ └── mcp-builder/ # MCP 构建技能│ ├── SKILL.md # 开发指南│ └── reference/ # 参考文档│ ├── python_mcp_server.md│ ├── node_mcp_server.md│ └── mcp_best_practices.md└── node_modules/oh-my-opencode/ └── dist/ ├── mcp/ # 内置 MCP 客户端 ├── features/ │ ├── skill-mcp-manager/ # MCP 连接管理器 │ └── claude-code-mcp-loader/ # Claude MCP 加载器 └── tools/skill-mcp/ # skill_mcp 工具2.2 Claude Desktop 配置
配置文件位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.claude.json
配置示例:
{ "mcpServers": { "server-name": { "type": "stdio", "command": "npx", "args": ["-y", "@your/mcp-server"], "env": { "API_KEY": "your-api-key" } } }}2.3 配置字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
type | string | 传输类型:stdio 或 http |
command | string | 启动命令(stdio 模式) |
args | string[] | 命令参数 |
env | object | 环境变量 |
url | string | 服务器地址(http 模式) |
headers | object | HTTP 请求头(http 模式) |
oauth | object | OAuth 配置 |
3. 连接原理
3.1 架构图
┌─────────────────┐ JSON-RPC ┌──────────────────┐│ AI Client │ ◄───────────────► │ MCP Server ││ (OpenCode/ │ │ (Python/Node) ││ Claude) │ │ │└─────────────────┘ └──────────────────┘ │ │ │ Transport Layer │ ├─ stdio ◄────────────────────────► │ │ stdin /stdout │ │ │ └─ Streamable HTTP ◄───────────────► │ POST / mcp3.2 通信流程
- 客户端初始化:创建 MCP Client 实例
- 建立连接:通过 Transport 层连接服务器
- 能力协商:交换支持的 Tools/Resources/Prompts
- 调用工具:通过 JSON-RPC 调用服务器提供的功能
3.3 核心组件
| 组件 | 作用 | TypeScript 导入 |
|---|---|---|
| Transport | 通信层 | StdioServerTransport 或 StreamableHTTPServerTransport |
| Client | MCP 客户端 | @modelcontextprotocol/sdk/client |
| Server | MCP 服务器 | McpServer 类 |
| Tool | 可调用函数 | 通过 registerTool 注册 |
| Resource | 数据源 | 通过 registerResource 注册 |
| Prompt | 提示模板 | 通过 registerPrompt 注册 |
3.4 连接代码示例
// stdio 传输(本地)import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const transport = new StdioServerTransport();await server.connect(transport);
// HTTP 传输(远程)import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true});await server.connect(transport);4. 如何部署自定义 MCP
4.1 方案 A:Python FastMCP(推荐入门)
安装依赖:
pip install "mcp[cli]" httpx pydantic完整示例:
#!/usr/bin/env python3from mcp.server.fastmcp import FastMCPfrom pydantic import BaseModel, Field, ConfigDictfrom typing import Optionalimport httpx
# 初始化 MCP 服务器mcp = FastMCP("my_service_mcp")
# 定义输入模型class SearchInput(BaseModel): model_config = ConfigDict( str_strip_whitespace=True, validate_assignment=True )
query: str = Field( ..., description="搜索关键词", min_length=2, max_length=200 ) limit: Optional[int] = Field( default=20, description="返回结果数量限制", ge=1, le=100 )
# 注册工具@mcp.tool( name="my_search", annotations={ "readOnlyHint": True, "destructiveHint": False, "idempotentHint": True, "openWorldHint": True })async def my_search(params: SearchInput) -> str: """执行搜索操作,返回匹配的结果。
Args: params: 搜索参数 - query: 搜索关键词 - limit: 返回结果数量
Returns: str: JSON 格式的搜索结果 """ async with httpx.AsyncClient() as client: response = await client.get( "https://api.example.com/search", params={"q": params.query, "limit": params.limit}, timeout=30.0 ) response.raise_for_status() return response.text
# 启动服务器if __name__ == "__main__": # stdio 模式(本地) mcp.run()
# HTTP 模式(远程) # mcp.run(transport="streamable_http", port=8000)运行:
python my_mcp_server.py4.2 方案 B:Node/TypeScript SDK(推荐生产)
项目结构:
my-service-mcp-server/├── package.json├── tsconfig.json├── src/│ ├── index.ts # 主入口│ ├── types.ts # 类型定义│ ├── tools/ # 工具实现│ │ └── search.ts│ └── services/ # API 客户端│ └── api.ts└── dist/ # 编译输出package.json:
{ "name": "my-service-mcp-server", "version": "1.0.0", "type": "module", "main": "dist/index.js", "scripts": { "build": "tsc", "start": "node dist/index.js", "dev": "tsx watch src/index.ts" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.6.1", "axios": "^1.7.9", "zod": "^3.23.8" }, "devDependencies": { "@types/node": "^22.10.0", "tsx": "^4.19.2", "typescript": "^5.7.2" }}tsconfig.json:
{ "compilerOptions": { "target": "ES2022", "module": "Node16", "moduleResolution": "Node16", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"]}src/index.ts:
#!/usr/bin/env nodeimport { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";import { z } from "zod";import axios from "axios";
// 常量配置const API_BASE_URL = "https://api.example.com/v1";
// 创建 MCP 服务器const server = new McpServer({ name: "my-service-mcp-server", version: "1.0.0"});
// Zod 输入验证 Schemaconst SearchSchema = z.object({ query: z.string() .min(2, "关键词至少 2 个字符") .max(200, "关键词最多 200 个字符") .describe("搜索关键词"), limit: z.number() .int() .min(1) .max(100) .default(20) .describe("返回结果数量限制")}).strict();
// 工具注册server.registerTool( "my_search", { title: "搜索工具", description: `执行搜索操作,返回匹配的结果。
Args: - query: 搜索关键词 - limit: 返回结果数量 (默认 20)
Returns: JSON 格式的搜索结果`, inputSchema: SearchSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true } }, async (params) => { try { const response = await axios.get(`${API_BASE_URL}/search`, { params: { q: params.query, limit: params.limit }, timeout: 30000 });
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], structuredContent: response.data }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { content: [{ type: "text", text: `Error: ${message}` }] }; } });
// 启动服务器async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("MCP server running via stdio");}
main().catch(console.error);构建和运行:
npm installnpm run buildnpm start4.3 Transport 选择指南
| 场景 | 推荐 Transport |
|---|---|
| 本地开发工具 | stdio |
| 桌面应用集成 | stdio |
| 云端部署 | Streamable HTTP |
| 多客户端服务 | Streamable HTTP |
| 需要 OAuth | Streamable HTTP |
5. 接入 OpenCode
5.1 方法 1:作为 Skill MCP(推荐)
创建 skill 目录:
~/.config/opencode/skills/my-mcp/├── SKILL.md # 技能描述├── mcp.json # MCP 服务器配置└── scripts/ └── run.sh # 启动脚本SKILL.md:
---name: my-mcpdescription: 我的自定义 MCP 服务---
# My MCP Service
提供 XXX 功能的 MCP 服务器。mcp.json:
{ "my_service": { "type": "stdio", "command": "python", "args": ["/home/fenlyin/my_mcp_server.py"], "env": { "API_KEY": "your-api-key" } }}5.2 方法 2:项目级配置
编辑 ~/.claude.json:
{ "projects": { "/home/fenlyin/your-project": { "mcpServers": { "my-custom-mcp": { "type": "stdio", "command": "node", "args": ["/path/to/dist/index.js"], "env": { "MY_API_KEY": "xxx" } } } } }}5.3 方法 3:远程 HTTP MCP
{ "mcpServers": { "my-remote-mcp": { "type": "http", "url": "https://your-server.com/mcp", "headers": { "Authorization": "Bearer your-token" } } }}6. 测试与调试
6.1 使用 MCP Inspector
# 测试本地 Python 服务器npx @modelcontextprotocol/inspector python my_mcp_server.py
# 测试本地 Node 服务器npx @modelcontextprotocol/inspector node dist/index.js
# 测试远程 HTTP 服务器npx @modelcontextprotocol/inspector http://localhost:8000/mcp6.2 调试技巧
Python 日志:
import logginglogging.basicConfig(level=logging.DEBUG)Node.js 日志:
// 使用 console.error 而不是 console.log(stdout 用于通信)console.error("Debug message:", data);6.3 常见问题
| 问题 | 解决方案 |
|---|---|
| 连接超时 | 检查 command 路径是否正确 |
| 环境变量未生效 | 确认 env 配置格式正确 |
| 工具未显示 | 检查工具注册代码 |
| 参数验证失败 | 检查 Zod/Pydantic schema |
7. 官方资源
7.1 文档与规范
7.2 SDK 与工具
| 资源 | 链接 |
|---|---|
| Python SDK (PyPI) | https://pypi.org/project/mcp/ |
| Python SDK (GitHub) | https://github.com/modelcontextprotocol/python-sdk |
| TypeScript SDK | https://github.com/modelcontextprotocol/typescript-sdk |
| MCP Inspector | https://github.com/modelcontextprotocol/inspector |
7.3 示例与生态
| 资源 | 链接 |
|---|---|
| 官方服务器示例 | https://github.com/modelcontextprotocol/servers |
| MCP Registry | https://modelcontextprotocol.io/tools/registry/ |
| Awesome MCP | https://github.com/punkpeye/awesome-mcp-servers |
附录:Tool Annotations 说明
| Annotation | 类型 | 默认值 | 说明 |
|---|---|---|---|
readOnlyHint | boolean | false | 工具不会修改环境 |
destructiveHint | boolean | true | 工具可能执行破坏性操作 |
idempotentHint | boolean | false | 重复调用无额外效果 |
openWorldHint | boolean | true | 工具与外部实体交互 |
文档生成于 2026-03-10
如有问题,请参考官方文档或提交 GitHub Issue
OpenCode MCP 集成完整指南
- MCP 配置文件查找目录(优先级从低到高) 优先级 1 2 3 4 5 6 7 (最高) OAuth tokens 存储位置: ~/.local/share/opencode/mcp-auth.json
-
MCP 自动启动机制 是的,OpenCode 在启动时自动启动所有 MCP 服务器。 关键代码 (mcp/index.ts:185-218): const state = Instance.state( async () => { const cfg = await Config.get() const config = cfg.mcp ?? {}
// 并行启动所有 MCP await Promise.all( Object.entries(config).map(async ([key, mcp]) => {
// enabled: false 则跳过if (mcp.enabled === false) {status[key] = { status: "disabled" }return}// 创建连接const result = await create(key, mcp)// ...}), ) } ) 启动流程:
-
读取配置 → 提取 mcp 字段
-
并行启动 → Promise.all 并发连接
-
连接类型:
- local → StdioClientTransport 启动子进程
- remote → StreamableHTTPClientTransport 或 SSEClientTransport
-
默认超时:30秒(可通过 timeout 字段配置)
- MCP 配置格式
{
“mcp”: {
“local-filesystem”: {
“type”: “local”,
“command”: [“npx”, “-y”, “@modelcontextprotocol/server-filesystem”, “/path”],
“environment”: { “MY_VAR”: “value” },
“enabled”: true,
“timeout”: 5000
},
“remote-sentry”: {
“type”: “remote”,
“url”: “https://mcp.sentry.dev/mcp”,
“headers”: { “Authorization”: “Bearer {env
}” }, “oauth”: {}, “enabled”: true } } }
- CLI 命令
opencode mcp add # 交互式添加 MCP
opencode mcp list # 列出所有 MCP 状态
opencode mcp auth
# OAuth 认证 opencode mcp logout # 移除 OAuth 凭证 opencode mcp debug # 调试连接问题
- 禁用自动启动 { “mcp”: { “my-mcp”: { “type”: “local”, “command”: [”…”], “enabled”: false } } }
- 按 Agent 控制 MCP { “mcp”: { “my-mcp”: { “type”: “local”, “command”: [”…”], “enabled”: true } }, “tools”: { “my-mcp*”: false }, “agent”: { “my-agent”: { “tools”: { “my-mcp*”: true } } } }