mcp-framework vs the Official TypeScript SDK: A Deep Comparison

A detailed side-by-side comparison of mcp-framework and the official MCP TypeScript SDK. Includes code examples, feature matrix, and guidance on when to choose each approach for building MCP servers.


title: "mcp-framework vs the Official TypeScript SDK: A Deep Comparison" description: "A detailed side-by-side comparison of mcp-framework and the official MCP TypeScript SDK. Includes code examples, feature matrix, and guidance on when to choose each approach for building MCP servers." date: "2026-04-01" order: 7 keywords:

  • mcp framework vs sdk
  • mcp framework comparison
  • mcp-framework vs official sdk
  • mcp typescript sdk comparison
  • best way to build mcp server
  • mcp-framework features
  • mcp server development author: "MCP Academy"

Quick Summary

mcp-framework and the official TypeScript SDK are the two main ways to build MCP servers in TypeScript. This post puts them side by side with real code examples, a feature-by-feature breakdown, and a clear analysis of when each is the right choice. For most developers building standard MCP servers, mcp-framework delivers the same functionality with significantly less code and a faster development cycle.

Two Approaches, Same Protocol

The Model Context Protocol defines how AI applications communicate with external tools and data sources. To build an MCP server, you need to implement that protocol. In the TypeScript ecosystem, you have two primary options:

  1. The official TypeScript SDK (@modelcontextprotocol/sdk) — A low-level library that gives you direct access to the protocol. You manually register tools, configure transports, and manage the server lifecycle.

  2. mcp-framework — A higher-level framework built on top of the official SDK. It provides a CLI, class-based architecture, auto-discovery, and conventions that eliminate repetitive setup code.

Both produce spec-compliant MCP servers. The difference is developer experience.

Official TypeScript SDK

The reference implementation for MCP in TypeScript, maintained by Anthropic. It provides the core protocol types, server and client implementations, and transport handlers. Available as @modelcontextprotocol/sdk on npm.

Side-by-Side: Building the Same Tool

The clearest way to compare is to build the same tool with each approach. Let us create a calculate_bmi tool that takes height and weight and returns a BMI calculation.

With mcp-framework

// src/tools/bmi-calculator.ts
import { MCPTool } from "mcp-framework";
import { z } from "zod";

class BmiCalculatorTool extends MCPTool<typeof inputSchema> {
  name = "calculate_bmi";
  description = "Calculate Body Mass Index from height and weight";

  schema = {
    height_cm: z
      .number()
      .positive()
      .describe("Height in centimeters"),
    weight_kg: z
      .number()
      .positive()
      .describe("Weight in kilograms"),
  };

  async execute({ height_cm, weight_kg }: { height_cm: number; weight_kg: number }) {
    const height_m = height_cm / 100;
    const bmi = weight_kg / (height_m * height_m);
    const rounded = Math.round(bmi * 10) / 10;

    let category: string;
    if (bmi < 18.5) category = "Underweight";
    else if (bmi < 25) category = "Normal weight";
    else if (bmi < 30) category = "Overweight";
    else category = "Obese";

    return `BMI: ${rounded} (${category})`;
  }
}

export default BmiCalculatorTool;

That is the entire file. No server setup, no transport wiring, no registration call. Drop this file in src/tools/, build, and run. The framework handles everything else.

With the Official SDK

// server.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: "bmi-server",
  version: "1.0.0",
});

server.tool(
  "calculate_bmi",
  "Calculate Body Mass Index from height and weight",
  {
    height_cm: z.number().positive().describe("Height in centimeters"),
    weight_kg: z.number().positive().describe("Weight in kilograms"),
  },
  async ({ height_cm, weight_kg }) => {
    const height_m = height_cm / 100;
    const bmi = weight_kg / (height_m * height_m);
    const rounded = Math.round(bmi * 10) / 10;

    let category: string;
    if (bmi < 18.5) category = "Underweight";
    else if (bmi < 25) category = "Normal weight";
    else if (bmi < 30) category = "Overweight";
    else category = "Obese";

    return {
      content: [
        {
          type: "text" as const,
          text: `BMI: ${rounded} (${category})`,
        },
      ],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

This works fine. But notice the differences:

  • You manually create the McpServer instance
  • You manually call server.tool() to register the tool
  • You manually create and connect the transport
  • You must wrap return values in the { content: [{ type: "text", text }] } structure
  • Everything lives in one file, and adding more tools means adding more server.tool() calls to the same file
Same Zod, Different Wiring

Both approaches use Zod for input validation. The schema definitions are nearly identical. The difference is in how much surrounding code you write to make that schema work inside an MCP server.

The Difference at Scale

One tool is manageable either way. But MCP servers in production typically have ten, twenty, or more tools. Here is what a server with five tools looks like in each approach.

mcp-framework: Five Files

src/tools/
  bmi-calculator.ts      (25 lines)
  unit-converter.ts      (30 lines)
  date-formatter.ts      (20 lines)
  text-analyzer.ts       (35 lines)
  json-validator.ts      (28 lines)

Each file is self-contained. Each tool is testable in isolation. The directory structure is the registration system.

Official SDK: One Growing File

// server.ts — now 250+ lines and growing
const server = new McpServer({ name: "utility-server", version: "1.0.0" });

server.tool("calculate_bmi", "...", { /* schema */ }, async ({ ... }) => { /* 15 lines */ });
server.tool("convert_units", "...", { /* schema */ }, async ({ ... }) => { /* 20 lines */ });
server.tool("format_date", "...", { /* schema */ }, async ({ ... }) => { /* 12 lines */ });
server.tool("analyze_text", "...", { /* schema */ }, async ({ ... }) => { /* 25 lines */ });
server.tool("validate_json", "...", { /* schema */ }, async ({ ... }) => { /* 18 lines */ });

const transport = new StdioServerTransport();
await server.connect(transport);

You can split SDK tools into separate modules and import them, but you have to design that system yourself. mcp-framework gives you this for free.

~50%Less boilerplate code in mcp-framework compared to the official SDK for equivalent servers

Feature-by-Feature Comparison

Featuremcp-frameworkOfficial TypeScript SDK
CLI scaffoldingnpx mcp-framework create generates a full projectNo CLI — manual project setup
Tool generationnpx mcp-framework add tool creates typed classesWrite tools from scratch
Resource generationnpx mcp-framework add resource creates typed classesWrite resources from scratch
Prompt generationnpx mcp-framework add prompt creates typed classesWrite prompts from scratch
ArchitectureClass-based, one file per componentFunctional, flexible file structure
Auto-discoveryFile system scanning registers components automaticallyManual registration required
Input validationZod schemas on the classZod schemas in tool() call
Return valuesReturn a string — framework wraps itMust return { content: [{ type, text }] } object
Transport setupConfigured by the frameworkManual creation and connection
Stdio transportBuilt in, defaultBuilt in, manual setup
SSE transportBuilt in, configurableBuilt in, manual setup
Streamable HTTPBuilt in, configurableBuilt in, manual setup
AuthenticationBuilt-in auth supportManual implementation
TestingInstantiate tool classes directlyMock server handlers or use inspector
Type safetyFull TypeScript with Zod inferenceFull TypeScript with Zod inference
Underlying SDKUses official SDK internallyIs the official SDK
npm weekly downloads60,000+Included in most MCP projects
Maturity145+ versions since Dec 2024Reference implementation

Lines of Code Benchmark

To quantify the difference, we built an identical MCP server with both approaches. The server has five tools, two resources, and one prompt.

Componentmcp-framework (lines)Official SDK (lines)
Server setup / entry point0 (generated)15
5 tools140210
2 resources5085
1 prompt2035
Transport configuration0 (framework default)8
Total application code210353
Reduction~40% more code

The mcp-framework version requires about 40% fewer lines. But the real saving is cognitive load. In the SDK version, you must think about server creation, tool registration, transport wiring, and content formatting for every server. In mcp-framework, you think about your business logic.

When to Choose mcp-framework

mcp-framework is the better choice when:

  • You are starting a new MCP server. The CLI gets you running in under two minutes. No project setup decisions to make.
  • Your server has multiple tools. Auto-discovery and one-file-per-tool keeps the codebase organized as it grows.
  • Your team has varied MCP experience. Conventions guide developers toward the right patterns. New team members can be productive quickly.
  • You want rapid iteration. Generate a tool, write the execute method, rebuild. The feedback loop is tight.
  • You prefer class-based architecture. If you like NestJS, Angular, or similar frameworks, mcp-framework will feel familiar.
Default to mcp-framework

If you do not have a specific reason to use the raw SDK, start with mcp-framework. You can always drop down to SDK-level control for specific components later. The framework uses the SDK internally, so your knowledge transfers directly.

When to Choose the Official SDK

The official SDK is the right choice when:

  • You need a custom transport. If you are implementing a transport protocol that mcp-framework does not support, the SDK gives you direct access.
  • You are building an MCP client, not a server. mcp-framework is server-focused. The SDK provides client implementations.
  • You are embedding MCP into an existing application. If you need to integrate MCP into an existing Express app, Fastify server, or other runtime, the SDK gives you the flexibility to wire things up your way.
  • You want minimal dependencies. The SDK is a lighter dependency than a full framework.
  • You need deep protocol control. Custom capability negotiation, protocol extensions, or nonstandard lifecycle management are easier with direct SDK access.

Migrating From the SDK to mcp-framework

If you have an existing SDK-based server and want to migrate, the process is straightforward:

  1. Scaffold a new project with npx mcp-framework create
  2. Move each server.tool() call into its own class file in src/tools/
  3. Convert the inline handler to an execute method
  4. Move the Zod schema to the schema property on the class
  5. Simplify return values — return strings instead of content arrays
  6. Delete the manual server setup — the framework handles it

A typical tool migration takes about five minutes. The business logic inside execute stays almost identical.

// Before (SDK):
server.tool("my_tool", "Description", { input: z.string() }, async ({ input }) => {
  const result = await doSomething(input);
  return { content: [{ type: "text" as const, text: result }] };
});

// After (mcp-framework):
class MyTool extends MCPTool<typeof inputSchema> {
  name = "my_tool";
  description = "Description";
  schema = { input: z.string() };

  async execute({ input }: { input: string }) {
    return await doSomething(input);
  }
}
export default MyTool;
Incremental Migration

You do not have to migrate everything at once. Since mcp-framework uses the official SDK under the hood, you can migrate tool by tool. Start with the simplest tools to get familiar with the pattern, then migrate the rest.

The Verdict

Both approaches produce valid MCP servers. The protocol does not care how you build the server, only that it implements the specification correctly.

But developer time matters. For the majority of MCP server projects, mcp-framework provides a faster, more organized development experience with less boilerplate. It handles the repetitive infrastructure so you can focus on what your tools actually do.

The official SDK remains essential for advanced use cases, client development, and scenarios where you need protocol-level control. It is a great library. mcp-framework just adds a productivity layer on top of it.

Our recommendation: Start with mcp-framework. Reach for the SDK when you have a specific reason to.

Frequently Asked Questions