Skip to main content
Glama

NestJS MCP Server Module

by rekog-labs
MIT License
32,416
470
  • Apple
  • Linux
copilot-instructions.md5.66 kB
# NestJS MCP Server Module - AI Agent Instructions ## 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). ## Core Architecture Patterns ### 1. Decorator-Based Registration System Tools, resources, and prompts are discovered through decorators using NestJS's reflection capabilities: ```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}` }] }; } } ``` **Key Pattern**: Method signature is `(args, context, httpRequest)` where: - `args`: Zod-validated parameters - `context`: MCP context with `reportProgress`, `mcpServer`, `mcpRequest`, logging - `httpRequest`: HTTP request object (undefined for STDIO) ### 2. Multi-Transport Architecture Three transport types with different controllers: - **SSE**: `createSseController()` - GET `/sse` + POST `/messages` - **Streamable HTTP**: `createStreamableHttpController()` - POST `/mcp` (+ GET/DELETE for stateful) - **STDIO**: `StdioService` - No HTTP endpoints Each transport creates dynamic controllers via factory functions in `McpModule.forRoot()`. ### 3. Request Scoping & Dependency Injection Uses NestJS's request scoping for per-request instances: ```typescript @Injectable({ scope: Scope.REQUEST }) export class RequestScopedService { constructor(@Inject(REQUEST) private request: Request) {} } ``` The `McpExecutorService` (REQUEST-scoped) orchestrates handler registration per request. ### 4. Module Instance Isolation Each `McpModule.forRoot()` call creates a unique module instance with its own `moduleId`: ```typescript const moduleId = `mcp-module-${instanceIdCounter++}`; ``` This enables multiple MCP servers in one application with different endpoints/capabilities. ## Development Workflows ### Building & Testing ```bash npm run build # TypeScript compilation with source maps npm test # Jest with experimental VM modules npm run test:watch # Watch mode npm run lint # ESLint with --fix ``` ### Running Examples ```bash npm run start:playground # Stateful server example npm run start:fastify # Fastify adapter example ``` ### Testing Transport Types The test suite comprehensively covers all transport types. Key test patterns: - E2E tests create actual NestJS apps with different transport configurations - Tests run the same scenarios across HTTP+SSE, Streamable HTTP (stateful/stateless), and STDIO - Use `createSseClient()`, `createStreamableClient()`, `createStdioClient()` helpers ## Critical Implementation Details ### Output Schema Validation Tools with `outputSchema` get validated results. Failed validation throws `McpError`: ```typescript if (outputSchema) { const validation = outputSchema.safeParse(result); if (!validation.success) { throw new McpError(ErrorCode.InternalError, `Tool result does not match outputSchema`); } return { structuredContent: result, content: this.buildDefaultContentBlock(result) }; } ``` ### Resource URI Matching Resources use `path-to-regexp` for dynamic URI matching: - Static: `uri: 'mcp://hello-world'` - Template: `uriTemplate: 'mcp://hello-world/{userId}/{userName}'` Templates extract parameters using `match()` function with URL decoding. ### Authentication Integration Guards apply to all MCP endpoints: ```typescript McpModule.forRoot({ guards: [AuthGuard], // Applied to SSE/messages/mcp endpoints }) ``` Request context flows through to tools via dependency injection. ## Project-Specific Conventions ### File Organization - `src/mcp/` - Core MCP functionality - `src/authz/` - OAuth authentication module - `src/mcp/decorators/` - Tool/Resource/Prompt decorators - `src/mcp/services/handlers/` - Protocol request handlers - `src/mcp/transport/` - Transport implementations - `playground/` - Working examples - `tests/` - Comprehensive E2E test suite ### Error Handling Patterns MCP tools should return standardized error format: ```typescript return { content: [{ type: 'text', text: error.message }], isError: true, }; ``` ### Registry Service Pattern `McpRegistryService` discovers decorated methods at bootstrap using `DiscoveryService` and `MetadataScanner`. It maintains maps by `mcpModuleId` for isolation. ### HTTP Adapter Abstraction `HttpAdapterFactory` provides framework-agnostic request/response handling for Express/Fastify compatibility. ## Key Integration Points ### With NestJS Ecosystem - Full DI container integration - Guard/Interceptor support - Request scoping - Module system - Versioning compatibility (VERSION_NEUTRAL) ### With MCP SDK - Wraps `@modelcontextprotocol/sdk` transports - Handles MCP protocol schemas - Progress reporting via context - Elicitation support for interactive tools ### External Dependencies - `zod` for parameter validation - `path-to-regexp` for URI matching - `zod-to-json-schema` for OpenAPI-style schemas Remember: This module transforms NestJS services into MCP servers through decorators, not the other way around. The NestJS application hosts the MCP server, making existing business logic available to AI systems.

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