用 MCP 把自己的接口接入 AI

概念

MCP和API的区别?

一句话总结:MCP 是为大模型量身定制的API,让模型能像人一样对话式调用工具;传统 API 则是给程序员用的,需要代码对接。

特性 MCP 传统 API
目标 给 LLM(大模型)提供上下文和功能,专为 LLM 设计 给应用或前端提供数据和功能,供人或程序调用
调用方式 可以通过工具(Tool)或资源(Resource)动态提供信息,支持提示模板(Prompt)和交互 通常是 REST/GraphQL 调用,直接请求数据或触发动作
返回内容 可以包含文本、结构化内容、ResourceLink(资源引用)等,便于 LLM 消化和生成 通常返回 JSON 或二进制数据
交互方式 支持持续会话、交互式输入(elicitation)、上下文感知 请求-响应模式,通常无持续会话(除非额外实现)
扩展性 可以随时动态注册/更新工具、资源、提示模板 扩展需要新增 API 接口或改后端逻辑

几个概念:

  • resources:类似API的GET接口,用来提供数据,不能有副作用。比如根据参数返回数据库查询结果
  • tools:类似POST操作,调用外部服务,然后返回结果
  • prompts:预定义好的对话模板,比如给review-code定义好一些预设,模型需要去review code时会把prompt添加到上下文

官方代码解释

GitHub - modelcontextprotocol/typescript-sdk: The official TypeScript SDK for Model Context Protocol servers and clients

typescript 复制代码
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

// Create an MCP server
const server = new McpServer({
  name: "demo-server",
  version: "1.0.0"
});

// Add an addition tool
server.registerTool("add",
  {
    title: "Addition Tool",
    description: "Add two numbers",
    inputSchema: { a: z.number(), b: z.number() }
  },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);

// Add a dynamic greeting resource
server.registerResource(
  "greeting",
  new ResourceTemplate("greeting://{name}", { list: undefined }),
  { 
    title: "Greeting Resource",      // Display name for UI
    description: "Dynamic greeting generator"
  },
  async (uri, { name }) => ({
    contents: [{
      uri: uri.href,
      text: `Hello, ${name}!`
    }]
  })
);

// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
await server.connect(transport);

title、description是模型可读取的,用来知道工具的作用。inputSchema 告诉模型工具需要的参数和类型。

模型端会根据对话上下文或者用户输入生成参数,例如:

sequenceDiagram participant U as 用户 participant M as 模型 (LLM) participant MCP as MCP 服务器 participant T as 工具: add U->>M: 请输入 "请帮我算 3 + 5" M->>M: 解析意图 → 识别需要调用 add 工具 M->>M: 按 schema 生成参数 { a: 3, b: 5 } M->>MCP: 调用工具请求 (add, {a:3, b:5}) MCP->>T: 执行加法 T-->>MCP: 返回结果 8 MCP-->>M: 返回 { content: "8" } M-->>U: 回复 "结果是 8"

让大模型调用mcp

首先在本地创建mcp server

javascript 复制代码
# /Projects/mcp-demo

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

// Create an MCP server
const server = new McpServer({
  name: "demo-server",
  version: "1.0.0"
});

// Add an addition tool
server.registerTool("add",
  {
    title: "Addition Tool",
    description: "Add two numbers",
    inputSchema: { a: z.number(), b: z.number() }
  },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);

// Add a dynamic greeting resource
server.registerResource(
  "greeting",
  new ResourceTemplate("greeting://{name}", { list: undefined }),
  { 
    title: "Greeting Resource",      // Display name for UI
    description: "Dynamic greeting generator"
  },
  async (uri, { name }) => ({
    contents: [{
      uri: uri.href,
      text: `Hello, ${name}!`
    }]
  })
);

// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
await server.connect(transport);

cursor使用

按command + shfirt + p ,输入 open mcp settings

点击 new mcp server,会创建 ~/.cursor/mcp.json,写入如下配置,保存后会全局生效:

json 复制代码
{
  "mcpServers": {
    "test-tools": {
      "command": "tsx",
      "args": ["/Projects/mcp-demo/server.ts"]
    }
  }
}

这样cursor就知道如何启动mcp服务器,列出所有工具、resource等等。

当你在 Cursor 配好 ~/.cursor/mcp.json 后:

  • Cursor 会在后台 启动你的 server.ts ,通过 stdio(标准输入/输出流)跟它通信;
  • 启动时,MCP server 会向 Cursor 声明自己有哪些工具、资源、prompts
  • 模型对话时,如果 Cursor 判断需要用到某个 MCP 工具,就会把参数补齐,然后发消息给 MCP server;
  • MCP server 返回结果,Cursor 再交给模型。

这种是零开发成本,但前提是你在 Cursor 里使用。

自己实现调用逻辑

如果你有一个自己的 AI API 调用逻辑(例如调用 OpenAI、Anthropic、DeepSeek...),想让它知道 MCP 工具,就要模拟 Cursor 的做法:

流程分三步:

(1) 启动 MCP server

用 SDK 提供的 client 启动你的 server.ts:

typescript 复制代码
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { McpClient } from "@modelcontextprotocol/sdk/client/mcp.js";

const transport = new StdioClientTransport({
  command: "tsx",
  args: ["./server.ts"]
});

const client = new McpClient(transport);
await client.connect();

(2) 取出 MCP 工具定义

typescript 复制代码
const tools = await client.listTools();
console.log("Available tools:", tools);

这里会返回工具的 name, title, description, inputSchema ------ 你要把这些转成 OpenAI API 的 functions 或 Anthropic 的 tools 格式。

(3) 把工具注册给大模型

以 OpenAI 为例:

typescript 复制代码
import OpenAI from "openai";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

const completion = await openai.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "请帮我算 3 + 5" }],
  tools: tools.map(tool => ({
    type: "function",
    function: {
      name: tool.name,
      description: tool.description,
      parameters: tool.inputSchema // MCP 的 schema 可以直接转
    }
  }))
});

(4) 执行工具调用

模型可能返回:

typescript 复制代码
{
  "tool_calls": [
    {
      "function": "add",
      "arguments": { "a": 3, "b": 5 }
    }
  ]
}

你就用 MCP client 去执行:

typescript 复制代码
const result = await client.callTool("add", { a: 3, b: 5 });
console.log("MCP result:", result);

再把结果发回模型,继续对话。

相关推荐
古夕2 小时前
技术复盘文档:解决 `watchEffect` 导致的图片闪烁无限循环问题
前端·javascript·vue.js
拾缘2 小时前
esm和cmj混用报错分析
前端·javascript
古夕2 小时前
技术复盘文档:`resourceLogoUrl` 数据丢失问题分析与最终解决方案
前端·javascript·vue.js
streaker3032 小时前
前端开发者的 AI 学习笔记 🚀
前端·openai
高热度网2 小时前
从 Vercel 构建失败谈 Git 大小写敏感性问题:一个容易被忽视的跨平台陷阱
前端·javascript
青衫旧故2 小时前
Uniapp Vue2 Vue3常量保存及调用
前端·javascript·vue.js·uni-app
知白守黑2673 小时前
访问控制、用户认证、https
linux·服务器·前端
小妖怪的夏天3 小时前
electron 打包web页面解决跨域问题
前端·javascript·electron
骚饼3 小时前
Git 命令配置别名、Git命令缩写(Mac版)
前端·git