1.0.0-alpha.3 • Published 5 months ago

@millionfor/nestjs-mcp-server v1.0.0-alpha.3

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

nestjs-mcp-server

A mcp service encapsulation based on nestjs framework

Install

# npm
npm install @millionfor/nestjs-mcp-server @modelcontextprotocol/sdk zod

# yarn
yarn add @millionfor/nestjs-mcp-server @modelcontextprotocol/sdk zod

# pnpm
pnpm add @millionfor/nestjs-mcp-server @modelcontextprotocol/sdk zod

Usage

1. Import module

Import McpModule in your module

import { Module } from "@nestjs/common";
import { McpModule } from "@millionfor/nestjs-mcp-server";

@Module({
  imports: [
    McpModule.register({
      controllerBaseUrl: "api/mcp",
      mcpServerConfigs: [
        {
          serverId: "my-mcp-server",
          serverInfo: {
            name: "my-mcp-server",
            version: "1.0.0",
          },
        },
      ],
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

In addition, you can also import modules through forRoot and forFeature, the differences are as follows:

  • forRoot: Usually registered in the root module
  • forFeature: Share Service instance with forRoot registered module
  • register: Register once and do not share with any module

2. Operation McpServer

After creating MCP Server, you can obtain the official sdk's native MCP Server instance through the getServer method. This instance has no encapsulation and is completely native.

For example, you can register a tool

import { Controller } from "@nestjs/common";
import { McpServerService } from "@millionfor/nestjs-mcp-server";
import { z } from "zod";

@Controller()
export class AppController {
  constructor(private readonly mcpServerService: McpServerService) {
    this.mcpServerService.getServer("server-id")?.tool(
      "get-current-time",
      {
        format: z
          .enum(["iso", "locale", "unix"])
          .optional()
          .default("iso")
          .describe("时间格式: iso, locale, 或 unix"),
      },
      async ({ format }: { format: "iso" | "locale" | "unix" }) => {
        const now = new Date();
        let timeValue: string | number;

        switch (format) {
          case "iso":
            timeValue = now.toISOString();
            break;
          case "locale":
            timeValue = now.toLocaleString();
            break;
          case "unix":
            timeValue = now.getTime();
            break;
          default:
            timeValue = now.toISOString();
        }

        return {
          content: [{ type: "text", text: String(timeValue) }],
        };
      }
    );
  }
}

3. Manually register the server instance

The above example directly passes in mcpServerConfigs in McpModule.register, which creates an MCP Server when the module is initialized.

Of course this is not necessary. You can manually register the MCP Server in the Controller or Service without passing in mcpServerConfigs:

import { Controller } from "@nestjs/common";
import { McpServerService } from "@millionfor/nestjs-mcp-server";
import { z } from "zod";

@Controller()
export class AppController {
  constructor(private readonly mcpServerService: McpServerService) {
    // 手动注册一个MCP Server实例
    this.mcpServerService.registerServer({
      serverId: "another-server",
      serverInfo: {
        name: "another-mcp-server",
        version: "1.0.0",
      },
    });
  }
}

Server access endpoint

After registering the module, the following endpoints are automatically created:

  • SSE connection endpoint: /{controllerBaseUrl}/{serverId}/sse
  • Message processing endpoint: /{controllerBaseUrl}/{serverId}/messages

For example, if you use controllerBaseUrl: 'api/mcp' and serverId: 'my-mcp-server', the access URL is:

  • http://localhost:3000/api/mcp/my-mcp-server/sse - for SSE connections
  • http://localhost:3000/api/mcp/my-mcp-server/messages - for message processing

API

McpModule.register

  • controllerBaseUrl: Basic URL path for MCP Controller
  • sseEndpoint: SSE connection endpoint name, default is sse
  • messagesEndpoint: Message processing endpoint name, default is messages
  • mcpServerConfigs:
  • serverId: McpServer id, use id to manage multiple instances
  • serverInfo: As the first parameter, pass it directly into the native MCP TS-SDK McpServer class
  • serverOptions: As the second parameter, pass it directly into the native MCP TS-SDK McpServer class

forRoot same as register, forFeature only receives mcpServerConfigs

McpServerService

McpModule export service to manage multiple McpServer instances.

You can inject it into your Controller or Service using the following methods:

registerServer

  • Function: Register a McpServer instance
  • Parameters: mcpServerConfigs same as McpModule.forRoot
  • Return value: Registered McpServer instance

getServer

  • Function: Get the specified McpServer instance
  • Parameters: serverId
  • Return value: McpServer instance

getServerIds

  • Function: Get all registered McpServer instance ids
  • Return value: string[] All registered McpServer instance id arrays

hasServer

  • Function: determine whether the specified McpServer instance has been registered
  • Parameters: serverId
  • Return value: boolean

connect

  • Function: Connecting McpServer to the transport layer generally does not need to be used unless you want to manually manage the connection.
  • Parameters:
  • serverId
  • transport, Transport instance
  • Return value: void

McpTransportService

McpModule export service to manage multiple SSEServerTransport instances.

It is usually not necessary to use unless you want to manually manage the connection.

The following only lists the possible methods. For more methods, please refer to the source code.

getTransport

  • Function: Get a specific transmission connection
  • Parameters: serverId, sessionId
  • Return value: SSEServerTransport instance

getActiveSessionIds

  • Function: Get all active session IDs of McpServer
  • Parameters: serverId
  • Return value: string[] All active session ID array

Advanced Configuration

Custom endpoint name

You can customize the SSE and message endpoint names when module registration:

McpModule.register({
  controllerBaseUrl: "api/mcp",
  sseEndpoint: "connect", // Default is 'sse'
  messagesEndpoint: "rpc", // Default is 'messages'
  mcpServerConfigs: [
    /* ... */
  ],
});

License

MIT