Documentation Index Fetch the complete documentation index at: https://mintlify.com/microsoft/mcp-for-beginners/llms.txt
Use this file to discover all available pages before exploring further.
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.
Clone and navigate
git clone https://github.com/microsoft/mcp-for-beginners.git
cd mcp-for-beginners/03-GettingStarted/samples/typescript
Build and run
This runs tsc then node ./build/index.js. 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 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. Advanced server with ResourceTemplate and event system Located at 04-PracticalImplementation/samples/typescript, this sample organises the server as a typed class with private methods for registration, a completion tool, and a dynamic search resource using ResourceTemplate.
Navigate to the advanced sample
cd 04-PracticalImplementation/samples/typescript
Server code Class definition
Completion tool
Search resource
Entry point
import { EventEmitter } from 'events' ;
import { McpServer , ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js' ;
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' ;
import { z } from 'zod' ;
export class ExtendedMcpServer {
private serverName : string ;
private models : string [];
private events : EventEmitter ;
private mcpServer : McpServer ;
constructor ( options : {
serverName ?: string ;
version ?: string ;
models ?: string [];
} = {}) {
this . serverName = options . serverName || 'TypeScript MCP Server' ;
this . models = options . models || [ 'gpt-4' , 'llama-3-70b' , 'claude-3-sonnet' ];
this . events = new EventEmitter ();
this . mcpServer = new McpServer ({
name: this . serverName ,
version: options . version || '1.0.0'
});
this . registerCompletionTool ();
this . registerSearchResource ();
}
public async connect () : Promise < void > {
const transport = new StdioServerTransport ();
await this . mcpServer . connect ( transport );
}
public on ( event : string , listener : ( ... args : any []) => void ) : void {
this . events . on ( event , listener );
}
}
Key TypeScript patterns Pattern Detail Private registration methods registerCompletionTool() and registerSearchResource() keep the constructor cleanResourceTemplateDeclares a URI template (test://{query}) with typed parameters EventEmitterTyped events for request/completion metrics Strict typing models: string[], options: { temperature?: number } — all inferred by the compiler