MCP基本通信格式

1. 初始化

request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "roots": {
        "listChanged": true
      },
      "sampling": {},
      "elicitation": {}
    },
    "clientInfo": {
      "name": "ExampleClient",
      "title": "Example Client Display Name",
      "version": "1.0.0"
    }
  }
}

response

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "logging": {},
      "prompts": {
        "listChanged": true
      },
      "resources": {
        "subscribe": true,
        "listChanged": true
      },
      "tools": {
        "listChanged": true
      }
    },
    "serverInfo": {
      "name": "ExampleServer",
      "title": "Example Server Display Name",
      "version": "1.0.0"
    },
    "instructions": "Optional instructions for the client"
  }
}

2. 工具发现

request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "cursor": "optional-cursor-value"
  }
}

response

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "get_weather",
        "title": "Weather Information Provider",
        "description": "Get current weather information for a location",
        "inputSchema": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "City name or zip code"
            }
          },
          "required": ["location"]
        }
      }
    ],
    "nextCursor": "next-page-cursor"
  }
}

3. 工具调用

request

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "location": "New York"
    }
  }
}

response

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
      }
    ],
    "isError": false
  }
}

Node实现一个基础的MCP服务器

const readline = require('readline');

// 创建readline接口
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

// ============== 工具定义 ==============
const tools = [
  {
    name: "sum",
    title: "求和",
    description: "计算两数之和",
    inputSchema: {
      type: "object",
      properties: {
        a: { 
          type: "number", 
          description: "第一个数" 
        },
        b: { 
          type: "number", 
          description: "第二个数" 
        }
      },
      required: ["a", "b"]
    }
  }
];

// ============== 工具处理器 ==============
const toolHandlers = {
  // 计算两数之和
  sum: ({ a, b }) => {
    if (typeof a !== 'number' || typeof b !== 'number') {
      throw new Error("Both arguments must be numbers");
    }
    return `${a} + ${b} = ${a + b}`;
  }
};

// ============== 请求处理器 ==============
const requestHandlers = {
  // 处理初始化请求
  "initialize": (params, id) => ({
    jsonrpc: "2.0",
    id,
    result: {
      protocolVersion: params.protocolVersion,
      capabilities: {
        prompts: { listChanged: true },
        resources: { subscribe: true, listChanged: true },
        tools: { listChanged: true }
      },
      serverInfo: {
        name: "XiaoZheMCP",
        title: "XiaoZhe MCP Server",
        version: "0.0.0"
      },
      instructions: "测试"
    }
  }),
  
  // 返回工具列表
  "tools/list": (_, id) => ({
    jsonrpc: "2.0",
    id,
    result: { tools }
  }),
  
  // 处理工具调用
  "tools/call": async (params, id) => {
    const { name, arguments: args } = params;
    const handler = toolHandlers[name];
    
    try {
      // 检查工具是否存在
      if (!handler) {
        throw new Error(`Tool '${name}' not found`);
      }
      
      // 执行工具处理
      const result = await handler(args);
      
      return {
        jsonrpc: "2.0",
        id,
        result: {
          content: [{ type: "text", text: result }],
          isError: false
        }
      };
    } catch (error) {
      return {
        jsonrpc: "2.0",
        id,
        error: {
          code: -32000,
          message: "Tool execution failed",
          data: error.message
        }
      };
    }
  }
};

// ============== 主处理逻辑 ==============
rl.on('line', async (line) => {
  try {
    const request = JSON.parse(line);
    const handler = requestHandlers[request.method];
    
    if (!handler) {
      throw new Error(`Unsupported method: ${request.method}`);
    }
    
    // 处理请求并发送响应
    const response = await handler(request.params, request.id);
    console.log(JSON.stringify(response));
    
  } catch (error) {
    // 处理解析错误
    const errorResponse = {
      jsonrpc: "2.0",
      id: null,
      error: {
        code: -32700,
        message: "Parse error",
        data: error.message
      }
    };
    console.error(JSON.stringify(errorResponse));
  }
});

MCP调试工具

npx @modelcontextprotocol/inspector

执行后完成后会自动打开一个网页,然后就可以愉快的测试了

官方库快速开发MCP服务器

安装依赖包:

npm i @modelcontextprotocol/sdk
npm i zod

示例代码:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from 'zod';

const server = new McpServer({
  name: "XiaoZheMCP",
  title: "XiaoZhe MCP Server",
  version: "1.0.0",
});

// 创建工具
server.registerTool(
    'sum',
    {
        title: '求和',
        description: '计算两数之和',
        inputSchema: {
            a: z.number().describe('第一个数'),
            b: z.number().describe('第二个数')
        }
    },
    ({a, b})=>{
        return {
            content: [
                {
                    type: 'text',
                    text: `${a} + ${b} = ${a + b}`
                }
            ]
        }
    }
)

const transport = new StdioServerTransport();
server.connect(transport);

最后

可以使用任意支持MCP服务器和大模型的客户端,这样就可以使用对话的方式和自己的MCP服务器交互了!!