Repository Public MIT
1#!/usr/bin/env node2// Minimal MCP server over stdio: JSON-RPC 2.0, one message per line.3// One tool, `echo`. No dependencies, no network, no filesystem access.4import { createInterface } from "node:readline";56const SUPPORTED = ["2025-06-18", "2025-03-26", "2024-11-05"];7const TOOLS = [8 {9 name: "echo",10 description: "Returns the text it receives, unchanged.",11 inputSchema: {12 type: "object",13 properties: { text: { type: "string", description: "Text to echo back." } },14 required: ["text"],15 additionalProperties: false,16 },17 },18];1920const send = (message) => process.stdout.write(JSON.stringify(message) + "\n");21const result = (id, value) => send({ jsonrpc: "2.0", id, result: value });22const error = (id, code, message) => send({ jsonrpc: "2.0", id, error: { code, message } });2324function handle(message) {25 const isRequest = message.id !== undefined && message.id !== null;26 if (message.jsonrpc !== "2.0" || typeof message.method !== "string") {27 if (isRequest) error(message.id, -32600, "Invalid Request");28 return;29 }30 if (!isRequest) return; // notifications (for example notifications/initialized) need no reply31 const params = message.params ?? {};32 switch (message.method) {33 case "initialize":34 return result(message.id, {35 protocolVersion: SUPPORTED.includes(params.protocolVersion) ? params.protocolVersion : SUPPORTED[0],36 capabilities: { tools: {} },37 serverInfo: { name: "echo-mcp-server", version: "1.0.1" },38 });39 case "ping":40 return result(message.id, {});41 case "tools/list":42 return result(message.id, { tools: TOOLS });43 case "tools/call": {44 if (params.name !== "echo") return error(message.id, -32602, `Unknown tool: ${String(params.name)}`);45 const text = params.arguments?.text;46 if (typeof text !== "string") {47 return result(message.id, { content: [{ type: "text", text: "The `text` argument must be a string." }], isError: true });48 }49 return result(message.id, { content: [{ type: "text", text }], isError: false });50 }51 default:52 return error(message.id, -32601, `Method not found: ${message.method}`);53 }54}5556createInterface({ input: process.stdin, crlfDelay: Infinity }).on("line", (line) => {57 if (!line.trim()) return;58 let message;59 try {60 message = JSON.parse(line);61 } catch {62 return error(null, -32700, "Parse error");63 }64 if (Array.isArray(message)) return error(null, -32600, "Batch requests are not supported");65 handle(message);66});67