Skip to content

MCP 服务器开发

本指南将详细介绍如何开发自己的 MCP (Model Context Protocol) 服务器,包括基础概念、开发流程和最佳实践。

开发概述

MCP 服务器是一个独立的程序,它通过标准化的协议与 MCP 客户端(如 Claude Desktop)进行通信。服务器可以提供:

  • 🔧 工具 (Tools) - 可执行的功能
  • 📚 资源 (Resources) - 可访问的数据
  • 💬 提示 (Prompts) - 预定义的提示模板

技术架构

通信协议

MCP 基于 JSON-RPC 2.0 协议,支持多种传输方式:

┌─────────────────┐    JSON-RPC    ┌─────────────────┐
│   MCP Client    │ ←──────────→   │   MCP Server    │
│ (Claude Desktop)│                │  (Your Server)  │
└─────────────────┘                └─────────────────┘

传输层选择

  • stdio - 标准输入输出(推荐)
  • SSE - Server-Sent Events
  • WebSocket - 双向实时通信

快速开始

环境准备

bash
# Node.js 项目
mkdir my-mcp-server
cd my-mcp-server
npm init -y

# 安装 MCP SDK
npm install @modelcontextprotocol/sdk

# TypeScript 支持(推荐)
npm install -D typescript @types/node
npx tsc --init

基础服务器结构

typescript
#!/usr/bin/env node

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

// 创建服务器实例
const server = new Server(
  {
    name: "my-mcp-server",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// 列出可用工具
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "hello",
        description: "Say hello to someone",
        inputSchema: {
          type: "object",
          properties: {
            name: {
              type: "string",
              description: "Name of the person to greet",
            },
          },
          required: ["name"],
        },
      },
    ],
  };
});

// 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "hello") {
    const personName = args.name as string;
    return {
      content: [
        {
          type: "text",
          text: `Hello, ${personName}! Nice to meet you.`,
        },
      ],
    };
  }

  throw new Error(`Unknown tool: ${name}`);
});

// 启动服务器
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("MCP server running on stdio");
}

main().catch((error) => {
  console.error("Server error:", error);
  process.exit(1);
});

核心概念详解

1. 工具 (Tools)

工具是服务器提供的可执行功能:

typescript
// 工具定义
{
  name: "read_file",
  description: "Read contents of a file",
  inputSchema: {
    type: "object",
    properties: {
      path: {
        type: "string",
        description: "File path to read"
      }
    },
    required: ["path"]
  }
}

// 工具实现
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "read_file") {
    const path = request.params.arguments.path as string;
    const content = await fs.readFile(path, 'utf-8');
    
    return {
      content: [
        {
          type: "text",
          text: content
        }
      ]
    };
  }
});

2. 资源 (Resources)

资源提供对数据的访问:

typescript
import { ListResourcesRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";

// 列出资源
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: "file://config.json",
        name: "Configuration",
        description: "Application configuration file",
        mimeType: "application/json"
      }
    ]
  };
});

// 读取资源
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  const uri = request.params.uri;
  
  if (uri === "file://config.json") {
    const config = await loadConfig();
    return {
      contents: [
        {
          uri,
          mimeType: "application/json",
          text: JSON.stringify(config, null, 2)
        }
      ]
    };
  }
  
  throw new Error(`Resource not found: ${uri}`);
});

3. 提示 (Prompts)

提示提供预定义的模板:

typescript
import { ListPromptsRequestSchema, GetPromptRequestSchema } from "@modelcontextprotocol/sdk/types.js";

// 列出提示
server.setRequestHandler(ListPromptsRequestSchema, async () => {
  return {
    prompts: [
      {
        name: "code_review",
        description: "Review code for best practices",
        arguments: [
          {
            name: "language",
            description: "Programming language",
            required: true
          }
        ]
      }
    ]
  };
});

// 获取提示
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
  if (request.params.name === "code_review") {
    const language = request.params.arguments?.language || "JavaScript";
    
    return {
      description: `Code review prompt for ${language}`,
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `Please review this ${language} code for best practices, security issues, and performance optimizations.`
          }
        }
      ]
    };
  }
  
  throw new Error(`Prompt not found: ${request.params.name}`);
});

高级功能

错误处理

typescript
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  try {
    // 工具逻辑
    return result;
  } catch (error) {
    throw new McpError(
      ErrorCode.InternalError,
      `Tool execution failed: ${error.message}`
    );
  }
});

Released under the MIT License.