mcp-nest Documentation

repository·main·Indexed 20 days ago

https://github.com/rekog-labs/mcp-nest

A NestJS module for exposing Model Context Protocol (MCP) capabilities—including tools, resources, and prompts—from NestJS applications. It supports Stdio and StreamableHttp transports, automatic tool discovery via @McpController, and granular authorization through @rekog/mcp-nest-auth or external MCP-spec-compliant servers.

Tokens
93K
Snippets
234
Records
326
Agent score
71%

What's inside mcp-nest

  1. Overview of MCP-Nest example projects

    main

    The examples/ directory contains greenfield projects that demonstrate specific features of @rekog/mcp-nest. Each project corresponds to a specific documentation topic:

    • Core MCP Features:
      • tools: Tools, progress, output schema, elicitation, guards, and filters.
      • resources: Static resources.
      • resource-templates: Parameterized URI templates.
      • prompts: Prompt templates, roles, and content types.
    • NestJS Integration:
      • dependency-injection: Dependency Injection (DI) and request scoping.
      • custom-controllers: HTTP vs RPC pipelines, middleware, interceptors, exception filters, and McpExceptionFilter.
      • tool-discovery: Decorator discovery and feature modules.
      • multiple-servers: Running multiple named servers on different paths (e.g., /weather/mcp and /travel/mcp).
    • Advanced Server Logic:
      • dynamic-capabilities: Runtime registration and deregistration of capabilities.
      • server-mutation: Instrumentation and tracing via serverMutator hooks.
    • Authorization & Security:
      • per-tool-authorization: Using @PublicTool, @ToolScopes, and @ToolRoles.
      • per-tool-authorization-jwt: Local JWT authentication.
      • per-tool-authorization-oauth: OAuth per-tool authentication.
      • built-in-authorization-server: Using McpAuthModule as an OAuth server.
      • external-authorization-server-casdoor: Using Casdoor as an external Authorization Server.
      • azure-ad-provider / azure-ad-oauth-provider: Azure AD integration.
  2. Overview of @rekog/mcp-nest-auth

    main

    The @rekog/mcp-nest-auth package provides an OAuth 2.1 and MCP Authorization specification-compliant authorization server designed for @rekog/mcp-nest.

    Key capabilities include:

    • Federated Authentication: Connects to upstream identity providers like GitHub, Google, and Azure AD.
    • Dynamic Client Registration: Implements RFC 7591, allowing MCP clients to register themselves and obtain tokens automatically without manual configuration.
    • Pluggable Storage: Supports memory-based storage or TypeORM for persistent OAuth data.
    • NestJS Integration: Plugs directly into NestJS via McpAuthModule and provides JwtTokenService and OAuth provider configurations.
  3. Overview of Azure AD OAuth Provider

    main

    The Azure AD OAuth provider implements OAuth 2.0 / OpenID Connect authentication flow with Microsoft Azure Active Directory. It allows users to authenticate using Microsoft work, school, or personal accounts to access your MCP (Model Context Protocol) server.

    Key features include:

    • Multi-tenant and Single-tenant authentication support.
    • Microsoft Graph API integration for user profile data.
    • Standard OAuth 2.0 flows with PKCE support.
    • JWT token-based authentication for MCP server access.
  4. What is the Built-in Authorization Server?

    main

    The McpAuthModule is an OAuth 2.1 compliant Identity Provider (IdP) implementation designed to secure MCP servers. It implements the MCP Authorization specification (revision 2025-06-18) and provides built-in support for popular OAuth providers like GitHub and Google.

    It works by providing OAuth 2.1 controllers and a NestJS guard (McpAuthJwtGuard) that validates Bearer JWTs on transport requests. This allows you to secure your MCP transport routes while keeping OAuth endpoints (like /auth/* and /.well-known/*) open for the initial handshake.

  5. How to create and register tools

    main

    Tools in mcp-nest can be managed in several ways:

    1. Automatic Discovery: Use the @McpController decorator to automatically discover and register tools.
    2. Dynamic Capabilities: Register tools, resources, and prompts programmatically at runtime (e.g., from a database or external configuration) using the dynamic capabilities API.
    3. Per-Tool Authorization: Implement fine-grained access control for individual tools using JWTs or OAuth via @rekog/mcp-nest-auth.
  6. Understand the dual-era client testing strategy

    main

    To prevent regressions during the migration from the v1 @modelcontextprotocol/sdk to the v2 @modelcontextprotocol/{core,node,server} ecosystem, the e2e suite uses two distinct client packages:

    1. Legacy Era: Uses @modelcontextprotocol/sdk@1.10.0 (pinned). This ensures that clients already in the wild continue to work with the new server implementation.
    2. Modern Era: Uses @modelcontextprotocol/client (pinned to 2026-07-28). This ensures the current v2 implementation correctly serves modern requests.

    Tests are written against an EraClient abstraction (defined in harness.ts) which normalizes the differing APIs of these two eras. The modern client is explicitly pinned rather than using mode: 'auto' to ensure that if a server loses its modern capabilities, the tests fail rather than silently falling back to legacy behavior.

  7. How Resource Templates work in mcp-nest

    main

    Resource Templates are dynamic resources that use URI patterns to match different paths and extract parameters. They are defined using the @ResourceTemplate() decorator within an @McpController().

    Unlike static resources, templates allow you to handle a range of URIs with a single method by capturing segments of the URI as variables. To use them, you must register the controller class in a NestJS module's controllers array (not providers).

    import { McpController, ResourceTemplate } from '@rekog/mcp-nest';
    
    @McpController()
    export class MyResourceController {
      @ResourceTemplate({
        name: 'my-template',
        description: 'A description of what this template does',
        mimeType: 'application/json',
        uriTemplate: 'mcp://prefix/{param}',
      })
      handleTemplate(@Payload() { uri, param }: { uri: string; param: string }) {
        // Implementation
      }
    }
  8. Understand MCP protocol version negotiation

    main

    MCP-Nest supports both legacy and modern MCP protocol versions. The protocol 'era' is determined by the client on a per-request basis, not by the server.

    • Client Behavior: The MCP SDK v2 client defaults to versionNegotiation: 'legacy' (the 2025 sequence). To use the modern 2026-07-28 protocol, the client must explicitly opt into 'auto' or pin the version to '2026-07-28'.
    • Server Behavior: A server created via createMcpHandler is 'dual-era', meaning it can serve both legacy and modern requests from a single factory. The server does not prefer one over the other; it responds based on the request received.
    • Error Handling: If a client attempts to use the 2026-07-28 protocol on an older version of MCP-Nest, the server will reject it with the error code -32000 Unsupported protocol version.
  9. How MCP-Nest handles protocol revisions

    main

    MCP-Nest provides Dual-Era Protocol Support. A single endpoint can concurrently serve both the 2025-era protocol (which uses initialize handshakes and sessions) and the stateless 2026-07-28 revision.

    • Stateless (2026-07-28): The default for StreamableHttpTransport. Tools can use ctx.reportProgress() to stream updates back to the client even in a sessionless environment.
    • Stateful (2025-era): Requires a session-aware transport such as StdioTransport or StreamableHttpTransport({ statefulMode: true }). On stateless transports, progress reporting is a no-op for legacy clients.

    This allows you to write tool code once and support both modern and legacy MCP clients without modification.

  10. How tool discovery and registration works in MCP-Nest

    main

    Capabilities (Tools, Resources, Prompts) can be exposed on an McpStrategy using two distinct methods:

    1. Automatic discovery (decorator-based): Uses decorators like @Tool, @Resource, @ResourceTemplate, and @Prompt on methods within classes decorated with @McpController(). These handlers run through the full NestJS RPC pipeline, including guards, pipes, interceptors, and exception filters.
    2. Dynamic registration (runtime): Capabilities are registered programmatically using strategy.registerTool(), registerResource(), or registerPrompt(). These handlers are invoked directly and bypass the NestJS RPC pipeline.

    Choose automatic discovery when you want to leverage NestJS features like dependency injection, validation pipes, and guards. Choose dynamic registration for runtime-defined capabilities that do not require the standard NestJS middleware stack.

  11. Use modern logging and progress notifications in request context

    main

    When handling sessionless modern requests, you can use the request context to send progress updates and logs. The response will automatically upgrade from a standard JSON response to a text/event-stream to support these features.

    • Progress/Logging: Use ctx.mcpReq.notify and ctx.mcpReq.log within the request context.
    • Note: server.server.notification(...) calls are silently dropped in this sessionless modern request flow; you must use the context methods instead.
    // Example usage within a handler context
    // ctx.mcpReq.notify and ctx.mcpReq.log are used for modern sessionless requests
  12. Understand the two-layer request handling pipeline

    main

    An MCP server built with the strategy API uses two distinct layers for request handling. Understanding which layer to attach NestJS pieces (middleware, guards, interceptors, etc.) to is critical for correct behavior.

    1. HTTP Layer (McpHttpController):

      • Handles the raw /mcp route.
      • Runs on every transport request (e.g., initialize, tools/list, SSE stream, and every tools/call).
      • This layer is era-agnostic and sees the raw HTTP request/response before MCP decoding.
      • Use this for: Request logging, raw-header authentication, rate-limiting headers, and timing.
    2. RPC Layer (@McpController):

      • Handles capability invocations (e.g., @Tool, @Resource, @Prompt).
      • Runs once per capability invocation.
      • Sees parsed tool names, validated arguments, and the McpContext.
      • Use this for: Tool-call auditing, result shaping, role/scope guards, and error surfacing.

    Key distinction: A single tool call produces one RPC-layer event but multiple HTTP-layer events.