MCP HubMCP Hub
QuantGeekDev

mcp-framework

by: QuantGeekDev

A framework for writing modelcontextprotocol (MCP) servers in Typescript

578created 08/12/2024
Visit
Typescript
framework

📌Overview

Purpose: The MCP Framework aims to provide an elegant way to build Model Context Protocol (MCP) servers using TypeScript.

Overview: MCP-Framework offers a robust structure for developing MCP servers, featuring automatic discovery of tools, resources, and prompts along with a command-line interface (CLI) that simplifies server setup. It utilizes TypeScript for type safety and is built on the official MCP SDK, enabling developers to create powerful applications with minimal effort.

Key Features:

  • Automatic Discovery: Automatically discovers and loads tools, resources, and prompts, streamlining the development process.

  • Multiple Transport Support: Offers flexibility with transport options such as stdio, Server-Sent Events (SSE), and HTTP Stream for varied communication needs.

  • TypeScript-first Development: Ensures full type safety, enhancing code quality and reducing runtime errors.

  • Base Classes for Abstractions: Provides easy-to-use base classes for defining tools, resources, and prompts efficiently.

  • Out-of-the-box Authentication: Includes built-in authentication mechanisms, particularly for SSE endpoints, ensuring secure interactions.


MCP Framework

MCP-Framework is a TypeScript framework for building Model Context Protocol (MCP) servers elegantly. It offers architecture out of the box, including automatic directory-based discovery for tools, resources, and prompts. The framework provides powerful MCP abstractions to define these components elegantly, and a CLI for easy project setup.

Features

  • Automatic discovery and loading of tools, resources, and prompts
  • Multiple transport support (stdio, SSE, HTTP Stream)
  • TypeScript-first development with full type safety
  • Built on the official MCP SDK
  • Easy-to-use base classes for tools, prompts, and resources
  • Out of the box authentication for SSE endpoints

Documentation

Read the full docs here.


Getting Started

Creating a Repository with MCP Framework

Using the CLI (Recommended)

# Install the framework globally
npm install -g mcp-framework

# Create a new MCP server project
mcp create my-mcp-server

# Navigate to your project
cd my-mcp-server

# Your server is ready to use!

CLI Usage Overview

  • Create a new project:

    mcp create <project-name>
    
  • Create a new project with HTTP transport:

    mcp create <project-name> --http --port 1337 --cors
    

    Options:

    • --http: Use HTTP transport instead of default stdio
    • --port <number>: Specify HTTP port (default: 8080)
    • --cors: Enable CORS with wildcard (*) access
  • Add a new tool:

    mcp add tool <tool-name>
    
  • Add a new prompt:

    mcp add prompt <prompt-name>
    
  • Add a new resource:

    mcp add resource <resource-name>
    

Development Workflow

  1. Create your project and navigate into it:

    mcp create my-mcp-server
    cd my-mcp-server
    
  2. Add tools as needed:

    mcp add tool data-fetcher
    mcp add tool data-processor
    mcp add tool report-generator
    
  3. Build your project:

    npm run build
    
  4. Add to MCP Client (see below for Claude Desktop example).


Using With Claude Desktop

Local Development

Add this configuration to your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "${projectName}": {
      "command": "node",
      "args": ["/absolute/path/to/${projectName}/dist/index.js"]
    }
  }
}

After Publishing

Add this configuration to your Claude Desktop config file:

{
  "mcpServers": {
    "${projectName}": {
      "command": "npx",
      "args": ["${projectName}"]
    }
  }
}

Building and Testing

  1. Make changes to your tools
  2. Run npm run build to compile
  3. Server will automatically load your tools on startup

Environment Variables

The framework supports the following environment variables:

VariableDescriptionDefault
MCP_ENABLE_FILE_LOGGINGEnable logging to files (true/false)false
MCP_LOG_DIRECTORYDirectory where log files will be storedlogs
MCP_DEBUG_CONSOLEDisplay debug messages in console (true/false)false

Example usage:

# Enable file logging and debug console
MCP_ENABLE_FILE_LOGGING=true MCP_DEBUG_CONSOLE=true node dist/index.js

# Specify a custom log directory
MCP_ENABLE_FILE_LOGGING=true MCP_LOG_DIRECTORY=my-logs node dist/index.js

Quick Start

Creating a Tool

import { MCPTool } from "mcp-framework";
import { z } from "zod";

interface ExampleInput {
  message: string;
}

class ExampleTool extends MCPTool<ExampleInput> {
  name = "example_tool";
  description = "An example tool that processes messages";

  schema = {
    message: {
      type: z.string(),
      description: "Message to process",
    },
  };

  async execute(input: ExampleInput) {
    return `Processed: ${input.message}`;
  }
}

export default ExampleTool;

Setting Up the Server

import { MCPServer } from "mcp-framework";

// Using default stdio transport
const server = new MCPServer();

// Or with SSE transport
const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      port: 8080 // Optional, default is 8080
    }
  }
});

// Start the server
await server.start();

Transport Configuration

stdio Transport (Default)

const server = new MCPServer();
// or explicitly:
const server = new MCPServer({
  transport: { type: "stdio" }
});

SSE Transport

const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      port: 8080,
      endpoint: "/sse",                    // default "/sse"
      messageEndpoint: "/messages",        // default "/messages"
      cors: {
        allowOrigin: "*",
        allowMethods: "GET, POST, OPTIONS",
        allowHeaders: "Content-Type, Authorization, x-api-key",
        exposeHeaders: "Content-Type, Authorization, x-api-key",
        maxAge: "86400"
      }
    }
  }
});

HTTP Stream Transport

const server = new MCPServer({
  transport: {
    type: "http-stream",
    options: {
      port: 8080,
      endpoint: "/mcp",
      responseMode: "batch",       // "batch" or "stream"
      batchTimeout: 30000,          // 30 seconds timeout
      maxMessageSize: "4mb",
      session: {
        enabled: true,
        headerName: "Mcp-Session-Id",
        allowClientTermination: true,
      },
      resumability: {
        enabled: false,
        historyDuration: 300000,    // 5 minutes
      },
      cors: {
        allowOrigin: "*"
      }
    }
  }
});

Response Modes

  • Batch Mode (default): Sends all responses as a single JSON-RPC batch response.
  • Stream Mode: Sends responses over a persistent SSE connection per request, ideal for long-running or multi-message responses.

Example configuring response modes:

// Batch mode
const server = new MCPServer({
  transport: {
    type: "http-stream",
    options: { responseMode: "batch" }
  }
});

// Stream mode
const server = new MCPServer({
  transport: {
    type: "http-stream",
    options: { responseMode: "stream" }
  }
});

HTTP Stream Transport Features

  • Session management
  • Stream resumability (optional)
  • JSON-RPC batch processing
  • Comprehensive error handling with JSON-RPC codes

Authentication

MCP Framework provides optional authentication for SSE endpoints. Supported options include JWT, API Key, or custom authentication providers.

JWT Authentication Example

import { MCPServer, JWTAuthProvider } from "mcp-framework";
import { Algorithm } from "jsonwebtoken";

const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      auth: {
        provider: new JWTAuthProvider({
          secret: process.env.JWT_SECRET,
          algorithms: ["HS256" as Algorithm], // default ["HS256"]
          headerName: "Authorization"         // default "Authorization"
        }),
        endpoints: {
          sse: true,      // Protect SSE endpoint (default false)
          messages: true  // Protect message endpoint (default true)
        }
      }
    }
  }
});

Clients must include a valid JWT token in the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

API Key Authentication Example

import { MCPServer, APIKeyAuthProvider } from "mcp-framework";

const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      auth: {
        provider: new APIKeyAuthProvider({
          keys: [process.env.API_KEY],
          headerName: "X-API-Key" // default "X-API-Key"
        })
      }
    }
  }
});

Clients must include a valid API key in the X-API-Key header:

X-API-Key: your-api-key

Custom Authentication Provider Example

Implement your own provider by implementing the AuthProvider interface:

import { AuthProvider, AuthResult } from "mcp-framework";
import { IncomingMessage } from "node:http";

class CustomAuthProvider implements AuthProvider {
  async authenticate(req: IncomingMessage): Promise<boolean | AuthResult> {
    // Your authentication logic here
    return true;
  }

  getAuthError() {
    return {
      status: 401,
      message: "Authentication failed"
    };
  }
}

License

MIT