MCP Basics
The Model Context Protocol (MCP) is an open standard that allows AI assistants (like Claude, Cursor, and ChatGPT) to communicate securely with external software, APIs, and data sources.
NitroStack provides a production framework for building, testing, and deploying MCP servers with TypeScript and Python.
The Three MCP Primitives
Every capability exposed by an MCP server maps to one of three foundational primitives:
┌────────────────────────────────────────────────────────────────────────┐
│ THE THREE MCP PRIMITIVES │
├───────────────┬────────────────────────────┬───────────────────────────┤
│ Primitive │ Invocation / Control │ Typical Use Cases │
├───────────────┼────────────────────────────┼───────────────────────────┤
│ Tools │ Model-controlled actions │ DB queries, API calls, │
│ │ with side-effects │ file edits, computations │
├───────────────┼────────────────────────────┼───────────────────────────┤
│ Resources │ Application-controlled │ File contents, system logs│
│ │ read-only data endpoints │ metrics, schemas, docs │
├───────────────┼────────────────────────────┼───────────────────────────┤
│ Prompts │ User-controlled reusable │ Code review prompts, │
│ │ prompt templates │ debugging workflows │
└───────────────┴────────────────────────────┴───────────────────────────┘
Protocol Wire vs. NitroStack Code
MCP clients interact with your server by sending JSON-RPC 2.0 messages over standard transports (stdio or Streamable HTTP).
NitroStack maps these wire messages directly to clean, decorator-based TypeScript classes:
Wire Protocol Request (JSON-RPC)
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "calculate",
"arguments": {
"a": 10,
"b": 5,
"operation": "add"
}
},
"id": 1
}
NitroStack Implementation (TypeScript)
import { Tool, ExecutionContext } from '@nitrostack/core';
import { z } from 'zod';
export class CalculatorTools {
@Tool({
name: 'calculate',
description: 'Perform arithmetic calculations on two numbers',
inputSchema: z.object({
a: z.number().describe('First operand'),
b: z.number().describe('Second operand'),
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
}),
})
async calculate(
input: { a: number; b: number; operation: 'add' | 'subtract' | 'multiply' | 'divide' },
ctx: ExecutionContext
) {
if (input.operation === 'divide' && input.b === 0) {
throw new Error('Cannot divide by zero');
}
const result = input.operation === 'add' ? input.a + input.b
: input.operation === 'subtract' ? input.a - input.b
: input.operation === 'multiply' ? input.a * input.b
: input.a / input.b;
return {
result,
expression: `${input.a} ${input.operation} ${input.b} = ${result}`,
};
}
}
Why NitroStack vs. Raw MCP SDKs?
While the official @modelcontextprotocol/sdk gives you low-level protocol handlers, NitroStack provides the complete application framework needed for production services:
┌────────────────────────────────┬─────────────────┬─────────────────────┐
│ Feature │ Raw MCP SDK │ NitroStack Core │
├────────────────────────────────┼─────────────────┼─────────────────────┤
│ Architectural Pattern │ Imperative │ Modular & Decorator │
│ Dependency Injection │ Manual │ Built-in Singleton │
│ Input Validation │ Manual Schemas │ Native Zod & Pipes │
│ Interceptors & Transforms │ Not Included │ Built-in Pipeline │
│ Authentication (OAuth/API Key) │ Custom Code │ Built-in Modules │
│ Interactive UI Widgets │ None │ Next.js & React SDK │
│ Multi-Transport Dev Server │ Manual Server │ Dual HTTP + Widgets │
└────────────────────────────────┴─────────────────┴─────────────────────┘
Next Steps
- Quickstart: Build your first server in 5 steps.
- Connect to Clients: Connect Claude Desktop, Cursor, and VS Code.
- Request Pipeline: Discover Guards, Middleware, and Interceptors.