@muzikanto/nestjs-mcp 1.0.1 → 1.1.1
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/CHANGELOG.md +12 -0
- package/README.md +176 -27
- package/dist/decorators/mcp-prompt.decorator.d.ts +20 -0
- package/dist/decorators/mcp-prompt.decorator.js +16 -0
- package/dist/decorators/mcp-tool.decorator.d.ts +4 -1
- package/dist/dto/McpMessage.dto.js +2 -2
- package/dist/dto/McpPrompt.dto.d.ts +4 -0
- package/dist/dto/McpPrompt.dto.js +30 -0
- package/dist/dto/McpPromptMessage.d.ts +5 -0
- package/dist/dto/McpPromptMessage.js +40 -0
- package/dist/dto/McpPromptMessages.dto.d.ts +4 -0
- package/dist/dto/McpPromptMessages.dto.js +26 -0
- package/dist/dto/McpPrompts.dto.d.ts +4 -0
- package/dist/dto/McpPrompts.dto.js +26 -0
- package/dist/dto/McpTool.dto.js +12 -3
- package/dist/dto/McpTools.dto.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp.controller.d.ts +10 -3
- package/dist/mcp.controller.js +95 -12
- package/dist/mcp.explorer.js +13 -0
- package/dist/mcp.module.d.ts +4 -2
- package/dist/mcp.module.js +17 -2
- package/dist/mcp.service.d.ts +10 -2
- package/dist/mcp.service.js +27 -2
- package/dist/utils/context.decorator.d.ts +1 -0
- package/dist/utils/context.decorator.js +5 -0
- package/dist/utils/inject-tokens.d.ts +1 -0
- package/dist/utils/inject-tokens.js +4 -0
- package/package.json +10 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# @muzikanto/nestjs-mcp
|
|
2
2
|
|
|
3
|
-

|
|
4
|
-

|
|
5
|
-

|
|
6
|
-

|
|
3
|
+
[](https://www.npmjs.com/package/@muzikanto/nestjs-mcp)
|
|
4
|
+
[]((https://www.npmjs.com/package/@muzikanto/nestjs-mcp))
|
|
5
|
+
[](https://github.com/Muzikanto/nestjs-mcp)
|
|
6
|
+
[](https://github.com/Muzikanto/nestjs-mcp/blob/main/LICENSE)
|
|
7
7
|
|
|
8
8
|
NestJS MCP (Model Context Protocol) module — allows you to create “tools” (functions) for LLM or HTTP, with automatic detection via decorators, validation, and integration with OpenAI Function Calls.
|
|
9
9
|
|
|
@@ -15,17 +15,24 @@ NestJS MCP (Model Context Protocol) module — allows you to create “tools”
|
|
|
15
15
|
- [Usage](#usage)
|
|
16
16
|
- [Connecting the MCP module](#connecting-the-mcp-module)
|
|
17
17
|
- [Create MCP tool](#create-mcp-tool)
|
|
18
|
+
- [Create MCP prompt](#create-mcp-prompt)
|
|
18
19
|
- [Calling MCP tools via HTTP](#calling-mcp-tools-via-http)
|
|
19
20
|
- [Obtaining all tools](#obtaining-all-tools)
|
|
21
|
+
- [Obtaining all prompts](#obtaining-all-prompts)
|
|
22
|
+
- [Obtain prompt](#obtain-prompt)
|
|
23
|
+
- [Auth guard](#auth-guard)
|
|
20
24
|
- [Integration with OpenAI Function Calls](#integration-with-openai-function-calls)
|
|
21
25
|
|
|
22
26
|
## Features
|
|
23
27
|
|
|
24
28
|
- Register MCP tools using the `@McpTool()` decorator
|
|
29
|
+
- Register MCP prompts using the `@McpPrompt()` decorator
|
|
25
30
|
- Automatic detection of all providers (tools) in the module
|
|
26
31
|
- Input data validation
|
|
27
32
|
- HTTP endpoint for calling tools (`POST /mcp`)
|
|
28
33
|
- Endpoint for a list of all tools (`GET /mcp/tools`)
|
|
34
|
+
- Endpoint for a list of all prompts (`GET /mcp/prompts`)
|
|
35
|
+
- Endpoint for prompt (`GET /mcp/prompts/:name`)
|
|
29
36
|
- Easy integration with LLM (OpenAI Function Calls)
|
|
30
37
|
- Full TypeScript typing
|
|
31
38
|
|
|
@@ -46,14 +53,14 @@ Peer dependencies: `@nestjs/common, @nestjs/core, reflect-metadata`
|
|
|
46
53
|
```ts
|
|
47
54
|
import { Module } from '@nestjs/common';
|
|
48
55
|
import { McpModule } from '@muzikanto/nestjs-mcp';
|
|
49
|
-
import {
|
|
56
|
+
import { TelegramSendMessageTool } from './tools/telegram-send-message.tool';
|
|
57
|
+
import { TelegramAutoReplyPrompt } from './prompts/telegram-auto-reply.prompt';
|
|
50
58
|
|
|
51
59
|
@Module({
|
|
52
60
|
imports: [
|
|
53
|
-
McpModule.forRoot(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
GetCurrentDateTool,
|
|
61
|
+
McpModule.forRoot({
|
|
62
|
+
providers: [TelegramSendMessageTool, TelegramAutoReplyPrompt],
|
|
63
|
+
}),
|
|
57
64
|
],
|
|
58
65
|
})
|
|
59
66
|
export class AppModule {}
|
|
@@ -63,21 +70,35 @@ export class AppModule {}
|
|
|
63
70
|
|
|
64
71
|
```ts
|
|
65
72
|
import { IMcpTool, McpTool } from '@muzikanto/nestjs-mcp';
|
|
73
|
+
import { Telegraf } from 'telegraf';
|
|
66
74
|
|
|
67
75
|
@McpTool()
|
|
68
|
-
export class
|
|
69
|
-
|
|
76
|
+
export class TelegramSendMessageTool implements IMcpTool<
|
|
77
|
+
{ chatId: string; text: string },
|
|
78
|
+
{ success: boolean }
|
|
79
|
+
> {
|
|
80
|
+
name = 'telegram.sendMessage';
|
|
70
81
|
|
|
71
82
|
inputSchema = {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
type: "object",
|
|
84
|
+
properties: {
|
|
85
|
+
chatId: {
|
|
86
|
+
type: "string",
|
|
87
|
+
description: "Telegram chat id"
|
|
88
|
+
},
|
|
89
|
+
text: {
|
|
90
|
+
type: "string",
|
|
91
|
+
description: "Message text"
|
|
92
|
+
}
|
|
75
93
|
},
|
|
76
|
-
|
|
94
|
+
required: ["chatId", "text"]
|
|
77
95
|
};
|
|
78
96
|
|
|
79
|
-
|
|
80
|
-
|
|
97
|
+
constructor(private readonly bot: Telegraf) {}
|
|
98
|
+
|
|
99
|
+
async execute(input: { chatId: string; text: string }) {
|
|
100
|
+
await this.bot.telegram.sendMessage(input.chatId, input.text);
|
|
101
|
+
return { success: true };
|
|
81
102
|
}
|
|
82
103
|
}
|
|
83
104
|
```
|
|
@@ -88,9 +109,10 @@ POST /mcp
|
|
|
88
109
|
|
|
89
110
|
```json
|
|
90
111
|
{
|
|
91
|
-
"type": "
|
|
112
|
+
"type": "telegram.sendMessage",
|
|
92
113
|
"payload": {
|
|
93
|
-
"
|
|
114
|
+
"chatId": "...",
|
|
115
|
+
"text": "Hi, how are you ?"
|
|
94
116
|
}
|
|
95
117
|
}
|
|
96
118
|
```
|
|
@@ -99,7 +121,7 @@ POST /mcp
|
|
|
99
121
|
```json
|
|
100
122
|
{
|
|
101
123
|
"data": {
|
|
102
|
-
"
|
|
124
|
+
"success": true
|
|
103
125
|
}
|
|
104
126
|
}
|
|
105
127
|
```
|
|
@@ -111,15 +133,132 @@ GET /mcp/tool
|
|
|
111
133
|
```json
|
|
112
134
|
[
|
|
113
135
|
{
|
|
114
|
-
"name": "
|
|
115
|
-
"description": "",
|
|
136
|
+
"name": "telegram.sendMessage",
|
|
137
|
+
"description": "Sent message via Telegram",
|
|
116
138
|
"inputSchema": {
|
|
117
|
-
"
|
|
139
|
+
"chatId": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"description": "Telegram chat ID"
|
|
142
|
+
},
|
|
143
|
+
"text": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "Message text"
|
|
146
|
+
}
|
|
118
147
|
}
|
|
119
148
|
}
|
|
120
149
|
]
|
|
121
150
|
```
|
|
122
151
|
|
|
152
|
+
### Create MCP prompt
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { IMcpPrompt, McpPrompt } from '@muzikanto/nestjs-mcp';
|
|
156
|
+
|
|
157
|
+
@McpPrompt()
|
|
158
|
+
export class TelegramAutoReplyPrompt implements IMcpPrompt<{ text: string; chatId: number; }> {
|
|
159
|
+
name = 'telegram_auto_reply';
|
|
160
|
+
description = 'Generate a short, fiendly reply to an incoming Telegram message and send it back to the same chat using teegram.sendMessage tool';
|
|
161
|
+
|
|
162
|
+
async execute({ text, chatId }: { text: string; chatId: number }) {
|
|
163
|
+
return [
|
|
164
|
+
{
|
|
165
|
+
role: "system",
|
|
166
|
+
content: `You are a friendly Telegram bot. Reply briefly and to the point.`
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
role: "user",
|
|
170
|
+
content: text
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
role: "assistant",
|
|
174
|
+
tool_call: {
|
|
175
|
+
name: "telegram.sendMessage",
|
|
176
|
+
arguments: {
|
|
177
|
+
chatId,
|
|
178
|
+
text: "{{model_output}}"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Obtaining all prompts
|
|
188
|
+
|
|
189
|
+
GET /mcp/prompts
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
[
|
|
193
|
+
{
|
|
194
|
+
"name": "telegram_auto_reply",
|
|
195
|
+
"description": "Generate a short, fiendly reply to an incoming Telegram message and send it back to the same chat using teegram.sendMessage tool"
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Obtainin prompt
|
|
201
|
+
|
|
202
|
+
POST /mcp/prompts/telegram_auto_reply
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"text": "Hi. How are you ?",
|
|
207
|
+
"chatId": 100000000
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Response
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"messages": [
|
|
215
|
+
{
|
|
216
|
+
"role": "system",
|
|
217
|
+
"content": "You are a friendly Telegram bot. Reply briefly and to the point."
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"role": "user",
|
|
221
|
+
"content": "Hi. How are you ?"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"role": "assistant",
|
|
225
|
+
"tool_call": {
|
|
226
|
+
"name": "telegram.sendMessage",
|
|
227
|
+
"arguments": {
|
|
228
|
+
"chatId": 100000000,
|
|
229
|
+
"text": "{{model_output}}"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Auth guard
|
|
238
|
+
```ts
|
|
239
|
+
import { McpModule } from '@muzikanto/nestjs-mcp';
|
|
240
|
+
import { Module, CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
|
|
241
|
+
|
|
242
|
+
@Injectable()
|
|
243
|
+
export class TestGuard implements CanActivate {
|
|
244
|
+
canActivate(context: ExecutionContext): Promise<boolean> {
|
|
245
|
+
const request = context.switchToHttp().getRequest();
|
|
246
|
+
const authHeader = request.headers['authorization'];
|
|
247
|
+
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
@Module({
|
|
253
|
+
imports: [
|
|
254
|
+
McpModule.forRoot({
|
|
255
|
+
guard: TestGuard
|
|
256
|
+
}),
|
|
257
|
+
],
|
|
258
|
+
})
|
|
259
|
+
export class AppModule {}
|
|
260
|
+
```
|
|
261
|
+
|
|
123
262
|
### Integration with OpenAI Function Calls
|
|
124
263
|
|
|
125
264
|
```ts
|
|
@@ -128,6 +267,7 @@ import OpenAI from 'openai';
|
|
|
128
267
|
|
|
129
268
|
const MCP_URL = 'http://localhost:3000/mcp';
|
|
130
269
|
const MCP_TOOLS_URL = 'http://localhost:3000/mcp/tools';
|
|
270
|
+
const MCP_TELEGRAM_PROMPT_URL = 'http://localhost:3000/mcp/prompts/telegram_auto_reply';
|
|
131
271
|
|
|
132
272
|
// Create OpenAI client
|
|
133
273
|
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
@@ -135,11 +275,19 @@ const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
|
135
275
|
/**
|
|
136
276
|
* Get all tools
|
|
137
277
|
*/
|
|
138
|
-
async function
|
|
278
|
+
async function getMcpTools() {
|
|
139
279
|
const response = await axios.get(MCP_TOOLS_URL);
|
|
140
280
|
return response.data;
|
|
141
281
|
}
|
|
142
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Get all prompts
|
|
285
|
+
*/
|
|
286
|
+
async function getMcpPrompt() {
|
|
287
|
+
const response = await axios.post(MCP_TELEGRAM_PROMPT_URL, {/* propmpt generation arguments */});
|
|
288
|
+
return response.data;
|
|
289
|
+
}
|
|
290
|
+
|
|
143
291
|
/**
|
|
144
292
|
* Request mcp tool
|
|
145
293
|
*/
|
|
@@ -156,12 +304,13 @@ async function callMcpTool(toolName: string, payload: Record<string, any>) {
|
|
|
156
304
|
* Example
|
|
157
305
|
*/
|
|
158
306
|
(async () => {
|
|
159
|
-
const
|
|
307
|
+
const toolsResponse = await getMcpTools();
|
|
308
|
+
const promptResponse = await getMcpPrompt();
|
|
160
309
|
|
|
161
310
|
const completion = await client.chat.completions.create({
|
|
162
311
|
model: 'gpt-4.1-mini',
|
|
163
|
-
messages:
|
|
164
|
-
functions,
|
|
312
|
+
messages: promptResponse.messages,
|
|
313
|
+
functions: toolsResponse.tools,
|
|
165
314
|
function_call: 'auto',
|
|
166
315
|
});
|
|
167
316
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
export type IMcpPromptMessage = {
|
|
3
|
+
role: string;
|
|
4
|
+
content?: string;
|
|
5
|
+
tool_call?: {
|
|
6
|
+
name: string;
|
|
7
|
+
arguments: object;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export interface IMcpPrompt<Payload = any, Result extends IMcpPromptMessage[] = IMcpPromptMessage[]> {
|
|
11
|
+
name: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
inputSchema?: object | object[];
|
|
14
|
+
execute(input: Payload): Promise<Result>;
|
|
15
|
+
}
|
|
16
|
+
export declare const MCP_PROMPT_METADATA = "mcp:prompt-class";
|
|
17
|
+
/**
|
|
18
|
+
* Декоратор класса для MCP prompt
|
|
19
|
+
*/
|
|
20
|
+
export declare const McpPrompt: () => (target: any) => void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.McpPrompt = exports.MCP_PROMPT_METADATA = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
require("reflect-metadata");
|
|
6
|
+
exports.MCP_PROMPT_METADATA = "mcp:prompt-class";
|
|
7
|
+
/**
|
|
8
|
+
* Декоратор класса для MCP prompt
|
|
9
|
+
*/
|
|
10
|
+
const McpPrompt = () => {
|
|
11
|
+
return (target) => {
|
|
12
|
+
(0, common_1.Injectable)()(target);
|
|
13
|
+
Reflect.defineMetadata(exports.MCP_PROMPT_METADATA, {}, target);
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
exports.McpPrompt = McpPrompt;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
+
export type IMcpToolContext = {
|
|
3
|
+
request: any;
|
|
4
|
+
};
|
|
2
5
|
export interface IMcpTool<Payload = any, Result = any> {
|
|
3
6
|
name: string;
|
|
4
7
|
description?: string;
|
|
5
8
|
inputSchema?: object | object[];
|
|
6
|
-
execute(input: Payload): Promise<Result>;
|
|
9
|
+
execute(input: Payload, context: IMcpToolContext): Promise<Result>;
|
|
7
10
|
}
|
|
8
11
|
export declare const MCP_TOOL_METADATA = "mcp:tool-class";
|
|
9
12
|
/**
|
|
@@ -17,10 +17,10 @@ class McpMessageDto {
|
|
|
17
17
|
}
|
|
18
18
|
exports.McpMessageDto = McpMessageDto;
|
|
19
19
|
__decorate([
|
|
20
|
-
(0, swagger_1.ApiProperty)({ type:
|
|
20
|
+
(0, swagger_1.ApiProperty)({ type: "string", description: "Tool name" }),
|
|
21
21
|
__metadata("design:type", String)
|
|
22
22
|
], McpMessageDto.prototype, "type", void 0);
|
|
23
23
|
__decorate([
|
|
24
|
-
(0, swagger_1.ApiProperty)({ description:
|
|
24
|
+
(0, swagger_1.ApiProperty)({ description: "Tool handler payload" }),
|
|
25
25
|
__metadata("design:type", Object)
|
|
26
26
|
], McpMessageDto.prototype, "payload", void 0);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.McpPromptDto = void 0;
|
|
13
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
14
|
+
class McpPromptDto {
|
|
15
|
+
name;
|
|
16
|
+
description;
|
|
17
|
+
}
|
|
18
|
+
exports.McpPromptDto = McpPromptDto;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, swagger_1.ApiProperty)({ type: "string", description: "Propmt name" }),
|
|
21
|
+
__metadata("design:type", String)
|
|
22
|
+
], McpPromptDto.prototype, "name", void 0);
|
|
23
|
+
__decorate([
|
|
24
|
+
(0, swagger_1.ApiProperty)({
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "Propmt description",
|
|
27
|
+
nullable: true,
|
|
28
|
+
}),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], McpPromptDto.prototype, "description", void 0);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.McpPromptMessageDto = void 0;
|
|
13
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
14
|
+
class McpPromptMessageDto {
|
|
15
|
+
role;
|
|
16
|
+
content;
|
|
17
|
+
tool_call;
|
|
18
|
+
}
|
|
19
|
+
exports.McpPromptMessageDto = McpPromptMessageDto;
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, swagger_1.ApiProperty)({ type: "string", description: "AI role" }),
|
|
22
|
+
__metadata("design:type", String)
|
|
23
|
+
], McpPromptMessageDto.prototype, "role", void 0);
|
|
24
|
+
__decorate([
|
|
25
|
+
(0, swagger_1.ApiProperty)({
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Request ai message",
|
|
28
|
+
nullable: true,
|
|
29
|
+
}),
|
|
30
|
+
__metadata("design:type", String)
|
|
31
|
+
], McpPromptMessageDto.prototype, "content", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, swagger_1.ApiProperty)({
|
|
34
|
+
type: "object",
|
|
35
|
+
description: "Tool call context",
|
|
36
|
+
nullable: true,
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
}),
|
|
39
|
+
__metadata("design:type", Object)
|
|
40
|
+
], McpPromptMessageDto.prototype, "tool_call", void 0);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.McpPromptMessagesDto = void 0;
|
|
13
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
14
|
+
const McpPromptMessage_1 = require("./McpPromptMessage");
|
|
15
|
+
class McpPromptMessagesDto {
|
|
16
|
+
messages;
|
|
17
|
+
}
|
|
18
|
+
exports.McpPromptMessagesDto = McpPromptMessagesDto;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, swagger_1.ApiProperty)({
|
|
21
|
+
type: McpPromptMessage_1.McpPromptMessageDto,
|
|
22
|
+
isArray: true,
|
|
23
|
+
description: "Messages list",
|
|
24
|
+
}),
|
|
25
|
+
__metadata("design:type", Array)
|
|
26
|
+
], McpPromptMessagesDto.prototype, "messages", void 0);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.McpPromptsDto = void 0;
|
|
13
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
14
|
+
const McpPrompt_dto_1 = require("./McpPrompt.dto");
|
|
15
|
+
class McpPromptsDto {
|
|
16
|
+
prompts;
|
|
17
|
+
}
|
|
18
|
+
exports.McpPromptsDto = McpPromptsDto;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, swagger_1.ApiProperty)({
|
|
21
|
+
type: McpPrompt_dto_1.McpPromptDto,
|
|
22
|
+
isArray: true,
|
|
23
|
+
description: "Prompts list",
|
|
24
|
+
}),
|
|
25
|
+
__metadata("design:type", Array)
|
|
26
|
+
], McpPromptsDto.prototype, "prompts", void 0);
|
package/dist/dto/McpTool.dto.js
CHANGED
|
@@ -18,14 +18,23 @@ class McpToolDto {
|
|
|
18
18
|
}
|
|
19
19
|
exports.McpToolDto = McpToolDto;
|
|
20
20
|
__decorate([
|
|
21
|
-
(0, swagger_1.ApiProperty)({ type:
|
|
21
|
+
(0, swagger_1.ApiProperty)({ type: "string", description: "Tool name" }),
|
|
22
22
|
__metadata("design:type", String)
|
|
23
23
|
], McpToolDto.prototype, "name", void 0);
|
|
24
24
|
__decorate([
|
|
25
|
-
(0, swagger_1.ApiProperty)({
|
|
25
|
+
(0, swagger_1.ApiProperty)({
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Tool description",
|
|
28
|
+
nullable: true,
|
|
29
|
+
}),
|
|
26
30
|
__metadata("design:type", String)
|
|
27
31
|
], McpToolDto.prototype, "description", void 0);
|
|
28
32
|
__decorate([
|
|
29
|
-
(0, swagger_1.ApiProperty)({
|
|
33
|
+
(0, swagger_1.ApiProperty)({
|
|
34
|
+
type: "object",
|
|
35
|
+
description: "Tool validation schema",
|
|
36
|
+
nullable: true,
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
}),
|
|
30
39
|
__metadata("design:type", Object)
|
|
31
40
|
], McpToolDto.prototype, "parameters", void 0);
|
package/dist/dto/McpTools.dto.js
CHANGED
|
@@ -17,6 +17,6 @@ class McpToolsDto {
|
|
|
17
17
|
}
|
|
18
18
|
exports.McpToolsDto = McpToolsDto;
|
|
19
19
|
__decorate([
|
|
20
|
-
(0, swagger_1.ApiProperty)({ type: McpTool_dto_1.McpToolDto, isArray: true, description:
|
|
20
|
+
(0, swagger_1.ApiProperty)({ type: McpTool_dto_1.McpToolDto, isArray: true, description: "Tools list" }),
|
|
21
21
|
__metadata("design:type", Array)
|
|
22
22
|
], McpToolsDto.prototype, "tools", void 0);
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./mcp.module"), exports);
|
|
18
18
|
__exportStar(require("./decorators/mcp-tool.decorator"), exports);
|
|
19
|
+
__exportStar(require("./decorators/mcp-prompt.decorator"), exports);
|
package/dist/mcp.controller.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { ExecutionContext, CanActivate } from "@nestjs/common";
|
|
1
2
|
import { McpService } from "./mcp.service";
|
|
2
3
|
import { McpMessageDto } from "./dto/McpMessage.dto";
|
|
3
4
|
import { McpToolsDto } from "./dto/McpTools.dto";
|
|
5
|
+
import { McpPromptsDto } from "./dto/McpPrompts.dto";
|
|
6
|
+
import { McpPromptMessagesDto } from "./dto/McpPromptMessages.dto";
|
|
4
7
|
export declare class McpController {
|
|
5
8
|
private readonly service;
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
private readonly guard;
|
|
10
|
+
constructor(service: McpService, guard: CanActivate);
|
|
11
|
+
handle(body: McpMessageDto, request: any, context: ExecutionContext): Promise<{
|
|
8
12
|
success: boolean;
|
|
9
13
|
data: any;
|
|
10
14
|
error?: undefined;
|
|
@@ -13,5 +17,8 @@ export declare class McpController {
|
|
|
13
17
|
error: any;
|
|
14
18
|
data?: undefined;
|
|
15
19
|
}>;
|
|
16
|
-
getTools(): Promise<McpToolsDto>;
|
|
20
|
+
getTools(context: ExecutionContext): Promise<McpToolsDto>;
|
|
21
|
+
getPrompts(context: ExecutionContext): Promise<McpPromptsDto>;
|
|
22
|
+
getPrompt(name: string, body: object, context: ExecutionContext): Promise<McpPromptMessagesDto>;
|
|
23
|
+
private checkGuard;
|
|
17
24
|
}
|
package/dist/mcp.controller.js
CHANGED
|
@@ -18,53 +18,136 @@ const mcp_service_1 = require("./mcp.service");
|
|
|
18
18
|
const McpMessage_dto_1 = require("./dto/McpMessage.dto");
|
|
19
19
|
const swagger_1 = require("@nestjs/swagger");
|
|
20
20
|
const McpTools_dto_1 = require("./dto/McpTools.dto");
|
|
21
|
+
const McpPrompts_dto_1 = require("./dto/McpPrompts.dto");
|
|
22
|
+
const McpPromptMessages_dto_1 = require("./dto/McpPromptMessages.dto");
|
|
23
|
+
const context_decorator_1 = require("./utils/context.decorator");
|
|
24
|
+
const inject_tokens_1 = require("./utils/inject-tokens");
|
|
21
25
|
let McpController = class McpController {
|
|
22
26
|
service;
|
|
23
|
-
|
|
27
|
+
guard;
|
|
28
|
+
constructor(service, guard) {
|
|
24
29
|
this.service = service;
|
|
30
|
+
this.guard = guard;
|
|
25
31
|
}
|
|
26
|
-
async handle(body) {
|
|
27
|
-
|
|
32
|
+
async handle(body, request, context) {
|
|
33
|
+
await this.checkGuard(context);
|
|
34
|
+
return this.service.sendMessage(body, { request });
|
|
28
35
|
}
|
|
29
|
-
async getTools() {
|
|
36
|
+
async getTools(context) {
|
|
37
|
+
await this.checkGuard(context);
|
|
30
38
|
const tools = this.service.listTools();
|
|
31
39
|
return { tools };
|
|
32
40
|
}
|
|
41
|
+
async getPrompts(context) {
|
|
42
|
+
await this.checkGuard(context);
|
|
43
|
+
const prompts = this.service.listPrompts();
|
|
44
|
+
return { prompts };
|
|
45
|
+
}
|
|
46
|
+
async getPrompt(name, body, context) {
|
|
47
|
+
await this.checkGuard(context);
|
|
48
|
+
const messages = await this.service.getPrompt(name, body);
|
|
49
|
+
return {
|
|
50
|
+
messages,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async checkGuard(context) {
|
|
54
|
+
if (!(await this.guard.canActivate(context))) {
|
|
55
|
+
throw new common_1.ForbiddenException();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
33
58
|
};
|
|
34
59
|
exports.McpController = McpController;
|
|
35
60
|
__decorate([
|
|
36
61
|
(0, common_1.Post)(),
|
|
37
62
|
(0, common_1.Header)("Content-Type", "application/json"),
|
|
38
63
|
(0, swagger_1.ApiOperation)({
|
|
39
|
-
summary:
|
|
64
|
+
summary: "Request tool",
|
|
40
65
|
}),
|
|
41
66
|
(0, swagger_1.ApiResponse)({
|
|
42
67
|
status: 200,
|
|
43
|
-
description:
|
|
68
|
+
description: "Tool execution result",
|
|
44
69
|
}),
|
|
45
70
|
(0, swagger_1.ApiBadRequestResponse)({
|
|
46
|
-
description:
|
|
71
|
+
description: "Invalid request body",
|
|
72
|
+
}),
|
|
73
|
+
(0, swagger_1.ApiForbiddenResponse)({
|
|
74
|
+
description: "No access to method",
|
|
47
75
|
}),
|
|
48
76
|
__param(0, (0, common_1.Body)()),
|
|
77
|
+
__param(1, (0, common_1.Request)()),
|
|
78
|
+
__param(2, (0, context_decorator_1.Context)()),
|
|
49
79
|
__metadata("design:type", Function),
|
|
50
|
-
__metadata("design:paramtypes", [McpMessage_dto_1.McpMessageDto]),
|
|
80
|
+
__metadata("design:paramtypes", [McpMessage_dto_1.McpMessageDto, Object, Object]),
|
|
51
81
|
__metadata("design:returntype", Promise)
|
|
52
82
|
], McpController.prototype, "handle", null);
|
|
53
83
|
__decorate([
|
|
54
84
|
(0, common_1.Get)("tools"),
|
|
55
85
|
(0, swagger_1.ApiOperation)({
|
|
56
|
-
summary:
|
|
86
|
+
summary: "Get tool list",
|
|
57
87
|
}),
|
|
58
88
|
(0, swagger_1.ApiResponse)({
|
|
59
89
|
status: 200,
|
|
60
|
-
description:
|
|
90
|
+
description: "Tools list",
|
|
61
91
|
type: McpTools_dto_1.McpToolsDto,
|
|
62
92
|
}),
|
|
93
|
+
(0, swagger_1.ApiForbiddenResponse)({
|
|
94
|
+
description: "No access to method",
|
|
95
|
+
}),
|
|
96
|
+
__param(0, (0, context_decorator_1.Context)()),
|
|
63
97
|
__metadata("design:type", Function),
|
|
64
|
-
__metadata("design:paramtypes", []),
|
|
98
|
+
__metadata("design:paramtypes", [Object]),
|
|
65
99
|
__metadata("design:returntype", Promise)
|
|
66
100
|
], McpController.prototype, "getTools", null);
|
|
101
|
+
__decorate([
|
|
102
|
+
(0, common_1.Get)("prompts"),
|
|
103
|
+
(0, swagger_1.ApiOperation)({
|
|
104
|
+
summary: "Get prompt list",
|
|
105
|
+
}),
|
|
106
|
+
(0, swagger_1.ApiResponse)({
|
|
107
|
+
status: 200,
|
|
108
|
+
description: "Prompts list",
|
|
109
|
+
type: McpPrompts_dto_1.McpPromptsDto,
|
|
110
|
+
}),
|
|
111
|
+
(0, swagger_1.ApiForbiddenResponse)({
|
|
112
|
+
description: "No access to method",
|
|
113
|
+
}),
|
|
114
|
+
__param(0, (0, context_decorator_1.Context)()),
|
|
115
|
+
__metadata("design:type", Function),
|
|
116
|
+
__metadata("design:paramtypes", [Object]),
|
|
117
|
+
__metadata("design:returntype", Promise)
|
|
118
|
+
], McpController.prototype, "getPrompts", null);
|
|
119
|
+
__decorate([
|
|
120
|
+
(0, common_1.Post)("prompts/:name"),
|
|
121
|
+
(0, swagger_1.ApiOperation)({
|
|
122
|
+
summary: "Generate messages by prompt name",
|
|
123
|
+
}),
|
|
124
|
+
(0, swagger_1.ApiBody)({
|
|
125
|
+
description: "Any body structure",
|
|
126
|
+
type: Object, // Указываем, что тело может быть любым объектом
|
|
127
|
+
}),
|
|
128
|
+
(0, swagger_1.ApiResponse)({
|
|
129
|
+
status: 200,
|
|
130
|
+
description: "Prompt messages",
|
|
131
|
+
type: McpPromptMessages_dto_1.McpPromptMessagesDto,
|
|
132
|
+
}),
|
|
133
|
+
(0, swagger_1.ApiNotFoundResponse)({
|
|
134
|
+
description: "Not found prompt",
|
|
135
|
+
}),
|
|
136
|
+
(0, swagger_1.ApiBadRequestResponse)({
|
|
137
|
+
description: "Invalid prompt arguments",
|
|
138
|
+
}),
|
|
139
|
+
(0, swagger_1.ApiForbiddenResponse)({
|
|
140
|
+
description: "No access to method",
|
|
141
|
+
}),
|
|
142
|
+
__param(0, (0, common_1.Param)("name")),
|
|
143
|
+
__param(1, (0, common_1.Body)()),
|
|
144
|
+
__param(2, (0, context_decorator_1.Context)()),
|
|
145
|
+
__metadata("design:type", Function),
|
|
146
|
+
__metadata("design:paramtypes", [String, Object, Object]),
|
|
147
|
+
__metadata("design:returntype", Promise)
|
|
148
|
+
], McpController.prototype, "getPrompt", null);
|
|
67
149
|
exports.McpController = McpController = __decorate([
|
|
68
150
|
(0, common_1.Controller)("mcp"),
|
|
69
|
-
|
|
151
|
+
__param(1, (0, common_1.Inject)(inject_tokens_1.MCP_GUARD)),
|
|
152
|
+
__metadata("design:paramtypes", [mcp_service_1.McpService, Object])
|
|
70
153
|
], McpController);
|
package/dist/mcp.explorer.js
CHANGED
|
@@ -14,6 +14,7 @@ const core_1 = require("@nestjs/core");
|
|
|
14
14
|
const common_1 = require("@nestjs/common");
|
|
15
15
|
const mcp_service_1 = require("./mcp.service");
|
|
16
16
|
const mcp_tool_decorator_1 = require("./decorators/mcp-tool.decorator");
|
|
17
|
+
const mcp_prompt_decorator_1 = require("./decorators/mcp-prompt.decorator");
|
|
17
18
|
let McpExplorer = class McpExplorer {
|
|
18
19
|
discovery;
|
|
19
20
|
mcpService;
|
|
@@ -35,6 +36,18 @@ let McpExplorer = class McpExplorer {
|
|
|
35
36
|
}
|
|
36
37
|
this.mcpService.registerTool(instance.name, instance);
|
|
37
38
|
});
|
|
39
|
+
providers.forEach(({ instance, metatype }) => {
|
|
40
|
+
if (!instance || !metatype)
|
|
41
|
+
return;
|
|
42
|
+
const metadata = Reflect.getMetadata(mcp_prompt_decorator_1.MCP_PROMPT_METADATA, metatype);
|
|
43
|
+
if (!metadata)
|
|
44
|
+
return;
|
|
45
|
+
// Проверка интерфейса
|
|
46
|
+
if (typeof instance.execute !== "function") {
|
|
47
|
+
throw new Error(`MCP Prompt ${instance.name} must implement IMcpPrompt with execute() method`);
|
|
48
|
+
}
|
|
49
|
+
this.mcpService.registerPrompt(instance.name, instance);
|
|
50
|
+
});
|
|
38
51
|
}
|
|
39
52
|
};
|
|
40
53
|
exports.McpExplorer = McpExplorer;
|
package/dist/mcp.module.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { DynamicModule, ModuleMetadata } from "@nestjs/common";
|
|
2
|
-
type Metadata = Pick<ModuleMetadata,
|
|
1
|
+
import { CanActivate, DynamicModule, ModuleMetadata, Provider } from "@nestjs/common";
|
|
2
|
+
type Metadata = Pick<ModuleMetadata, "providers" | "imports" | "exports"> & {
|
|
3
|
+
guard?: Provider<CanActivate>;
|
|
4
|
+
};
|
|
3
5
|
export declare class McpModule {
|
|
4
6
|
static forRoot(metadata?: Metadata): DynamicModule;
|
|
5
7
|
}
|
package/dist/mcp.module.js
CHANGED
|
@@ -13,18 +13,33 @@ const core_1 = require("@nestjs/core");
|
|
|
13
13
|
const mcp_service_1 = require("./mcp.service");
|
|
14
14
|
const mcp_explorer_1 = require("./mcp.explorer");
|
|
15
15
|
const mcp_controller_1 = require("./mcp.controller");
|
|
16
|
+
const inject_tokens_1 = require("./utils/inject-tokens");
|
|
17
|
+
const publicGuard = { canActivate: () => Promise.resolve(true) };
|
|
16
18
|
let McpModule = McpModule_1 = class McpModule {
|
|
17
19
|
static forRoot(metadata = {}) {
|
|
20
|
+
const guardProvider = metadata.guard
|
|
21
|
+
? { provide: inject_tokens_1.MCP_GUARD, useExisting: metadata.guard }
|
|
22
|
+
: {
|
|
23
|
+
provide: inject_tokens_1.MCP_GUARD,
|
|
24
|
+
useValue: publicGuard,
|
|
25
|
+
};
|
|
18
26
|
return {
|
|
19
27
|
module: McpModule_1,
|
|
20
28
|
imports: [core_1.DiscoveryModule, ...(metadata.imports || [])],
|
|
21
|
-
providers: [
|
|
22
|
-
|
|
29
|
+
providers: [
|
|
30
|
+
mcp_service_1.McpService,
|
|
31
|
+
mcp_explorer_1.McpExplorer,
|
|
32
|
+
guardProvider,
|
|
33
|
+
...(metadata.guard ? [metadata.guard] : []),
|
|
34
|
+
...(metadata.providers || []),
|
|
35
|
+
],
|
|
36
|
+
exports: [mcp_service_1.McpService, ...(metadata.exports || [])],
|
|
23
37
|
controllers: [mcp_controller_1.McpController],
|
|
24
38
|
};
|
|
25
39
|
}
|
|
26
40
|
};
|
|
27
41
|
exports.McpModule = McpModule;
|
|
28
42
|
exports.McpModule = McpModule = McpModule_1 = __decorate([
|
|
43
|
+
(0, common_1.Global)(),
|
|
29
44
|
(0, common_1.Module)({})
|
|
30
45
|
], McpModule);
|
package/dist/mcp.service.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OnModuleInit } from "@nestjs/common";
|
|
2
|
-
import { IMcpTool } from "./decorators/mcp-tool.decorator";
|
|
2
|
+
import { IMcpTool, IMcpToolContext } from "./decorators/mcp-tool.decorator";
|
|
3
|
+
import { IMcpPrompt } from "./decorators/mcp-prompt.decorator";
|
|
3
4
|
export interface McpMessage {
|
|
4
5
|
type: string;
|
|
5
6
|
payload: any;
|
|
@@ -11,6 +12,7 @@ export interface McpResponse {
|
|
|
11
12
|
}
|
|
12
13
|
export declare class McpService implements OnModuleInit {
|
|
13
14
|
private tools;
|
|
15
|
+
private prompts;
|
|
14
16
|
private ajv;
|
|
15
17
|
onModuleInit(): void;
|
|
16
18
|
/**
|
|
@@ -21,14 +23,20 @@ export declare class McpService implements OnModuleInit {
|
|
|
21
23
|
description: string;
|
|
22
24
|
parameters: object;
|
|
23
25
|
}[];
|
|
26
|
+
listPrompts(): {
|
|
27
|
+
name: string;
|
|
28
|
+
description: string;
|
|
29
|
+
}[];
|
|
24
30
|
registerTool(name: string, handler: IMcpTool): void;
|
|
31
|
+
registerPrompt(name: string, handler: IMcpPrompt): void;
|
|
32
|
+
getPrompt(name: string, payload: object): Promise<import("./decorators/mcp-prompt.decorator").IMcpPromptMessage[]>;
|
|
25
33
|
/**
|
|
26
34
|
* Отправить сообщение в MCP "сервер"
|
|
27
35
|
*/
|
|
28
36
|
sendMessage(msg: {
|
|
29
37
|
type: string;
|
|
30
38
|
payload: any;
|
|
31
|
-
}): Promise<{
|
|
39
|
+
}, context: IMcpToolContext): Promise<{
|
|
32
40
|
success: boolean;
|
|
33
41
|
data: any;
|
|
34
42
|
error?: undefined;
|
package/dist/mcp.service.js
CHANGED
|
@@ -11,6 +11,7 @@ const common_1 = require("@nestjs/common");
|
|
|
11
11
|
const ajv_1 = require("ajv");
|
|
12
12
|
let McpService = class McpService {
|
|
13
13
|
tools = new Map();
|
|
14
|
+
prompts = new Map();
|
|
14
15
|
ajv = new ajv_1.default();
|
|
15
16
|
onModuleInit() {
|
|
16
17
|
// console.log('MCP Service initialized');
|
|
@@ -25,13 +26,37 @@ let McpService = class McpService {
|
|
|
25
26
|
parameters: t.inputSchema || {},
|
|
26
27
|
}));
|
|
27
28
|
}
|
|
29
|
+
listPrompts() {
|
|
30
|
+
return Array.from(this.prompts.values()).map((t) => ({
|
|
31
|
+
name: t.name,
|
|
32
|
+
description: t.description || "",
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
28
35
|
registerTool(name, handler) {
|
|
29
36
|
this.tools.set(name, handler);
|
|
30
37
|
}
|
|
38
|
+
registerPrompt(name, handler) {
|
|
39
|
+
this.prompts.set(name, handler);
|
|
40
|
+
}
|
|
41
|
+
getPrompt(name, payload) {
|
|
42
|
+
if (!this.prompts.has(name)) {
|
|
43
|
+
throw new common_1.NotFoundException("Not found prompt");
|
|
44
|
+
}
|
|
45
|
+
const prompt = this.prompts.get(name);
|
|
46
|
+
// Валидация через AJV, если есть inputSchema
|
|
47
|
+
if (prompt.inputSchema) {
|
|
48
|
+
const validate = this.ajv.compile(prompt.inputSchema);
|
|
49
|
+
const valid = validate(payload);
|
|
50
|
+
if (!valid) {
|
|
51
|
+
throw new common_1.NotFoundException("Invalid prompt arguments");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return prompt.execute(payload);
|
|
55
|
+
}
|
|
31
56
|
/**
|
|
32
57
|
* Отправить сообщение в MCP "сервер"
|
|
33
58
|
*/
|
|
34
|
-
async sendMessage(msg) {
|
|
59
|
+
async sendMessage(msg, context) {
|
|
35
60
|
const tool = this.tools.get(msg.type);
|
|
36
61
|
if (!tool) {
|
|
37
62
|
return { success: false, error: `Unknown tool: "${msg.type}"` };
|
|
@@ -45,7 +70,7 @@ let McpService = class McpService {
|
|
|
45
70
|
}
|
|
46
71
|
}
|
|
47
72
|
try {
|
|
48
|
-
const result = await tool.execute(msg.payload);
|
|
73
|
+
const result = await tool.execute(msg.payload, context);
|
|
49
74
|
return { success: true, data: result };
|
|
50
75
|
}
|
|
51
76
|
catch (err) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const Context: (...dataOrPipes: unknown[]) => ParameterDecorator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const MCP_GUARD = "MCP:guard";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muzikanto/nestjs-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "NestJS MCP (Model Context Protocol) module for creating tools for LLM or HTTP with validation, decorators, and OpenAI Function Calls integration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nestjs",
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsc",
|
|
21
21
|
"prepublishOnly": "npm run build",
|
|
22
|
+
"lint": "prettier --check 'src/**/*.ts'",
|
|
23
|
+
"format": "prettier --write 'src/**/*.ts'",
|
|
22
24
|
"ch": "changeset",
|
|
23
25
|
"vers": "changeset version",
|
|
24
26
|
"pub": "changeset publish"
|
|
@@ -49,8 +51,15 @@
|
|
|
49
51
|
"name": "Maxim Schiriy"
|
|
50
52
|
}
|
|
51
53
|
],
|
|
54
|
+
"homepage": "https://github.com/Muzikanto/nestjs-mcp#readme",
|
|
52
55
|
"repository": {
|
|
53
56
|
"type": "git",
|
|
54
57
|
"url": "https://github.com/Muzikanto/nestjs-mcp"
|
|
58
|
+
},
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/Muzikanto/nestjs-mcp/issues"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=18.0.0"
|
|
55
64
|
}
|
|
56
65
|
}
|