Skip to main content
The TypeScript samples use the @modelcontextprotocol/sdk package with Zod for schema validation and TypeScript for end-to-end type safety.

Basic calculator server

Located at 03-GettingStarted/samples/typescript, this is a strongly-typed MCP server with four arithmetic tools.
1

Clone and navigate

git clone https://github.com/microsoft/mcp-for-beginners.git
cd mcp-for-beginners/03-GettingStarted/samples/typescript
2

Install dependencies

npm install
3

Build and run

npm start
This runs tsc then node ./build/index.js.

package.json

package.json
{
  "name": "tutorial-mcp",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "tsc && node ./build/index.js"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": ">=1.26.0",
    "zod": "^3.24.2"
  },
  "devDependencies": {
    "@types/node": "^22.13.17",
    "typescript": "^5.8.2"
  }
}

Server code

src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "Calculator MCP Server",
  version: "1.0.0"
});

server.tool(
  "add",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a + b) }]
  })
);

server.tool(
  "subtract",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a - b) }]
  })
);

server.tool(
  "multiply",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => ({
    content: [{ type: "text", text: String(a * b) }]
  })
);

server.tool(
  "divide",
  { a: z.number(), b: z.number() },
  async ({ a, b }) => {
    if (b === 0) {
      return {
        content: [{ type: "text", text: "Error: Cannot divide by zero" }],
        isError: true
      };
    }
    return {
      content: [{ type: "text", text: String(a / b) }]
    };
  }
);

const transport = new StdioServerTransport();
server.connect(transport).catch(console.error);

console.log("Calculator MCP Server started");
The Zod schemas are inferred at compile time — TypeScript ensures the handler receives the exact types declared in the schema.

Build docs developers (and LLMs) love