How to Build a TypeScript Stdio‑Mode MCP Server for Weather Queries
This article explains the motivation behind Model Context Protocol (MCP), compares its communication modes, and provides a step‑by‑step tutorial for creating a TypeScript‑based MCP Server in Stdio mode that exposes a weather‑lookup tool, builds it, runs it, and tests it with the official inspector.
Why MCP?
MCP aims to lower the technical barrier for AI agents that need to call external tools. The article lists three pain points of current tool integration: high coupling between agent and tool code, poor tool reusability across languages, and fragmented ecosystems caused by lack of a standard.
In 2025 the proposed solution is to decouple tools into a separate MCP Server layer that standardizes context and tool invocation for agents.
Stdio Transport
Stdio (standard input/output) is the simplest communication method, suitable for local processes. The client sends commands and data via stdin, the server processes them and returns results via stdout.
Development Setup
Prepare a Node.js environment (recommended via NVM) and install the required dependencies:
{
"name": "@wuchubuzai/tianqi-mcp-server",
"version": "0.0.1",
"description": "基于天气的MCP Server",
"author": "爱海贼的无处不在",
"type": "module",
"license": "MIT",
"main": "bin/index.js",
"bin": { "tianqi-mcp-server": "dist/index.js" },
"files": ["dist"],
"scripts": { "build": "tsc && shx chmod +x dist/*.js", "prepare": "npm run build", "watch": "tsc --watch" },
"dependencies": { "@modelcontextprotocol/sdk": "1.10.2", "@types/node-fetch": "^2.6.12", "node-fetch": "^3.3.2" },
"devDependencies": { "@types/node": "^22.15.3", "shx": "^0.3.4", "typescript": "^5.8.3" },
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" }
}Create tsconfig.json with a typical Node16 configuration:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"outDir": "./dist",
"rootDir": "."
},
"include": ["./**/*.ts"],
"exclude": ["node_modules"]
}Tool Definition
Define a weather‑lookup tool that accepts a city name and returns the weather JSON from a free API:
const GET_TIANQI: Tool = {
name: "get_city_tianqi",
description: "根据城市名称,返回当前查询城市的天气情况信息",
inputSchema: {
type: "object",
properties: { city: { type: "string", description: "需要查询天气的城市名称" } },
required: ["city"]
}
};
const SUPPORT_TOOLS = [GET_TIANQI] as const;Server Code
The server uses the Model Context Protocol SDK. It registers two request handlers: one for listing tools and one for invoking the weather tool. Helper functions build success or error responses.
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema, Tool } from "@modelcontextprotocol/sdk/types.js";
import fetch from "node-fetch";
function buildSuccessResponse(text: string) { return { content: [{ type: "text", text }], isError: false }; }
function buildErrorResponse(text: string) { return { content: [{ type: "text", text }], isError: true }; }
async function handleGetTianqiData(city: string) {
if (!city) return buildErrorResponse('参数不完整,请确保提供了city参数');
const url = "https://api.苏苏.cn/API/moji.php?city=" + city + "&n=1";
const response1 = await fetch(url, { method: 'GET' });
const respBody: any = await response1.json();
return buildSuccessResponse(JSON.stringify(respBody, null, 2));
}
const server = new Server({ name: "tianqi-mcp-server", version: "0.0.1" }, { capabilities: { tools: {} } });
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: SUPPORT_TOOLS }));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
switch (request.params.name) {
case "get_city_tianqi": {
const { city } = request.params.arguments as { city: string };
return await handleGetTianqiData(city);
}
default:
return { content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }], isError: true };
}
} catch (error) {
return { content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true };
}
});
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Tianqi MCP Server running on stdio");
}
runServer().catch((error) => { console.error("Fatal error running server:", error); process.exit(1); });Running and Testing
Build the project with npm run build, then start the server using the Model Context Protocol inspector:
npx -y @modelcontextprotocol/inspector node dist/index.jsIn the inspector UI select “Stdio” mode, list the tool, provide a city name (e.g., “哈尔滨”), and verify that the JSON weather data is returned. The article also shows screenshots of the inspector and of registering the server in Cherry Studio.
Publishing
Because the project uses TypeScript, it can be published to npm. After committing the source to a GitHub repository, run npm login and npm publish to share the MCP Server with others.
Conclusion
The tutorial demonstrates that building an MCP Server with the TypeScript SDK is straightforward: set up the environment, scaffold the project, define tool schemas, implement request handlers, run the server in Stdio mode, and test it with the official inspector. This lowers the entry barrier for developers who want to integrate external tools into AI agents.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ubiquitous Tech
A ubiquitous public account for pirate enthusiasts, regularly sharing curated experiences, tech learning, and growth insights. Currently publishing articles on AI RAG customer service, AI MCP technology, and open-source design. Personal free Knowledge Planet: Awakening New World Programmer.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
