NestJS MCP Server Module

NestJS MCP Server Module

A NestJS module that allows services to be exposed as an MCP server with Server-Sent Events transport, facilitating tool discovery and execution by clients.

Category
Visit Server

README

NestJS MCP Server Module

A NestJS module for exposing your services as an MCP (Model Context Protocol) server with Server-Sent Events (SSE) transport. This package simplifies exposing tools that clients can discover and execute via SSE.

Features

  • SSE Transport: Built-in /sse endpoint for streaming and /messages for handling tool execution
  • Tool Discovery: Automatically discover and register tools using decorators
  • Tool Request Validation: Define Zod schemas to validate tool requests.
  • Progress Notifications: Send continuous progress updates from tools to clients.
  • Authentication: Integrates with NestJS Guards for securing endpoints.

Installation

npm install @rekog/mcp-nest reflect-metadata @modelcontextprotocol/sdk zod @nestjs/common @nestjs/core

Quick Start

1. Import Module

// app.module.ts
import { Module } from '@nestjs/common';
import { McpModule } from '@rekog/mcp-nest';
import { GreetingTool } from './greeting.tool';

@Module({
  imports: [
    McpModule.forRoot({
      name: 'my-mcp-server',
      version: '1.0.0',
    })
  ],
  providers: [GreetingTool]
})
export class AppModule {}

2. Define Tools

// greeting.tool.ts
import { Injectable } from '@nestjs/common';
import { Tool, Context } from '@rekog/mcp-nest';
import { z } from 'zod';
import { Progress } from '@modelcontextprotocol/sdk/types';

@Injectable()
export class GreetingTool {
  constructor() {}

  @Tool({
    name: 'hello-world',
    description:
      'Returns a greeting and simulates a long operation with progress updates',
    parameters: z.object({
      name: z.string().default('World'),
    }),
  })
  async sayHello({ name }, context: Context) {
    const greeting = `Hello, ${name}!`;

    const totalSteps = 5;
    for (let i = 0; i < totalSteps; i++) {
      await new Promise((resolve) => setTimeout(resolve, 500));

      // Send a progress update.
      await context.reportProgress({
        progress: (i + 1) * 20,
        total: 100,
      } as Progress);
    }

    return {
      content: [{ type: 'text', text: greeting }],
    };
  }
}

You are done!

Authentication

You can secure your MCP endpoints using standard NestJS Guards.

1. Create a Guard

Implement the CanActivate interface. The guard should handle request validation (e.g., checking JWTs, API keys) and optionally attach user information to the request object. <details> <summary>Example Guard Implementation</summary>

// auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    const authorization = request.headers.authorization;

    // Example: Check for a specific Bearer token
    if (authorization && authorization.startsWith('Bearer ')) {
      const token = authorization.substring(7);
      if (token === 'your-secret-token') {
        // Attach user info if needed (optional)
        request.user = { id: 'user-123', roles: ['admin'] };
        return true; // Allow access
      }
    }

    return false; // Deny access
  }
}

</details>

2. Apply the Guard

Pass your guard(s) to the McpModule.forRoot configuration. The guard(s) will be applied to both the /sse and /messages endpoints.

// app.module.ts
import { Module } from '@nestjs/common';
import { McpModule } from '@rekog/mcp-nest';
import { GreetingTool } from './greeting.tool';
import { AuthGuard } from './auth.guard';

@Module({
  imports: [
    McpModule.forRoot({
      name: 'my-mcp-server',
      version: '1.0.0',
      guards: [AuthGuard] // Apply the guard here
    })
  ],
  providers: [GreetingTool, AuthGuard] // Ensure the Guard is also provided
})
export class AppModule {}

3. Access User Context in Tools (Optional)

If your guard attaches user information to the request object (e.g., request.user = ...), you can access it in your tool as the third parameter.

// authenticated-greeting.tool.ts
import { Injectable } from '@nestjs/common';
import { Tool, Context } from '@rekog/mcp-nest';
import { z } from 'zod';
import { Request } from 'express'; // Import Request from express

@Injectable()
export class AuthenticatedGreetingTool {

  @Tool({
    name: 'auth-hello-world',
    description: 'Greets the authenticated user',
    parameters: z.object({}), // No parameters needed for this example
  })
  // Add 'request' as the third parameter
  async sayAuthHello(args: {}, context: Context, request: Request & { user?: { id: string } }) {
    const userId = request.user?.id || 'Anonymous';
    const greeting = `Hello, user ${userId}!`;

    return {
      content: [{ type: 'text', text: greeting }],
    };
  }
}

Note: Ensure your tool (AuthenticatedGreetingTool in this example) is added to the providers array in your AppModule.

Client Connection

Clients need to provide the necessary credentials (e.g., Authorization header) when connecting if authentication is enabled.

Unauthenticated Client

// client.ts (no authentication)
import { Client } from '@modelcontextprotocol/sdk/client';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse';

const client = new Client(
  { name: 'client-name', version: '1.0.0' },
  { capabilities: {} }
);

await client.connect(
  new SSEClientTransport(new URL('http://localhost:3000/sse'))
);

// ... list tools, call tools etc.

Authenticated Client

Pass request options (like headers) to the SSEClientTransport.

// client.ts (with authentication)
import { Client } from '@modelcontextprotocol/sdk/client';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse';

const client = new Client(
  { name: 'client-name', version: '1.0.0' },
  { capabilities: {} }
);

const transport = new SSEClientTransport(
  new URL('http://localhost:3000/sse'),
  {
    // Provide necessary credentials here
    requestInit: {
      headers: {
        Authorization: 'Bearer your-secret-token' // Match guard expectation
      }
    }
  }
);

await client.connect(transport);


// Execute the 'auth-hello-world' tool
const greetResult = await client.callTool(
  {
    name: 'auth-hello-world',
    arguments: {},
  },
  undefined, // responseSchema is optional
  {
    onprogress: (progress) => { // Example progress handler
      console.log(
        `Progress: ${progress.progress}/${progress.total}`
      );
    },
  },
);

console.log(greetResult.content[0].text); // Output: Hello, user user-123!

API Endpoints

  • GET /sse: SSE connection endpoint (Protected by guards if configured)
  • POST /messages: Tool execution endpoint (Protected by guards if configured)

Configuration Reference

McpOptions

Property Type Description Default Value
name string Server name -
version string Server version -
capabilities Record<string, any> Server capabilities, defines what the server can do. {}
guards any[] (NestJS Guards) An array of NestJS Guards to apply to the MCP endpoints. []
sseEndpoint string (optional) Endpoint for SSE connections. 'sse'
messagesEndpoint string (optional) Endpoint for handling tool execution. 'messages'
globalApiPrefix string (optional) Global API prefix for all endpoints. ''

Tool Decorator

The @Tool decorator is used to define a method as an MCP tool.

@Tool({ name: string, description: string, parameters?: z.ZodObject<any> })
  • name: The name of the tool. This will be used to list it in the listTools request.
  • description: A description of the tool.
  • parameters: (Optional) A Zod schema defining the expected structure of the tool's input arguments.

Context Parameter

The second parameter passed to a @Tool decorated method is the Context object.

  • context.reportProgress(progress: Progress): Sends a progress update message to the client. Progress typically has { progress: number, total: number }.

Request Paramter

The third parameter passed to a @Tool decorated method is the Request object.

  • request: The request object from the underlying HTTP framework (e.g., Express). This can be used to access headers, query parameters, etc.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured