CodeL
以前端为翼,以 AI 为脑,向全栈而行
2026-03-31

MCP 入门教程:让 AI 连接你的工具和数据

MCP 入门教程:让 AI 连接你的工具和数据 一篇搞定:MCP 是什么、怎么用、怎么开发自己的 MCP Server 目录 一、核心概念 二、快速体验 MCP 三、使用现有 MCP Server 四、开发自己的 MCP...

MCP 入门教程:让 AI 连接你的工具和数据 #

一篇搞定:MCP 是什么、怎么用、怎么开发自己的 MCP Server


目录 #


一、核心概念 #

1.1 什么是 MCP? #

MCP = Model Context Protocol(模型上下文协议)

打个比方:

  • AI 就像是一个「聪明的助手」,但它被困在房间里,看不到外面的世界
  • MCP 就像是给这个助手开了「窗户」和「门」,让它能接触到外部的工具和数据
  • 通过 MCP,AI 可以:读取文件、搜索网页、操作数据库、调用 API...

官方定义:

MCP 是一个开放协议,让 AI 助手能够安全地连接外部数据源和工具。

1.2 为什么需要 MCP? #

没有 MCP 之前的问题:

问题 说明
信息孤岛 AI 无法访问你的本地文件、数据库、私有 API
重复开发 每个 AI 应用都要自己实现工具集成
安全风险 给 AI 完全访问权限太危险
不互通 Claude 能用的工具,GPT 用不了

MCP 的解决方案:

┌─────────────────────────────────────────────────┐
│                   AI 应用                        │
│        (Claude / Cursor / Windsurf...)          │
└─────────────────────┬───────────────────────────┘
                      │ MCP 协议
        ┌─────────────┼─────────────┐
        ▼             ▼             ▼
   ┌─────────┐   ┌─────────┐   ┌─────────┐
   │ 文件系统 │   │  数据库  │   │ Web API │
   │  Server │   │  Server │   │  Server │
   └─────────┘   └─────────┘   └─────────┘

MCP 的好处:

好处 说明
一次开发,到处使用 写一个 MCP Server,Claude、Cursor、Windsurf 都能用
安全可控 用户决定 AI 能访问什么,不能访问什么
标准化 统一的协议,不用每个工具单独适配
可组合 可以连接多个 MCP Server,组合使用

1.3 MCP 的核心概念 #

概念 英文 说明 类比
MCP Host Host 运行 AI 的应用程序 Claude Desktop、Cursor、Windsurf
MCP Client Client Host 内部的 MCP 客户端 Claude 里的 MCP 连接器
MCP Server Server 提供工具和数据的服务端 文件系统 Server、GitHub Server
Resource Resource 可读取的数据源 文件内容、数据库记录
Tool Tool 可执行的函数 搜索文件、发送请求
Prompt Prompt 预定义的提示词模板 「帮我分析这个文件」模板

1.4 MCP 能做什么? #

访问数据(Resources):

// AI 可以读取你的文件
读取文件内容"你好,这是 README.md 的内容..."
 
// AI 可以查询数据库
查询用户表 → [{ id: 1, name: "张三" }, ...]
 
// AI 可以获取网页内容
获取网页"这是页面内容..."

执行操作(Tools):

// AI 可以帮你操作
创建文件"已创建 test.js"
发送请求"请求已发送,返回 200"
执行命令"命令执行成功"

使用模板(Prompts):

// 预定义好的提示词模板
"分析代码"自动读取文件 + 专业分析
"生成文档"自动扫描代码 + 生成 README

1.5 哪些应用支持 MCP? #

应用 支持状态 说明
Claude Desktop ✅ 官方支持 Anthropic 官方应用
Cursor ✅ 支持 AI 代码编辑器
Windsurf ✅ 支持 Codeium 出品
Zed ✅ 支持 高性能编辑器
OpenAI 🔄 规划中 微软正在整合
OpenClaw ✅ 支持 你正在用的这个!

二、快速体验 MCP #

2.1 Claude Desktop 配置 MCP #

第一步:安装 Claude Desktop

claude.ai/download 下载安装。

第二步:配置 MCP Server

Claude Desktop 的配置文件位置:

系统 路径
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json

第三步:添加文件系统 MCP

创建或编辑配置文件:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/你的用户名/Desktop",
        "/Users/你的用户名/Documents"
      ]
    }
  }
}

第四步:重启 Claude Desktop

关闭并重新打开 Claude Desktop。

第五步:测试 MCP

在 Claude 中输入:

请列出我桌面上的文件

Claude 会询问是否允许访问文件系统,点击允许。然后你就能看到文件列表了!

2.2 配置多个 MCP Server #

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/你的用户名/projects"
      ]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "你的GitHub Token"
      }
    },
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "你的Brave API Key"
      }
    }
  }
}

2.3 在 Cursor 中使用 MCP #

配置步骤:

  1. 打开 Cursor 设置(Cmd + ,
  2. 搜索 MCP
  3. 点击 Edit MCP Settings
  4. 添加配置:
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "${workspaceFolder}"
      ]
    }
  }
}

使用方式:

在 Cursor 的 Chat 面板中,AI 现在可以访问你的项目文件了。


三、使用现有 MCP Server #

3.1 官方 MCP Server 列表 #

Server 功能 安装方式
filesystem 文件系统访问 @modelcontextprotocol/server-filesystem
github GitHub 操作 @modelcontextprotocol/server-github
brave-search 网页搜索 @modelcontextprotocol/server-brave-search
google-maps 地图服务 @modelcontextprotocol/server-google-maps
postgres PostgreSQL 数据库 @modelcontextprotocol/server-postgres
sqlite SQLite 数据库 @modelcontextprotocol/server-sqlite
slack Slack 集成 @modelcontextprotocol/server-slack
puppeteer 浏览器自动化 @modelcontextprotocol/server-puppeteer

3.2 文件系统 MCP 详解 #

配置:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/path/to/allowed/dir1",
        "/path/to/allowed/dir2"
      ]
    }
  }
}

提供的工具:

工具 功能 示例
read_file 读取文件内容 读取 README.md
write_file 写入文件 创建新文件
list_directory 列出目录内容 查看文件夹结构
create_directory 创建目录 新建文件夹
move_file 移动/重命名文件 重命名文件
search_files 搜索文件 查找 *.js 文件
get_file_info 获取文件信息 查看文件大小、修改时间

使用示例:

用户:请帮我读取 package.json 文件
 
AI 调用 read_file → 返回文件内容
 
AI:这是你的 package.json 内容:
{
  "name": "my-project",
  "version": "1.0.0",
  ...
}

3.3 GitHub MCP 详解 #

前提:需要 GitHub Personal Access Token

  1. 访问 github.com/settings/tokens
  2. 点击 Generate new token (classic)
  3. 勾选需要的权限(repo、issues、pull_requests)
  4. 生成并保存 Token

配置:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"
      }
    }
  }
}

提供的工具:

工具 功能
search_repositories 搜索仓库
get_repository 获取仓库信息
list_issues 列出 Issue
create_issue 创建 Issue
create_pull_request 创建 PR
fork_repository Fork 仓库
create_branch 创建分支
push_files 推送文件

使用示例:

用户:帮我搜索 React 相关的热门仓库
 
AI 调用 search_repositories → 返回结果
 
AI:找到以下热门 React 仓库:
1. facebook/react - 220k stars
2. reactjs/reactjs.org - 8.5k stars
...
 
用户:帮我给 facebook/react 创建一个 Issue
 
AI:好的,请告诉我 Issue 的标题和内容...

3.4 数据库 MCP 详解 #

PostgreSQL 配置:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "DATABASE_URL": "postgresql://user:password@localhost:5432/mydb"
      }
    }
  }
}

SQLite 配置:

{
  "mcpServers": {
    "sqlite": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-sqlite",
        "/path/to/database.db"
      ]
    }
  }
}

使用示例:

用户:帮我查询用户表有多少条记录
 
AI 调用 query → SELECT COUNT(*) FROM users
 
AI:用户表共有 1,234 条记录。
 
用户:帮我查看最近注册的 5 个用户
 
AI:最近的 5 个用户是:
1. 张三 - 2024-03-20
2. 李四 - 2024-03-19
...

3.5 Brave Search MCP 详解 #

前提:需要 Brave Search API Key

  1. 访问 brave.com/search/api
  2. 注册并创建 API Key

配置:

{
  "mcpServers": {
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "BSAxxxxxxxxxxxx"
      }
    }
  }
}

使用示例:

用户:帮我搜索 2024 年 React 最佳实践
 
AI 调用 brave_search → 返回搜索结果
 
AI:找到以下相关文章:
1. React Best Practices in 2024 - Medium
2. 10 React Patterns You Should Know - Dev.to
...

四、开发自己的 MCP Server #

4.1 MCP Server 基础结构 #

最简 MCP Server:

// server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
 
// 1. 创建 Server 实例
const server = new Server(
  { name: "my-mcp-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);
 
// 2. 定义工具列表
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "hello",
        description: "向用户打招呼",
        inputSchema: {
          type: "object",
          properties: {
            name: {
              type: "string",
              description: "用户名称",
            },
          },
          required: ["name"],
        },
      },
    ],
  };
});
 
// 3. 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
 
  if (name === "hello") {
    return {
      content: [
        {
          type: "text",
          text: `你好,${args.name}!欢迎使用 MCP!`,
        },
      ],
    };
  }
 
  throw new Error(`Unknown tool: ${name}`);
});
 
// 4. 启动 Server
const transport = new StdioServerTransport();
await server.connect(transport);

4.2 创建一个实用的 MCP Server #

场景:创建一个天气查询 MCP Server

第一步:初始化项目

mkdir weather-mcp-server
cd weather-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node

第二步:创建 Server 代码

// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
 
// 天气 API(模拟)
async function getWeather(city: string): Promise<string> {
  // 实际项目中,这里应该调用真实的天气 API
  // 比如 OpenWeatherMap、和风天气等
  
  const mockData: Record<string, string> = {
    "北京": "晴天,温度 18°C,空气质量良好",
    "上海": "多云,温度 20°C,有轻微雾霾",
    "广州": "小雨,温度 25°C,湿度较高",
    "深圳": "晴天,温度 26°C,适合出行",
    "成都": "阴天,温度 16°C,可能下雨",
  };
  
  return mockData[city] || `未找到 ${city} 的天气信息`;
}
 
// 创建 Server
const server = new Server(
  { 
    name: "weather-mcp-server", 
    version: "1.0.0" 
  },
  { 
    capabilities: { 
      tools: {} 
    } 
  }
);
 
// 定义输入 Schema
const GetWeatherSchema = z.object({
  city: z.string().describe("城市名称,如:北京、上海"),
});
 
// 注册工具列表
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "get_weather",
        description: "获取指定城市的天气信息",
        inputSchema: {
          type: "object",
          properties: {
            city: {
              type: "string",
              description: "城市名称,如:北京、上海、广州",
            },
          },
          required: ["city"],
        },
      },
      {
        name: "list_cities",
        description: "列出支持查询天气的城市",
        inputSchema: {
          type: "object",
          properties: {},
        },
      },
    ],
  };
});
 
// 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
 
  switch (name) {
    case "get_weather": {
      const { city } = GetWeatherSchema.parse(args);
      const weather = await getWeather(city);
      
      return {
        content: [
          {
            type: "text",
            text: `🌤️ ${city}天气:${weather}`,
          },
        ],
      };
    }
    
    case "list_cities": {
      const cities = ["北京", "上海", "广州", "深圳", "成都"];
      
      return {
        content: [
          {
            type: "text",
            text: `支持查询的城市:\n${cities.map(c => `- ${c}`).join("\n")}`,
          },
        ],
      };
    }
    
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});
 
// 启动 Server
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Weather MCP Server started");
}
 
main().catch(console.error);

第三步:配置 package.json

{
  "name": "weather-mcp-server",
  "version": "1.0.0",
  "type": "module",
  "bin": {
    "weather-mcp-server": "./dist/index.js"
  },
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0",
    "zod": "^3.23.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.0.0"
  }
}

第四步:配置 TypeScript

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

第五步:构建和测试

# 构建
npm run build
 
# 本地测试
node dist/index.js
 
# 发布到 npm(可选)
npm publish

第六步:在 Claude Desktop 中使用

{
  "mcpServers": {
    "weather": {
      "command": "node",
      "args": ["/path/to/weather-mcp-server/dist/index.js"]
    }
  }
}

4.3 添加 Resources(数据源) #

Resources 让 AI 可以读取你提供的数据。

import {
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
 
// 定义资源
const resources = new Map([
  ["config", JSON.stringify({ theme: "dark", language: "zh-CN" })],
  ["readme", "# My Project\n\n这是一个示例项目..."],
]);
 
// 注册资源列表
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: "config://app",
        name: "应用配置",
        description: "当前应用的配置信息",
        mimeType: "application/json",
      },
      {
        uri: "file://readme",
        name: "README",
        description: "项目说明文档",
        mimeType: "text/markdown",
      },
    ],
  };
});
 
// 处理资源读取
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  const { uri } = request.params;
  
  if (uri === "config://app") {
    return {
      contents: [
        {
          uri,
          mimeType: "application/json",
          text: resources.get("config")!,
        },
      ],
    };
  }
  
  if (uri === "file://readme") {
    return {
      contents: [
        {
          uri,
          mimeType: "text/markdown",
          text: resources.get("readme")!,
        },
      ],
    };
  }
  
  throw new Error(`Unknown resource: ${uri}`);
});

4.4 添加 Prompts(提示词模板) #

Prompts 让用户可以快速使用预定义的提示词。

import {
  ListPromptsRequestSchema,
  GetPromptRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
 
// 注册提示词列表
server.setRequestHandler(ListPromptsRequestSchema, async () => {
  return {
    prompts: [
      {
        name: "analyze_code",
        description: "分析代码质量和潜在问题",
        arguments: [
          {
            name: "file_path",
            description: "要分析的文件路径",
            required: true,
          },
        ],
      },
      {
        name: "generate_docs",
        description: "为代码生成文档",
        arguments: [
          {
            name: "file_path",
            description: "要生成文档的文件路径",
            required: true,
          },
        ],
      },
    ],
  };
});
 
// 处理提示词请求
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
 
  switch (name) {
    case "analyze_code": {
      return {
        messages: [
          {
            role: "user",
            content: {
              type: "text",
              text: `请分析以下代码的质量和潜在问题:
 
文件:${args?.file_path}
 
请从以下维度进行分析:
1. 代码风格
2. 性能问题
3. 安全隐患
4. 可维护性
5. 改进建议`,
            },
          },
        ],
      };
    }
    
    case "generate_docs": {
      return {
        messages: [
          {
            role: "user",
            content: {
              type: "text",
              text: `请为以下代码生成详细的文档:
 
文件:${args?.file_path}
 
文档应包括:
1. 功能描述
2. 参数说明
3. 返回值说明
4. 使用示例
5. 注意事项`,
            },
          },
        ],
      };
    }
    
    default:
      throw new Error(`Unknown prompt: ${name}`);
  }
});

五、实战场景 #

场景 1:公司内部 API MCP Server #

需求:让 AI 能访问公司内部 API

// company-api-mcp-server.ts
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 API_BASE = "https://api.company.com/v1";
 
// API 请求封装
async function apiRequest(
  endpoint: string,
  method: string = "GET",
  body?: unknown
) {
  const response = await fetch(`${API_BASE}${endpoint}`, {
    method,
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${process.env.COMPANY_API_KEY}`,
    },
    body: body ? JSON.stringify(body) : undefined,
  });
  
  if (!response.ok) {
    throw new Error(`API Error: ${response.status}`);
  }
  
  return response.json();
}
 
const server = new Server(
  { name: "company-api-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);
 
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "get_user",
        description: "获取用户信息",
        inputSchema: {
          type: "object",
          properties: {
            user_id: { type: "string", description: "用户ID" },
          },
          required: ["user_id"],
        },
      },
      {
        name: "list_orders",
        description: "获取订单列表",
        inputSchema: {
          type: "object",
          properties: {
            status: { 
              type: "string", 
              description: "订单状态:pending/completed/cancelled",
            },
            limit: { 
              type: "number", 
              description: "返回数量,默认 10",
            },
          },
        },
      },
      {
        name: "create_task",
        description: "创建任务",
        inputSchema: {
          type: "object",
          properties: {
            title: { type: "string", description: "任务标题" },
            description: { type: "string", description: "任务描述" },
            assignee: { type: "string", description: "负责人ID" },
          },
          required: ["title", "assignee"],
        },
      },
    ],
  };
});
 
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
 
  switch (name) {
    case "get_user": {
      const user = await apiRequest(`/users/${args.user_id}`);
      return {
        content: [{ type: "text", text: JSON.stringify(user, null, 2) }],
      };
    }
    
    case "list_orders": {
      const params = new URLSearchParams();
      if (args.status) params.set("status", args.status as string);
      if (args.limit) params.set("limit", String(args.limit));
      
      const orders = await apiRequest(`/orders?${params}`);
      return {
        content: [{ type: "text", text: JSON.stringify(orders, null, 2) }],
      };
    }
    
    case "create_task": {
      const task = await apiRequest("/tasks", "POST", args);
      return {
        content: [{ 
          type: "text", 
          text: `任务创建成功!\n${JSON.stringify(task, null, 2)}`,
        }],
      };
    }
    
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});
 
const transport = new StdioServerTransport();
server.connect(transport);

配置:

{
  "mcpServers": {
    "company-api": {
      "command": "node",
      "args": ["/path/to/company-api-mcp-server/dist/index.js"],
      "env": {
        "COMPANY_API_KEY": "your-api-key"
      }
    }
  }
}

场景 2:数据库查询 MCP Server #

需求:让 AI 能安全地查询数据库

// database-mcp-server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { Pool } from "pg";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
 
// 数据库连接
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});
 
// 白名单查询(只允许 SELECT)
const ALLOWED_TABLES = ["users", "products", "orders"];
const MAX_RESULTS = 100;
 
const server = new Server(
  { name: "database-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);
 
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "query_table",
        description: "查询数据库表(只读)",
        inputSchema: {
          type: "object",
          properties: {
            table: { 
              type: "string", 
              description: "表名",
              enum: ALLOWED_TABLES,
            },
            columns: { 
              type: "array", 
              items: { type: "string" },
              description: "要查询的列,默认查询全部",
            },
            where: { 
              type: "string", 
              description: "WHERE 条件(可选)",
            },
            limit: { 
              type: "number", 
              description: `返回数量限制,默认 ${MAX_RESULTS}`,
            },
          },
          required: ["table"],
        },
      },
      {
        name: "describe_table",
        description: "查看表结构",
        inputSchema: {
          type: "object",
          properties: {
            table: { 
              type: "string", 
              description: "表名",
              enum: ALLOWED_TABLES,
            },
          },
          required: ["table"],
        },
      },
    ],
  };
});
 
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
 
  switch (name) {
    case "query_table": {
      const { table, columns, where, limit = MAX_RESULTS } = args as any;
      
      // 安全校验
      if (!ALLOWED_TABLES.includes(table)) {
        return {
          content: [{
            type: "text",
            text: `错误:不允许查询表 "${table}"。允许的表:${ALLOWED_TABLES.join(", ")}`,
          }],
        };
      }
      
      // 构建 SQL
      const cols = columns?.length ? columns.join(", ") : "*";
      const safeLimit = Math.min(limit, MAX_RESULTS);
      
      let sql = `SELECT ${cols} FROM ${table} LIMIT ${safeLimit}`;
      if (where) {
        sql = `SELECT ${cols} FROM ${table} WHERE ${where} LIMIT ${safeLimit}`;
      }
      
      try {
        const result = await pool.query(sql);
        return {
          content: [{
            type: "text",
            text: `查询成功,共 ${result.rows.length} 条记录:\n${JSON.stringify(result.rows, null, 2)}`,
          }],
        };
      } catch (error) {
        return {
          content: [{
            type: "text",
            text: `查询失败:${error.message}`,
          }],
        };
      }
    }
    
    case "describe_table": {
      const { table } = args as any;
      
      const sql = `
        SELECT column_name, data_type, is_nullable
        FROM information_schema.columns
        WHERE table_name = $1
      `;
      
      const result = await pool.query(sql, [table]);
      
      return {
        content: [{
          type: "text",
          text: `表 "${table}" 结构:\n${JSON.stringify(result.rows, null, 2)}`,
        }],
      };
    }
    
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});
 
const transport = new StdioServerTransport();
server.connect(transport);

场景 3:前端组件库 MCP Server #

需求:让 AI 了解并使用你的组件库

// component-library-mcp-server.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
 
// 组件文档
const components = {
  Button: {
    description: "按钮组件",
    props: [
      { name: "variant", type: "'primary' | 'secondary' | 'ghost'", default: "'primary'" },
      { name: "size", type: "'sm' | 'md' | 'lg'", default: "'md'" },
      { name: "disabled", type: "boolean", default: "false" },
    ],
    example: `<Button variant="primary" size="md">点击我</Button>`,
  },
  Input: {
    description: "输入框组件",
    props: [
      { name: "type", type: "'text' | 'password' | 'email'", default: "'text'" },
      { name: "placeholder", type: "string", default: "''" },
      { name: "value", type: "string", default: "''" },
      { name: "onChange", type: "(value: string) => void", default: "-" },
    ],
    example: `<Input placeholder="请输入" value={value} onChange={setValue} />`,
  },
  Modal: {
    description: "弹窗组件",
    props: [
      { name: "open", type: "boolean", default: "false" },
      { name: "onClose", type: "() => void", default: "-" },
      { name: "title", type: "string", default: "''" },
    ],
    example: `<Modal open={isOpen} onClose={() => setIsOpen(false)} title="提示">内容</Modal>`,
  },
};
 
const server = new Server(
  { name: "component-library-server", version: "1.0.0" },
  { capabilities: { tools: {}, resources: {} } }
);
 
// 注册资源(组件文档)
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: Object.entries(components).map(([name, info]) => ({
      uri: `component://${name.toLowerCase()}`,
      name: `${name} 组件`,
      description: info.description,
      mimeType: "text/markdown",
    })),
  };
});
 
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  const { uri } = request.params;
  const match = uri.match(/^component:\/\/(.+)$/);
  
  if (match) {
    const name = match[1].charAt(0).toUpperCase() + match[1].slice(1);
    const info = components[name as keyof typeof components];
    
    if (info) {
      const doc = `# ${name} 组件
 
## 描述
${info.description}
 
## Props
 
| 属性 | 类型 | 默认值 |
|------|------|--------|
${info.props.map(p => `| ${p.name} | ${p.type} | ${p.default} |`).join("\n")}
 
## 使用示例
 
\`\`\`tsx
${info.example}
\`\`\`
`;
      
      return {
        contents: [{ uri, mimeType: "text/markdown", text: doc }],
      };
    }
  }
  
  throw new Error(`Unknown resource: ${uri}`);
});
 
// 注册工具
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "generate_component_code",
        description: "生成组件使用代码",
        inputSchema: {
          type: "object",
          properties: {
            component: {
              type: "string",
              description: "组件名称",
              enum: Object.keys(components),
            },
            props: {
              type: "object",
              description: "组件属性",
            },
          },
          required: ["component"],
        },
      },
    ],
  };
});
 
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
 
  if (name === "generate_component_code") {
    const { component, props = {} } = args as any;
    const info = components[component as keyof typeof components];
    
    if (!info) {
      return {
        content: [{
          type: "text",
          text: `未知组件:${component}`,
        }],
      };
    }
    
    // 生成代码
    const propsStr = Object.entries(props)
      .map(([key, value]) => {
        if (typeof value === "string") {
          return `${key}="${value}"`;
        } else if (typeof value === "boolean") {
          return value ? key : "";
        } else {
          return `${key}={${JSON.stringify(value)}}`;
        }
      })
      .filter(Boolean)
      .join(" ");
    
    const code = `<${component}${propsStr ? " " + propsStr : ""}>按钮</${component}>`;
    
    return {
      content: [{
        type: "text",
        text: `生成的代码:\n\`\`\`tsx\n${code}\n\`\`\``,
      }],
    };
  }
 
  throw new Error(`Unknown tool: ${name}`);
});
 
const transport = new StdioServerTransport();
server.connect(transport);

使用效果:

用户:我需要一个登录表单,用你们公司的组件库
 
AI:我来帮你创建登录表单。让我先查看可用的组件...
 
AI 读取 Button、Input 组件文档...
 
AI:好的,这是登录表单的代码:
 
```tsx
import { Button, Input } from '@company/ui';
 
function LoginForm() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
 
  return (
    <form>
      <Input
        type="text"
        placeholder="用户名"
        value={username}
        onChange={setUsername}
      />
      <Input
        type="password"
        placeholder="密码"
        value={password}
        onChange={setPassword}
      />
      <Button variant="primary">登录</Button>
    </form>
  );
}
 
---
 
## 六、常见问题
 
### Q1: MCP Server 连接失败怎么办?
 
**检查步骤:**
 
```bash
# 1. 确认 Node.js 版本(需要 18+)
node --version
 
# 2. 手动测试 MCP Server
npx @modelcontextprotocol/server-filesystem /tmp
 
# 3. 查看日志(Claude Desktop)
# macOS: ~/Library/Logs/Claude/
# Windows: %APPDATA%\Claude\logs\
 
# 4. 检查配置文件路径是否正确
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json

常见错误:

错误 原因 解决
ENOENT 找不到命令 确认 npx/node 在 PATH 中
Connection refused Server 未启动 检查命令是否正确
Permission denied 权限问题 chmod +x 或检查路径

Q2: 如何调试 MCP Server? #

方法一:直接运行

# 直接运行 Server,查看输出
node /path/to/your-server/dist/index.js
 
# 通过 stdin 发送测试请求
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node dist/index.js

方法二:使用 MCP Inspector

# 安装并运行 Inspector
npx @modelcontextprotocol/inspector node dist/index.js
 
# 打开浏览器查看界面
# http://localhost:5173

方法三:添加日志

// 在 Server 代码中添加
console.error("Debug message"); // 使用 stderr,不会影响 MCP 通信
 
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  console.error("Received request:", request.params);
  // ...
});

Q3: 如何限制 MCP Server 的权限? #

限制文件访问范围:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/username/projects/my-project"  // 只允许访问这个目录
      ]
    }
  }
}

限制网络访问:

// 在代码中限制允许访问的域名
const ALLOWED_DOMAINS = ["api.example.com", "cdn.example.com"];
 
async function fetchWithRestriction(url: string) {
  const { hostname } = new URL(url);
  if (!ALLOWED_DOMAINS.includes(hostname)) {
    throw new Error(`Domain ${hostname} is not allowed`);
  }
  return fetch(url);
}

Q4: 如何在 MCP Server 中处理错误? #

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  try {
    const { name, arguments: args } = request.params;
    
    // 处理逻辑...
    
  } catch (error) {
    // 返回友好的错误信息
    return {
      content: [{
        type: "text",
        text: `❌ 操作失败:${error.message}`,
      }],
      isError: true,  // 标记为错误响应
    };
  }
});

Q5: 如何让 MCP Server 支持流式响应? #

// MCP SDK 目前不直接支持流式响应
// 但可以通过多次调用实现类似效果
 
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const items = ["项目1", "项目2", "项目3"];
  const results = [];
  
  for (const item of items) {
    // 处理每个项目
    const result = await processItem(item);
    results.push(result);
    
    // 可以在这里发送进度更新(通过 Resource)
  }
  
  return {
    content: [{
      type: "text",
      text: results.join("\n"),
    }],
  };
});

Q6: MCP Server 可以调用其他 MCP Server 吗? #

可以!这叫「MCP 链式调用」。

// 在 MCP Server 中调用另一个 MCP Server
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
 
// 连接到文件系统 MCP
const transport = new StdioClientTransport({
  command: "npx",
  args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
});
 
const client = new Client({ name: "my-client", version: "1.0.0" }, {});
await client.connect(transport);
 
// 调用文件系统的工具
const result = await client.request(
  { method: "tools/call", params: { name: "list_directory", arguments: { path: "/tmp" } } },
  CallToolResultSchema
);

七、资源汇总 #

官方资源 #

资源 链接 说明
MCP 官网 modelcontextprotocol.io 官方文档
MCP GitHub github.com/modelcontextprotocol 源码和示例
MCP SDK @modelcontextprotocol/sdk TypeScript SDK
MCP Servers github.com/modelcontextprotocol/servers 官方 Servers
MCP Inspector @modelcontextprotocol/inspector 调试工具

社区资源 #

资源 链接 说明
awesome-mcp github.com/punkpeye/awesome-mcp MCP 资源集合
MCP Marketplace mcp.so MCP Server 市场
Smithery smithery.ai MCP 工具目录

常用 MCP Server #

Server 功能 链接
filesystem 文件系统 @modelcontextprotocol/server-filesystem
github GitHub 集成 @modelcontextprotocol/server-github
postgres PostgreSQL @modelcontextprotocol/server-postgres
sqlite SQLite @modelcontextprotocol/server-sqlite
brave-search 网页搜索 @modelcontextprotocol/server-brave-search
puppeteer 浏览器自动化 @modelcontextprotocol/server-puppeteer
slack Slack 集成 @modelcontextprotocol/server-slack
google-maps 地图服务 @modelcontextprotocol/server-google-maps
fetch HTTP 请求 @modelcontextprotocol/server-fetch
memory 记忆存储 @modelcontextprotocol/server-memory

快速命令速查 #

# 运行文件系统 MCP
npx -y @modelcontextprotocol/server-filesystem /path/to/dir
 
# 运行 GitHub MCP
GITHUB_TOKEN=xxx npx -y @modelcontextprotocol/server-github
 
# 运行 SQLite MCP
npx -y @modelcontextprotocol/server-sqlite /path/to/db.sqlite
 
# 运行 Inspector 调试
npx @modelcontextprotocol/inspector node your-server.js

总结速记 #

概念 说明
MCP 模型上下文协议,让 AI 连接工具和数据
Host 运行 AI 的应用(Claude、Cursor)
Server 提供工具和数据的服务端
Tool 可执行的函数
Resource 可读取的数据源
Prompt 预定义的提示词模板

开发 MCP Server 的核心步骤:

  1. 安装 @modelcontextprotocol/sdk
  2. 创建 Server 实例
  3. 注册 Tools / Resources / Prompts
  4. 实现处理逻辑
  5. 配置到 Host 应用

最后更新:2026-03-29