首页
/ MCP TypeScript SDK从零上手实战指南

MCP TypeScript SDK从零上手实战指南

2026-05-03 09:09:50作者:虞亚竹Luna

你是否在寻找一种标准化方式为大语言模型提供上下文?还在为构建兼容MCP的服务器和客户端而烦恼?Model Context Protocol TypeScript SDK(简称MCP TypeScript SDK)正是为解决这些问题而生。本文将通过"问题-解决方案"的实战模式,带你快速掌握这个官方TypeScript实现的核心功能,从环境搭建到高级部署,构建完整的MCP应用。

🌱 入门:MCP SDK基础与环境准备

为什么需要MCP SDK?

当你尝试为LLM构建上下文服务时,是否遇到过这些问题:不同模型接口不兼容、上下文管理混乱、工具调用方式各异?MCP TypeScript SDK通过标准化协议解决了这些痛点,将上下文提供与LLM交互解耦,让你专注于业务逻辑而非通信细节。

环境搭建步骤

# 克隆项目仓库
git clone https://gitcode.com/GitHub_Trending/ty/typescript-sdk
cd typescript-sdk

# 安装依赖
npm install

# 验证安装
npm run test

💡 核心价值:MCP SDK提供统一的通信协议和接口,使你的AI应用具有更好的可维护性和扩展性,同时兼容各种LLM模型和传输方式。

🔧 实战:核心组件与基础应用

McpServer:解决服务端统一管理问题

问题:如何高效管理工具、资源和会话,确保协议合规性?

解决方案:使用McpServer作为服务端核心,统一处理连接、消息路由和协议验证。

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

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

// 注册工具示例
server.registerTool(
  'calculate-bmi',
  {
    title: 'BMI计算器',
    description: '计算身体质量指数',
    inputSchema: {
      weightKg: z.number(),
      heightM: z.number()
    },
    outputSchema: { bmi: z.number() }
  },
  async ({ weightKg, heightM }) => {
    const bmi = weightKg / (heightM * heightM);
    return {
      content: [{ type: 'text', text: `BMI值: ${bmi.toFixed(2)}` }],
      structuredContent: { bmi }
    };
  }
);

核心实现:packages/server/src/server/mcp.ts

客户端交互:解决服务调用复杂性

问题:如何简化与MCP服务器的通信过程,处理不同传输方式?

解决方案:使用McpClient统一接口,屏蔽底层传输细节。

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

async function callBmiTool() {
  const transport = new StreamableHttpClientTransport({
    url: 'http://localhost:3000/mcp'
  });
  
  const client = new McpClient(transport);
  await client.connect();
  
  try {
    const result = await client.callTool('calculate-bmi', {
      weightKg: 70,
      heightM: 1.75
    });
    console.log('BMI计算结果:', result.structuredContent.bmi);
  } finally {
    await client.disconnect();
  }
}

callBmiTool().catch(console.error);

🔄 传输方式选型:选择最适合你的通信方案

三种传输方式对比

传输方式 适用场景 优势 局限 实现文件
Streamable HTTP 远程服务、Web应用 双向通信、会话支持 需要HTTP服务器 packages/server/src/server/streamableHttp.ts
Stdio 本地进程通信 简单轻量、低延迟 仅限本地应用 packages/server/src/server/stdio.ts
WebSocket 实时交互场景 全双工、低延迟 需WebSocket支持 packages/client/src/client/websocket.ts

实战配置:无状态Streamable HTTP服务器

import express from 'express';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';

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);
});

app.listen(3000, () => {
  console.log('MCP服务器运行在 http://localhost:3000/mcp');
});

🚀 进阶:架构设计与高级部署

资源与提示:丰富LLM上下文能力

问题:如何高效为LLM提供结构化上下文数据和交互模板?

解决方案:使用资源(Resources)提供上下文数据,使用提示(Prompts)提供交互模板。

// 注册动态资源
server.registerResource(
  'user-profile',
  new ResourceTemplate('users://{userId}/profile'),
  {
    title: '用户资料',
    description: '获取用户个人资料信息'
  },
  async (uri, { userId }) => {
    // 从数据库获取用户信息
    const user = await db.getUser(userId);
    return {
      contents: [{
        uri: uri.href,
        text: JSON.stringify(user)
      }]
    };
  }
);

// 注册代码审查提示
server.registerPrompt(
  'review-code',
  {
    title: '代码审查',
    description: '审查代码质量和潜在问题',
    argsSchema: { code: z.string() }
  },
  ({ code }) => ({
    messages: [{
      role: 'user',
      content: { type: 'text', text: `请审查以下代码:\n\n${code}` }
    }]
  })
);

多节点部署策略

问题:如何在生产环境中扩展MCP服务,保证高可用和负载均衡?

解决方案:根据业务需求选择合适的部署模式:

  1. 无状态模式:适合简单API代理,每个请求独立处理
  2. 持久存储模式:使用数据库存储会话状态,支持服务重启
  3. 分布式消息路由:结合消息队列实现会话路由,支持水平扩展
// 持久存储模式配置示例
const transport = new StreamableHTTPServerTransport({
  sessionIdGenerator: () => randomUUID(),
  eventStore: new DatabaseEventStore({ 
    connectionString: process.env.DB_CONNECTION 
  })
});

🔍 常见问题诊断

问题1:工具调用参数验证失败

错误表现:客户端收到"invalid_input"错误,工具调用失败

解决方案:检查工具输入模式定义,确保Zod模式正确,客户端参数类型匹配

// 错误示例:缺少必要参数
server.registerTool('add', {
  inputSchema: { a: z.number() } // 缺少b参数
}, async ({ a, b }) => ({ /* ... */ }));

// 正确示例:完整定义所有参数
server.registerTool('add', {
  inputSchema: { a: z.number(), b: z.number() }
}, async ({ a, b }) => ({ /* ... */ }));

问题2:会话连接中断

错误表现:客户端频繁断开连接,无法维持长会话

解决方案:检查传输配置,实现心跳机制,确保正确处理连接关闭事件

// 添加连接关闭处理
transport.on('close', () => {
  console.log('连接已关闭');
  // 清理资源和状态
});

// 实现心跳机制
setInterval(() => {
  if (transport.isConnected()) {
    transport.sendHeartbeat();
  }
}, 30000);

问题3:资源访问权限问题

错误表现:客户端收到"access_denied"错误,无法访问资源

解决方案:实现认证中间件,验证用户权限

server.use(async (context, next) => {
  const token = context.request.headers.authorization?.split(' ')[1];
  if (!isValidToken(token)) {
    return { status: 'error', code: 'access_denied', message: '未授权访问' };
  }
  return next();
});

开发资源卡

通过本文的实战指南,你已经掌握了MCP TypeScript SDK的核心功能和最佳实践。从基础的服务器搭建到高级的分布式部署,MCP SDK提供了一套完整的解决方案,帮助你构建强大而灵活的AI上下文服务。现在就开始动手实践,体验标准化AI上下文管理的魅力吧!

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