创建本地MCP服务器的教程。
npx giget@latest gh:7nohe/local-mcp-server-tutorial my-mcp-server
cd my-mcp-server
npm install
git init
git branch -M main
git add .
git commit -m "Initial commit"
我们将构建并运行以下src/index.ts的内容。
#!/usr/bin/env node
async function main() {
console.error("Hello, world!");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
npm run build
./dist/index.js
# Hello, world!
[!NOTE] 根据package.json中的bin属性设置,会在node_modules/.bin/下创建符号链接,从而可以执行./dist/index.js。
npm install @modelcontextprotocol/sdk zod
#!/usr/bin/env node
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// 创建MCP服务器实例。
const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0",
capabilities: {
resources: {},
tools: {},
},
});
async function main() {
const transport = new StdioServerTransport();
// 资源
// 定义一个返回“Hello, world!”的资源。
server.resource(
"Greeting",
"greeting://hello",
(uri, { }) => {
console.log(uri)
return {
contents: [
{
uri: uri.href,
text: "Hello, world!",
}
]
}
})
// 对于动态资源,我们使用ResourceTemplate类。
// list选项是一个回调函数,用于列出与该模板匹配的所有资源。如果使用ResourceTemplate,则需要指定list为undefined。
server.resource(
"Greeting with name",
new ResourceTemplate("greeting://hello/{name}", {
// list是
list: async () => {
// 例如,这里可以通过API获取用户列表。
await setTimeout(() => { }, 1000);
// 这里返回的是模拟数据。
return {
resources:
[
{ name: "Alice", uri: "greeting://hello/Alice" },
{ name: "Bob", uri: "greeting://hello/Bob" },
{ name: "Charlie", uri: "greeting://hello/Charlie" },
]
}
},
}),
(uri, { name }) => {
return {
contents: [
{
uri: uri.href,
text: `Hello, ${name}!`,
}
]
}
})
// 提示
server.prompt(
"Japanese Translation",
{
englishText: z.string().describe("要翻译的英文文本"),
},
({ englishText }) => ({
messages: [{
role: 'user',
content: {
type: 'text',
text: `你是一位专业的翻译者,请将下面的文本翻译成日语: ${englishText}`,
}
}]
}));
// 工具
server.tool(
"calculate-bmi",
"计算BMI",
{
weightKg: z.number().describe("体重(kg)"),
heightM: z.number().describe("身高(m)"),
},
({ weightKg, heightM }) => {
return {
content: [
{
type: "text",
text: String(weightKg / (heightM * heightM)),
}
]
}
})
server.connect(transport);
console.error("my-mcp-server started");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
使用Inspector进行调试。
npx @modelcontextprotocol/inspector ./dist/index.js
在浏览器中打开http://127.0.0.1:6274,可以查看定义的资源和工具的响应。
[!NOTE] 如果每次都要手动运行构建命令很麻烦,可以运行
npm run watch,这样每次有改动时都会自动构建。
接下来,在Claude Desktop中进行验证。 在Settings -> Developer -> Edit Config中打开claude_desktop_config.json文件,并做如下设置。
{
"mcpServers": {
"my-mcp-server": {
"command": "/<到项目的绝对路径>/my-mcp-server/dist/index.js"
}
}
}
保存后重启Claude Desktop。
从Tools按钮确认列表,从Attach from MCP按钮选择资源或提示,如果能正常显示则表示成功。
npm login
npm publish
[!NOTE] 在npm publish时,可以通过将package.json中的name设置为@username/my-mcp-server的形式,使自己的包更容易识别。
[!WARNING] 一旦发布npm包,删除会非常困难,因此请谨慎发布。
要点:
"bin": "./dist/index.js"
"files": [
"dist"
]
更改Claude Desktop的设置如下。
"my-mcp-server": {
"command": "npx",
"args": [
"@your-name/my-mcp-server@latest"
]
}