Module 4: MCP Server in TypeScript

Module 4: MCP Server in TypeScript

Module 4: MCP Server in TypeScript

Capsule description

You've reached Phase 2. Modules 1-3 built your vocabulary and mental model: you know what MCP is, how the Host-Client-Server architecture works, and what Resources, Tools, and Prompts are. You even built a minimal server with the 3 primitives. But that server was a prototype — code in a single file, without structure, without robust validation, without transport configuration.

Now you're going to build a real MCP server.

TypeScript isn't an arbitrary choice — it's the language of the MCP ecosystem. Most open source MCP servers are written in TypeScript. The official TypeScript SDK (@modelcontextprotocol/sdk) is the most mature. Anthropic's official documentation uses TypeScript as a reference. If you look at the MCP server repositories on GitHub, TypeScript dominates by a wide margin. Starting with TypeScript means you can read, understand, and contribute to most of the ecosystem from day one.

This module is the densest of Phase 2, and it's intentional. The patterns you learn here — project setup, Zod schemas, error handling, transports — repeat in Python (module 5), in MCP Apps (module 6), and in the capstone project (module 8). Mastering the MCP server in TypeScript is mastering the fundamentals that apply to any language.


Where are we?

Context within the guide

Phase 1: MCP Fundamentals (Modules 1-3)
  ✅ Module 1: What MCP is and why it matters
  ✅ Module 2: Host-Client-Server Architecture
  ✅ Module 3: Three Primitives — Resources, Tools, Prompts

Phase 2: Build MCP Servers (Modules 4-6)
  → Module 4: MCP Server in TypeScript (YOU ARE HERE)
  ○ Module 5: MCP Server in Python
  ○ Module 6: MCP Apps and Interactive UI

Phase 3: Production (Modules 7-8)
  ○ Module 7: Testing, Debugging, and Integration
  ○ Module 8: Project — Real MCP Server

What you already know

From the previous modules you bring:

  • The M×N vs M+N mental model — why a standard protocol is necessary
  • The Host-Client-Server architecture — how the pieces connect
  • The 3 primitives — Resources (data), Tools (actions), Prompts (templates)
  • A minimal MCP server — 1 resource, 1 tool, 1 prompt working in Claude Code
  • Experience with the basic SDK — McpServer, StdioServerTransport, z from Zod

What's missing

Your server from module 3 was a monolithic file. It didn't have a real project structure. The Zod schemas were basic. You didn't explore dynamic resources or URI templates. And you only used stdio as a transport. In this module you're going to close those gaps.


Why TypeScript dominates the MCP ecosystem

The numbers

If you explore the MCP server repositories on GitHub, the pattern is clear:

Distribution of open source MCP servers (approximate):
├── TypeScript/JavaScript  ~65%
├── Python                 ~25%
├── Go                     ~5%
├── Rust                   ~3%
└── Others                 ~2%

It's not accidental. There are technical and ecosystem reasons:

1. The SDK was born in TypeScript

The TypeScript @modelcontextprotocol/sdk was the first official SDK. It has the most complete API surface, the most detailed documentation, and the most polished reference examples. When Anthropic builds a new official MCP server, it does so in TypeScript first.

2. Zod as the validation standard

Zod is the validation library the SDK uses to define tool schemas. It's not a wrapper over JSON Schema — it's a typed validation library that generates JSON Schema automatically. This means:

// With Zod: typed definition + validation + JSON Schema, all in one
{
  filePath: z.string().describe("Path of the file"),
  content: z.string().min(1).describe("Content"),
  overwrite: z.boolean().default(false),
}

// Equivalent in manual JSON Schema:
{
  "type": "object",
  "properties": {
    "filePath": { "type": "string", "description": "Path of the file" },
    "content": { "type": "string", "minLength": 1, "description": "Content" },
    "overwrite": { "type": "boolean", "default": false }
  },
  "required": ["filePath", "content"]
}

Zod is more concise, more readable, and gives you runtime validation for free. You'll see this in detail in capsule 03.

3. The Node.js ecosystem is the natural match

MCP servers need filesystem access, process execution, networking. Node.js has mature APIs for all of this. Also, many integrations an MCP server needs (GitHub API, Slack API, database clients) have first-class SDKs in JavaScript/TypeScript.

4. TypeScript strict mode catches errors before runtime

When you use strict: true in your tsconfig.json, TypeScript catches a whole category of errors that in JavaScript or Python only appear when the code runs:

// ❌ TypeScript strict mode detects it at compile time
function processResult(result: ToolResult) {
  console.log(result.content[0].text.toUpperCase());
  //                               ^^^^ Error: 'text' is possibly undefined
}

// ✅ The fix is explicit
function processResult(result: ToolResult) {
  const text = result.content[0]?.text;
  if (text) {
    console.log(text.toUpperCase());
  }
}

In an MCP server, where inputs come from a language model and outputs go to a protocol with a strict format, this level of type safety prevents real bugs.

Comparison: TypeScript vs Python for MCP servers

AspectTypeScript SDKPython SDK
MaturityMore mature, more complete APIMature, evolving API
ValidationZod (typed + runtime)Pydantic / type hints
StyleMethods: server.tool()Decorators: @server.tool()
ConcurrencyNative event loop (Node.js)asyncio
EcosystemMore reference MCP serversMore ML/AI libraries
CommunityDominant in MCP serversDominant in AI/ML apps
Setupnpm + tsconfigpip + venv
Error handlingtry/catch + isErrortry/except + raise

The choice isn't "one is better than the other" — it's "which fits your use case better." For MCP servers, TypeScript has the edge because of the ecosystem. For integrating with ML pipelines, Python has the edge. You'll learn both.

What the community says

If you review the most popular MCP server repositories, the pattern is clear:

  • Filesystem Server (Anthropic) → TypeScript
  • GitHub Server (Anthropic) → TypeScript
  • Slack Server (Anthropic) → TypeScript
  • PostgreSQL Server (community) → TypeScript
  • Brave Search Server (community) → TypeScript

Anthropic's official servers are all in TypeScript. The most maintained community servers tend to be in TypeScript. This doesn't mean Python is worse — it means that when you look for examples, documentation, or servers to study, TypeScript will be your first resource.

The Zod factor

Zod deserves special mention because it's more than a validation library — it's the runtime type system of the MCP ecosystem in TypeScript. When you define a Zod schema for a tool:

  1. TypeScript infers the handler's types automatically
  2. The SDK generates JSON Schema for the MCP protocol
  3. Validation happens at runtime before your code runs
  4. Validation errors are automatically formatted for the model

This means a single Zod schema solves three problems: typing, validation, and protocol documentation. In Python, you need to combine type hints (typing), Pydantic (validation), and docstrings (documentation) to achieve the same.

It's not that Python is inferior — FastMCP's decorators are elegant and concise. But Zod offers a more integrated experience for the specific case of MCP servers.


Module objective

By the end of this module, you'll be able to:

  • ✅ Create an MCP project in TypeScript from scratch — npm init, dependencies, tsconfig, structure
  • ✅ Implement multiple tools with Zod schemas that validate inputs automatically
  • ✅ Implement static and dynamic resources with URI templates
  • ✅ Understand and configure transports — stdio for local development, HTTP/SSE for remote use
  • ✅ Handle robust error handling in tools and resources
  • ✅ Build a complete MCP server with multiple tools for a real use case
  • ✅ Connect your server to Claude Code and verify that it works end-to-end

The jump from module 3 to module 4

So you understand the magnitude of the progress:

Module 3 — Minimal server:
├── 1 file (src/index.ts)
├── 1 resource (static)
├── 1 tool (basic)
├── 1 prompt (simple)
├── Trivial Zod schemas
├── No project structure
├── Only stdio
└── ~150 lines of code

Module 4 — Complete server:
├── Professional project structure
├── Multiple resources (static + templates)
├── Multiple tools (with full validation)
├── Advanced Zod schemas (enums, arrays, nested objects)
├── Robust error handling
├── Transports: stdio + HTTP/SSE + Streamable HTTP
├── Modular and maintainable code
└── ~500+ lines of code

Don't worry about the magnitude — you go step by step. Each capsule adds a piece, and at the end everything fits together.


Module roadmap

CapsuleTopicWhat you'll learn
02Project and SDK setupCreate a project from scratch: npm, TypeScript, dependencies, structure
03Implement ToolsTools with Zod schemas: basic, complex, with error handling
04Implement ResourcesStatic resources, dynamic ones, URI templates, discovery
05Transports: stdio and HTTPConfigure stdio for local, HTTP/SSE for remote, when to use each
06Project: TS MCP ServerComplete server with multiple tools for a real use case

Learning flow

The progression is deliberate:

  1. Setup (capsule 02) — first things first: a project that compiles and runs. Without this, nothing else works.
  2. Tools (capsule 03) — the most important primitive. Here you spend 80% of the implementation time of a real MCP server.
  3. Resources (capsule 04) — contextual data with URI templates. They complement the tools and make your server richer.
  4. Transports (capsule 05) — how your server communicates with the host. It determines where and how it runs.
  5. Project (capsule 06) — everything together: a complete MCP server you could use in your real work.

Each capsule is ~40% theory and ~60% practice. You're going to write a lot of code.


Connection to the capstone project (Module 8)

The server you build in capsule 06 of this module is the prototype of the capstone project in Module 8. The patterns are the same:

Module 4 → Module 8:
├── Project setup             → Same pattern, more dependencies
├── Zod schemas               → Same library, more complex schemas
├── Error handling            → Same patterns, more edge cases
├── Resources with templates  → Same API, connected to a real DB
├── Tools with validation     → Same patterns, more complex operations
└── Transport configuration   → Same setup, possible remote deploy

Every decision you make in this module — how you structure your code, how you define your schemas, how you handle errors — you'll use directly in the final project. You're not learning something temporary; you're building habits you'll apply in every MCP server you create.


Prerequisites

For this module you need:

  • ✅ Node.js v18+ installed — node --version
  • ✅ npm installed — npm --version
  • ✅ Claude Code installed and working — claude --version
  • ✅ A code editor with TypeScript support (VS Code, Cursor, etc.)
  • ✅ Modules 1-3 completed — especially the module 3 mini-project

TypeScript knowledge needed

You don't need to be a TypeScript expert. What you need to know:

// Typed variables
const name: string = "hello";
const count: number = 42;
const items: string[] = ["a", "b"];

// Interfaces / types
interface User {
  id: string;
  name: string;
  email: string;
}

// Async functions
async function getData(): Promise<string> {
  const result = await fetch("...");
  return result.text();
}

// Imports/exports
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
export function helper() { ... }

If this looks familiar, you're ready. If not, you can learn as you go — the examples are self-explanatory.


Boundaries: what is NOT covered in this module

  • ❌ Implementation in Python — That comes in module 5
  • ❌ MCP Apps with UI — Covered in module 6
  • ❌ Automated testing — Covered in module 7
  • ❌ Deploy to production — Covered in module 8
  • ❌ Sampling (server-initiated LLM calls) — Advanced feature outside the scope of this guide
  • ❌ MCP Roots — A context feature the host can send, mentioned but not implemented

This module is pure construction. You're building the "how to do it in TypeScript" after having understood the "what it can do" in the previous modules.


Signs of success

By the end of this module, you'll know you succeeded if:

  • ✅ You can create an MCP project in TypeScript from scratch in less than 5 minutes
  • ✅ Your tools have Zod schemas that validate inputs automatically
  • ✅ You can implement resources with URI templates that are discovered dynamically
  • ✅ You understand when to use stdio vs HTTP/SSE and can configure both
  • ✅ You have a functional MCP server with multiple tools connected to Claude Code
  • ✅ You feel comfortable reading open source MCP server code in TypeScript
  • ✅ You're ready to implement the same in Python (module 5) or scale to the final project (module 8)

Mindset for this module

This module is a workshop. It's not a lecture where you listen passively. The ratio is ~80% code, ~20% explanation. Each concept is demonstrated with runnable code you can copy, compile, and test.

Four principles to get the most out of it:

  1. Write the code, don't just read it mentally. The difference between reading code and writing it is enormous. Write each example, compile, run. The compilation errors you find are part of the learning.

  2. Test with MCP Inspector before Claude Code. The Inspector gives you immediate and visual feedback. Claude Code is the final destination, but the Inspector is your development tool.

  3. Break things on purpose. What happens if you send a string where Zod expects a number? What happens if the resource points to a file that doesn't exist? What happens if the transport doesn't connect? Discovering the failure modes teaches you more than just following the happy path.

  4. Read the code of existing servers. When you finish each capsule, open an open source MCP server on GitHub and look for the same patterns. Seeing how other developers implement tools and resources solidifies your understanding.


Frequently asked questions before starting

"Do I need to know TypeScript for this module?"

You need the basics: types, interfaces, async/await, imports. You don't need to know advanced generics, mapped types, or conditional types. The examples are self-explanatory and the focus is on the MCP patterns, not on advanced TypeScript.

"Can I jump straight to module 5 (Python)?"

You can, but I don't recommend it. The concepts are explained in more depth here because TypeScript is the main module. Module 5 assumes you already understand the patterns from this module and focuses on Python's idiomatic differences.

"Is my server from module 3 still useful?"

Yes. In fact, you can use your module 3 server as a reference while you build this module's. You're going to see the same patterns, but more complete and robust.

"How much code am I going to write?"

The capsule 06 project has ~500+ lines distributed across several files. You don't write them all at once — each capsule adds a piece. At the end, everything integrates.

"Do I need an IDE with TypeScript support?"

Highly recommended. VS Code or Cursor with the TypeScript Language Server give you autocompletion, real-time error detection, and code navigation. If you don't use an IDE with TS support, compilation errors are your only feedback — it's slower but it works.


Tools you'll use in this module

ToolWhat you use it for
Node.jsRuntime of your MCP server
npmDependency management
TypeScript (tsc)Compiler — converts .ts to .js
@modelcontextprotocol/sdkOfficial SDK to create MCP servers
ZodSchema validation for tools
MCP InspectorVisual testing of your server (tools, resources, prompts)
Claude CodeThe host that consumes your MCP server
VS Code / CursorRecommended IDE with TypeScript support

You don't need to install everything now — capsule 02 guides you step by step.


Summary

  • This module marks the start of Phase 2: Build MCP Servers
  • TypeScript is the dominant language of the MCP ecosystem — the most mature SDK, more reference servers, Zod for validation
  • You go from a minimal server (1 file, 3 primitives) to a professional server (project structure, complex schemas, transports)
  • The capsules follow an arc: Setup → Tools → Resources → Transports → Project
  • The patterns you learn here apply directly to the capstone project in Module 8
  • This module is ~80% code — it's a workshop, not a lecture
  • TypeScript first isn't an arbitrary preference — it's where the ecosystem, the documentation, and the reference examples are

Additional resources

  1. MCP TypeScript SDK - Official SDK you'll use throughout the module
  2. Zod Documentation - Validation library for tool schemas
  3. TypeScript Handbook - TypeScript reference if you need a refresher
  4. MCP Specification - Official protocol specification
  5. MCP Inspector - Visual testing and debugging tool
  6. Awesome MCP Servers - Directory of community MCP servers (most in TypeScript)
  7. Node.js fs/promises API - Filesystem API you'll use frequently
  8. Official MCP Servers (Anthropic) - Reference servers implemented in TypeScript

Next capsule: Project and SDK setup — create an MCP project in TypeScript from scratch, configured and ready to implement tools and resources.