首页
/ 3大痛点解决!TypeScript SDK掌控模型上下文协议全指南

3大痛点解决!TypeScript SDK掌控模型上下文协议全指南

2026-05-04 10:40:30作者:乔或婵

你是否在为LLM开发中的上下文管理而头疼?还在寻找标准化的模型交互方式?想快速构建兼容MCP协议的应用却不知从何入手?本文将带你从零开始,掌握Model Context Protocol(模型上下文协议)TypeScript SDK的核心功能,轻松应对LLM开发中的上下文管理挑战,实现标准化的模型交互。

为什么选择MCP TypeScript SDK?

MCP TypeScript SDK是Model Context Protocol(模型上下文协议)的官方TypeScript实现,它将上下文提供与LLM交互的关注点分离,让你能够以标准化方式为大语言模型提供上下文。通过这个SDK,你可以轻松创建MCP服务器、构建MCP客户端,并使用多种传输方式进行通信,彻底解决LLM应用开发中的上下文管理难题。

MCP知识图谱

graph TD
    A[MCP核心] --> B[McpServer]
    A --> C[McpClient]
    B --> D[工具系统]
    B --> E[资源系统]
    B --> F[提示系统]
    A --> G[传输层]
    G --> H[Streamable HTTP]
    G --> I[Stdio]
    G --> J[Websocket]
    D --> K[工具注册]
    D --> L[工具调用]
    E --> M[静态资源]
    E --> N[动态资源]
    F --> O[提示模板]
    F --> P[参数处理]

如何快速搭建你的第一个MCP服务器?

环境准备

在开始之前,请确保你的开发环境满足以下要求:

  • Node.js 14或更高版本
  • npm 6或更高版本

首先,克隆项目仓库:

git clone https://gitcode.com/GitHub_Trending/ty/typescript-sdk
cd typescript-sdk

然后安装项目依赖:

npm install

✅ 完成这一步后,你的开发环境就准备好了!

创建基础服务器

创建一个名为server.ts的文件,输入以下代码:

// 导入必要的模块
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import express from 'express';
import { z } from 'zod';

// 创建MCP服务器实例,就像开了一家提供特定服务的公司
const server = new McpServer({
    name: 'demo-server',  // 服务器名称,相当于公司名称
    version: '1.0.0'      // 版本号,用于管理API变更
});

// 注册一个加法工具,就像公司添加了一项新服务
server.registerTool(
    'add',  // 工具名称,用于在API中标识该工具
    {
        title: '加法工具',          // 工具的友好名称
        description: '将两个数字相加', // 工具功能描述
        inputSchema: { a: z.number(), b: z.number() }, // 输入数据结构验证
        outputSchema: { result: z.number() }           // 输出数据结构验证
    },
    // 工具实现函数,处理实际业务逻辑
    async ({ a, b }) => {
        const output = { result: a + b };
        return {
            content: [{ type: 'text', text: JSON.stringify(output) }],
            structuredContent: output
        };
    }
);

// 设置Express应用,就像搭建公司的接待前台
const app = express();
app.use(express.json());

// 定义MCP接口端点,相当于公司的服务窗口
app.post('/mcp', async (req, res) => {
    // 创建HTTP传输实例,处理网络通信
    const transport = new StreamableHTTPServerTransport({
        sessionIdGenerator: undefined,  // 不生成会话ID,每次请求都是独立的
        enableJsonResponse: true        // 支持JSON格式响应
    });

    // 当客户端断开连接时关闭传输
    res.on('close', () => {
        transport.close();
    });

    // 连接服务器和传输层
    await server.connect(transport);
    // 处理请求
    await transport.handleRequest(req, res, req.body);
});

// 启动服务器,开始对外提供服务
const port = parseInt(process.env.PORT || '3000');
app.listen(port, () => {
    console.log(`MCP服务器运行在 http://localhost:${port}/mcp`);
});

启动服务器:

npx -y tsx server.ts

✅ 恭喜!你已经成功搭建了一个基础的MCP服务器!

📌 要点回顾

  • MCP服务器是通过McpServer类创建的
  • 工具是服务器的核心功能,通过registerTool方法注册
  • Streamable HTTP是推荐的传输方式,适用于大多数场景
  • 每个工具需要定义输入输出验证规则,确保数据安全

MCP核心概念深度解析

什么是McpServer?

McpServer是MCP协议的核心接口,负责管理连接、确保协议合规性和路由消息。把它想象成一家公司的总经理,负责协调各个部门(工具、资源、提示)的工作,确保客户(LLM)的需求得到满足。

问题:如何确保LLM与工具之间的通信标准化? 方案:McpServer定义了统一的接口规范,所有工具和资源都遵循相同的交互模式。 验证:通过注册工具和资源,McpServer能够自动处理请求验证和路由,确保通信符合MCP协议规范。

核心代码位于packages/server/src/server/mcp.ts

工具(Tools)如何让AI拥有超能力?

工具允许LLM通过服务器执行操作,如计算、获取数据或产生副作用。把工具想象成公司的各个部门,每个部门负责处理特定类型的任务,如计算部门、数据查询部门等。

// BMI计算器工具示例
server.registerTool(
    'calculate-bmi',  // 工具唯一标识符
    {
        title: 'BMI计算器',  // 工具的友好名称
        description: '计算身体质量指数',  // 详细描述工具功能
        inputSchema: {
            weightKg: z.number().description('体重(公斤)'),  // 体重参数
            heightM: z.number().description('身高(米)')      // 身高参数
        },
        outputSchema: { bmi: z.number().description('身体质量指数') }  // 输出BMI值
    },
    // 工具实现函数,接收输入参数并返回结果
    async ({ weightKg, heightM }) => {
        const bmi = weightKg / (heightM * heightM);  // BMI计算公式
        const output = { bmi: parseFloat(bmi.toFixed(2)) };  // 保留两位小数
        
        return {
            content: [{ type: 'text', text: `BMI计算结果: ${output.bmi}` }],
            structuredContent: output
        };
    }
);

💡 思考问题:为什么工具需要同时定义输入输出模式(schema)?这对LLM使用工具有什么帮助?

📌 要点回顾

  • 工具通过registerTool方法注册,需要唯一名称
  • 每个工具必须定义清晰的描述,帮助LLM理解其功能
  • 输入输出模式使用zod验证,确保数据格式正确
  • 工具实现函数处理实际业务逻辑并返回结果

资源(Resources)如何为AI提供上下文数据?

资源向LLMs公开数据,但不像工具那样执行大量计算或产生副作用。可以把资源想象成公司的资料库或数据库,LLM可以查询这些资料来获取完成任务所需的信息。

// 静态资源示例 - 应用配置
server.registerResource(
    'config',  // 资源名称
    'config://app',  // 资源URI
    {
        title: '应用配置',  // 资源标题
        description: '应用的基本配置数据',  // 资源描述
        mimeType: 'text/plain'  // 数据格式
    },
    // 资源获取函数
    async uri => ({
        contents: [
            {
                uri: uri.href,
                text: '{"theme":"dark","notifications":true,"language":"zh-CN"}'
            }
        ]
    })
);

// 动态资源示例 - 用户资料
server.registerResource(
    'user-profile',  // 资源名称
    new ResourceTemplate('users://{userId}/profile', { list: undefined }),  // 带参数的URI模板
    {
        title: '用户资料',
        description: '获取指定用户的个人资料信息'
    },
    // 资源获取函数,接收URI参数
    async (uri, { userId }) => {
        // 在实际应用中,这里会从数据库获取用户数据
        const mockUserData = {
            id: userId,
            name: '张三',
            email: 'zhangsan@example.com',
            joinDate: '2023-01-15'
        };
        
        return {
            contents: [
                {
                    uri: uri.href,
                    text: JSON.stringify(mockUserData, null, 2)
                }
            ]
        };
    }
);

📌 要点回顾

  • 资源通过registerResource方法注册
  • 资源可以是静态的(固定内容)或动态的(根据参数生成)
  • URI模板允许创建参数化的资源访问路径
  • 资源主要提供数据,不执行复杂计算或副作用操作

提示(Prompts)如何引导AI交互?

提示是可重用的模板,帮助人类提示模型与服务器交互。可以把提示想象成公司的服务指南,告诉客户如何最有效地使用公司提供的服务。

import { completable } from '@modelcontextprotocol/sdk/server/completable.js';

// 代码审查提示示例
server.registerPrompt(
    'review-code',  // 提示名称
    {
        title: '代码审查',  // 提示标题
        description: '审查代码以获取最佳实践和潜在问题',  // 提示描述
        argsSchema: { code: z.string().description('需要审查的代码') }  // 提示参数
    },
    // 提示生成函数
    ({ code }) => ({
        messages: [
            {
                role: 'user',
                content: {
                    type: 'text',
                    text: `请作为资深代码审查员,审查以下代码并提供改进建议:
                    
${code}

审查要点:
1. 代码可读性和可维护性
2. 潜在的性能问题
3. 错误处理是否完善
4. 是否遵循最佳实践`
                }
            }
        ]
    })
);

📌 要点回顾

  • 提示通过registerPrompt方法注册
  • 提示为LLM提供预定义的交互模板
  • 提示可以接收参数,动态生成内容
  • 提示帮助用户更有效地与LLM和MCP服务器交互

实战操作:从基础到专家

基础级:实现多传输方式的MCP服务器

除了Streamable HTTP,MCP还支持Stdio传输方式,适用于本地进程间通信。下面实现一个同时支持两种传输方式的服务器:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import express from 'express';
import { z } from 'zod';

// 创建MCP服务器
const server = new McpServer({
    name: 'multi-transport-server',
    version: '1.0.0'
});

// 添加基础工具
server.registerTool(
    'greet',
    {
        title: '问候工具',
        description: '向用户发送问候消息',
        inputSchema: { name: z.string() },
        outputSchema: { message: z.string() }
    },
    async ({ name }) => ({
        content: [{ type: 'text', text: `你好,${name}!` }],
        structuredContent: { message: `你好,${name}!` }
    })
);

// 启动Stdio传输
async function startStdioTransport() {
    const transport = new StdioServerTransport();
    await server.connect(transport);
    console.log('Stdio传输已启动');
}

// 启动HTTP传输
async function startHttpTransport() {
    const app = express();
    app.use(express.json());
    
    app.post('/mcp', async (req, res) => {
        const transport = new StreamableHTTPServerTransport({
            sessionIdGenerator: undefined,
            enableJsonResponse: true
        });
        
        res.on('close', () => transport.close());
        await server.connect(transport);
        await transport.handleRequest(req, res, req.body);
    });
    
    const port = 3000;
    app.listen(port, () => {
        console.log(`HTTP传输已启动,地址: http://localhost:${port}/mcp`);
    });
}

// 启动两种传输方式
startStdioTransport();
startHttpTransport();

启动服务器后,你可以通过两种方式与其交互:

  1. HTTP方式:发送POST请求到http://localhost:3000/mcp
  2. Stdio方式:通过标准输入输出与进程交互

✅ 基础级挑战完成!你现在可以使用多种方式与MCP服务器通信了。

进阶级:构建完整的MCP客户端

下面创建一个完整的MCP客户端,实现与服务器的交互:

import { McpClient } from '@modelcontextprotocol/sdk/client/client.js';
import { StreamableHttpClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

async function main() {
    // 创建HTTP传输
    const transport = new StreamableHttpClientTransport({
        url: 'http://localhost:3000/mcp'  // 服务器地址
    });
    
    // 创建MCP客户端
    const client = new McpClient(transport);
    
    try {
        // 连接到服务器
        console.log('连接到MCP服务器...');
        await client.connect();
        console.log('成功连接到服务器');
        
        // 获取服务器能力
        console.log('\n获取服务器能力...');
        const capabilities = await client.getCapabilities();
        console.log('服务器能力:', JSON.stringify(capabilities, null, 2));
        
        // 调用工具
        console.log('\n调用greet工具...');
        const result = await client.callTool('greet', { name: 'MCP开发者' });
        console.log('工具调用结果:', result.structuredContent);
        
        // 获取资源
        console.log('\n获取config资源...');
        const resource = await client.getResource('config://app');
        console.log('资源内容:', resource.contents[0].text);
        
    } catch (error) {
        console.error('发生错误:', error);
    } finally {
        // 断开连接
        await client.disconnect();
        console.log('\n已断开与服务器的连接');
    }
}

main();

运行客户端:

npx tsx client.ts

✅ 进阶级挑战完成!你现在可以构建能够与MCP服务器完整交互的客户端了。

专家级:实现多节点部署架构

在生产环境中,你可能需要部署多个MCP服务器节点以提高可用性和处理能力。下面是一个多节点部署的实现方案:

// 无状态服务器配置 (server-stateless.ts)
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import express from 'express';
import { z } from 'zod';
import { RedisEventStore } from './stores/redis-event-store.js';  // 假设的Redis事件存储

// 创建Redis事件存储,用于在多节点间共享会话数据
const eventStore = new RedisEventStore({
    url: process.env.REDIS_URL || 'redis://localhost:6379'
});

// 创建MCP服务器
const server = new McpServer({
    name: 'stateless-mcp-server',
    version: '1.0.0'
});

// 注册工具... (与前面示例类似)

// 设置Express应用
const app = express();
app.use(express.json());

// MCP端点
app.post('/mcp', async (req, res) => {
    // 创建带会话管理的传输
    const transport = new StreamableHTTPServerTransport({
        sessionIdGenerator: () => {
            // 从请求头获取会话ID,或生成新的
            return req.headers['x-session-id'] as string || crypto.randomUUID();
        },
        eventStore: eventStore,  // 使用Redis事件存储
        enableJsonResponse: true
    });

    res.setHeader('X-Session-ID', transport.sessionId);
    res.on('close', () => transport.close());
    
    await server.connect(transport);
    await transport.handleRequest(req, res, req.body);
});

// 启动服务器
const port = parseInt(process.env.PORT || '3000');
app.listen(port, () => {
    console.log(`无状态MCP服务器运行在 http://localhost:${port}/mcp`);
});

多节点部署架构示意图:

┌─────────────────────────────────────────────┐
│                  Client                     │
└─────────────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────┐
│                Load Balancer                │
└─────────────────────────────────────────────┘
           │                       │
           ▼                       ▼
┌─────────────────┐     ┌─────────────────────┐
│  MCP Server #1  │◄───►│    MCP Server #2    │
│ (无状态节点)    │     │   (无状态节点)      │
└─────────────────┘     └─────────────────────┘
           ▲│                     ▲│
           │▼                     │▼
┌─────────────────────────────────────────────┐
│               Redis 集群                    │
│          (共享事件存储/会话数据)            │
└─────────────────────────────────────────────┘

✅ 专家级挑战完成!你现在掌握了MCP服务器的高级部署策略。

常见问题诊断指南

连接问题:无法连接到MCP服务器

症状:客户端提示"连接超时"或"无法建立连接"

可能原因及解决方案

  1. 服务器未运行

    • 检查服务器进程是否正在运行
    • 重新启动服务器:npx tsx server.ts
  2. 端口被占用

    • 更换端口:PORT=3001 npx tsx server.ts
    • 查找并终止占用端口的进程:lsof -i :3000
  3. 网络问题

    • 检查防火墙设置,确保端口开放
    • 验证服务器地址和端口是否正确

工具调用问题:工具返回错误或无响应

症状:调用工具时返回错误,或长时间没有响应

可能原因及解决方案

  1. 工具未正确注册

    • 检查工具名称是否拼写正确
    • 确保工具在服务器启动前完成注册
  2. 输入参数验证失败

    • 检查输入数据是否符合工具的inputSchema
    • 查看服务器日志,获取详细的验证错误信息
  3. 工具实现有bug

    • 添加日志到工具实现函数,调试问题
    • 确保工具函数正确返回格式正确的响应

性能问题:服务器响应缓慢

症状:服务器响应时间长,处理请求缓慢

可能原因及解决方案

  1. 工具实现效率低

    • 优化工具函数中的算法
    • 对耗时操作实现异步处理
  2. 资源获取耗时

    • 实现资源缓存机制
    • 考虑使用分布式缓存提高性能
  3. 服务器负载过高

    • 实施负载均衡,增加服务器节点
    • 优化服务器代码,提高并发处理能力

生态扩展资源

官方文档和示例

开发工具

高级功能

进阶挑战任务

  1. 任务一:实现一个文件处理工具,支持上传、转换和下载文件

    • 提示:使用zod验证文件元数据,实现分块上传逻辑
  2. 任务二:构建一个实时通知系统,使用Websocket传输

  3. 任务三:实现完整的OAuth2认证流程,保护MCP服务器API

通过这些资源和挑战,你可以不断扩展自己的MCP技能,构建更复杂和强大的LLM应用。无论你是刚开始接触MCP,还是已经有一定经验,这个SDK都能帮助你实现标准化的LLM上下文管理,为你的AI应用提供强大支持。

📌 最终要点回顾

  • MCP TypeScript SDK提供了标准化的LLM上下文管理方案
  • 核心组件包括服务器、客户端、工具、资源和提示
  • 支持多种传输方式,适应不同部署场景
  • 从简单应用到分布式系统,MCP都能满足需求
  • 丰富的生态资源和示例代码加速开发过程

现在,你已经准备好使用MCP TypeScript SDK构建自己的LLM应用了。开始你的MCP开发之旅吧!

登录后查看全文
热门项目推荐
相关项目推荐