Skip to main content
Glama

NestJS MCP Server Module

by rekog-labs
MIT License
32,416
452
  • Apple
  • Linux
CLAUDE.md9.31 kB
# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. # NestJS MCP Server Module ## Project Overview This is `@rekog/mcp-nest`, a NestJS module that transforms NestJS applications into Model Context Protocol (MCP) servers. It exposes tools, resources, and prompts for AI consumption via decorators, supporting multiple transport protocols (HTTP+SSE, Streamable HTTP, STDIO) with optional OAuth 2.1 authentication. ## Essential Development Commands ### Build, Test & Quality ```bash npm run build # TypeScript compilation with source maps npm test # Jest with experimental VM modules (required for ES modules) npm run test:watch # Jest in watch mode npm run lint # ESLint with automatic fixes npm run format # Prettier formatting for src and tests ``` ### Running Playground Examples ```bash npm run start:playground # Default stateful server (Express) npm run start:fastify # Fastify adapter server npm run test:fastify # Test Fastify client connection ``` ### Single Test Execution ```bash # Run specific test file npx --node-options=--experimental-vm-modules jest tests/mcp-tool.e2e.spec.ts # Run tests matching pattern npx --node-options=--experimental-vm-modules jest --testNamePattern="auth" ``` ## Core Components ### 1. McpModule - The Primary MCP Server Module Located at `src/mcp/mcp.module.ts:18`. This is the main module for creating MCP servers. **Key Features**: - Decorator-based tool/resource/prompt discovery via `McpRegistryService` - Multi-transport support (HTTP+SSE, Streamable HTTP, STDIO) - Dynamic controller generation for different transport types - Module instance isolation with unique `moduleId` per `forRoot()` call **Basic Usage**: ```typescript McpModule.forRoot({ name: 'my-mcp-server', version: '1.0.0', transport: [McpTransportType.SSE, McpTransportType.STREAMABLE_HTTP], guards: [SomeGuard], // Optional authentication }) ``` ### 2. McpAuthModule - OAuth 2.1 Authorization Server Located at `src/authz/mcp-oauth.module.ts:76`. Provides complete OAuth 2.1 compliant Identity Provider implementation. **Key Features**: - Built-in GitHub and Google OAuth providers - Multiple storage backends (memory, TypeORM, custom) - MCP Authorization specification compliance (2025-06-18) - Dynamic client registration (RFC 7591) - PKCE support and comprehensive token validation **Basic Usage**: ```typescript McpAuthModule.forRoot({ provider: GitHubOAuthProvider, clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, jwtSecret: process.env.JWT_SECRET!, serverUrl: 'http://localhost:3030', apiPrefix: 'auth', }) ``` ### 3. Tool Definition Pattern Tools are defined using decorators with three-parameter method signature: ```typescript @Injectable() export class MyService { @Tool({ name: 'my-tool', description: 'Description', parameters: z.object({ name: z.string() }), outputSchema: z.object({ result: z.string() }), // Optional annotations: { readOnlyHint: true } // Optional }) async myTool({ name }, context: Context, request: Request) { await context.reportProgress({ progress: 50, total: 100 }); return { content: [{ type: 'text', text: `Hello ${name}` }] }; } } ``` **Method Parameters**: - `args`: Zod-validated parameters from tool call - `context`: MCP context with `reportProgress`, `mcpServer`, `mcpRequest`, logging - `request`: HTTP request object (undefined for STDIO transport) ### 4. Transport Architecture Three transport types with dynamic controller creation: - **SSE**: `createSseController()` - GET `/sse` + POST `/messages` - **Streamable HTTP**: `createStreamableHttpController()` - POST `/mcp` (+ GET/DELETE for stateful) - **STDIO**: `StdioService` - No HTTP endpoints, uses standard input/output Controllers are generated dynamically in `McpModule.forRoot()` based on transport configuration. ### 5. Module Integration Pattern Both modules work together for authenticated MCP servers: ```typescript @Module({ imports: [ McpAuthModule.forRoot({ /* OAuth config */ }), McpModule.forRoot({ guards: [McpAuthJwtGuard], // Links auth to MCP /* other MCP config */ }), ], providers: [McpAuthJwtGuard], }) class AppModule {} ``` ## Documentation Structure The project maintains comprehensive documentation in the `docs/` directory: ### Core Guides - `docs/tools.md` - Tool creation, parameters, progress reporting, elicitation - `docs/resources.md` - Static and dynamic content serving - `docs/resource-templates.md` - Parameterized resource URIs - `docs/prompts.md` - Reusable prompt templates - `docs/server-examples.md` - Complete server configurations and transport examples - `docs/dependency-injection.md` - NestJS DI patterns within MCP context ### Authorization Documentation - `docs/built-in-authorization-server.md` - Complete McpAuthModule usage and configuration - `docs/external-authorization-server/README.md` - External OAuth server integration ## Key Implementation Details ### Module Instance Isolation Each `McpModule.forRoot()` creates isolated instances with unique `moduleId`: ```typescript const moduleId = `mcp-module-${instanceIdCounter++}`; ``` This enables multiple MCP servers in one application with different capabilities. ### Request Scoping & Discovery - `McpRegistryService` discovers decorated methods at bootstrap using `DiscoveryService` - `McpExecutorService` (REQUEST-scoped) handles per-request tool execution - Registry maintains maps by `mcpModuleId` for isolation ### Output Schema Validation Tools with `outputSchema` validate results, throwing `McpError` on failure: ```typescript if (outputSchema) { const validation = outputSchema.safeParse(result); if (!validation.success) { throw new McpError(ErrorCode.InternalError, `Tool result does not match outputSchema`); } } ``` ### Resource URI Templates Resources use `path-to-regexp` for dynamic URIs: - Static: `uri: 'mcp://hello-world'` - Template: `uriTemplate: 'mcp://hello-world/{userId}/{userName}'` ### OAuth Store Configuration McpAuthModule supports multiple storage backends: - Memory store (default, testing) - TypeORM store (production, with unique connection name to avoid clashes) - Custom store implementation via `IOAuthStore` interface ## Testing Patterns - E2E tests create actual NestJS apps with different transport configurations - Tests run scenarios across HTTP+SSE, Streamable HTTP (stateful/stateless), and STDIO - All tests require `--node-options=--experimental-vm-modules` flag - Use client helpers: `createSseClient()`, `createStreamableClient()`, `createStdioClient()` ## Project Structure ### File Organization - `src/mcp/` - Core MCP functionality (McpModule, transports, services) - `src/authz/` - OAuth authentication module (McpAuthModule) - `src/mcp/decorators/` - Tool/Resource/Prompt decorators - `src/mcp/services/handlers/` - MCP protocol request handlers - `src/mcp/transport/` - Transport implementations (SSE, Streamable HTTP, STDIO) - `src/authz/providers/` - OAuth providers (GitHub, Google, custom interface) - `src/authz/stores/` - Storage backends (memory, TypeORM, custom interface) - `playground/` - Working examples and demo servers - `tests/` - Comprehensive E2E test suite covering all transports - `docs/` - Complete documentation for all features ### HTTP Adapter Abstraction `HttpAdapterFactory` at `src/mcp/adapters/` provides framework-agnostic request/response handling for Express/Fastify compatibility. ## Integration Points ### With NestJS Ecosystem - Full dependency injection container integration - Guard/Interceptor support for authentication - Request scoping for per-request instances - Module system with dynamic module configuration - Compatibility with NestJS versioning (VERSION_NEUTRAL) ### With MCP SDK - Wraps `@modelcontextprotocol/sdk` for transport layer - Handles MCP protocol message schemas - Progress reporting via context object - Elicitation support for interactive tool calls ### External Dependencies - `@modelcontextprotocol/sdk` - Core MCP protocol implementation - `zod` - Parameter validation and schema definition - `path-to-regexp` - Dynamic URI matching for resource templates - `zod-to-json-schema` - Schema conversion for tool parameters - `passport` + provider strategies - OAuth authentication - `@nestjs/jwt` - JWT token management - `typeorm` (optional) - Database storage for OAuth data ## Key Architecture Principles ### Transform Pattern The module transforms existing NestJS services into MCP servers through decorators, making business logic available to AI systems without modification. ### Transport Agnostic Each `McpModule.forRoot()` can serve multiple transport protocols simultaneously, with clients choosing their preferred connection method. ### Security Integration Authentication is handled at the transport level via NestJS Guards, ensuring all MCP endpoints respect the same security policies as the rest of the application. ### Stateful vs Stateless Supports both stateful (session-based) and stateless operation modes, with configurable session ID generation for multi-user scenarios. - don't run linting, I don't care about it or formatting

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rekog-labs/MCP-Nest'

If you have feedback or need assistance with the MCP directory API, please join our Discord server