# @alcyone-labs/modelcontextprotocol-sdk 中文文档

规范地址：https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/

版本：1\.16\.0
npm 元数据更新时间：2025-08-01T08:44:29.012Z
中文译文更新时间：2026-11-05T20:45:46.798Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40alcyone-labs/modelcontextprotocol-sdk
原文对照：https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/?lang=original
项目主页：https://modelcontextprotocol.io/
源码仓库：https://github.com/Alcyone-Labs/mcp-typescript-sdk

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：2.1 MB，413 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：未声明
- Node.js 要求：\>=18
- 运行依赖：11 个
- 首次发布：2025-08-01T08:44:28.413Z
- 最新版本发布：2025-08-01T08:44:28.726Z
- 近 30 天下载量：24617（2026-10-06 至 2026-11-04，npm 官方下载统计）
- 已发布版本数：1（近 12 个月 0 个）

## 中文简介

升级到 Zod V4 用于类型脚本的模型背景协议执行

## 安装

```sh
npm install @alcyone-labs/modelcontextprotocol-sdk
```

也可以使用：`pnpm add @alcyone-labs/modelcontextprotocol-sdk`、`yarn add @alcyone-labs/modelcontextprotocol-sdk`、`bun add @alcyone-labs/modelcontextprotocol-sdk`

## README

# MCP 类型脚本 SDK

**重要说明** 这是一个非官方的叉子升级到Zod V4. 您可以直接检查 github 仓库上的更改

## 原订本

![NPM Version](https://img.shields.io/npm/v/%40modelcontextprotocol%2Fsdk) ![MIT licensed](https://img.shields.io/npm/l/%40modelcontextprotocol%2Fsdk) 原订本

## 这个叉子

![NPM Version](https://img.shields.io/npm/v/%40alcyone-labs%2Fmodelcontextprotocol-sdk) ![MIT licensed](https://img.shields.io/npm/l/%40alcyone-labs%2Fmodelcontextprotocol-sdk)

## 目录

-   [概览](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-overview)
-   [安装](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-installation)
-   [快速启动](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-quick-start)
-   [什么是MCP吗?](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-what-is-mcp)
-   [核心概念](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-core-concepts)
    -   [服务器](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-server)
    -   [资源](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-resources)
    -   [工具](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-tools)
    -   [提示](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-prompts)
    -   [完成情况](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-completions)
    -   [取样](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-sampling)
-   [运行您的服务器](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-running-your-server)
    -   [静态](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-stdio)
    -   [可流取的 HTTP](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-streamable-http)
    -   [测试和调试](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-testing-and-debugging)
-   [实例](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-examples)
    -   [Echo 服务器](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-echo-server)
    -   [SQLite 浏览器](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-sqlite-explorer)
-   [高级使用](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-advanced-usage)
    -   [动态服务器](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-dynamic-servers)
    -   [低级服务器](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-low-level-server)
    -   [写入 MCP 客户端](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-writing-mcp-clients)
    -   [代理授权请求上游](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-proxy-authorization-requests-upstream)
    -   [后向兼容性](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-backwards-compatibility)
-   [文档](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-documentation)
-   [捐款](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-contributing)
-   [许可证](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-license)

## 概览

模式上下文协议允许应用程序以标准化的方式为LLMs提供上下文,将提供上下文的关切与实际LLM交互区分开来. 这种TypeScript SDK执行完整的MCP规格,使其易于:

-   构建可以连接到任何 MCP 服务器的 MCP 客户端
-   创建曝光资源、提示和工具的 MCP 服务器
-   使用 Stdio 和可流式 HTTP 等标准运输
-   处理所有 MCP 协议信息和生命周期事件

## 安装

```bash
npm install @modelcontextprotocol/sdk
```

> QQ MCP要求Node.js v18.x或更高值的工作罚款.

## 快速启动

让我们创建一个简单的MCP服务器,暴露一个计算工具和一些数据:

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

## 什么是MCP吗?

这个 [示范背景协议(MCP)](https://modelcontextprotocol.io/) 允许您以安全,标准化的方式建立服务器,使数据和功能暴露于LLM应用程序. 把它想成一个网络API,但专门为LLM交互设计. MCP服务器可以:

-   将数据通过 **资源** (想想这些像Get end points;它们用来将信息装入LLM的上下文)
-   通过 **工具** (类似 POST 的终点;用于执行代码或以其他方式产生副作用)
-   通过 **提示** (LLM互动可重复使用的模板)
-   还有更多!

## 核心概念

### 服务器

McpServer是您与MCP协议的核心接口. 它处理连接管理,协议遵守,以及消息路由:

```typescript
const server = new McpServer({
  name: "my-app",
  version: "1.0.0",
});
```

### 资源

资源是您如何向LLMs披露数据。 它们类似于在 REST API 中获取端点 — 它们提供数据,但不应该进行重大的计算或产生副作用:

```typescript
// Static resource
server.registerResource(
  "config",
  "config://app",
  {
    title: "Application Config",
    description: "Application configuration data",
    mimeType: "text/plain",
  },
  async (uri) => ({
    contents: [
      {
        uri: uri.href,
        text: "App configuration here",
      },
    ],
  }),
);

// Dynamic resource with parameters
server.registerResource(
  "user-profile",
  new ResourceTemplate("users://{userId}/profile", { list: undefined }),
  {
    title: "User Profile",
    description: "User profile information",
  },
  async (uri, { userId }) => ({
    contents: [
      {
        uri: uri.href,
        text: `Profile data for user ${userId}`,
      },
    ],
  }),
);

// Resource with context-aware completion
server.registerResource(
  "repository",
  new ResourceTemplate("github://repos/{owner}/{repo}", {
    list: undefined,
    complete: {
      // Provide intelligent completions based on previously resolved parameters
      repo: (value, context) => {
        if (context?.arguments?.["owner"] === "org1") {
          return ["project1", "project2", "project3"].filter((r) =>
            r.startsWith(value),
          );
        }
        return ["default-repo"].filter((r) => r.startsWith(value));
      },
    },
  }),
  {
    title: "GitHub Repository",
    description: "Repository information",
  },
  async (uri, { owner, repo }) => ({
    contents: [
      {
        uri: uri.href,
        text: `Repository: ${owner}/${repo}`,
      },
    ],
  }),
);
```

### 工具

工具让 LLMs 通过您的服务器采取行动 。 与资源不同,预计工具会进行计算并具有副作用:

```typescript
// Simple tool with parameters
server.registerTool(
  "calculate-bmi",
  {
    title: "BMI Calculator",
    description: "Calculate Body Mass Index",
    inputSchema: {
      weightKg: z.number(),
      heightM: z.number(),
    },
  },
  async ({ weightKg, heightM }) => ({
    content: [
      {
        type: "text",
        text: String(weightKg / (heightM * heightM)),
      },
    ],
  }),
);

// Async tool with external API call
server.registerTool(
  "fetch-weather",
  {
    title: "Weather Fetcher",
    description: "Get weather data for a city",
    inputSchema: { city: z.string() },
  },
  async ({ city }) => {
    const response = await fetch(`https://api.weather.com/${city}`);
    const data = await response.text();
    return {
      content: [{ type: "text", text: data }],
    };
  },
);

// Tool that returns ResourceLinks
server.registerTool(
  "list-files",
  {
    title: "List Files",
    description: "List project files",
    inputSchema: { pattern: z.string() },
  },
  async ({ pattern }) => ({
    content: [
      { type: "text", text: `Found files matching "${pattern}":` },
      // ResourceLinks let tools return references without file content
      {
        type: "resource_link",
        uri: "file:///project/README.md",
        name: "README.md",
        mimeType: "text/markdown",
        description: "A README file",
      },
      {
        type: "resource_link",
        uri: "file:///project/src/index.ts",
        name: "index.ts",
        mimeType: "text/typescript",
        description: "An index file",
      },
    ],
  }),
);
```

#### 资源链接

工具可以返回 `ResourceLink` 对象为不嵌入全部内容的参考资源。 这对于处理大文件或许多资源时的性能至关重要 - 然后客户端可以有选择地只读取他们使用所提供的URI所需要的资源.

### 提示

提示是可重复使用的模板, 帮助 LLMS 与您的服务器有效互动 :

```typescript
import { completable } from "@modelcontextprotocol/sdk/server/completable.js";

server.registerPrompt(
  "review-code",
  {
    title: "Code Review",
    description: "Review code for best practices and potential issues",
    argsSchema: { code: z.string() },
  },
  ({ code }) => ({
    messages: [
      {
        role: "user",
        content: {
          type: "text",
          text: `Please review this code:\n\n${code}`,
        },
      },
    ],
  }),
);

// Prompt with context-aware completion
server.registerPrompt(
  "team-greeting",
  {
    title: "Team Greeting",
    description: "Generate a greeting for team members",
    argsSchema: {
      department: completable(z.string(), (value) => {
        // Department suggestions
        return ["engineering", "sales", "marketing", "support"].filter((d) =>
          d.startsWith(value),
        );
      }),
      name: completable(z.string(), (value, context) => {
        // Name suggestions based on selected department
        const department = context?.arguments?.["department"];
        if (department === "engineering") {
          return ["Alice", "Bob", "Charlie"].filter((n) => n.startsWith(value));
        } else if (department === "sales") {
          return ["David", "Eve", "Frank"].filter((n) => n.startsWith(value));
        } else if (department === "marketing") {
          return ["Grace", "Henry", "Iris"].filter((n) => n.startsWith(value));
        }
        return ["Guest"].filter((n) => n.startsWith(value));
      }),
    },
  },
  ({ department, name }) => ({
    messages: [
      {
        role: "assistant",
        content: {
          type: "text",
          text: `Hello ${name}, welcome to the ${department} team!`,
        },
      },
    ],
  }),
);
```

### 完成情况

MCP支持完成参数以帮助用户填写即时参数和资源模板参数. 见上文实例 [资源完成情况](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-resources) 财务报告和审定财务报表 [及时完成](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/#readme-prompts)。 。 。 .

#### 客户端使用

```typescript
// Request completions for any argument
const result = await client.complete({
  ref: {
    type: "ref/prompt", // or "ref/resource"
    name: "example", // or uri: "template://..."
  },
  argument: {
    name: "argumentName",
    value: "partial", // What the user has typed so far
  },
  context: {
    // Optional: Include previously resolved arguments
    arguments: {
      previousArg: "value",
    },
  },
});
```

### 显示名称和元数据

所有资源、工具和提示都支持可选 `title` 字段,用于更好的 UI 演示。 这个 `title` 用作显示名称,而 `name` 仍然是唯一的标识符.

**说明:** 这个 `register*` 方法(单位:千美元)`registerTool`, (中文(简体) ), `registerPrompt`, (中文(简体) ), `registerResource`)是新守则的建议方法。 较旧的方法`tool`, (中文(简体) ), `prompt`, (中文(简体) ), `resource`) 仍然可供反向兼容.

#### 工具标题优先

具体地说,对于工具,有两种方式来指定标题:

-   `title` 字段在工具配置中
-   `annotations.title` 字段( 当使用旧字段时) `tool()` 带有说明的方法)

优先顺序为: `title` → `annotations.title` → `name`

```typescript
// Using registerTool (recommended)
server.registerTool(
  "my_tool",
  {
    title: "My Tool", // This title takes precedence
    annotations: {
      title: "Annotation Title", // This is ignored if title is set
    },
  },
  handler,
);

// Using tool with annotations (older API)
server.tool(
  "my_tool",
  "description",
  {
    title: "Annotation Title", // This is used as title
  },
  handler,
);
```

在构建客户端时, 使用所提供的工具获取适当的显示名 :

```typescript
import { getDisplayName } from "@modelcontextprotocol/sdk/shared/metadataUtils.js";

// Automatically handles the precedence: title → annotations.title → name
const displayName = getDisplayName(tool);
```

### 取样

MCP服务器可以请求支持采样的连接客户端完成LLM.

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

const mcpServer = new McpServer({
  name: "tools-with-sample-server",
  version: "1.0.0",
});

// Tool that uses LLM sampling to summarize any text
mcpServer.registerTool(
  "summarize",
  {
    description: "Summarize any text using an LLM",
    inputSchema: {
      text: z.string().describe("Text to summarize"),
    },
  },
  async ({ text }) => {
    // Call the LLM through MCP sampling
    const response = await mcpServer.server.createMessage({
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `Please summarize the following text concisely:\n\n${text}`,
          },
        },
      ],
      maxTokens: 500,
    });

    return {
      content: [
        {
          type: "text",
          text:
            response.content.type === "text"
              ? response.content.text
              : "Unable to generate summary",
        },
      ],
    };
  },
);

async function main() {
  const transport = new StdioServerTransport();
  await mcpServer.connect(transport);
  console.log("MCP server is running...");
}

main().catch((error) => {
  console.error("Server error:", error);
  process.exit(1);
});
```

## 运行您的服务器

TypeScript中的MCP服务器需要连接到一个传输上才能与客户端通信. 您如何启动服务器取决于运输的选择 :

### 静态

对于命令行工具和直接集成:

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new McpServer({
  name: "example-server",
  version: "1.0.0",
});

// ... set up server resources, tools, and prompts ...

const transport = new StdioServerTransport();
await server.connect(transport);
```

### 可流取的 HTTP

对于远程服务器,设置可流的HTTP传输,既处理客户端请求,又处理服务器对客户端通知.

#### 有会话管理

在某些情况下,服务器需要状态. 这是通过 [会话管理](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#session-management)。 。 。 .

```typescript
import express from "express";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";

const app = express();
app.use(express.json());

// Map to store transports by session ID
const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {};

// Handle POST requests for client-to-server communication
app.post("/mcp", async (req, res) => {
  // Check for existing session ID
  const sessionId = req.headers["mcp-session-id"] as string | undefined;
  let transport: StreamableHTTPServerTransport;

  if (sessionId && transports[sessionId]) {
    // Reuse existing transport
    transport = transports[sessionId];
  } else if (!sessionId && isInitializeRequest(req.body)) {
    // New initialization request
    transport = new StreamableHTTPServerTransport({
      sessionIdGenerator: () => randomUUID(),
      onsessioninitialized: (sessionId) => {
        // Store the transport by session ID
        transports[sessionId] = transport;
      },
      // DNS rebinding protection is disabled by default for backwards compatibility. If you are running this server
      // locally, make sure to set:
      // enableDnsRebindingProtection: true,
      // allowedHosts: ['127.0.0.1'],
    });

    // Clean up transport when closed
    transport.onclose = () => {
      if (transport.sessionId) {
        delete transports[transport.sessionId];
      }
    };
    const server = new McpServer({
      name: "example-server",
      version: "1.0.0",
    });

    // ... set up server resources, tools, and prompts ...

    // Connect to the MCP server
    await server.connect(transport);
  } else {
    // Invalid request
    res.status(400).json({
      jsonrpc: "2.0",
      error: {
        code: -32000,
        message: "Bad Request: No valid session ID provided",
      },
      id: null,
    });
    return;
  }

  // Handle the request
  await transport.handleRequest(req, res, req.body);
});

// Reusable handler for GET and DELETE requests
const handleSessionRequest = async (
  req: express.Request,
  res: express.Response,
) => {
  const sessionId = req.headers["mcp-session-id"] as string | undefined;
  if (!sessionId || !transports[sessionId]) {
    res.status(400).send("Invalid or missing session ID");
    return;
  }

  const transport = transports[sessionId];
  await transport.handleRequest(req, res);
};

// Handle GET requests for server-to-client notifications via SSE
app.get("/mcp", handleSessionRequest);

// Handle DELETE requests for session termination
app.delete("/mcp", handleSessionRequest);

app.listen(3000);
```

> \[TIP\] 在远程环境中使用此选项时, 确保允许页眉参数 `mcp-session-id` 在中央统计局。 否则,可能导致: `Bad Request: No valid session ID provided` 错误。 下节为例.

#### 基于浏览器的客户端的 CORS 配置

如果您希望您的服务器能够被基于浏览器的MCP客户端访问,则需要配置 CORS 头. 这个 `Mcp-Session-Id` 浏览器客户端必须被曝光才能访问:

```typescript
import cors from "cors";

// Add CORS middleware before your MCP routes
app.use(
  cors({
    origin: "*", // Configure appropriately for production, for example:
    // origin: ['https://your-remote-domain.com', 'https://your-other-remote-domain.com'],
    exposedHeaders: ["Mcp-Session-Id"],
    allowedHeaders: ["Content-Type", "mcp-session-id"],
  }),
);
```

这种配置是必要的,因为:

-   MCP可流式HTTP运输使用 `Mcp-Session-Id` 会话管理头
-   浏览器限制访问响应头, 除非通过 CORS 明确曝光
-   如果没有这种配置,基于浏览器的客户端将无法从初始化回复读取会话ID

#### 无会话管理( 无状态)

简单使用不需要会话管理的案例:

```typescript
const app = express();
app.use(express.json());

app.post("/mcp", async (req: Request, res: Response) => {
  // In stateless mode, create a new instance of transport and server for each request
  // to ensure complete isolation. A single instance would cause request ID collisions
  // when multiple clients connect concurrently.

  try {
    const server = getServer();
    const transport: StreamableHTTPServerTransport =
      new StreamableHTTPServerTransport({
        sessionIdGenerator: undefined,
      });
    res.on("close", () => {
      console.log("Request closed");
      transport.close();
      server.close();
    });
    await server.connect(transport);
    await transport.handleRequest(req, res, req.body);
  } catch (error) {
    console.error("Error handling MCP request:", error);
    if (!res.headersSent) {
      res.status(500).json({
        jsonrpc: "2.0",
        error: {
          code: -32603,
          message: "Internal server error",
        },
        id: null,
      });
    }
  }
});

// SSE notifications not supported in stateless mode
app.get("/mcp", async (req: Request, res: Response) => {
  console.log("Received GET MCP request");
  res.writeHead(405).end(
    JSON.stringify({
      jsonrpc: "2.0",
      error: {
        code: -32000,
        message: "Method not allowed.",
      },
      id: null,
    }),
  );
});

// Session termination not needed in stateless mode
app.delete("/mcp", async (req: Request, res: Response) => {
  console.log("Received DELETE MCP request");
  res.writeHead(405).end(
    JSON.stringify({
      jsonrpc: "2.0",
      error: {
        code: -32000,
        message: "Method not allowed.",
      },
      id: null,
    }),
  );
});

// Start the server
const PORT = 3000;
setupServer()
  .then(() => {
    app.listen(PORT, (error) => {
      if (error) {
        console.error("Failed to start server:", error);
        process.exit(1);
      }
      console.log(
        `MCP Stateless Streamable HTTP Server listening on port ${PORT}`,
      );
    });
  })
  .catch((error) => {
    console.error("Failed to set up the server:", error);
    process.exit(1);
  });
```

这种无国籍做法有助于:

-   简单的 API 包装
-   每项请求都是独立的可重复的情景
-   没有共享会话状态的横向部署

#### DNS 重新绑定的保护

流动式HTTP运输包括DNS重新绑定保护以防止安全漏洞. 默认情况下,这种保护是 **已禁用** 为后向相容性.

**重要**: 如果您正在本地运行此服务器, 请启用 DNS 重新绑定保护 :

```typescript
const transport = new StreamableHTTPServerTransport({
  sessionIdGenerator: () => randomUUID(),
  enableDnsRebindingProtection: true,

  allowedHosts: ['127.0.0.1', ...],
  allowedOrigins: ['https://yourdomain.com', 'https://www.yourdomain.com']
});
```

### 测试和调试

为了测试您的服务器, 您可以使用 [MCP 检查员](https://github.com/modelcontextprotocol/inspector)。关于更多信息,请参看其研究.

## 实例

### Echo 服务器

一个简单的服务器, 演示资源、 工具和提示 :

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

const server = new McpServer({
  name: "echo-server",
  version: "1.0.0",
});

server.registerResource(
  "echo",
  new ResourceTemplate("echo://{message}", { list: undefined }),
  {
    title: "Echo Resource",
    description: "Echoes back messages as resources",
  },
  async (uri, { message }) => ({
    contents: [
      {
        uri: uri.href,
        text: `Resource echo: ${message}`,
      },
    ],
  }),
);

server.registerTool(
  "echo",
  {
    title: "Echo Tool",
    description: "Echoes back the provided message",
    inputSchema: { message: z.string() },
  },
  async ({ message }) => ({
    content: [{ type: "text", text: `Tool echo: ${message}` }],
  }),
);

server.registerPrompt(
  "echo",
  {
    title: "Echo Prompt",
    description: "Creates a prompt to process a message",
    argsSchema: { message: z.string() },
  },
  ({ message }) => ({
    messages: [
      {
        role: "user",
        content: {
          type: "text",
          text: `Please process this message: ${message}`,
        },
      },
    ],
  }),
);
```

### SQLite 浏览器

一个显示数据库整合的更复杂的例子:

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import sqlite3 from "sqlite3";
import { promisify } from "util";
import { z } from "zod";

const server = new McpServer({
  name: "sqlite-explorer",
  version: "1.0.0",
});

// Helper to create DB connection
const getDb = () => {
  const db = new sqlite3.Database("database.db");
  return {
    all: promisify<string, any[]>(db.all.bind(db)),
    close: promisify(db.close.bind(db)),
  };
};

server.registerResource(
  "schema",
  "schema://main",
  {
    title: "Database Schema",
    description: "SQLite database schema",
    mimeType: "text/plain",
  },
  async (uri) => {
    const db = getDb();
    try {
      const tables = await db.all(
        "SELECT sql FROM sqlite_master WHERE type='table'",
      );
      return {
        contents: [
          {
            uri: uri.href,
            text: tables.map((t: { sql: string }) => t.sql).join("\n"),
          },
        ],
      };
    } finally {
      await db.close();
    }
  },
);

server.registerTool(
  "query",
  {
    title: "SQL Query",
    description: "Execute SQL queries on the database",
    inputSchema: { sql: z.string() },
  },
  async ({ sql }) => {
    const db = getDb();
    try {
      const results = await db.all(sql);
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(results, null, 2),
          },
        ],
      };
    } catch (err: unknown) {
      const error = err as Error;
      return {
        content: [
          {
            type: "text",
            text: `Error: ${error.message}`,
          },
        ],
        isError: true,
      };
    } finally {
      await db.close();
    }
  },
);
```

## 高级使用

### 动态服务器

如果您想要提供一组初始工具/ 即时/ 资源, 但稍后根据用户动作或外部状态变化添加更多工具/ 即时/ 资源, 您可以添加/ 更新/ 重新移动 _之后_ 服务器已连接。 这将自动释放相应的 `listChanged` 通知:

```ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

const server = new McpServer({
  name: "Dynamic Example",
  version: "1.0.0",
});

const listMessageTool = server.tool(
  "listMessages",
  { channel: z.string() },
  async ({ channel }) => ({
    content: [{ type: "text", text: await listMessages(channel) }],
  }),
);

const putMessageTool = server.tool(
  "putMessage",
  { channel: z.string(), message: z.string() },
  async ({ channel, message }) => ({
    content: [{ type: "text", text: await putMessage(channel, message) }],
  }),
);
// Until we upgrade auth, `putMessage` is disabled (won't show up in listTools)
putMessageTool.disable();

const upgradeAuthTool = server.tool(
  "upgradeAuth",
  { permission: z.enum(["write", "admin"]) },
  // Any mutations here will automatically emit `listChanged` notifications
  async ({ permission }) => {
    const { ok, err, previous } = await upgradeAuthAndStoreToken(permission);
    if (!ok) return { content: [{ type: "text", text: `Error: ${err}` }] };

    // If we previously had read-only access, 'putMessage' is now available
    if (previous === "read") {
      putMessageTool.enable();
    }

    if (permission === "write") {
      // If we've just upgraded to 'write' permissions, we can still call 'upgradeAuth'
      // but can only upgrade to 'admin'.
      upgradeAuthTool.update({
        paramSchema: { permission: z.enum(["admin"]) }, // change validation rules
      });
    } else {
      // If we're now an admin, we no longer have anywhere to upgrade to, so fully remove that tool
      upgradeAuthTool.remove();
    }
  },
);

// Connect as normal
const transport = new StdioServerTransport();
await server.connect(transport);
```

### 改进网络效率,并发布通知

当执行可触发通知的批量更新(例如,在一个回路中允许或使多个工具失效)时,SDK可以在短时间内发送大量信息. 为了提高性能并减少网络流量,您可以启用通知分解.

这个特性将多个,快速的调用相同的通知类型汇入单个消息. 例如,如果连续禁用5个工具,则只有一个 `notifications/tools/list_changed` 信件将改为5个.

> \[大 这个特性是为在其参数中不携带独特数据的"简单"通知而设计的. 为防止无声数据丢失 **自动绕过** 任何含有下列内容的通知: `params` 对象或一个 `relatedRequestId`这种通知将始终立即发出.

这是服务器初始化时配置的选入功能 .

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

const server = new McpServer(
  {
    name: "efficient-server",
    version: "1.0.0"
  },
  {
    // Enable notification debouncing for specific methods
    debouncedNotificationMethods: [
      'notifications/tools/list_changed',
      'notifications/resources/list_changed',
      'notifications/prompts/list_changed'
    ]
  }
);

// Now, any rapid changes to tools, resources, or prompts will result
// in a single, consolidated notification for each type.
server.registerTool("tool1", ...).disable();
server.registerTool("tool2", ...).disable();
server.registerTool("tool3", ...).disable();
// Only one 'notifications/tools/list_changed' is sent.
```

### 低级服务器

为了进行更多的控制,您可以直接使用低级服务器类:

```typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  ListPromptsRequestSchema,
  GetPromptRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
  {
    name: "example-server",
    version: "1.0.0",
  },
  {
    capabilities: {
      prompts: {},
    },
  },
);

server.setRequestHandler(ListPromptsRequestSchema, async () => {
  return {
    prompts: [
      {
        name: "example-prompt",
        description: "An example prompt template",
        arguments: [
          {
            name: "arg1",
            description: "Example argument",
            required: true,
          },
        ],
      },
    ],
  };
});

server.setRequestHandler(GetPromptRequestSchema, async (request) => {
  if (request.params.name !== "example-prompt") {
    throw new Error("Unknown prompt");
  }
  return {
    description: "Example prompt",
    messages: [
      {
        role: "user",
        content: {
          type: "text",
          text: "Example prompt text",
        },
      },
    ],
  };
});

const transport = new StdioServerTransport();
await server.connect(transport);
```

### Eliening 用户输入

MCP服务器可以通过引出功能要求用户提供更多信息. 用于服务器需要用户输入或确认的交互式工作流程:

```typescript
// Server-side: Restaurant booking tool that asks for alternatives
server.tool(
  "book-restaurant",
  {
    restaurant: z.string(),
    date: z.string(),
    partySize: z.number(),
  },
  async ({ restaurant, date, partySize }) => {
    // Check availability
    const available = await checkAvailability(restaurant, date, partySize);

    if (!available) {
      // Ask user if they want to try alternative dates
      const result = await server.server.elicitInput({
        message: `No tables available at ${restaurant} on ${date}. Would you like to check alternative dates?`,
        requestedSchema: {
          type: "object",
          properties: {
            checkAlternatives: {
              type: "boolean",
              title: "Check alternative dates",
              description: "Would you like me to check other dates?",
            },
            flexibleDates: {
              type: "string",
              title: "Date flexibility",
              description: "How flexible are your dates?",
              enum: ["next_day", "same_week", "next_week"],
              enumNames: ["Next day", "Same week", "Next week"],
            },
          },
          required: ["checkAlternatives"],
        },
      });

      if (result.action === "accept" && result.content?.checkAlternatives) {
        const alternatives = await findAlternatives(
          restaurant,
          date,
          partySize,
          result.content.flexibleDates as string,
        );
        return {
          content: [
            {
              type: "text",
              text: `Found these alternatives: ${alternatives.join(", ")}`,
            },
          ],
        };
      }

      return {
        content: [
          {
            type: "text",
            text: "No booking made. Original date not available.",
          },
        ],
      };
    }

    // Book the table
    await makeBooking(restaurant, date, partySize);
    return {
      content: [
        {
          type: "text",
          text: `Booked table for ${partySize} at ${restaurant} on ${date}`,
        },
      ],
    };
  },
);
```

客户端: 处理查询请求

```typescript
// This is a placeholder - implement based on your UI framework
async function getInputFromUser(
  message: string,
  schema: any,
): Promise<{
  action: "accept" | "decline" | "cancel";
  data?: Record<string, any>;
}> {
  // This should be implemented depending on the app
  throw new Error("getInputFromUser must be implemented for your platform");
}

client.setRequestHandler(ElicitRequestSchema, async (request) => {
  const userResponse = await getInputFromUser(
    request.params.message,
    request.params.requestedSchema,
  );

  return {
    action: userResponse.action,
    content: userResponse.action === "accept" ? userResponse.data : undefined,
  };
});
```

**说明**: Election需要客户端支持. 客户必须声明 `elicitation` 初始化期间的能力.

### 写入 MCP 客户端

SDK提供了一个高级客户界面:

```typescript
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"],
});

const client = new Client({
  name: "example-client",
  version: "1.0.0",
});

await client.connect(transport);

// List prompts
const prompts = await client.listPrompts();

// Get a prompt
const prompt = await client.getPrompt({
  name: "example-prompt",
  arguments: {
    arg1: "value",
  },
});

// List resources
const resources = await client.listResources();

// Read a resource
const resource = await client.readResource({
  uri: "file:///example.txt",
});

// Call a tool
const result = await client.callTool({
  name: "example-tool",
  arguments: {
    arg1: "value",
  },
});
```

### 代理授权请求上游

您可以代理 OAuth 请求外部授权提供者 :

```typescript
import express from "express";
import { ProxyOAuthServerProvider } from "@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js";
import { mcpAuthRouter } from "@modelcontextprotocol/sdk/server/auth/router.js";

const app = express();

const proxyProvider = new ProxyOAuthServerProvider({
  endpoints: {
    authorizationUrl: "https://auth.external.com/oauth2/v1/authorize",
    tokenUrl: "https://auth.external.com/oauth2/v1/token",
    revocationUrl: "https://auth.external.com/oauth2/v1/revoke",
  },
  verifyAccessToken: async (token) => {
    return {
      token,
      clientId: "123",
      scopes: ["openid", "email", "profile"],
    };
  },
  getClient: async (client_id) => {
    return {
      client_id,
      redirect_uris: ["http://localhost:3000/callback"],
    };
  },
});

app.use(
  mcpAuthRouter({
    provider: proxyProvider,
    issuerUrl: new URL("http://auth.external.com"),
    baseUrl: new URL("http://mcp.example.com"),
    serviceDocumentationUrl: new URL("https://docs.example.com/"),
  }),
);
```

这个设置允许您:

-   将 OAuth 请求转发到外部提供者
-   添加自定义符号验证逻辑
-   管理客户注册
-   提供自定义文档 URL
-   保持对 OAuth 流量的控制,同时将权限下放给外部提供者

### 后向兼容性

具有可流式Http运输的客户端和服务器可以维护 [向后兼容](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#backwards-compatibility) 与被贬值的HTTP+SSE运输(从协议版本2024-11-05)如下:

#### 客户端兼容性

对于需要同时使用可流式HTTP和旧的SSE服务器的客户端:

```typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
let client: Client | undefined = undefined;
const baseUrl = new URL(url);
try {
  client = new Client({
    name: "streamable-http-client",
    version: "1.0.0",
  });
  const transport = new StreamableHTTPClientTransport(new URL(baseUrl));
  await client.connect(transport);
  console.log("Connected using Streamable HTTP transport");
} catch (error) {
  // If that fails with a 4xx error, try the older SSE transport
  console.log(
    "Streamable HTTP connection failed, falling back to SSE transport",
  );
  client = new Client({
    name: "sse-client",
    version: "1.0.0",
  });
  const sseTransport = new SSEClientTransport(baseUrl);
  await client.connect(sseTransport);
  console.log("Connected using SSE transport");
}
```

#### 服务器系统兼容性

对于需要同时支持可流式HTTP和旧客户端的服务器:

```typescript
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";

const server = new McpServer({
  name: "backwards-compatible-server",
  version: "1.0.0",
});

// ... set up server resources, tools, and prompts ...

const app = express();
app.use(express.json());

// Store transports for each session type
const transports = {
  streamable: {} as Record<string, StreamableHTTPServerTransport>,
  sse: {} as Record<string, SSEServerTransport>,
};

// Modern Streamable HTTP endpoint
app.all("/mcp", async (req, res) => {
  // Handle Streamable HTTP transport for modern clients
  // Implementation as shown in the "With Session Management" example
  // ...
});

// Legacy SSE endpoint for older clients
app.get("/sse", async (req, res) => {
  // Create SSE transport for legacy clients
  const transport = new SSEServerTransport("/messages", res);
  transports.sse[transport.sessionId] = transport;

  res.on("close", () => {
    delete transports.sse[transport.sessionId];
  });

  await server.connect(transport);
});

// Legacy message endpoint for older clients
app.post("/messages", async (req, res) => {
  const sessionId = req.query.sessionId as string;
  const transport = transports.sse[sessionId];
  if (transport) {
    await transport.handlePostMessage(req, res, req.body);
  } else {
    res.status(400).send("No transport found for sessionId");
  }
});

app.listen(3000);
```

**说明**:SSE运输现在被贬值,有利于流式HTTP. 新的实施应当使用可流式HTTP,现有的SSE实施应当计划迁移.

## 文档

-   [示范背景协议文件](https://modelcontextprotocol.io/)
-   [MCP 规格](https://spec.modelcontextprotocol.io/)
-   [示例服务器](https://github.com/modelcontextprotocol/servers)

## 捐款

GitHub网站欢迎提出问题和拉动请求 [https://github.com/modelcontextprotocol/typescript-sdk (中文(简体) )](https://github.com/modelcontextprotocol/typescript-sdk)。 。 。 .

## 许可证

这个项目根据麻省理工学院许可证获得许可——见 [自由主义](https://npmcn.com/package/%40alcyone-labs/modelcontextprotocol-sdk/LICENSE) 详细文件.

## 常见问题

### @alcyone-labs/modelcontextprotocol-sdk 是什么？

升级到 Zod V4 用于类型脚本的模型背景协议执行

### 如何安装 @alcyone-labs/modelcontextprotocol-sdk？

在项目目录运行 npm install @alcyone-labs/modelcontextprotocol-sdk，或使用 pnpm add / yarn add / bun add。

### @alcyone-labs/modelcontextprotocol-sdk 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/alcyone-labs\_\_modelcontextprotocol-sdk 是否存在。

### @alcyone-labs/modelcontextprotocol-sdk 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @alcyone-labs/modelcontextprotocol-sdk 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @alcyone-labs/modelcontextprotocol-sdk 可以商用吗？

@alcyone-labs/modelcontextprotocol-sdk 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @alcyone-labs/modelcontextprotocol-sdk 的下载量有多少？

根据 npm 官方下载统计，@alcyone-labs/modelcontextprotocol-sdk 在 2026/10/06 – 2026/11/04 这 30 天内被下载 24,617 次，日均约 821 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @alcyone-labs/modelcontextprotocol-sdk 还在维护吗？

最新版本 1\.16\.0 发布于 2025/08/01（1\.3 年前）；至今共发布 1 个版本，其中过去 12 个月发布了 0 个；首次发布于 2025/08/01。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

