Skip to content

Conversation

abrenoch
Copy link

@abrenoch abrenoch commented May 6, 2025

This pull request adds support for the (undocumented) InMemoryTransport.

My use case for this behavior is using the MCP server within the same process that is facilitating the communication with the LLM, such as running a custom chat server. When initialized with McpTransportType.IN_MEMORY, the McpClientService would enable a separate service (such as one used in a websocket gateway) to access the MCP server as a client

Here is a quick example of how this might be used:

//chat.module.ts

@Module({
  imports: [
    McpModule.forRoot({
      name: 'my-mcp-server',
      version: '1.0.0',
      transport: McpTransportType.IN_MEMORY,
    }),
  ],
  providers: [
    McpClientService,
    ChatService,
    // ChatGateway, ...
  ],
})
export class ChatModule {}
//chat.service.ts

@Injectable()
export class ChatService {
  constructor(
    private readonly mcpClientService: McpClientService,
  ) {}

  // ... other llm related calls

  async getTools() {
    return this.mcpClientService.getClient().listTools().catch((error) => {
      throw error;
    });
  }

  async callTool(
    toolName: string,
    params: any
  ) {
    return this.mcpClientService.getClient()
      .callTool({
        name: toolName,
        arguments: params,
      })
      .catch((error) => {
        throw error;
      });
  }
}

I'll open this as a draft to get some feedback first. This also still needs a test whipped up for it.

Thanks for the great nestjs package, I was working on something almost identical before I found this one!

@rinormaloku
Copy link
Contributor

rinormaloku commented May 7, 2025

Thank you @abrenoch !

I'll take some time asap (but might take a few days) to try this out and get a feel for this. Such as trying it out with your use case. If you can drop some more information or code samples it would help me go faster through this.

What I want to know is: Why not move the logic to a service from the MCP tools if you want to use it in other areas of the code. (Or are there more benefits of using the inmemory approach?) Though when I take a deeper look it might make sense to me

@abrenoch
Copy link
Author

abrenoch commented May 7, 2025

What I want to know is: Why not move the logic to a service from the MCP tools if you want to use it in other areas of the code. (Or are there more benefits of using the inmemory approach?)

In my case this is a part of an existing larger application that offers more or less your run of the mill CRUD REST/GQL functionality. Most of the functions of the MCP tools are already baked into other nestjs modules which are then accessed via the MCP "server". True in this context the whole MCP library really isn't even needed technically, but using it I feel like would better standardize how the tools and their parameters are communicated to an LLM. Not to mention I like the @Tool decorator for easily whipping up new tools 😸.

I hope that answers your question; I'll look into whipping up a little demo repo or something when I get a moment!

@rinormaloku
Copy link
Contributor

rinormaloku commented Jun 21, 2025

@abrenoch I still have this on my radar.

And you were hinting at something important. This wiring of the mcp server might be one of the best benefits, the controllers, and even transport types, are making it too opinionated on how people should use the module. It is additionally making it harder to maintain compatibility with the spec, where most of the work instead of implementing latest features, is to propagate changes so that controllers are wired up correctly.

I have captured the improvement I plan here: #64 which I think is the same technical thing just a different way of expressing the same feature from UX perspective.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants