MCP Server Template for TypeScript and Python
TypeScript 与 Python 的 MCP Server 模板
A minimal MCP server is four files: a manifest, one source file that registers tools and connects a stdio transport, and a README with the host config.
Below is the exact template MCP Server Generator produces, in TypeScript and Python, with what each part does and how to extend it.
Both versions were run on 2026-10-17 (@modelcontextprotocol/sdk 1.32.1 on Node 20, mcp 2.3.0 on Python 3.13) using the exact host configs from their READMEs, and answered tools/list and tools/call correctly.
最小的 MCP server 只需四个文件:清单、一个注册工具并连接 stdio 的源码文件,以及带主机配置的 README。下面是生成器实际输出的 TypeScript / Python 模板、各部分作用与扩展方法;两版均已实测可用。
TypeScript template
TypeScript 模板
weather-helper/
├── package.json
├── tsconfig.json # ES2022, NodeNext, strict, outDir dist
├── src/index.ts
└── README.md
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";
const server = new McpServer({
name: "weather-helper",
version: "1.0.0",
});
server.registerTool(
"get_weather",
{
description: "Get current weather for a city",
inputSchema: z.object({
city: z.string().describe("City name, e.g. San Francisco")
}),
},
async ({ city }) => {
// TODO: replace this placeholder with real logic for get_weather
const text = "[get_weather] " + "city=" + JSON.stringify(city);
return {
content: [{ type: "text", text }],
};
}
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("weather-helper MCP server running on stdio");
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
#!/usr/bin/env nodesurvivestsc, so the compileddist/index.jsworks as the package'sbinafternpm run build.McpServerholds the server name and version the host displays.registerTool(name, {description, inputSchema}, handler): the Zod object becomes the JSON Schema the model sees;.describe()text is passed to the model as the parameter description.- The handler returns
{ content: [{ type: "text", text }] }. Replace theTODOwith your logic. StdioServerTransporttalks JSON-RPC over stdin/stdout. That is why the startup message usesconsole.error: anything printed to stdout corrupts the protocol.
package.json (trimmed)
{
"name": "weather-helper",
"type": "module",
"bin": { "weather-helper": "./dist/index.js" },
"scripts": {
"start": "node --import tsx src/index.ts",
"build": "tsc -p tsconfig.json",
"start:dist": "node dist/index.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.32.1",
"zod": "^3.25.76"
},
"devDependencies": {
"@types/node": "^22.10.2",
"tsx": "^4.19.2",
"typescript": "^5.7.2"
},
"engines": { "node": ">=18" }
}
Python template
Python 模板
weather-helper/
├── server.py
├── requirements.txt # mcp>=2.0.0
├── pyproject.toml # requires-python >=3.10
└── README.md
server.py
"""Example MCP server with a weather lookup tool"""
from mcp.server import MCPServer
mcp = MCPServer("weather-helper", version="1.0.0")
@mcp.tool()
def get_weather(city: str) -> str:
"""Get current weather for a city
Args:
city: City name, e.g. San Francisco
"""
# TODO: replace this placeholder with real logic for get_weather
return "[get_weather] " + "city=" + repr(city)
if __name__ == "__main__":
mcp.run()
MCPServeris the high-level server inmcp2.x (it was calledFastMCPin 1.x). Passingversion="1.0.0"makes the host see a real version; without itserverInfo.versionis empty.@mcp.tool()turns a function into a tool. Type hints (str,float,bool) become the input schema, and the docstring becomes the description.mcp.run()defaults to stdio, which is what Claude Desktop and Cursor launch.
Add a tool with an optional parameter
新增一个带可选参数的工具
This is the code the generator writes when you add a second tool and untick required on days. Paste it above main() / if __name__:
TypeScript
server.registerTool(
"get_forecast",
{
description: "Get a multi-day forecast for a city",
inputSchema: z.object({
city: z.string().describe("City name"),
days: z.number().describe("Number of days (1-7)").optional(),
}),
},
async ({ city, days }) => {
// TODO: call your forecast API here
const text = "[get_forecast] city=" + JSON.stringify(city) + ", days=" + JSON.stringify(days);
return { content: [{ type: "text", text }] };
}
);
Python
@mcp.tool()
def get_forecast(city: str, days: float = 0.0) -> str:
"""Get a multi-day forecast for a city
Args:
city: City name
days: Number of days (1-7)
"""
# TODO: call your forecast API here
return "[get_forecast] city=" + repr(city) + ", days=" + repr(days)
Optional parameters get .optional() in Zod and a default value in Python. Keep each tool task-shaped (one clear job, a verb in the name) rather than one tool per endpoint; models choose between a handful of well-described tools more reliably.
Run and test it
运行与测试
# TypeScript
npm install
npx @modelcontextprotocol/inspector npm start
# Python
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
npx @modelcontextprotocol/inspector .venv/bin/python server.py
The MCP Inspector launches your server the same way a host does and lets you list and call tools before you touch any host config. When it works there, connect the server to Claude Desktop or Cursor.
What the template does not include
模板不包含什么
- Real handler logic: tools echo their arguments until you replace the
TODOs - Resources, prompts, auth, or an HTTP transport
- Parameter types beyond string, number and boolean (edit the Zod schema or type hints for arrays, enums or objects)
Generate this template with your own tools
用你自己的工具生成模板
Name your tools and parameters in the form; the ZIP has the same structure as above. No OpenAPI needed.
FAQ
常见问题
Is this an official MCP server template?
No. It is generated by MCP Server Generator, but it uses the official SDKs: @modelcontextprotocol/sdk for TypeScript and the mcp package for Python.
中文: 不是官方模板,但使用的是官方 SDK(TypeScript 的 @modelcontextprotocol/sdk 与 Python 的 mcp)。
Why does the Python template use MCPServer instead of FastMCP?
In version 2 of the mcp Python package, FastMCP was renamed to MCPServer and is imported from mcp.server. The template pins mcp>=2.0.0, so it uses the new name. On mcp 1.x you would write from mcp.server.fastmcp import FastMCP instead.
中文: mcp v2 把 FastMCP 改名为 MCPServer(从 mcp.server 导入);模板要求 mcp>=2.0.0。若用 1.x,请改用 from mcp.server.fastmcp import FastMCP。
Do I need to compile the TypeScript template?
No. npm start runs src/index.ts directly through tsx. npm run build compiles to dist/ with tsc if you prefer plain Node in production.
中文: 不需要。npm start 通过 tsx 直接运行 src/index.ts;需要时可用 npm run build 用 tsc 编译到 dist/。
Can the template run as a remote HTTP server?
Not as generated. It uses the stdio transport, which is what Claude Desktop and Cursor launch locally. Switching to Streamable HTTP means replacing the transport code yourself.
中文: 按生成的样子不行:它使用 stdio 传输,供 Claude Desktop / Cursor 本地启动。如需 Streamable HTTP 需要自行替换传输层代码。
How do I get the template with my own tool names?
Fill in the form on the MCP Server Generator homepage and download the ZIP. Tool names, descriptions and typed parameters are written into the code for you.
中文: 在首页表单填写工具名、描述和参数类型,下载 ZIP 即可得到定制模板。