Build a Weather MCP Server with TypeScript Using HTTP SSE (Part 2)
This tutorial walks through creating a weather‑focused MCP server with the Model Context Protocol TypeScript SDK, explaining Server‑Sent Events, setting up the Node.js environment, writing the TypeScript code, building, running, and testing the HTTP SSE service end‑to‑end.
With the AI boom expected in 2025, MCP services are becoming essential for developers. This article demonstrates how to build a weather‑based MCP server using the Model Context Protocol TypeScript SDK and the HTTP Server‑Sent Events (SSE) communication mode.
SSE is an HTTP‑based streaming mechanism that lets a server push events to a client over a single long‑lived GET request, making it suitable for real‑time updates such as chat, weather forecasts, or news feeds.
Development environment : Install Node.js (recommended via NVM to switch versions easily). Create a project folder and initialize the following package.json (fields translated to English):
{
"name": "@wuchubuzai/tianqi-mcp-server",
"version": "0.0.1",
"description": "Weather‑based MCP Server",
"author": "AuthorName",
"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",
"express": "^4.18.2",
"node-fetch": "^3.3.2"
},
"devDependencies": {
"@types/express": "^5.0.1",
"@types/node": "^22.15.3",
"shx": "^0.3.4",
"typescript": "^5.8.3"
},
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org" }
}Initialize the TypeScript project with the following tsconfig.json:
{
"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"]
}Define the weather tool that will be exposed to the MCP client:
const GET_TIANQI: Tool = {
name: "get_city_tianqi",
description: "Return weather information for the queried city based on city name",
inputSchema: {
type: "object",
properties: {
city: { type: "string", description: "Name of the city to query" }
},
required: ["city"]
}
};
const SUPPORT_TOOLS = [GET_TIANQI] as const;Implement a helper that fetches weather data from a free API and returns a structured MCP response:
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) {
// Parameter validation
if (!city) {
return buildErrorResponse("Incomplete parameters, please ensure city parameter is provided");
}
const url = "https://api.susu.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));
}Set up the Express server, create the SSE transport, register the tool handlers, and start listening on port 3000:
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";
import { CallToolRequestSchema, ListToolsRequestSchema, Tool } from "@modelcontextprotocol/sdk/types.js";
import fetch from "node-fetch";
const app = express();
app.use(express.json());
const transports: Record<string, Record<string, SSEServerTransport>> = { sse: {} };
app.get('/sse', async (req: any, res: any) => {
console.log("http /sse request start.......");
const transport = new SSEServerTransport('/messages', res);
transports.sse[transport.sessionId] = transport;
res.on('close', () => { delete transports.sse[transport.sessionId]; });
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 };
}
});
await server.connect(transport);
console.log("http /sse request connect");
});
app.post('/messages', async (req: any, res: any) => {
const sessionId = req.query.sessionId as string;
const transport = transports.sse[sessionId];
if (transport) {
await transport.handlePostMessage(req, res, req.body);
} else {
res.status(400).send('No transport found for sessionId');
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log("HTTP SSE Server Started.....");
console.log(`Server is running on port ${PORT}`);
}).on('error', (err) => {
console.error('Server error', err);
});After writing the code, install dependencies with npm install, build the project using npm run build, and start the server with node dist/index.js. The server will expose /sse for SSE connections and /messages for client‑to‑server messages.
Testing can be done with the Cherry Studio client: configure the MCP endpoint as http://<em>your‑host</em>:3000/sse, send a request like {"name":"get_city_tianqi","arguments":{"city":"Beijing"}}, and observe the weather JSON returned from the free API. Console logs show request handling and any errors.
To deploy, place the compiled server on any reachable host and expose the /sse URL. This lightweight HTTP SSE MCP server is well‑suited for enterprise scenarios where a simple, real‑time AI tool integration is needed.
The tutorial illustrates the full development workflow, from environment preparation and project scaffolding to code implementation, building, running, and verification, providing a concrete example of how the Model Context Protocol can be leveraged with TypeScript to create AI‑enabled services.
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.
