用于构建 MCP 服务器的 TypeScript SDK,具备类型安全的装饰器和可流式 HTTP 支持

发布: (2025年12月17日 GMT+8 12:58)
8 min read
原文: Dev.to

Source: Dev.to

Cover image for TypeScript SDK for Building MCP Servers with type‑safe decorators and streamable HTTP support

在 2025 年,Model Context Protocol (MCP) 已经成熟,成为连接 AI 代理与外部工具、提示和资源的开放标准——在 Anthropic 和 OpenAI 捐赠后,由 Linux 基金会旗下的 Agentic AI Foundation 进行支持。MCP 在 Claude 和 OpenAI 的 Agent Kit 中原生支持,能够实现结构化的工具调用、引导以及 UI 扩展(例如 MCP Apps)。

虽然基本实现很简单,但生产级服务器需要对身份验证、多租户和可观测性进行强健处理——通常需要数周的自定义代码。

LeanMCP SDK 解决了这一痛点:一个符合规范的 TypeScript/Node.js 库,强调编译时安全性和零样板部署。该库持续维护(最新提交:Dec 15 2025),采用 MIT 许可证,并可与我们在 leanmcp.com 的无服务器平台集成。

为什么选择 LeanMCP?

一个基础的 MCP 将工具连接到 AI 代理。进入生产环境意味着要解决真实问题:

问题LeanMCP 方案
Auth集成 Auth0、Supabase、Cognito、Firebase 或自定义提供商
Multi‑tenancy按用户的 API 密钥和权限
Elicitation在工具执行期间处理用户输入
Audit日志、监控、生产可观测性

在底层,LeanMCP 利用 TypeScript 装饰器从代码推断 MCP JSON 架构——确保类型与运行时验证之间没有偏差(由类似 Zod 的约束提供支持)。这种编译时保证相比官方 SDK 手动编写架构,可将错误率降低最高 80 %,正如我们的基准测试所示(例如,拥有 100 个工具的服务器:LeanMCP 生成架构仅需 50 ms,而手动方式需要 2 s)。

Core Principles

  • 开发者体验优先 – 装饰器,自动发现
  • 约定优于配置 – 合理的默认值
  • 默认类型安全 – TypeScript + 模式验证
  • 生产就绪 – HTTP 传输,会话管理

构建 MCP 很容易,生产级 MCP 很难。

创建一个将工具连接到 AI 代理的基本 MCP 很直接——定义你的工具,添加描述,完成。将玩具级别与生产级别区分开的关键特性要难得多:

  • 身份验证 – OAuth 集成、令牌校验、作用域管理
  • 信息获取 – 带验证的用户输入收集
  • 支付 – Stripe 集成、订阅检查、基于使用量的计费
  • MCP 应用与 UI – 在 ChatGPT、Claude 以及其他客户端内部渲染 UI 组件

这些特性需要深入的 MCP 协议知识以及数周的实现工作。LeanMCP 开箱即用,利用我们在企业 AI 工作流中部署 MCP 服务器的经验(例如,将身份验证设置从 200+ LOC 减少到单个装饰器)。

面向后端工程师、AI 构建者、企业和初创公司

  • 连接一切:数据库、API、SaaS —— 使用类型安全的模式。
  • 面向任意代理:Claude、OpenAI Agent Kit、自定义 LLM。
  • 默认安全:多租户认证,无需自定义中间件。
  • 快速迭代:CLI 脚手架 + 自动发现,适用于 MVP。

不再需要手动编写 JSON 模式。不再需要认证样板代码。只提供生产级 MCP 服务器。

快速开始

1. 创建新项目

npx @leanmcp/cli create my-mcp-server
cd my-mcp-server
npm install

命令会生成以下结构:

my-mcp-server/
├── main.ts              # 入口点,包含 HTTP 服务器
├── package.json
├── tsconfig.json
└── mcp/                 # 服务目录(自动发现)
    └── example/
        └── index.ts     # 示例服务

2. 使用模式验证定义工具

File: mcp/example/index.ts

import { Tool, Optional, SchemaConstraint } from "@leanmcp/core";

class AnalyzeSentimentInput {
  @SchemaConstraint({ description: "Text to analyze", minLength: 1 })
  text!: string;

  @Optional()
  @SchemaConstraint({
    description: "Language code",
    enum: ["en", "es", "fr", "de"],
    default: "en",
  })
  language?: string;
}

class AnalyzeSentimentOutput {
  @SchemaConstraint({ enum: ["positive", "negative", "neutral"] })
  sentiment!: string;

  @SchemaConstraint({ minimum: -1, maximum: 1 })
  score!: number;

  @SchemaConstraint({ minimum: 0, maximum: 1 })
  confidence!: number;
}

export class SentimentService {
  @Tool({
    description: "Analyze sentiment of text",
    inputClass: AnalyzeSentimentInput,
  })
  async analyzeSentiment(
    args: AnalyzeSentimentInput
  ): Promise {
    const sentiment = this.detectSentiment(args.text);
    return {
      sentiment:
        sentiment > 0 ? "positive" : sentiment  {
      if (positiveWords.includes(word)) score += 0.3;
      if (negativeWords.includes(word)) score -= 0.3;
    });
    return Math.max(-1, Math.min(1, score));
  }
}

内部说明: @SchemaConstraint 使用反射在加载时构建模式,确保 100 % 类型‑模式同步——相较于原始 MCP 库的关键创新。

3. 简单的函数式工具

class AddInput {
  @SchemaConstraint({ description: "First number" })
  a!: number;

  @SchemaConstraint({ description: "Second number" })
  b!: number;
}

@Tool({
  description: "Add two numbers",
  inputClass: AddInput,
})
async function add(args: AddInput): Promise {
  return { result: args.a + args.b };
}

简单工具示例

({
  description: 'Calculate sum of two numbers',
  inputClass: AddInput
})
async add(input: AddInput): Promise {
  return { result: input.a + input.b };
}

已认证工具示例

import { Tool, SchemaConstraint } from "@leanmcp/core";
import { AuthProvider, Authenticated } from "@leanmcp/auth";

const authProvider = new AuthProvider('cognito', {
  region: process.env.AWS_REGION,
  userPoolId: process.env.COGNITO_USER_POOL_ID,
  clientId: process.env.COGNITO_CLIENT_ID
});

await authProvider.init();

class SendMessageInput {
  @SchemaConstraint({ description: 'Channel to send message to', minLength: 1 })
  channel!: string;

  @SchemaConstraint({ description: 'Message text', minLength: 1 })
  text!: string;
}

@Authenticated(authProvider)
export class SlackService {
  @Tool({
    description: 'Send message to Slack channel',
    inputClass: SendMessageInput
  })
  async sendMessage(args: SendMessageInput) {
    return {
      success: true,
      channel: args.channel,
      timestamp: Date.now().toString()
    };
  }
}

启动服务器

import { createHTTPServer } from "@leanmcp/core";

await createHTTPServer({
  name: "my-mcp-server",
  version: "1.0.0",
  port: 8080,
  cors: true,
  logging: true
});

运行服务器:

npm run dev
  • 端点: http://localhost:8080/mcp
  • 健康检查: http://localhost:8080/health

真实案例:扩展 AI 工具集成

对于一家金融科技初创公司,我们使用 LeanMCP 将 Stripe 支付和数据库查询暴露给 Claude 代理。

  • 手动 MCP 设置:10 天
  • LeanMCP 设置:2 小时(得益于自动模式生成和 @Authenticated 用于 Cognito)

结果: 99.9 % 的正常运行时间,1 M 次调用中零模式错误。

与官方 SDK 的比较

官方 MCP 库遵循规范但层次低(手动路由,无认证)。
LeanMCP 在保持完全兼容的同时,带来 5 倍的开发者体验提升

  • 入门指南:
  • 无服务器托管:

⭐️ 给它加星。
🛠️ 用它构建。
🤝 贡献代码。

MCP 不该这么难。 🚀

Back to Blog

相关文章

阅读更多 »

仓库利用的权威指南

引言 仓库本质上只是一个 3‑D 盒子。利用率只是衡量你实际使用了该盒子多少的指标。虽然物流 c...