MCP Server Generator
Template · TypeScript & Python

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 node survives tsc, so the compiled dist/index.js works as the package's bin after npm run build.
  • McpServer holds 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 the TODO with your logic.
  • StdioServerTransport talks JSON-RPC over stdin/stdout. That is why the startup message uses console.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()
  • MCPServer is the high-level server in mcp 2.x (it was called FastMCP in 1.x). Passing version="1.0.0" makes the host see a real version; without it serverInfo.version is 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 即可得到定制模板。