MCP 初识到实操:打造 AI 的“USB-C”接口,让大模型真正“手眼通天”

MCP 初识到实操:打造 AI 的"USB-C"接口,让大模型真正"手眼通天"

导读 :大模型很聪明,但它被关在"沙盒"里,看不见你的文件,动不了你的数据库。如何打破这层壁垒?Anthropic 推出的 MCP (Model Context Protocol) 给出了标准答案。本文将带你从理论到实战,用 Node.js 手写一个 MCP Server,并让它无缝接入 Cursor 和 LangChain,实现真正的"AI 自动化"。


一、痛点:LLM 的"残疾"与 Tool 的局限

我们早已习惯让大模型写代码、做规划。但你是否发现,传统的 LLM with Tools 模式存在天然瓶颈:

  1. 语言绑定:如果你的 Agent 是 Node.js 写的,那你的 Tool 也得是 JS/TS。那些用 Python 写的数据分析脚本、用 Rust 写的高性能计算器,难道要全部重写?
  2. 耦合严重:Tool 的逻辑硬编码在 Agent 项目里,每次新增功能都要重启主进程,难以复用。
  3. 部署困难:想在公司内部推广一个"查询内网数据库"的 Tool,难道要让每个员工的 Agent 都安装一遍依赖?

我们需要一种"插件化"的架构:Agent 只负责思考,具体的"手脚"(工具)可以独立开发、独立部署、热插拔。

这就是 MCP (Model Context Protocol) 诞生的背景。


二、什么是 MCP?AI 世界的 USB-C

MCP (Model Context Protocol) 是由 AI 巨头 Anthropic 于 2024 年 11 月发起,并在 2025 年 12 月正式捐赠给 Linux 基金会 下属的 Agentic AI Foundation (AAIF) 维护的开放标准协议。

你可以把它理解为 AI 领域的 USB-C 接口

  • 以前:每个设备(AI 应用)都需要特定的转接头(定制代码)才能连接打印机(工具)。
  • 现在:只要设备支持 USB-C(MCP 协议),任何符合标准的打印机(MCP Server)插上就能用。

1. 核心架构:三位一体

MCP 架构清晰地将角色分为三类:

角色 英文名称 职责比喻 典型代表
Host MCP Host 大脑/宿主:运行大模型,决定何时调用工具。 Cursor, Claude Desktop, 自定义 Agent
Client MCP Client 翻译官:内置在 Host 中,负责通过协议与 Server 通信。 (SDK 内部自动处理)
Server MCP Server 手脚/服务:封装具体能力(读写文件、查库、调用 API),对外暴露标准接口。 你写的 my-mcp-server.mjs

2. 通信方式:本地与远程的统一

MCP 最强大的地方在于它屏蔽了底层通信的差异:

  • 本地通信 (Stdio)

    • 场景:Cursor 调用你本地的脚本。
    • 原理 :类似"投币售货机"。Host 启动 Server 进程,通过 标准输入输出流 (stdin/stdout) 传递 JSON 消息。
    • 优势:零网络延迟,无需开放端口,安全性高。
  • 远程通信 (HTTP/SSE)

    • 场景:云端 Agent 调用公司内部的数据库服务。
    • 原理:Server 作为一个 Web 服务运行,Host 通过 HTTP 请求交互。
    • 优势:跨机器、跨网络,适合微服务架构。

三、实战:手把手编写第一个 MCP Server

我们将用 Node.js 编写一个最简单的 MCP Server,提供两个核心能力:

  1. Toolquery-user (查询用户信息)。
  2. Resource使用指南 (供模型阅读的文档)。

1. 环境准备

确保已安装 Node.js (v18+),初始化项目并安装 SDK:

bash 复制代码
mkdir my-mcp-server
cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod

2. 代码实现 (my-mcp-server.mjs)

新建文件 my-mcp-server.mjs,填入以下代码。注意注释中的关键点:

javascript 复制代码
#!/usr/bin/env node
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';

// 1. 模拟数据库
const database = {
    users: {
        "001": { id: "001", name: "张三", email: "zhangsan@example.com", role: "admin" },
        "002": { id: "002", name: "李四", email: "lisi@example.com", role: "user" },
        "003": { id: "003", name: "王五", email: "wangwu@example.com", role: "user" },
    }
};

// 2. 创建 Server 实例
const server = new McpServer({
    name: 'demo-user-server',
    version: '1.0.0',
});

// 3. 注册 Tool (工具)
// 核心:定义名字、描述、参数 Schema (Zod),以及执行函数
server.registerTool('query-user', {
    description: '查询数据库中的用户信息。输入用户ID, 返回该用户的详细信息(姓名、邮箱、角色)。',
    inputSchema: {
        // 使用 Zod 定义参数格式,模型会自动遵循此格式传参
        userId: z.string().describe("用户 ID, 例如:001, 002, 003")
    }
}, async ({ userId }) => {
    // ⚠️ 注意:这里不要使用 console.log,会污染通信协议!
    // 调试请只用 console.error
    console.error(`[DEBUG] Received request for user: ${userId}`);

    const user = database.users[userId];
    if (!user) {
        return {
            content: [
                { type: 'text', text: `❌ 用户ID ${userId} 不存在。可用的ID: 001, 002, 003` }
            ]
        };
    } else {
        return {
            content: [
                { 
                    type: 'text', 
                    text: `✅ 找到用户:\n- ID: ${user.id}\n- 姓名: ${user.name}\n- 邮箱: ${user.email}\n- 角色: ${user.role}` 
                }
            ]
        };
    }
});

// 4. 注册 Resource (资源)
// 资源不是用来"执行"的,而是给模型"阅读"的上下文(类似 RAG)
server.registerResource('使用指南', 'docs://guide', {
    description: 'MCP Server 使用文档,包含功能说明和使用建议。',
    mimeType: 'text/plain',
}, async () => {
    return {
        contents: [
            {
                uri: 'docs://guide',
                mimeType: 'text/plain',
                text: `MCP Server 使用指南\n功能:提供用户查询工具。\n使用:在对话中直接问"帮我查一下 001 号用户",系统会自动调用 query-user 工具。`,
            }
        ]
    };
});

// 5. 启动服务
// 使用 Stdio 传输层,通过标准输入输出与 Host 通信
const transport = new StdioServerTransport();
await server.connect(transport);

console.error('✅ MCP Server started successfully via Stdio.');

3. 关键注意点 (避坑指南)

  • 严禁 console.log :MCP 通过 stdout 传输 JSON。如果你打印了 "Server starting...",客户端解析 JSON 会失败,导致连接立即断开 (Client closed)。调试请务必使用 console.error
  • Zod 是必须的inputSchema 必须使用 Zod 定义,这是模型理解参数类型的唯一依据。
  • 路径问题 :Windows 用户在配置路径时,建议使用正斜杠 / 或双反斜杠 \\,避免转义错误。

四、部署与集成:让 AI 真正用起来

写好 Server 只是第一步,关键在于如何让它被 AI 调用。

场景 A:在 Cursor / Claude Desktop 中直接使用 (本地 Stdio)

这是最典型的用法,让编辑器直接拥有查询数据库的能力。

  1. 找到配置文件
    • 在cursor中找到设置进入 tools &mcp设置
  • 点击新增一个mcp server
  • 进入host json 文件进行配置
  1. 添加配置: 将以下配置加入 JSON 文件中。注意替换为你本地的绝对路径。

    json 复制代码
    {
      "mcpServers": {
        "user-db-lookup": {
          "command": "node",
          "args": [
            "D:/workspace/my-mcp-server/my-mcp-server.mjs"
          ],
          "env": {
             "NODE_ENV": "production"
          }
        }
      }
    }
  2. 验证

    • 重启 Cursor/Claude Desktop。
    • 在对话框输入:"帮我查一下用户 002 的邮箱是多少?"
    • 现象 :AI 会自动识别意图,调用 query-user 工具,并返回结果:"李四的邮箱是 lisi@example.com"。

场景 B:在 LangChain Agent 中集成 (代码级调用)

如果你想在自己的 Python/Node Agent 程序中复用这个 MCP Server,可以使用官方适配器。

安装适配器

bash 复制代码
pnpm install @langchain/mcp-adapters
# 或者 python
pip install langchain-mcp-adapters

代码示例 (TypeScript)

typescript 复制代码
import { McpClient } from '@langchain/mcp-adapters';
import { AgentExecutor, createReactAgent } from "langchain/agents";
// ... 其他导入

async function runAgent() {
  // 1. 连接到本地 MCP Server
  const client = new McpClient({
    command: "node",
    args: ["D:/workspace/my-mcp-server/my-mcp-server.mjs"],
    transportType: "stdio"
  });
  
  await client.connect();

  // 2. 将 MCP Tools 转换为 LangChain Tools
  const tools = await client.getTools();

  // 3. 构建 Agent
  const agent = createReactAgent({
    llm: model,
    tools: tools, // 这里直接注入了 MCP 提供的能力
    prompt: promptTemplate
  });

  const executor = new AgentExecutor({ agent, tools });

  // 4. 执行
  const result = await executor.invoke({ input: "查一下 001 号用户是谁?" });
  console.log(result.output);
  
  await client.close();
}

意义 :看!你的 LangChain 程序完全不需要知道数据库怎么查,也不需要引入 mysql 驱动。它只是调用了一个标准的 MCP Tool。解耦就此实现。


五、总结与展望

为什么 MCP 是必然趋势?

  1. 语言无关性:你可以用 Rust 写高性能计算 Server,用 Python 写数据分析 Server,用 Go 写网络爬虫 Server,然后让一个 JS 写的 Agent 统一调度它们。
  2. 安全边界:Server 运行在独立进程中,即使崩溃或被攻击,也不会影响 Host (主程序) 的稳定性。
  3. 生态爆发:随着 Linux 基金会的介入,未来会出现海量的公共 MCP Server(如"查询天气"、"操作 Jira"、"读取 Notion"),开发者只需"插拔"即可使用,无需重复造轮子。

下一步做什么?

  • 尝试 HTTP 传输 :将 StdioServerTransport 改为 StreamableHTTPServerTransport,把你的 Tool 发布为局域网服务。
  • 探索 Resources & Prompts:除了 Tool,利用 Resource 注入私有知识库,利用 Prompt 模板规范模型行为。
  • 贡献社区:将你现有的脚本封装成 MCP Server,分享给团队。

MCP 不仅仅是一个协议,它是 AI Agent 从"聊天机器人"进化为"超级员工"的基础设施。 现在,就动手写下你的第一个 Server 吧!

相关推荐
肥肥旭手记3 小时前
openclaw平替之nanobot源码解析(二):agent命令、消息总线与循环引擎
agent
Flittly3 小时前
【从零手写 ClaudeCode:learn-claude-code 项目实战笔记】(6)Context Compact (上下文压缩)
python·agent
亚马逊云开发者15 小时前
5 分钟用 Amazon Bedrock 搭一个 AI Agent:从零到能干活
人工智能·agent·amazon
肥肥旭手记17 小时前
opencalw平替之nanobot 源码解析(一):环境搭建、Debug 配置与 onboard 命令详解
agent
阿里云大数据AI技术18 小时前
告别先开发后治理:Agent 驱动的数据质量一体化交付
agent
老纪的技术唠嗑局19 小时前
Agent / Skills / Teams 架构演进流程及技术选型之道
人工智能·agent
数据智能老司机21 小时前
Kubernetes 上的生成式 AI——模型数据
kubernetes·llm·agent
302AI21 小时前
大白话聊一聊:为什么OpenClaw那么火
llm·agent·vibecoding
数据智能老司机1 天前
如何对 AI Web 智能体进行身份认证
websocket·agent