
使用typescript-sdk构建一个Hello MCP!
本文最后更新于 2025-03-21,文章内容可能已经过时。
为了加快博客文章的编写,本文使用ai辅助编写,更加清晰,比我手写的强多了,没那么多废话......
官方版SDK
src/index.ts
- MCP服务器实现,提供两个工具:say_hello
和add
package.json
- 项目依赖和脚本tsconfig.json
- TypeScript配置
MCP服务器搭建步骤
1. 初始化项目
# 创建项目目录
mkdir mcp_demo_1
cd mcp_demo_1
# 初始化npm项目
npm init -y
# 安装依赖
npm install @modelcontextprotocol/sdk zod
npm install --save-dev typescript @types/node
mkdir mcp_demo_1
:创建一个名为mcp_demo_1
的文件夹cd mcp_demo_1
:进入(切换工作目录到)刚创建的mcp_demo_1
文件夹npm init -y
:快速生成默认的package.json
文件(包含项目名称、版本、依赖等基础信息)npm install @modelcontextprotocol/sdk zod
:安装两个运行依赖包(@modelcontextprotocol/sdk
SDK 库和zod
数据验证库)npm install --save-dev typescript @types/node
:安装两个开发依赖包(typescript
编译器 和 Node.js 的 TypeScript 类型定义文件)
2. 配置TypeScript
创建tsconfig.json
文件:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"outDir": "build",
"rootDir": "src",
"sourceMap": true,
"declaration": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "build"]
}
compilerOptions
:TypeScript 编译器的全局配置项"target": "ES2022"
将代码编译为 ECMAScript 2022 标准,支持最新的 JavaScript 特性"module": "NodeNext"
使用 Node.js 原生的模块系统(.mjs
/.cjs
文件扩展名自动识别)"moduleResolution": "NodeNext"
按照 Node.js 的模块解析规则查找依赖(兼容package.json
的exports
字段)"esModuleInterop": true
允许 CommonJS 和 ES 模块互操作(如import React from 'react'
写法)"forceConsistentCasingInFileNames": true
强制文件名大小写敏感(避免跨平台系统的大小写冲突)"strict": true
启用所有严格类型检查(包括空值检查、隐式any
类型报错等)"skipLibCheck": true
跳过第三方库的类型检查(提升编译速度,但可能降低类型安全性)"outDir": "build"
输出编译后的文件到build
目录(与源代码分离)"rootDir": "src"
指定源代码根目录为src
(编译器仅编译此目录下的文件)"sourceMap": true
生成.map
文件(便于调试时映射编译后代码到源代码)"declaration": true
生成.d.ts
类型声明文件(供其他 TypeScript 项目使用你的库)"resolveJsonModule": true
允许直接导入 JSON 文件(如import data from './data.json'
)
include": ["src/**/*"]
指定编译范围:src
目录及其子目录下的所有文件exclude": ["node_modules", "build"]
排除编译范围:node_modules
和build
目录下的所有文件
3. 编写MCP服务器代码
创建src/index.ts
文件:
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// 创建MCP服务器
const server = new McpServer({
name: "hello-world",
version: "1.0.0"
});
// 添加一个简单的打招呼工具
server.tool(
"say_hello",
{ name: z.string().describe("要问候的名字") },
async (params: { name: string }) => ({
content: [{ type: "text", text: `你好,${params.name}!欢迎使用MCP!` }]
})
);
// 添加一个加法工具
server.tool(
"add",
{
a: z.number().describe("第一个数字"),
b: z.number().describe("第二个数字")
},
async (params: { a: number, b: number }) => ({
content: [{ type: "text", text: `${params.a} + ${params.b} = ${params.a + params.b}` }]
})
);
// 启动服务器
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Hello World 服务器已启动");
}
main().catch((error) => {
console.error("服务器启动失败:", error);
process.exit(1);
});
脚本声明和环境准备
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
#!/usr/bin/env node
:声明这是一个 Node.js 可执行脚本
导入的模块作用:
McpServer
:MCP 服务端核心类StdioServerTransport
:基于标准输入输出的通信模块zod
:用于数据验证的库
创建 MCP 服务器实例
const server = new McpServer({
name: "服务器名称",
version: "版本号"
});
初始化一个 MCP 服务:
name
:服务唯一标识名version
:服务版本号(用于接口兼容性管理)注册工具方法:打招呼功能
server.tool(
"工具名称",
{ 参数1: z.类型().describe("参数描述") },
async (params) => {
// 实现逻辑
return { content: [{ type: "text", text: "返回结果" }] };
}
);
工具注册三要素:
工具名称:
"say_hello"
参数验证:使用 Zod 定义必须的字符串类型
name
参数处理函数:接收参数后返回包含问候文本的标准化响应
注册工具方法:加法计算
server.tool(
"add",
{
a: z.number().describe("第一个数字"),
b: z.number().describe("第二个数字")
},
async (params: { a: number, b: number }) => ({
content: [{ type: "text", text: `${params.a} + ${params.b} = ${params.a + params.b}` }]
})
);
与前一工具类似,但:
参数定义为两个数字
a
和b
处理函数返回计算结果的文本
服务器启动逻辑
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Hello World 服务器已启动");
}
关键步骤:
创建标准输入输出通信通道 (
StdioServerTransport
)将服务器绑定到该通道
输出启动成功提示(到标准错误流避免干扰主输出)
错误处理
main().catch((error) => {
console.error("服务器启动失败:", error);
process.exit(1);
});
异常捕获机制:
打印详细的错误信息
以非零状态码退出进程(
1
表示异常终止)
4. 更新package.json
确保package.json包含以下内容:
{
"name": "mcp_demo_1",
"version": "1.0.0",
"description": "MCP服务器示例",
"main": "dist/index.js",
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.7.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^22.13.10",
"typescript": "^5.8.2"
}
}
"name": "mcp_demo_1"
定义项目名称标识(遵循 npm 包命名规范,使用小写和连字符)"version": "1.0.0"
指定项目版本号(遵循语义化版本规范)"description": "MCP服务器示例"
添加项目描述(显示在 npm 仓库和开发文档中)"main": "dist/index.js"
指定项目入口文件(指向 TypeScript 编译后的输出目录)"type": "module"
启用 ES 模块系统(允许使用import/export
语法)
"scripts"
:定义 npm 快捷命令"build": "tsc"
执行 TypeScript 编译(根据tsconfig.json
配置生成 JS 文件)"start": "node dist/index.js"
运行编译后的入口文件(启动服务)
"dependencies"
:生产环境依赖"@modelcontextprotocol/sdk": "^1.7.0"
MCP 协议核心 SDK(提供服务器和客户端功能)"zod": "^3.22.4"
数据验证库(用于接口参数类型校验)
"devDependencies"
:开发环境依赖"@types/node": "^22.13.10"
Node.js 类型定义文件(提供 TypeScript 类型支持)"typescript": "^5.8.2"
TypeScript 编译器(用于代码编译和类型检查)
5. 编译
# 编译项目
npm run build
6.运行
服务已经起来了,我们该如何去测试当前服务是否运行正确呢?
不需要单独去制作一个客户端去测试
使用
使用方式
//注意目录位置,你也可以使用绝对地址
npx @wong2/mcp-cli node ./build/index.js args...
在cursor终端中可以直接运行,他会跳出2个工具,一个是say hello 一个是 add,请使用 键盘“上下”来选择使用哪个工具,“回车”是确认
say_hello
向指定名字的人打招呼。
参数
name
: 要问候的名字
返回
包含问候语的文本
add
计算两个数字的和。
参数
a
: 第一个数字b
: 第二个数字
返回
包含加法计算结果的文本