Node
БесплатноНе проверенAn MCP server that offers arithmetic operations (addition and division) and current weather data from OpenWeatherMap. It serves as a learning project for buildi
Описание
An MCP server that offers arithmetic operations (addition and division) and current weather data from OpenWeatherMap. It serves as a learning project for building MCP servers with Node.js and TypeScript, supporting both stdio and Streamable HTTP transports.
README
A training project for building MCP (Model Context Protocol) servers with Node.js and TypeScript.
Stack
- Node.js with ES modules (
"type": "module") - TypeScript (
NodeNextmodule mode) - @modelcontextprotocol/sdk — official MCP TypeScript SDK
- Zod — input/output schema validation
- Express — HTTP server for Streamable HTTP transport
- openweather-api-node — OpenWeatherMap API client
- dotenv — environment variable loading
Project Structure
node-mcp/
├── index.ts # Server entry point — registers all tools, selects transport
├── toolHandler.ts # Generic error-handling wrapper for tool handlers
├── tools/
│ ├── opperations/
│ │ ├── add.ts # Add tool
│ │ └── divide.ts # Divide tool
│ └── weather/
│ └── weather.ts # Weather tool
├── types.d.ts # Module declarations for untyped packages
├── .env # API keys and config (not committed)
├── dist/ # Compiled output (generated by tsc)
├── tsconfig.json
└── package.json
Getting Started
pnpm install
Create a .env file in the project root:
OPEN_WEATHER_API_KEY=your_key_here
NODE_ENV=development
TRANSPORT=stdio # or "http"
MCP_PORT=3000 # optional, HTTP mode only
Build:
pnpm build
Running the Server
stdio mode (for Claude Desktop / Claude Code)
$env:TRANSPORT="stdio"; node dist/index.js
The server communicates over stdin/stdout and waits for JSON-RPC messages from an MCP client. No visible output when idle.
HTTP mode (persistent process)
$env:TRANSPORT="http"; node dist/index.js
Starts an Express server on port 3000 (or MCP_PORT):
Starting Express MCP server on port 3000
MCP endpoint: http://localhost:3000/mcp
Server is running on http://localhost:3000
Testing with MCP Inspector
stdio mode
pnpm exec mcp-inspector node dist/index.js
HTTP mode
Start the server first, then open the inspector without arguments:
pnpm exec mcp-inspector
In the inspector UI, set transport type to Streamable HTTP and URL to http://localhost:3000/mcp.
Connecting to Claude Code
stdio (project-level)
claude mcp add --scope project node-mcp-server node C:/Training/node-mcp/dist/index.js
HTTP
Add the server URL directly in Claude Code's MCP settings pointing at http://localhost:3000/mcp.
Tools
add
Adds two numbers together and returns the result.
Inputs
| Name | Type | Description |
|---|---|---|
numOne |
number | First operand |
numTwo |
number | Second operand |
Output
{ "result": "32 + 32 = 64" }
divide
Divides two numbers and returns the result. Both inputs must be positive — validated by Zod before the handler runs.
Inputs
| Name | Type | Description |
|---|---|---|
numOne |
number (positive) | Dividend |
numTwo |
number (positive) | Divisor (cannot be zero) |
Output
{ "result": "10 / 2 = 5" }
weather
Returns current weather data for a location using the OpenWeatherMap API. Results are in metric units.
Supply one of the following location strategies:
| Name | Type | Description |
|---|---|---|
lat |
number (-90 to 90) | Latitude (use with lng) |
lng |
number (-180 to 180) | Longitude (use with lat) |
locationName |
string | City or place name (e.g. "London") |
zipCode |
string | Zip/postal code (e.g. "90210") |
Priority order when multiple are provided: coordinates → zip code → location name. At least one strategy must be supplied or the tool returns an error.
Output
Returns a JSON object with temperature, humidity, wind speed, weather description, and more.
Requires OPEN_WEATHER_API_KEY in .env.
Key Concepts
Transport selection
The server supports two transports, selected via the TRANSPORT environment variable:
| Value | Use case |
|---|---|
stdio |
Local servers spawned as child processes (Claude Code, Claude Desktop) |
http |
Persistent process accessible over a network |
Tools are registered once and shared between both transports — the capability is decoupled from the delivery mechanism.
Tool registration pattern
Each tool lives in its own file and exports a registration function that accepts the server instance:
export const myTool = (server: McpServer) => {
server.registerTool('tool-name', { ... }, toolHandler(async (inputs) => {
// handler logic
}))
}
In index.ts:
myTool(server)
Error handling — toolHandler
All tool handlers are wrapped with toolHandler, a generic wrapper that catches any thrown error and returns it in the correct MCP format:
export const toolHandler = <T>(fn: (inputs: T) => Promise<CallToolResult>) => {
return async (inputs: T) => {
try {
return await fn(inputs)
} catch (err) {
return {
isError: true,
content: [{
type: 'text' as const,
text: err instanceof Error
? process.env.NODE_ENV === 'development' ? err.stack ?? err.message : err.message
: 'Something went wrong...'
}]
}
}
}
}
- In development (
NODE_ENV=development): returns the full stack trace - In production: returns the error message only
- For non-Error throws: returns a generic fallback message
Input validation with Zod
Zod schemas on inputSchema are validated by the SDK before your handler runs. Invalid inputs return a -32602 protocol error — they never reach your handler:
inputSchema: {
numTwo: z.number().positive() // rejects zero and negatives
numTwo: z.number().refine(n => n !== 0) // rejects only zero
}
Streamable HTTP transport
The HTTP transport uses Express with the SDK's StreamableHTTPServerTransport. Key points:
sessionIdGenerator: randomUUID— required, assigns a unique ID to each client sessionexpress.json()middleware parses the request body before it reaches the transport- The parsed body is passed as the third argument to
handleRequest— the SDK uses it directly rather than re-parsing the raw request
app.use(express.json())
app.all('/mcp', (req, res) => {
transport.handleRequest(req, res, req.body)
})
ES module import paths
With "module": "NodeNext" in tsconfig, imports require explicit .js extensions even in .ts source files:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
Environment variables
Loaded via import 'dotenv/config' at the top of index.ts. Add .env to .gitignore to avoid committing API keys.
Установка Node
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/styles102/node-mcpFAQ
Node MCP бесплатный?
Да, Node MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Node?
Нет, Node работает без API-ключей и переменных окружения.
Node — hosted или self-hosted?
Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.
Как установить Node в Claude Desktop, Claude Code или Cursor?
Открой Node на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare Node with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
