The official TypeScript SDK turns a function into an MCP tool. This builds one that any MCP client can call over stdio.
1. Set up the project
mkdir wordcount && cd wordcount
npm init -y
npm pkg set type=module
npm install @modelcontextprotocol/server zod
type=module matters — the SDK is ESM. @modelcontextprotocol/server is the v2 server
package; it replaces the older monolithic @modelcontextprotocol/sdk package, so ignore v1
snippets that import from there.
2. Write the server
server.ts:
import { McpServer } from "@modelcontextprotocol/server";
import { serveStdio } from "@modelcontextprotocol/server/stdio";
import * as z from "zod";
serveStdio(() => {
const server = new McpServer(
{ name: "wordcount", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.registerTool(
"word_count",
{
description: "Count the words in a piece of text.",
inputSchema: z.object({ text: z.string() }),
},
async ({ text }) => ({
content: [{ type: "text", text: String(text.trim().split(/\s+/).length) }],
})
);
return server;
});
serveStdio takes a factory that builds the server for each connection — it replaces the older
new StdioServerTransport() plus server.connect(transport) wiring. The zod schema is the
tool’s input contract, and the description is what the model reads when deciding whether to
call it.
3. One rule about output
stdout is the JSON-RPC channel. The client parses every line of it as a protocol message,
so a stray console.log corrupts the stream and the server looks broken. Log with
console.error instead.
4. Run and connect it
Node 24 runs .ts files directly in an ESM project, so there’s no build step:
node server.ts
It will sit there waiting for a client on stdin — that’s correct. Stop it with Ctrl+C and
hand the same command to Claude Code, with an absolute path:
claude mcp add wordcount -- node C:\path\to\server.ts
claude mcp add wordcount -- node /path/to/server.ts
On older Node versions that can’t strip types, compile to JavaScript first and point the command at the compiled file instead. Restart Claude Code, then check it loaded:
claude mcp list
5. Call it
Use the word_count tool to count the words in the first paragraph of README.md.
Next: build the same server in Python,
the best MCP servers to start with, or generate the
claude mcp add command with the MCP config generator.