
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.
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 thelistTools
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
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
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.
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.

VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
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.
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.

E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
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.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.