@nestjs-mcp/server 0.1.0-alpha.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +450 -134
- package/coverage/clover.xml +507 -0
- package/coverage/coverage-final.json +19 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +206 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/src/controllers/sse/index.html +146 -0
- package/coverage/lcov-report/src/controllers/sse/index.ts.html +91 -0
- package/coverage/lcov-report/src/controllers/sse/sse.controller.ts.html +160 -0
- package/coverage/lcov-report/src/controllers/sse/sse.service.ts.html +403 -0
- package/coverage/lcov-report/src/controllers/streamable/index.html +146 -0
- package/coverage/lcov-report/src/controllers/streamable/index.ts.html +91 -0
- package/coverage/lcov-report/src/controllers/streamable/streamable.controller.ts.html +157 -0
- package/coverage/lcov-report/src/controllers/streamable/streamable.service.ts.html +655 -0
- package/coverage/lcov-report/src/decorators/capabilities.constants.ts.html +106 -0
- package/coverage/lcov-report/src/decorators/capabilities.decorators.ts.html +535 -0
- package/coverage/lcov-report/src/decorators/index.html +146 -0
- package/coverage/lcov-report/src/decorators/index.ts.html +91 -0
- package/coverage/lcov-report/src/index.html +131 -0
- package/coverage/lcov-report/src/index.ts.html +118 -0
- package/coverage/lcov-report/src/interfaces/capabilities.interface.ts.html +703 -0
- package/coverage/lcov-report/src/interfaces/index.html +131 -0
- package/coverage/lcov-report/src/interfaces/index.ts.html +91 -0
- package/coverage/lcov-report/src/mcp.module.ts.html +817 -0
- package/coverage/lcov-report/src/registry/discovery.service.ts.html +433 -0
- package/coverage/lcov-report/src/registry/index.html +161 -0
- package/coverage/lcov-report/src/registry/index.ts.html +91 -0
- package/coverage/lcov-report/src/registry/logger.service.ts.html +514 -0
- package/coverage/lcov-report/src/registry/registry.service.ts.html +1183 -0
- package/coverage/lcov-report/src/services/index.html +116 -0
- package/coverage/lcov-report/src/services/session.manager.ts.html +163 -0
- package/coverage/lcov.info +912 -0
- package/dist/controllers/sse/sse.controller.d.ts +1 -3
- package/dist/controllers/sse/sse.controller.js +2 -8
- package/dist/controllers/sse/sse.controller.js.map +1 -1
- package/dist/interfaces/capabilities.interface.d.ts +1 -1
- package/dist/interfaces/{context.interface.d.ts → guards.interface.d.ts} +0 -2
- package/dist/interfaces/{message.types.js → guards.interface.js} +1 -1
- package/dist/interfaces/guards.interface.js.map +1 -0
- package/dist/interfaces/index.d.ts +1 -1
- package/dist/interfaces/index.js +1 -1
- package/dist/interfaces/index.js.map +1 -1
- package/dist/interfaces/mcp-server-options.interface.d.ts +2 -2
- package/dist/mcp.module.js +1 -17
- package/dist/mcp.module.js.map +1 -1
- package/dist/registry/registry.service.d.ts +1 -3
- package/dist/registry/registry.service.js +3 -8
- package/dist/registry/registry.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +16 -17
- package/src/controllers/sse/sse.service.ts +21 -5
- package/src/controllers/streamable/streamable.service.ts +45 -23
- package/src/interfaces/capabilities.interface.ts +112 -1
- package/src/interfaces/context.interface.ts +21 -6
- package/src/mcp.module.ts +4 -9
- package/src/registry/registry.service.ts +94 -10
- package/src/services/session.manager.ts +26 -0
- package/dist/interceptors/message.interceptor.d.ts +0 -10
- package/dist/interceptors/message.interceptor.js +0 -61
- package/dist/interceptors/message.interceptor.js.map +0 -1
- package/dist/interfaces/context.interface.js +0 -3
- package/dist/interfaces/context.interface.js.map +0 -1
- package/dist/interfaces/message.types.d.ts +0 -8
- package/dist/interfaces/message.types.js.map +0 -1
- package/dist/services/message.service.d.ts +0 -7
- package/dist/services/message.service.js +0 -25
- package/dist/services/message.service.js.map +0 -1
- package/src/interceptors/message.interceptor.ts +0 -70
- package/src/services/message.service.ts +0 -18
package/README.md
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# MCP Server NestJS Module Library <!-- omit in toc -->
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@nestjs-mcp/server)
|
|
4
|
+
[](https://github.com/semantic-release/semantic-release)
|
|
5
|
+
[](https://www.npmjs.com/package/@nestjs-mcp/server)
|
|
6
|
+
[](https://github.com/adrian-d-hidalgo/nestjs-mcp-server/actions/workflows/run-tests.yml)
|
|
7
|
+
[](https://codecov.io/gh/adrian-d-hidalgo/nestjs-mcp-server)
|
|
8
|
+
[](https://snyk.io/test/github/adrian-d-hidalgo/nestjs-mcp-server)
|
|
4
9
|
[](./LICENSE)
|
|
10
|
+
[](./CONTRIBUTING.md)
|
|
5
11
|
|
|
6
12
|
---
|
|
7
13
|
|
|
@@ -24,18 +30,24 @@
|
|
|
24
30
|
- [Prompt](#prompt)
|
|
25
31
|
- [Module API](#module-api)
|
|
26
32
|
- [forRoot](#mcpmoduleforroot)
|
|
33
|
+
- [forRootAsync](#mcpmoduleforrootasync)
|
|
27
34
|
- [forFeature](#mcpmoduleforfeature)
|
|
28
|
-
|
|
35
|
+
- [Module Usage](#module-usage)
|
|
36
|
+
- [1. Global Registration with `McpModule.forRoot`](#1-global-registration-with-mcpmoduleforroot)
|
|
37
|
+
- [2. Feature Module Registration with `McpModule.forFeature`](#2-feature-module-registration-with-mcpmoduleforfeature)
|
|
29
38
|
- [Capabilities](#capabilities)
|
|
30
|
-
- [
|
|
31
|
-
- [
|
|
32
|
-
- [
|
|
33
|
-
- [
|
|
39
|
+
- [Resolver Decorator](#resolver-decorator)
|
|
40
|
+
- [Prompt Decorator](#prompt-decorator)
|
|
41
|
+
- [Resource Decorator](#resource-decorator)
|
|
42
|
+
- [Tool Decorator](#tool-decorator)
|
|
34
43
|
- [Guards](#guards)
|
|
35
|
-
- [Global-level guards
|
|
36
|
-
- [Resolver-level guards
|
|
37
|
-
- [Method-level guards
|
|
44
|
+
- [Global-level guards](#global-level-guards)
|
|
45
|
+
- [Resolver-level guards](#resolver-level-guards)
|
|
46
|
+
- [Method-level guards](#method-level-guards)
|
|
38
47
|
- [Guard Example](#guard-example)
|
|
48
|
+
- [MCP Execution Context](#mcp-execution-context)
|
|
49
|
+
- [Session Management](#session-management)
|
|
50
|
+
- [Transport Options](#transport-options)
|
|
39
51
|
- [Inspector Playground](#inspector-playground)
|
|
40
52
|
- [Examples](#examples)
|
|
41
53
|
- [Changelog](#changelog)
|
|
@@ -60,14 +72,13 @@ Register the MCP module in your NestJS app and expose a simple tool:
|
|
|
60
72
|
|
|
61
73
|
```ts
|
|
62
74
|
import { Module } from '@nestjs/common';
|
|
63
|
-
import { Injectable } from '@nestjs/common';
|
|
64
75
|
|
|
65
76
|
import { CallToolResult } from '@modelcontextprotocol/sdk/types';
|
|
66
77
|
|
|
67
|
-
import { Tool } from '@nestjs-mcp/server';
|
|
78
|
+
import { Resolver, Tool, McpModule } from '@nestjs-mcp/server';
|
|
68
79
|
|
|
69
|
-
@
|
|
70
|
-
export class
|
|
80
|
+
@Resolver()
|
|
81
|
+
export class HealthResolver {
|
|
71
82
|
/**
|
|
72
83
|
* Simple health check tool
|
|
73
84
|
*/
|
|
@@ -91,7 +102,7 @@ export class AppService {
|
|
|
91
102
|
version: '1.0.0',
|
|
92
103
|
}),
|
|
93
104
|
],
|
|
94
|
-
providers: [
|
|
105
|
+
providers: [HealthResolver],
|
|
95
106
|
})
|
|
96
107
|
export class AppModule {}
|
|
97
108
|
```
|
|
@@ -138,19 +149,31 @@ A Prompt defines a conversational flow, template, or interaction pattern for LLM
|
|
|
138
149
|
|
|
139
150
|
### `McpModule.forRoot`
|
|
140
151
|
|
|
141
|
-
Registers the MCP Server globally in your NestJS application.
|
|
152
|
+
Registers the MCP Server globally in your NestJS application.
|
|
142
153
|
|
|
143
154
|
**Parameters:**
|
|
144
155
|
|
|
145
|
-
- `options:
|
|
156
|
+
- `options: McpModuleOptions` — Main server configuration object:
|
|
157
|
+
- `name: string`: The name of your MCP server.
|
|
158
|
+
- `version: string`: The version of your MCP server.
|
|
159
|
+
- `instructions?: string`: Optional description of the MCP server for the client.
|
|
160
|
+
- `capabilities?: Record<string, unknown>`: Optional additional capabilities metadata.
|
|
161
|
+
- `providers?: Provider[]`: Optional array of NestJS providers to include in the module.
|
|
162
|
+
- `imports?: any[]`: Optional array of NestJS modules to import.
|
|
163
|
+
- `logging?: McpLoggingOptions`: Optional logging configuration:
|
|
164
|
+
- `enabled?: boolean` (default: `true`): Enable/disable logging.
|
|
165
|
+
- `level?: 'error' | 'warn' | 'log' | 'debug' | 'verbose'` (default: `'verbose'`): Set the logging level.
|
|
166
|
+
- `transports?: McpModuleTransportOptions`: Optional transport configuration (see [Transport Options](#transport-options)).
|
|
167
|
+
- `protocolOptions?: Record<string, unknown>`: Optional parameters passed directly to the underlying `@modelcontextprotocol/sdk` server instance.
|
|
146
168
|
|
|
147
169
|
**Returns:**
|
|
148
170
|
|
|
149
|
-
- A dynamic NestJS module with all MCP providers registered
|
|
171
|
+
- A dynamic NestJS module with all MCP providers registered.
|
|
150
172
|
|
|
151
173
|
**Example:**
|
|
152
174
|
|
|
153
175
|
```ts
|
|
176
|
+
import { Module } from '@nestjs/common';
|
|
154
177
|
import { McpModule } from '@nestjs-mcp/server';
|
|
155
178
|
|
|
156
179
|
@Module({
|
|
@@ -158,6 +181,9 @@ import { McpModule } from '@nestjs-mcp/server';
|
|
|
158
181
|
McpModule.forRoot({
|
|
159
182
|
name: 'My Server',
|
|
160
183
|
version: '1.0.0',
|
|
184
|
+
instructions: 'A server providing utility tools and data.',
|
|
185
|
+
logging: { level: 'log' },
|
|
186
|
+
transports: { sse: { enabled: false } }, // Disable SSE transport
|
|
161
187
|
// ...other MCP options
|
|
162
188
|
}),
|
|
163
189
|
],
|
|
@@ -165,28 +191,84 @@ import { McpModule } from '@nestjs-mcp/server';
|
|
|
165
191
|
export class AppModule {}
|
|
166
192
|
```
|
|
167
193
|
|
|
194
|
+
### `McpModule.forRootAsync`
|
|
195
|
+
|
|
196
|
+
Registers the MCP Server globally using asynchronous options, useful for integrating with configuration modules like `@nestjs/config`.
|
|
197
|
+
|
|
198
|
+
**Parameters:**
|
|
199
|
+
|
|
200
|
+
- `options: McpModuleAsyncOptions` — Asynchronous configuration object:
|
|
201
|
+
- `imports?: any[]`: Optional modules to import before the factory runs.
|
|
202
|
+
- `useFactory: (...args: any[]) => Promise<McpModuleOptions> | McpModuleOptions`: A factory function that returns the `McpModuleOptions`.
|
|
203
|
+
- `inject?: any[]`: Optional providers to inject into the `useFactory`.
|
|
204
|
+
|
|
205
|
+
**Returns:**
|
|
206
|
+
|
|
207
|
+
- A dynamic NestJS module.
|
|
208
|
+
|
|
209
|
+
**Example (with ConfigModule):**
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
import { Module } from '@nestjs/common';
|
|
213
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
214
|
+
import { McpModule } from '@nestjs-mcp/server';
|
|
215
|
+
|
|
216
|
+
@Module({
|
|
217
|
+
imports: [
|
|
218
|
+
ConfigModule.forRoot(), // Make sure ConfigModule is imported
|
|
219
|
+
McpModule.forRootAsync({
|
|
220
|
+
imports: [ConfigModule], // Import ConfigModule here too
|
|
221
|
+
useFactory: (configService: ConfigService) => ({
|
|
222
|
+
name: configService.get<string>('MCP_SERVER_NAME', 'Default Server'),
|
|
223
|
+
version: configService.get<string>('MCP_SERVER_VERSION', '1.0.0'),
|
|
224
|
+
instructions: configService.get<string>('MCP_SERVER_DESC'),
|
|
225
|
+
logging: {
|
|
226
|
+
level: configService.get('MCP_LOG_LEVEL', 'verbose'),
|
|
227
|
+
},
|
|
228
|
+
// ... other options from configService
|
|
229
|
+
}),
|
|
230
|
+
inject: [ConfigService], // Inject ConfigService into the factory
|
|
231
|
+
}),
|
|
232
|
+
],
|
|
233
|
+
})
|
|
234
|
+
export class AppModule {}
|
|
235
|
+
```
|
|
236
|
+
|
|
168
237
|
### `McpModule.forFeature`
|
|
169
238
|
|
|
170
|
-
Registers additional MCP resources, tools, or prompts
|
|
239
|
+
Registers additional MCP resources, tools, or prompts within a feature module. Use this to organize large servers into multiple modules. Resolvers containing MCP capabilities must be included in the `providers` array of the feature module.
|
|
171
240
|
|
|
172
241
|
**Parameters:**
|
|
173
242
|
|
|
174
|
-
- `
|
|
243
|
+
- `options?: McpFeatureOptions` (Currently unused, reserved for future enhancements).
|
|
175
244
|
|
|
176
245
|
**Returns:**
|
|
177
246
|
|
|
178
|
-
- A dynamic module
|
|
247
|
+
- A dynamic module.
|
|
179
248
|
|
|
180
249
|
**Example:**
|
|
181
250
|
|
|
182
251
|
```ts
|
|
252
|
+
// src/status/status.resolver.ts
|
|
253
|
+
import { Resolver, Tool } from '@nestjs-mcp/server';
|
|
254
|
+
import { CallToolResult } from '@modelcontextprotocol/sdk/types';
|
|
255
|
+
|
|
256
|
+
@Resolver('status')
|
|
257
|
+
export class StatusResolver {
|
|
258
|
+
@Tool({ name: 'health_check' })
|
|
259
|
+
healthCheck(): CallToolResult {
|
|
260
|
+
return { content: [{ type: 'text', text: 'OK' }] };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/status/status.module.ts
|
|
265
|
+
import { Module } from '@nestjs/common';
|
|
183
266
|
import { McpModule } from '@nestjs-mcp/server';
|
|
267
|
+
import { StatusResolver } from './status.resolver';
|
|
184
268
|
|
|
185
269
|
@Module({
|
|
186
|
-
imports: [McpModule.forFeature()],
|
|
187
|
-
providers: [
|
|
188
|
-
/*Your Providers with Mcp Capabilities*/
|
|
189
|
-
],
|
|
270
|
+
imports: [McpModule.forFeature()], // Import forFeature here
|
|
271
|
+
providers: [StatusResolver], // Register your resolver
|
|
190
272
|
})
|
|
191
273
|
export class StatusModule {}
|
|
192
274
|
```
|
|
@@ -236,9 +318,9 @@ import { ToolsResolver } from './tools.resolver';
|
|
|
236
318
|
export class ToolsModule {}
|
|
237
319
|
```
|
|
238
320
|
|
|
239
|
-
- Use `forRoot` only once in your root module.
|
|
240
|
-
- Use `forFeature`
|
|
241
|
-
-
|
|
321
|
+
- Use `forRoot` or `forRootAsync` **only once** in your root module (`AppModule`).
|
|
322
|
+
- Use `forFeature` in any feature module where you define MCP capabilities (`@Resolver` classes).
|
|
323
|
+
- Ensure all Resolvers are listed in the `providers` array of their respective modules.
|
|
242
324
|
|
|
243
325
|
---
|
|
244
326
|
|
|
@@ -248,27 +330,38 @@ This library provides a set of decorators to define MCP capabilities and apply c
|
|
|
248
330
|
|
|
249
331
|
### Resolver Decorator
|
|
250
332
|
|
|
251
|
-
A Resolver is a class that groups related MCP capabilities
|
|
333
|
+
A Resolver is a class that groups related MCP capabilities. **All** MCP capability methods (`@Prompt`, `@Resource`, `@Tool`) **must** belong to a class decorated with `@Resolver`.
|
|
334
|
+
|
|
335
|
+
- **No `@Injectable()` Needed:** Resolver classes are automatically treated as providers by the MCP module and **do not** require the `@Injectable()` decorator.
|
|
336
|
+
- **Dependency Injection:** Standard NestJS dependency injection works within Resolver constructors.
|
|
337
|
+
- **Namespacing:** You can optionally provide a string argument to `@Resolver('my_namespace')` to namespace the capabilities within that resolver.
|
|
338
|
+
- **Guards:** Guards can be applied at the class level using `@UseGuards()`.
|
|
252
339
|
|
|
253
340
|
**Example:**
|
|
254
341
|
|
|
255
342
|
```ts
|
|
256
343
|
import { Resolver, Prompt, Resource, Tool } from '@nestjs-mcp/server';
|
|
344
|
+
// Import any services you need to inject
|
|
345
|
+
import { SomeService } from '../some.service';
|
|
257
346
|
|
|
258
|
-
@Resolver('workspace')
|
|
347
|
+
@Resolver('workspace') // No @Injectable()
|
|
259
348
|
export class MyResolver {
|
|
260
|
-
|
|
261
|
-
|
|
349
|
+
// Inject dependencies as usual
|
|
350
|
+
constructor(private readonly someService: SomeService) {}
|
|
351
|
+
|
|
352
|
+
@Prompt({ name: 'greet_user' }) // Capabilities must be inside a Resolver
|
|
353
|
+
greetPrompt(/*...args...*/) {
|
|
354
|
+
const greeting = this.someService.getGreeting();
|
|
262
355
|
/* ... */
|
|
263
356
|
}
|
|
264
357
|
|
|
265
|
-
@Resource({ name: '
|
|
266
|
-
getUserResource() {
|
|
358
|
+
@Resource({ name: 'user_profile', uri: 'user://{id}' })
|
|
359
|
+
getUserResource(/*...args...*/) {
|
|
267
360
|
/* ... */
|
|
268
361
|
}
|
|
269
362
|
|
|
270
|
-
@Tool({ name: '
|
|
271
|
-
sumTool() {
|
|
363
|
+
@Tool({ name: 'calculate_sum' })
|
|
364
|
+
sumTool(/*...args...*/) {
|
|
272
365
|
/* ... */
|
|
273
366
|
}
|
|
274
367
|
}
|
|
@@ -280,57 +373,123 @@ You can also apply guards at the resolver level:
|
|
|
280
373
|
import { UseGuards, Resolver } from '@nestjs-mcp/server';
|
|
281
374
|
import { MyGuard } from './guards/my.guard';
|
|
282
375
|
|
|
283
|
-
@UseGuards(MyGuard)
|
|
284
|
-
@Resolver('secure')
|
|
376
|
+
@UseGuards(MyGuard) // Applied to all capabilities in this Resolver
|
|
377
|
+
@Resolver('secure') // No @Injectable()
|
|
285
378
|
export class SecureResolver {
|
|
286
|
-
//
|
|
379
|
+
// All capabilities in this resolver will use MyGuard
|
|
287
380
|
}
|
|
288
381
|
```
|
|
289
382
|
|
|
290
383
|
### Prompt Decorator
|
|
291
384
|
|
|
292
|
-
Decorate methods within a Resolver to expose them as MCP Prompts.
|
|
385
|
+
Decorate methods within a Resolver class to expose them as MCP Prompts. Accepts options compatible with `server.prompt()` from `@modelcontextprotocol/sdk`. **The `name` should use `snake_case`.**
|
|
293
386
|
|
|
294
387
|
```ts
|
|
295
|
-
import { Prompt } from '@nestjs-mcp/server';
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
388
|
+
import { Prompt, Resolver } from '@nestjs-mcp/server';
|
|
389
|
+
import { RequestHandlerExtra } from '@nestjs-mcp/server'; // Import type for extra info
|
|
390
|
+
import { z } from 'zod'; // Example if using Zod schema
|
|
391
|
+
|
|
392
|
+
// Optional: Define schema if needed
|
|
393
|
+
// const SummaryArgs = z.object({ topic: z.string() });
|
|
394
|
+
|
|
395
|
+
@Resolver('prompts') // Must be in a Resolver class
|
|
396
|
+
export class MyPrompts {
|
|
397
|
+
@Prompt({
|
|
398
|
+
name: 'generate_summary',
|
|
399
|
+
description: 'Generates a summary for the given text.',
|
|
400
|
+
// argsSchema: SummaryArgs
|
|
401
|
+
})
|
|
402
|
+
generateSummaryPrompt(
|
|
403
|
+
// params: z.infer<typeof SummaryArgs>, // Arguments based on argsSchema (if defined)
|
|
404
|
+
extra: RequestHandlerExtra, // Contains sessionId and other metadata
|
|
405
|
+
) {
|
|
406
|
+
console.log(`Generating summary for session: ${extra.sessionId}`);
|
|
407
|
+
/* ... return CallPromptResult ... */
|
|
408
|
+
return { content: [{ type: 'text', text: 'Summary generated.' }] };
|
|
302
409
|
}
|
|
303
410
|
}
|
|
304
411
|
```
|
|
305
412
|
|
|
306
413
|
### Resource Decorator
|
|
307
414
|
|
|
308
|
-
Decorate methods within a Resolver to expose them as MCP Resources.
|
|
415
|
+
Decorate methods within a Resolver class to expose them as MCP Resources. Accepts options compatible with `server.resource()` from `@modelcontextprotocol/sdk`. **The `name` should use `snake_case`.**
|
|
309
416
|
|
|
310
417
|
```ts
|
|
311
|
-
import { Resource } from '@nestjs-mcp/server';
|
|
418
|
+
import { Resource, Resolver } from '@nestjs-mcp/server';
|
|
419
|
+
import { RequestHandlerExtra } from '@nestjs-mcp/server'; // Import type for extra info
|
|
420
|
+
import { URL } from 'url'; // Type for URI resource
|
|
421
|
+
import { z } from 'zod'; // Example if using Zod template
|
|
422
|
+
|
|
423
|
+
// Optional: Define template schema if needed
|
|
424
|
+
// const DocQueryTemplate = z.object({ query: z.string() });
|
|
425
|
+
|
|
426
|
+
@Resolver('data') // Must be in a Resolver class
|
|
427
|
+
export class MyResources {
|
|
428
|
+
@Resource({
|
|
429
|
+
name: 'user_profile',
|
|
430
|
+
uri: 'user://profiles/{userId}',
|
|
431
|
+
// metadata: { description: '...' } // Optional
|
|
432
|
+
})
|
|
433
|
+
getUserProfile(
|
|
434
|
+
uri: URL, // First argument is the parsed URI
|
|
435
|
+
// metadata: Record<string, any> // Second argument if is defined
|
|
436
|
+
extra: RequestHandlerExtra, // Contains sessionId and other metadata
|
|
437
|
+
) {
|
|
438
|
+
const userId = uri.pathname.split('/').pop(); // Example: Extract ID from URI
|
|
439
|
+
console.log(`Fetching profile for ${userId}, session: ${extra.sessionId}`);
|
|
440
|
+
/* ... return CallResourceResult ... */
|
|
441
|
+
return { content: [{ type: 'text', text: `Profile data for ${userId}` }] };
|
|
442
|
+
}
|
|
312
443
|
|
|
313
|
-
@
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
444
|
+
@Resource({
|
|
445
|
+
name: 'document_list',
|
|
446
|
+
template: { type: 'string', description: 'Document content query' }, // Simple template example
|
|
447
|
+
// metadata: { list: true } // Optional
|
|
448
|
+
})
|
|
449
|
+
findDocuments(
|
|
450
|
+
uri: URL, // First arg based on simple template type
|
|
451
|
+
variables: Record<string, string>, // Second arg is path params (if any)
|
|
452
|
+
extra: RequestHandlerExtra, // Contains sessionId and other metadata
|
|
453
|
+
) {
|
|
454
|
+
console.log(
|
|
455
|
+
`Finding documents matching '${query}', session: ${extra.sessionId}`,
|
|
456
|
+
);
|
|
457
|
+
/* ... return CallResourceResult ... */
|
|
458
|
+
return { content: [{ type: 'text', text: 'List of documents.' }] };
|
|
318
459
|
}
|
|
319
460
|
}
|
|
320
461
|
```
|
|
321
462
|
|
|
322
463
|
### Tool Decorator
|
|
323
464
|
|
|
324
|
-
Decorate methods within a Resolver to expose them as MCP Tools.
|
|
465
|
+
Decorate methods within a Resolver class to expose them as MCP Tools. Accepts options compatible with `server.tool()` from `@modelcontextprotocol/sdk`. **The `name` should use `snake_case`.**
|
|
325
466
|
|
|
326
467
|
```ts
|
|
327
|
-
import { Tool } from '@nestjs-mcp/server';
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
468
|
+
import { Tool, Resolver } from '@nestjs-mcp/server';
|
|
469
|
+
import { RequestHandlerExtra } from '@nestjs-mcp/server'; // Import type for extra info
|
|
470
|
+
import { z } from 'zod'; // Example using Zod for schema
|
|
471
|
+
|
|
472
|
+
// Example Zod schema for parameters
|
|
473
|
+
const SumParams = z.object({
|
|
474
|
+
num1: z.number(),
|
|
475
|
+
num2: z.number(),
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
@Resolver('utils') // Must be in a Resolver class
|
|
479
|
+
export class MyTools {
|
|
480
|
+
@Tool({
|
|
481
|
+
name: 'calculate_sum',
|
|
482
|
+
description: 'Calculates the sum of two numbers.',
|
|
483
|
+
paramSchema: SumParams, // Use the Zod schema
|
|
484
|
+
})
|
|
485
|
+
sumTool(
|
|
486
|
+
params: z.infer<typeof SumParams>, // First arg is typed parameters from schema
|
|
487
|
+
extra: RequestHandlerExtra, // Contains sessionId and other metadata
|
|
488
|
+
) {
|
|
489
|
+
console.log(`Calculating sum for session: ${extra.sessionId}`);
|
|
490
|
+
const result = params.num1 + params.num2;
|
|
491
|
+
/* ... return CallToolResult ... */
|
|
492
|
+
return { content: [{ type: 'text', text: `Result: ${result}` }] };
|
|
334
493
|
}
|
|
335
494
|
}
|
|
336
495
|
```
|
|
@@ -341,20 +500,22 @@ export class MyResolver {
|
|
|
341
500
|
|
|
342
501
|
Apply one or more guards to a Resolver, to individual methods, or globally. Guards must implement the NestJS `CanActivate` interface.
|
|
343
502
|
|
|
344
|
-
### Global-level guards
|
|
503
|
+
### Global-level guards
|
|
345
504
|
|
|
346
|
-
This approach uses the standard NestJS global guard system. A global guard will protect all
|
|
505
|
+
This approach uses the standard NestJS global guard system (`APP_GUARD`). A global guard will protect **all** NestJS routes, including the MCP transport endpoints (like `/mcp` or `/sse`). Use this for broad authentication or checks that apply before any MCP-specific logic runs.
|
|
347
506
|
|
|
348
507
|
```ts
|
|
349
508
|
// src/guards/global-auth.guard.ts
|
|
350
509
|
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
|
|
510
|
+
import { Request } from 'express';
|
|
351
511
|
|
|
352
512
|
@Injectable()
|
|
353
513
|
export class GlobalAuthGuard implements CanActivate {
|
|
354
514
|
canActivate(context: ExecutionContext): boolean {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
515
|
+
const request = context.switchToHttp().getRequest<Request>();
|
|
516
|
+
const apiKey = request.headers['x-api-key'];
|
|
517
|
+
// Example: Check for a valid API key
|
|
518
|
+
return !!apiKey && apiKey === 'EXPECTED_KEY';
|
|
358
519
|
}
|
|
359
520
|
}
|
|
360
521
|
```
|
|
@@ -362,21 +523,15 @@ export class GlobalAuthGuard implements CanActivate {
|
|
|
362
523
|
Register the guard globally in your main module:
|
|
363
524
|
|
|
364
525
|
```ts
|
|
526
|
+
// src/app.module.ts
|
|
365
527
|
import { Module } from '@nestjs/common';
|
|
366
528
|
import { APP_GUARD } from '@nestjs/core';
|
|
367
529
|
import { McpModule } from '@nestjs-mcp/server';
|
|
368
530
|
import { GlobalAuthGuard } from './guards/global-auth.guard';
|
|
369
|
-
import { PromptsResolver } from './prompts.resolver';
|
|
370
531
|
|
|
371
532
|
@Module({
|
|
372
|
-
imports: [
|
|
373
|
-
McpModule.forRoot({
|
|
374
|
-
name: 'My MCP Server',
|
|
375
|
-
version: '1.0.0',
|
|
376
|
-
}),
|
|
377
|
-
],
|
|
533
|
+
imports: [McpModule.forRoot(/*...*/)],
|
|
378
534
|
providers: [
|
|
379
|
-
PromptsResolver,
|
|
380
535
|
{
|
|
381
536
|
provide: APP_GUARD,
|
|
382
537
|
useClass: GlobalAuthGuard,
|
|
@@ -386,116 +541,275 @@ import { PromptsResolver } from './prompts.resolver';
|
|
|
386
541
|
export class AppModule {}
|
|
387
542
|
```
|
|
388
543
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
- The guard will run for every request handled by your NestJS application, including all MCP endpoints.
|
|
392
|
-
- You can implement any logic in canActivate, such as checking headers, tokens, or user roles.
|
|
393
|
-
- This approach is fully compatible with NestJS and your MCP Server module.
|
|
544
|
+
### Resolver-level guards
|
|
394
545
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
This is a custom feature of this library. Resolver-level guards are applied using the `@UseGuards` decorator on a Resolver class. All MCP methods (`@Prompt`, `@Resource`, `@Tool`) in the resolver will be protected by these guards. Use this to enforce logic (e.g., role checks) for a specific group of capabilities.
|
|
546
|
+
This is a custom feature of this library. Resolver-level guards are applied using the `@UseGuards()` decorator (exported from `@nestjs-mcp/server`) on a Resolver class. All MCP methods (`@Prompt`, `@Resource`, `@Tool`) **within that specific resolver** will be protected by these guards. Use this to enforce logic (e.g., role checks) for a group of related capabilities.
|
|
398
547
|
|
|
399
548
|
```ts
|
|
400
549
|
import { UseGuards, Resolver, Prompt } from '@nestjs-mcp/server';
|
|
401
|
-
import {
|
|
550
|
+
import { RoleGuard } from './guards/role.guard';
|
|
402
551
|
|
|
403
|
-
@UseGuards(
|
|
404
|
-
@Resolver('
|
|
405
|
-
export class
|
|
406
|
-
@Prompt({ name: '
|
|
407
|
-
|
|
552
|
+
@UseGuards(RoleGuard)
|
|
553
|
+
@Resolver('admin')
|
|
554
|
+
export class AdminResolver {
|
|
555
|
+
@Prompt({ name: 'admin_action' })
|
|
556
|
+
adminAction(/*...*/) {
|
|
408
557
|
/* ... */
|
|
409
558
|
}
|
|
559
|
+
// ... other admin capabilities
|
|
410
560
|
}
|
|
411
561
|
```
|
|
412
562
|
|
|
413
|
-
### Method-level guards
|
|
563
|
+
### Method-level guards
|
|
414
564
|
|
|
415
|
-
This is a custom feature of this library. Method-level guards are applied using the `@UseGuards` decorator directly on
|
|
565
|
+
This is a custom feature of this library. Method-level guards are applied using the `@UseGuards()` decorator directly on an MCP capability method (`@Prompt`, `@Resource`, `@Tool`). Only the decorated method will be protected by these guards. Use this for fine-grained access control on specific capabilities.
|
|
416
566
|
|
|
417
567
|
```ts
|
|
418
|
-
import { UseGuards, Resolver, Prompt } from '@nestjs-mcp/server';
|
|
419
|
-
import {
|
|
568
|
+
import { UseGuards, Resolver, Prompt, Tool } from '@nestjs-mcp/server';
|
|
569
|
+
import { SpecificCheckGuard } from './guards/specific-check.guard';
|
|
420
570
|
|
|
421
571
|
@Resolver('mixed')
|
|
422
572
|
export class MixedResolver {
|
|
423
|
-
@Prompt({ name: '
|
|
573
|
+
@Prompt({ name: 'public_prompt' })
|
|
424
574
|
publicPrompt() {
|
|
425
|
-
/*
|
|
575
|
+
/* Publicly accessible */
|
|
426
576
|
}
|
|
427
577
|
|
|
428
|
-
@UseGuards(
|
|
429
|
-
@
|
|
430
|
-
|
|
431
|
-
/*
|
|
578
|
+
@UseGuards(SpecificCheckGuard)
|
|
579
|
+
@Tool({ name: 'protected_tool' })
|
|
580
|
+
protectedTool(/*...*/) {
|
|
581
|
+
/* Requires SpecificCheckGuard to pass */
|
|
432
582
|
}
|
|
433
583
|
}
|
|
434
584
|
```
|
|
435
585
|
|
|
586
|
+
**Important:** Resolver and Method-level guards **only run for MCP capability invocations**, not for the initial connection establishment handled by global guards. They use the custom `McpExecutionContext`.
|
|
587
|
+
|
|
436
588
|
### Guard Example
|
|
437
589
|
|
|
590
|
+
A guard for Resolver or Method-level protection:
|
|
591
|
+
|
|
438
592
|
```ts
|
|
439
|
-
|
|
440
|
-
import {
|
|
593
|
+
// src/guards/my-mcp.guard.ts
|
|
594
|
+
import { CanActivate, Injectable } from '@nestjs/common';
|
|
595
|
+
import { McpExecutionContext, SessionManager } from '@nestjs-mcp/server';
|
|
596
|
+
|
|
597
|
+
@Injectable()
|
|
598
|
+
export class MyMcpGuard implements CanActivate {
|
|
599
|
+
constructor(private readonly sessionManager: SessionManager) {}
|
|
441
600
|
|
|
442
|
-
export class MyGuard implements CanActivate {
|
|
443
601
|
canActivate(context: McpExecutionContext): boolean {
|
|
444
|
-
|
|
602
|
+
const sessionId = context.getSessionId();
|
|
603
|
+
if (!sessionId) return false;
|
|
604
|
+
|
|
605
|
+
const handlerArgs = context.getArgs();
|
|
606
|
+
|
|
607
|
+
const session = this.sessionManager.getSession(sessionId);
|
|
608
|
+
const request = session?.request;
|
|
609
|
+
const userAgent = request?.headers['user-agent'];
|
|
610
|
+
|
|
611
|
+
console.log(`Guard activated for session ${sessionId} from ${userAgent}`);
|
|
612
|
+
console.log('Handler args:', handlerArgs);
|
|
613
|
+
|
|
445
614
|
return true;
|
|
446
615
|
}
|
|
447
616
|
}
|
|
448
617
|
```
|
|
449
618
|
|
|
450
|
-
###
|
|
619
|
+
### MCP Execution Context
|
|
451
620
|
|
|
452
|
-
When implementing
|
|
621
|
+
When implementing **Resolver-level** or **Method-level** guards using `@UseGuards()` from this library, your `canActivate` method receives an `McpExecutionContext` instance. This context provides access to MCP-specific information:
|
|
453
622
|
|
|
454
|
-
```
|
|
455
|
-
import { CanActivate } from '@nestjs/common';
|
|
456
|
-
import { McpExecutionContext } from '@nestjs-mcp/server';
|
|
457
|
-
import { Request
|
|
623
|
+
```typescript
|
|
624
|
+
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
|
|
625
|
+
import { McpExecutionContext, SessionManager } from '@nestjs-mcp/server';
|
|
626
|
+
import { Request } from 'express';
|
|
458
627
|
|
|
459
628
|
@Injectable()
|
|
460
629
|
export class McpAuthGuard implements CanActivate {
|
|
630
|
+
constructor(private readonly sessionManager: SessionManager) {}
|
|
631
|
+
|
|
461
632
|
canActivate(context: McpExecutionContext): boolean {
|
|
462
|
-
|
|
463
|
-
|
|
633
|
+
const sessionId = context.getSessionId();
|
|
634
|
+
if (!sessionId) {
|
|
635
|
+
console.error('Guard Error: MCP Session ID not found in context.');
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const handlerArgs = context.getArgs<any>();
|
|
640
|
+
console.log('MCP Handler Arguments:', handlerArgs);
|
|
641
|
+
|
|
642
|
+
const session = this.sessionManager.getSession(sessionId);
|
|
643
|
+
if (!session) {
|
|
644
|
+
console.error(`Guard Error: Session not found for ID: ${sessionId}`);
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
const request = session.request as Request;
|
|
648
|
+
|
|
649
|
+
const authHeader = request.headers.authorization;
|
|
650
|
+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
651
|
+
console.log('Guard Denied: Missing or invalid Bearer token.');
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
const token = authHeader.split(' ')[1];
|
|
655
|
+
const isValidToken = token === 'VALID_TOKEN';
|
|
656
|
+
|
|
657
|
+
if (isValidToken) {
|
|
658
|
+
console.log(`Guard Passed for session ${sessionId} with token.`);
|
|
659
|
+
return true;
|
|
660
|
+
} else {
|
|
661
|
+
console.log(`Guard Denied: Invalid token for session ${sessionId}.`);
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
**Key points for `McpExecutionContext`:**
|
|
669
|
+
|
|
670
|
+
- `getSessionId()`: Retrieves the unique ID for the current MCP session. **Crucial** for relating the guard check to the session state stored by `SessionManager`.
|
|
671
|
+
- Arguments (`handlerArgs`): Provides the arguments passed specifically to the MCP handler method (`@Tool`, `@Prompt`, `@Resource`) being invoked. The structure of these arguments depends on the capability type and its definition (e.g., `params` for tools, `query`/`params` for resources). You access these via `context.getArgs()`, but be mindful of the actual structure based on the capability.
|
|
672
|
+
- Request Data: Use the `SessionManager` injected into your guard to fetch the session details (including the original `Request`) based on the `sessionId` obtained from the context.
|
|
673
|
+
- `switchToHttp().getResponse()` / `switchToHttp().getNext()`: These will throw errors as the Response object is not directly available or relevant in this context.
|
|
674
|
+
|
|
675
|
+
Use `SessionManager` injected into your guard to fetch the session details (including the original `Request`) based on the `sessionId` obtained from the context.
|
|
464
676
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
677
|
+
---
|
|
678
|
+
|
|
679
|
+
## Session Management
|
|
680
|
+
|
|
681
|
+
This library includes a `SessionManager` service responsible for tracking active MCP sessions. Each incoming MCP connection establishes a session, identified by a unique `sessionId`. The `SessionManager` typically stores the associated initial `Request` object for each session.
|
|
682
|
+
|
|
683
|
+
**Why is it important?**
|
|
684
|
+
|
|
685
|
+
- **Accessing Request Data:** Since MCP operations (tool calls, prompt executions) might happen independently of the initial HTTP connection (especially with streaming transports like SSE), the `SessionManager` provides a way to retrieve the original `Request` context associated with a specific `sessionId`. This is essential for guards or capability methods (within Resolvers) that need access to request headers, parameters, or other connection-specific details from the original request.
|
|
686
|
+
- **State Management:** While currently focused on storing the request, the `SessionManager` could be extended to store additional session-specific state if needed by your application.
|
|
468
687
|
|
|
469
|
-
|
|
470
|
-
const request = req as Request;
|
|
471
|
-
const response = res as Response;
|
|
688
|
+
**Usage Example (in a Resolver):**
|
|
472
689
|
|
|
473
|
-
|
|
474
|
-
const authHeader = request.headers.authorization;
|
|
690
|
+
Resolvers might need access to the original request, for example, to get user information or API keys passed in headers during the initial connection.
|
|
475
691
|
|
|
476
|
-
|
|
477
|
-
|
|
692
|
+
```typescript
|
|
693
|
+
import { Tool, Resolver, SessionManager } from '@nestjs-mcp/server';
|
|
694
|
+
import { RequestHandlerExtra } from '@nestjs-mcp/server'; // Provides sessionId
|
|
695
|
+
import { Request } from 'express';
|
|
696
|
+
import { CallToolResult } from '@modelcontextprotocol/sdk/types';
|
|
697
|
+
import { z } from 'zod';
|
|
698
|
+
|
|
699
|
+
const UserToolParams = z.object({
|
|
700
|
+
user_id: z.string().optional(),
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
@Resolver('user_tools') // No @Injectable() needed
|
|
704
|
+
export class UserToolsResolver {
|
|
705
|
+
// Inject SessionManager
|
|
706
|
+
constructor(private readonly sessionManager: SessionManager) {}
|
|
707
|
+
|
|
708
|
+
@Tool({
|
|
709
|
+
name: 'get_user_agent',
|
|
710
|
+
description:
|
|
711
|
+
'Gets the user agent from the original request for the session.',
|
|
712
|
+
paramSchema: UserToolParams,
|
|
713
|
+
})
|
|
714
|
+
getUserAgent(
|
|
715
|
+
params: z.infer<typeof UserToolParams>,
|
|
716
|
+
extra: RequestHandlerExtra, // Get extra info, including sessionId
|
|
717
|
+
): CallToolResult {
|
|
718
|
+
const sessionId = extra.sessionId;
|
|
719
|
+
if (!sessionId) {
|
|
720
|
+
return {
|
|
721
|
+
content: [{ type: 'text', text: 'Error: Session ID missing.' }],
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Use sessionId to get the session from the manager
|
|
726
|
+
const session = this.sessionManager.getSession(sessionId);
|
|
727
|
+
if (!session) {
|
|
728
|
+
return {
|
|
729
|
+
content: [
|
|
730
|
+
{
|
|
731
|
+
type: 'text',
|
|
732
|
+
text: `Error: Session not found for ID: ${sessionId}`,
|
|
733
|
+
},
|
|
734
|
+
],
|
|
735
|
+
};
|
|
478
736
|
}
|
|
479
737
|
|
|
480
|
-
// Access the
|
|
481
|
-
const
|
|
738
|
+
// Access the original request stored in the session
|
|
739
|
+
const request = session.request as Request;
|
|
740
|
+
const userAgent = request.headers['user-agent'] || 'Unknown';
|
|
482
741
|
|
|
483
|
-
return
|
|
742
|
+
return {
|
|
743
|
+
content: [
|
|
744
|
+
{ type: 'text', text: `Session ${sessionId} User Agent: ${userAgent}` },
|
|
745
|
+
],
|
|
746
|
+
};
|
|
484
747
|
}
|
|
485
748
|
}
|
|
486
749
|
```
|
|
487
750
|
|
|
488
|
-
|
|
751
|
+
In this example:
|
|
752
|
+
|
|
753
|
+
1. The `@Tool` method receives `extra: RequestHandlerExtra`, which contains the `sessionId`.
|
|
754
|
+
2. The `SessionManager` is injected into the `UserToolsResolver`.
|
|
755
|
+
3. The `sessionId` is used with `sessionManager.getSession()` to retrieve the session data.
|
|
756
|
+
4. The original `request` object is accessed from the retrieved session data.
|
|
757
|
+
|
|
758
|
+
The `SessionManager` is automatically registered as a provider when you use `McpModule.forRoot` or `McpModule.forRootAsync` and can be injected like any other NestJS provider.
|
|
759
|
+
|
|
760
|
+
---
|
|
761
|
+
|
|
762
|
+
## Transport Options
|
|
763
|
+
|
|
764
|
+
The MCP server can communicate over different transport mechanisms. This library includes built-in support for:
|
|
765
|
+
|
|
766
|
+
1. **Streamable (`/mcp` endpoint):** A common transport using standard HTTP POST requests and responses. Suitable for most request/response interactions. Enabled by default.
|
|
767
|
+
2. **SSE (Server-Sent Events) (`/sse` endpoint):** A transport mechanism allowing the server to push updates to the client over a single HTTP connection. Useful for streaming responses or long-running operations. **Note:** This is considered a legacy transport but remains supported for compatibility. Enabled by default.
|
|
768
|
+
|
|
769
|
+
You can configure which transports are enabled globally using the `transports` option in `McpModule.forRoot` or `McpModule.forRootAsync`.
|
|
770
|
+
|
|
771
|
+
**Configuration:**
|
|
772
|
+
|
|
773
|
+
```typescript
|
|
774
|
+
import { Module } from '@nestjs/common';
|
|
775
|
+
import { McpModule } from '@nestjs-mcp/server';
|
|
776
|
+
|
|
777
|
+
@Module({
|
|
778
|
+
imports: [
|
|
779
|
+
McpModule.forRoot({
|
|
780
|
+
name: 'My Server',
|
|
781
|
+
version: '1.0.0',
|
|
782
|
+
transports: {
|
|
783
|
+
streamable: { enabled: true }, // Keep streamable enabled (default)
|
|
784
|
+
sse: { enabled: false }, // Disable legacy SSE transport
|
|
785
|
+
},
|
|
786
|
+
}),
|
|
787
|
+
],
|
|
788
|
+
})
|
|
789
|
+
export class AppModule {}
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
**Default Configuration:**
|
|
489
793
|
|
|
490
|
-
|
|
491
|
-
- `message`: The current message from the request, containing:
|
|
492
|
-
- `req`: The Express Request object
|
|
493
|
-
- `res`: The Express Response object
|
|
494
|
-
- `getType()`: Returns the type of execution context (always 'mcp' for MCP operations)
|
|
495
|
-
- `getClass()`: Returns the class of the resolver
|
|
496
|
-
- `getArgs()`: Returns the arguments passed to the method
|
|
794
|
+
If the `transports` option is omitted, both `streamable` (`/mcp`) and `sse` (`/sse`) are enabled by default.
|
|
497
795
|
|
|
498
|
-
|
|
796
|
+
```typescript
|
|
797
|
+
import { Module } from '@nestjs/common';
|
|
798
|
+
import { McpModule } from '@nestjs-mcp/server';
|
|
799
|
+
|
|
800
|
+
@Module({
|
|
801
|
+
imports: [
|
|
802
|
+
McpModule.forRoot({
|
|
803
|
+
name: 'My Server',
|
|
804
|
+
version: '1.0.0',
|
|
805
|
+
// Both streamable and sse will be enabled
|
|
806
|
+
}),
|
|
807
|
+
],
|
|
808
|
+
})
|
|
809
|
+
export class AppModule {}
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
Disabling unused transports can slightly reduce the application's surface area and resource usage.
|
|
499
813
|
|
|
500
814
|
---
|
|
501
815
|
|
|
@@ -507,17 +821,19 @@ Use the Inspector Playground to interactively test and debug your MCP server end
|
|
|
507
821
|
- Invoke endpoints and view responses in real time
|
|
508
822
|
- Validate your server implementation against the MCP specification
|
|
509
823
|
|
|
510
|
-
To launch the Inspector Playground:
|
|
824
|
+
To launch the Inspector Playground (make sure your NestJS MCP server is running):
|
|
511
825
|
|
|
512
826
|
```sh
|
|
513
827
|
npx @modelcontextprotocol/inspector
|
|
514
828
|
```
|
|
515
829
|
|
|
830
|
+
It will typically connect to `http://localhost:3000` by default, or you can specify a different target URL.
|
|
831
|
+
|
|
516
832
|
---
|
|
517
833
|
|
|
518
834
|
## Examples
|
|
519
835
|
|
|
520
|
-
The [`examples/`](./examples/) directory contains ready-to-use scenarios demonstrating how to register and expose MCP capabilities
|
|
836
|
+
The [`examples/`](./examples/) directory contains ready-to-use scenarios demonstrating how to register and expose MCP capabilities.
|
|
521
837
|
|
|
522
838
|
Each example is self-contained and follows best practices. For advanced usage, see the code and documentation in each example.
|
|
523
839
|
|