MCP TypeScript SDK的使用

MCP TypeScript SDK 架构

概述

MCP (Model Context Protocol) TypeScript SDK 实现了模型上下文协议,用于在 LLM 和外部数据源/工具之间建立标准化的通信。


架构图

arduino 复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                              MCP Architecture                                │
└─────────────────────────────────────────────────────────────────────────────┘

                              ┌─────────────────┐
                              │   LLM (AI)      │
                              └────────┬────────┘
                                       │
                          ┌────────────▼────────────┐
                          │      MCP Client         │
                          │  @modelcontextprotocol/ │
                          │      sdk/client         │
                          └────────────┬────────────┘
                                       │
                    ┌──────────────────┼──────────────────┐
                    │                  │                  │
          ┌─────────▼─────────┐ ┌──────▼──────┐ ┌───────▼──────┐
          │    Tools API      │ │ Resources   │ │   Prompts    │
          │  listTools()      │ │ listResources│ │ listPrompts()│
          │  callTool()       │ │ readResource │ │  getPrompt()  │
          └─────────┬─────────┘ └──────┬──────┘ └───────┬──────┘
                    │                   │                │
          ┌─────────▼───────────────────▼────────────────▼─────────┐
          │                    Transport Layer                     │
          │  ┌──────────────┐  ┌──────────────────┐  ┌──────────┐ │
          │  │    Stdio     │  │ Streamable HTTP  │  │   SSE    │ │
          │  │  (Local)     │  │   (Remote)       │  │(Legacy)  │ │
          │  └──────────────┘  └──────────────────┘  └──────────┘ │
          └──────────────────────────┬──────────────────────────────┘
                                    │
                    ┌───────────────┴───────────────┐
                    │                               │
          ┌─────────▼─────────┐         ┌─────────▼─────────┐
          │   MCP Server      │         │   MCP Client      │
          │  (Provider)       │◄───────►│  (Consumer)       │
          └─────────┬─────────┘   RPC   └───────────────────┘
                    │
          ┌─────────▼─────────────────────────────────────────┐
          │                  Capability Layer                   │
          │  ┌─────────┐  ┌──────────┐  ┌────────┐  ┌───────┐ │
          │  │ Tools   │  │ Resources │  │Prompts │  │Sampling│ │
          │  │         │  │          │  │        │  │Elicit │ │
          │  └─────────┘  └──────────┘  └────────┘  └───────┘ │
          └────────────────────────────────────────────────────┘

组件说明

组件 作用 职责说明
LLM 消费方 大语言模型,通过 MCP Client 发现和使用外部工具、资源。解析用户意图,决定调用哪些工具,处理返回结果
MCP Client 连接管理 SDK 客户端库,负责:① 与服务器建立连接 ② 发现并列出可用工具/资源/提示器 ③ 调用工具并传递参数 ④ 读取资源内容 ⑤ 处理服务器通知
MCP Server 能力提供 SDK 服务器端,负责:① 注册和暴露 Tools(可执行函数)② 注册和暴露 Resources(可读数据)③ 注册和暴露 Prompts(提示模板)④ 处理客户端请求并返回结果
Transport 通信通道 传输层,负责客户端与服务器之间的消息传递。支持多种传输方式:① Stdio - 本地进程间通信 ② HTTP Streamable - 远程 HTTP 通信,支持双向流 ③ SSE - 服务器单向推送事件
Tools 执行能力 服务器暴露的可调用函数,用于执行具体操作(如计算、查询、创建等)。带输入参数,返回执行结果
Resources 数据暴露 服务器暴露的只读数据,支持客户端读取和订阅变更。可以是配置文件、数据库记录、文件内容等
Prompts 模板复用 预定义的提示模板,支持参数化。客户端可以获取填充参数后的完整消息,用于标准化常见任务的提示
Sampling LLM 代理 允许服务器向客户端请求 LLM 推理能力。服务器可以请客户端的 LLM 生成文本、总结内容等
Elicitation 交互代理 允许服务器向客户端请求用户输入。用于需要用户确认、填写表单或做出选择的场景

SDK 模块结构

本项目使用 v1 版本的 @modelcontextprotocol/sdk 统一包。

模块 导入路径 用途
Client @modelcontextprotocol/sdk/client/index.js MCP 客户端实现,连接服务器、调用工具、读取资源
Server @modelcontextprotocol/sdk/server/mcp.js MCP 服务器实现,暴露工具、资源、提示器

协议层设计

Transport 层

Transport 层负责客户端与服务器之间的底层通信。

传输类型 适用场景
Stdio StdioServerTransport / StdioClientTransport 本地进程通信,同一系统内 spawn 子进程
HTTP Streamable StreamableHTTPClientTransport 远程服务器,支持 SSE 事件流(推荐)
SSE SSEClientTransport Server-Sent Events 单向事件流
Stdio 传输

适合本地场景,服务器作为子进程启动:

typescript 复制代码
// 服务器
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const transport = new StdioServerTransport();
await server.connect(transport);

// 客户端
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const transport = new StdioClientTransport({ command: 'node', args: ['server.js'] });
HTTP Streamable 传输

适合远程场景,服务器独立运行:

typescript 复制代码
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const transport = new StreamableHTTPClientTransport(new URL('http://localhost:3000/mcp'));
await client.connect(transport);

Capability 层

MCP 协议定义了四种主要能力。

Tools(工具)

工具是服务器暴露的可调用函数,LLM 可以通过工具执行实际操作。

服务器注册

typescript 复制代码
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import * as z from 'zod';

server.registerTool(
  'calculate-bmi',
  {
    title: 'BMI Calculator',
    description: 'Calculate Body Mass Index',
    inputSchema: z.object({
      weightKg: z.number().describe('Weight in kilograms'),
      heightM: z.number().describe('Height in meters')
    }),
    outputSchema: z.object({ bmi: z.number() })
  },
  async ({ weightKg, heightM }) => {
    const bmi = weightKg / (heightM * heightM);
    return {
      content: [{ type: 'text', text: `BMI: ${bmi.toFixed(2)}` }],
      structuredContent: { bmi }
    };
  }
);

客户端调用

typescript 复制代码
const result = await client.callTool({
  name: 'calculate-bmi',
  arguments: { weightKg: 70, heightM: 1.75 }
});

Resources(资源)

资源是服务器暴露的二进制或文本数据,客户端可以读取和订阅。

服务器注册

typescript 复制代码
server.registerResource(
  'config://app',
  {
    title: 'App Config',
    description: 'Application configuration',
    mimeType: 'application/json'
  },
  async () => ({
    contents: [{
      uri: 'config://app',
      text: JSON.stringify({ theme: 'dark', language: 'en' })
    }]
  })
);

客户端操作

typescript 复制代码
// 列出资源
const { resources } = await client.listResources();

// 读取资源
const { contents } = await client.readResource({ uri: 'config://app' });

// 订阅变更
await client.subscribeResource({ uri: 'config://app' });
client.setNotificationHandler('notifications/resources/updated', handler);

Prompts(提示器)

提示器是预定义的提示模板,可以携带参数生成消息。

服务器注册

typescript 复制代码
server.registerPrompt(
  'review-code',
  {
    title: 'Code Review',
    description: 'Review code for best practices',
    argsSchema: z.object({ code: z.string() })
  },
  ({ code }) => ({
    messages: [{
      role: 'user',
      content: { type: 'text', text: `Please review:\n\n${code}` }
    }]
  })
);

客户端调用

typescript 复制代码
const { messages } = await client.getPrompt({ name: 'review-code', arguments: { code: '...' } });

Sampling(采样)

Sampling 允许服务器向客户端请求 LLM 推理。

服务器端请求

typescript 复制代码
server.registerTool(
  'summarize',
  { inputSchema: z.object({ text: z.string() }) },
  async ({ text }, ctx) => {
    const response = await ctx.mcpReq.requestSampling({
      messages: [{ role: 'user', content: { type: 'text', text: `Summarize: ${text}` } }],
      maxTokens: 500
    });
    return { content: [{ type: 'text', text: JSON.stringify(response.content) }] };
  }
);

客户端处理

typescript 复制代码
client.setRequestHandler('sampling/createMessage', async request => {
  const lastMessage = request.params.messages.at(-1);
  // 转发给 LLM 并返回
  return { model: 'claude-3-5-sonnet', role: 'assistant', content: { type: 'text', text: '...' } };
});

Elicitation(请求用户输入)

Elicitation 允许服务器向客户端请求用户交互式输入。

服务器端请求

typescript 复制代码
const result = await ctx.mcpReq.elicitInput({
  mode: 'form',
  message: 'Please rate this:',
  requestedSchema: {
    type: 'object',
    properties: { rating: { type: 'integer', minimum: 1, maximum: 5 } },
    required: ['rating']
  }
});

客户端处理

typescript 复制代码
client.setRequestHandler('elicitation/create', async request => ({
  action: 'accept',
  content: { rating: 5 }
}));

Auth 层

SDK 支持 OAuth 2.0 认证。

Provider 用途
ClientCredentialsProvider 客户端凭证流,适用于服务间认证
PrivateKeyJwtProvider 私钥 JWT,适用于更安全的场景
typescript 复制代码
import { ClientCredentialsProvider } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const authProvider = new ClientCredentialsProvider({
  clientId: 'my-service',
  clientSecret: 'my-secret'
});

const transport = new StreamableHTTPClientTransport(
  new URL('http://localhost:3000/mcp'),
  { authProvider }
);

错误处理

SDK 提供 ProtocolErrorSdkError

typescript 复制代码
import { ProtocolError } from '@modelcontextprotocol/sdk/client/index.js';

if (error instanceof ProtocolError) {
  console.log(error.code); // 错误码
  console.log(error.message); // 错误消息
}
相关推荐
Awu12272 小时前
⚡精通 Claude 第 1 课:掌握 Slash Commands
前端·人工智能·ai编程
小村儿2 小时前
连载04-CLAUDE.md ---一起吃透 Claude Code,告别 AI coding 迷茫
前端·后端·ai编程
量子位3 小时前
Claude Mythos官宣!性能碾压Opus 4.6贵5倍,因太危险遭「囚禁」
ai编程
ServBay3 小时前
阿里超强编程模型Qwen 3.6 -Plus 发布,国产编程AI的春天?
后端·ai编程
程序员老刘3 小时前
Trae 按照Token计费,我的Flutter项目每个月要花多少钱?
flutter·ai编程·trae
与虾牵手4 小时前
TypeScript 类型体操实战:从看不懂到手撕 5 道高频面试题
ai编程
飞哥数智坊5 小时前
【大纲】TRAE AI 编程入门扩展课:一些可能有用的编程常识
人工智能·ai编程·trae
恋猫de小郭5 小时前
Google 开源大模型 Gemma4 怎么选,本地跑的话需要什么条件?
前端·人工智能·ai编程
用户415200867777 小时前
AI 编程助手实战:从单点工具到自动化工作流的演进
ai编程