# MCP (Model Context Protocol) 学习指南
·
1. 什么是 MCP?
MCP (Model Context Protocol) 是一个开放协议,用于连接 LLM 应用与外部数据源和工具。
┌─────────────┐ MCP ┌─────────────┐
│ Client │ ←─────────────────→ │ Server │
│ (opencode) │ JSON-RPC 消息 │ (你的服务) │
└─────────────┘ └─────────────┘
MCP 提供的能力
| 能力 | 说明 |
|---|---|
| Tools | 供 AI 调用的函数(如执行 SQL) |
| Resources | 供 AI 访问的上下文/数据 |
| Prompts | 预定义的提示模板 |
2. JSON-RPC 2.0 基础
MCP 基于 JSON-RPC 2.0,有三种消息类型:
2.1 Request(请求)- 需要响应
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
规则:
jsonrpc必须是"2.0"id不能为null,不能重复params可选
2.2 Response(响应)- 返回结果
成功响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": { ... }
}
错误响应:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Method not found"
}
}
规则:
id必须与请求的id一致result和error不能同时存在
2.3 Notification(通知)- 不需要响应
{
"jsonrpc": "2.0",
"method": "initialized"
}
规则:
- 不需要
id
2.4 标准错误码
| 错误码 | 含义 |
|---|---|
-32700 |
Parse error - JSON 解析失败 |
-32600 |
Invalid Request - 无效请求 |
-32601 |
Method not found - 方法不存在 |
-32602 |
Invalid params - 参数无效 |
-32603 |
Internal error - 内部错误 |
3. MCP 消息格式
请求格式
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
响应格式
{
jsonrpc: "2.0";
id: string | number;
result?: { [key: string]: unknown };
error?: {
code: number;
message: string;
data?: unknown;
};
}
4. MCP 核心方法
4.1 initialize - 初始化握手
客户端 → 服务器
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "opencode",
"version": "1.0.0"
}
}
}
服务器 → 客户端(响应)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"serverInfo": {
"name": "mysql-mcp",
"version": "1.0.0"
}
}
}
4.2 initialized - 握手完成
客户端 → 服务器
{
"jsonrpc": "2.0",
"method": "initialized"
}
4.3 ping - 心跳检测
请求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "ping"
}
响应:
{
"jsonrpc": "2.0",
"id": 2,
"result": {}
}
5. 工具 (Tools) 定义
5.1 tools/list - 列出可用工具
请求:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/list"
}
响应:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"tools": [
{
"name": "mysql_query",
"description": "Execute MySQL query",
"inputSchema": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "SQL statement to execute"
}
},
"required": ["sql"]
}
}
]
}
}
5.2 tools/call - 调用工具
请求:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "mysql_query",
"arguments": {
"sql": "SELECT * FROM users LIMIT 10"
}
}
}
响应:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "[{\"id\":1,\"name\":\"张三\"},...]"
}
]
}
}
6. 你的代码解析
你的 mysql-mcp.js 文件结构:
┌─────────────────────────────────────────────┐
│ 1. 创建连接池 (mysql2/promise) │
├─────────────────────────────────────────────┤
│ 2. 创建 stdin/stdout 通信接口 │
├─────────────────────────────────────────────┤
│ 3. 辅助函数 (sendResponse, sendError) │
├─────────────────────────────────────────────┤
│ 4. 处理请求 (handleRequest) │
│ - initialize │
│ - tools/list │
│ - tools/call │
├─────────────────────────────────────────────┤
│ 5. 主循环 (监听 stdin) │
├─────────────────────────────────────────────┤
│ 6. 优雅退出 (SIGINT) │
└─────────────────────────────────────────────┘
关键代码段
发送成功响应:
const sendResponse = (id, result) => {
console.log(JSON.stringify({
jsonrpc: "2.0",
id,
result
}));
};
发送错误响应:
const sendError = (id, code, message) => {
console.log(JSON.stringify({
jsonrpc: "2.0",
id,
error: { code, message }
}));
};
处理 initialize 请求:
if (method === "initialize") {
sendResponse(id, {
protocolVersion: "2024-11-05",
capabilities: { tools: {} },
serverInfo: { name: "mysql-mcp", version: "1.0.0" }
});
}
处理 tools/list 请求:
if (method === "tools/list") {
sendResponse(id, {
tools: [{
name: "mysql_query",
description: "Execute MySQL query",
inputSchema: {
type: "object",
properties: {
sql: { type: "string", description: "SQL statement to execute" }
},
required: ["sql"]
}
}]
});
}
处理 tools/call 请求:
if (method === "tools/call") {
const { name, arguments: args } = params;
if (name === "mysql_query") {
const { sql } = args;
const [results] = await pool.query(sql);
sendResponse(id, {
content: [{
type: "text",
text: JSON.stringify(results)
}]
});
}
}
7. 完整示例
客户端发送的完整消息序列
// 1. 初始化握手
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"opencode","version":"1.0.0"}}}
// 2. 握手完成通知
{"jsonrpc":"2.0","method":"initialized"}
// 3. 获取工具列表
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
// 4. 调用工具
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"mysql_query","arguments":{"sql":"SELECT * FROM users"}}}
服务器返回的完整响应序列
// 1. 初始化响应
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"mysql-mcp","version":"1.0.0"}}}
// 2. 工具列表响应
{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"mysql_query","description":"Execute MySQL query","inputSchema":{"type":"object","properties":{"sql":{"type":"string","description":"SQL statement to execute"}},"required":["sql"]}}]}}
// 3. 工具调用响应
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"[{\"id\":1,\"name\":\"张三\"}]"}]}}
快速参考表
必须遵循的键
| 键 | 值 | 说明 |
|---|---|---|
jsonrpc |
"2.0" |
版本号,必须 |
id |
string/number | 请求标识,不能为 null |
method |
string | 方法名 |
result |
object | 成功结果 |
error |
object | 错误信息 |
可自定义的键
| 位置 | 键 | 说明 |
|---|---|---|
| initialize 响应 | protocolVersion |
协议版本 |
| initialize 响应 | capabilities |
能力声明 |
| initialize 响应 | serverInfo |
服务器信息 |
| tools/list 响应 | tools |
工具数组 |
| 工具定义 | name, description, inputSchema |
工具属性 |
| 工具调用响应 | content |
返回内容 |
下一步
- 查看官方文档:https://modelcontextprotocol.info
- 查看 TypeScript Schema:https://github.com/modelcontextprotocol/specification
- 扩展你的 mysql-mcp.js,添加更多工具(如
mysql_execute用于 INSERT/UPDATE) - 添加 Resources 支持(如查询数据库表结构)
文档生成时间:2024
更多推荐
所有评论(0)