@qodalis/cli-server-node 1.0.0-beta.6 → 1.0.0-beta.7
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 +223 -1
- package/dist/package.json +77 -0
- package/dist/src/auth/cli-server-auth-gate.d.ts +2 -0
- package/dist/src/auth/cli-server-auth-gate.d.ts.map +1 -1
- package/dist/src/auth/cli-server-auth-gate.js +3 -0
- package/dist/src/auth/cli-server-auth-gate.js.map +1 -1
- package/dist/src/auth/cli-server-auth.d.ts +2 -0
- package/dist/src/auth/cli-server-auth.d.ts.map +1 -1
- package/dist/src/auth/cli-server-auth.js.map +1 -1
- package/dist/src/create-cli-server.d.ts +26 -0
- package/dist/src/create-cli-server.d.ts.map +1 -1
- package/dist/src/create-cli-server.js +77 -2
- package/dist/src/create-cli-server.js.map +1 -1
- package/dist/src/extensions/cli-builder.d.ts +10 -0
- package/dist/src/extensions/cli-builder.d.ts.map +1 -1
- package/dist/src/extensions/cli-builder.js +14 -0
- package/dist/src/extensions/cli-builder.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +23 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/index.d.ts +10 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +34 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/mcp/mcp-controller.d.ts +54 -0
- package/dist/src/mcp/mcp-controller.d.ts.map +1 -0
- package/dist/src/mcp/mcp-controller.js +358 -0
- package/dist/src/mcp/mcp-controller.js.map +1 -0
- package/dist/src/mcp/mcp-render.d.ts +10 -0
- package/dist/src/mcp/mcp-render.d.ts.map +1 -0
- package/dist/src/mcp/mcp-render.js +66 -0
- package/dist/src/mcp/mcp-render.js.map +1 -0
- package/dist/src/mcp/mcp-schema.d.ts +8 -0
- package/dist/src/mcp/mcp-schema.d.ts.map +1 -0
- package/dist/src/mcp/mcp-schema.js +64 -0
- package/dist/src/mcp/mcp-schema.js.map +1 -0
- package/dist/src/mcp/mcp-types.d.ts +70 -0
- package/dist/src/mcp/mcp-types.d.ts.map +1 -0
- package/dist/src/mcp/mcp-types.js +21 -0
- package/dist/src/mcp/mcp-types.js.map +1 -0
- package/dist/src/mcp/providers/commands-provider.d.ts +26 -0
- package/dist/src/mcp/providers/commands-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/commands-provider.js +142 -0
- package/dist/src/mcp/providers/commands-provider.js.map +1 -0
- package/dist/src/mcp/providers/data-explorer-provider.d.ts +15 -0
- package/dist/src/mcp/providers/data-explorer-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/data-explorer-provider.js +83 -0
- package/dist/src/mcp/providers/data-explorer-provider.js.map +1 -0
- package/dist/src/mcp/providers/filesystem-provider.d.ts +15 -0
- package/dist/src/mcp/providers/filesystem-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/filesystem-provider.js +166 -0
- package/dist/src/mcp/providers/filesystem-provider.js.map +1 -0
- package/dist/src/mcp/providers/jobs-provider.d.ts +23 -0
- package/dist/src/mcp/providers/jobs-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/jobs-provider.js +121 -0
- package/dist/src/mcp/providers/jobs-provider.js.map +1 -0
- package/dist/src/mcp/providers/server-provider.d.ts +19 -0
- package/dist/src/mcp/providers/server-provider.d.ts.map +1 -0
- package/dist/src/mcp/providers/server-provider.js +73 -0
- package/dist/src/mcp/providers/server-provider.js.map +1 -0
- package/dist/src/processors/cli-base64-command-processor.d.ts.map +1 -1
- package/dist/src/processors/cli-base64-command-processor.js +2 -0
- package/dist/src/processors/cli-base64-command-processor.js.map +1 -1
- package/dist/src/processors/cli-hash-command-processor.d.ts +1 -0
- package/dist/src/processors/cli-hash-command-processor.d.ts.map +1 -1
- package/dist/src/processors/cli-hash-command-processor.js +1 -0
- package/dist/src/processors/cli-hash-command-processor.js.map +1 -1
- package/dist/src/processors/cli-http-command-processor.d.ts.map +1 -1
- package/dist/src/processors/cli-http-command-processor.js +2 -0
- package/dist/src/processors/cli-http-command-processor.js.map +1 -1
- package/dist/src/services/session-bound-sockets.d.ts +1 -1
- package/dist/src/services/session-bound-sockets.d.ts.map +1 -1
- package/dist/src/services/session-bound-sockets.js +2 -2
- package/dist/src/services/session-bound-sockets.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MCP_SERVER_VERSION = exports.MCP_SERVER_NAME = exports.MCP_PROTOCOL_VERSIONS = void 0;
|
|
37
|
+
exports.resolveMcpOptions = resolveMcpOptions;
|
|
38
|
+
exports.mcpToolPatternMatches = mcpToolPatternMatches;
|
|
39
|
+
exports.isMcpToolAllowed = isMcpToolAllowed;
|
|
40
|
+
exports.collectMcpTools = collectMcpTools;
|
|
41
|
+
exports.createMcpPreGate = createMcpPreGate;
|
|
42
|
+
exports.createMcpController = createMcpController;
|
|
43
|
+
const express_1 = __importStar(require("express"));
|
|
44
|
+
const crypto_1 = require("crypto");
|
|
45
|
+
const cli_server_auth_1 = require("../auth/cli-server-auth");
|
|
46
|
+
const logger_1 = require("../utils/logger");
|
|
47
|
+
const package_json_1 = require("../../package.json");
|
|
48
|
+
const mcp_types_1 = require("./mcp-types");
|
|
49
|
+
const mcp_schema_1 = require("./mcp-schema");
|
|
50
|
+
const logger = (0, logger_1.createLogger)('Mcp');
|
|
51
|
+
/** Supported MCP protocol versions, newest first. */
|
|
52
|
+
exports.MCP_PROTOCOL_VERSIONS = ['2025-11-25', '2025-06-18', '2025-03-26'];
|
|
53
|
+
exports.MCP_SERVER_NAME = 'qodalis-cli-server';
|
|
54
|
+
exports.MCP_SERVER_VERSION = package_json_1.version;
|
|
55
|
+
/** Resolves the `mcp` server option: undefined when MCP is disabled. */
|
|
56
|
+
function resolveMcpOptions(option) {
|
|
57
|
+
if (!option)
|
|
58
|
+
return undefined;
|
|
59
|
+
if (option === true)
|
|
60
|
+
return {};
|
|
61
|
+
return option.enabled === false ? undefined : option;
|
|
62
|
+
}
|
|
63
|
+
/** True when `name` matches a pattern (exact, or prefix with a trailing `*`); case-insensitive. */
|
|
64
|
+
function mcpToolPatternMatches(name, pattern) {
|
|
65
|
+
const p = pattern.trim().toLowerCase();
|
|
66
|
+
const n = name.toLowerCase();
|
|
67
|
+
return p.endsWith('*') ? n.startsWith(p.slice(0, -1)) : n === p;
|
|
68
|
+
}
|
|
69
|
+
/** Applies the allow-list (`tools`) then the deny-list (`exclude`). */
|
|
70
|
+
function isMcpToolAllowed(name, tools, exclude) {
|
|
71
|
+
if (tools && !tools.some((p) => mcpToolPatternMatches(name, p)))
|
|
72
|
+
return false;
|
|
73
|
+
if (exclude && exclude.some((p) => mcpToolPatternMatches(name, p)))
|
|
74
|
+
return false;
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
const warned = new Set();
|
|
78
|
+
function warnOnce(key, message, ...args) {
|
|
79
|
+
if (warned.has(key))
|
|
80
|
+
return;
|
|
81
|
+
warned.add(key);
|
|
82
|
+
logger.warn(message, ...args);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Collects the tools of every provider, in priority order (first wins on a
|
|
86
|
+
* name collision, with a warning). Invalid tool names are skipped.
|
|
87
|
+
*/
|
|
88
|
+
async function collectMcpTools(providers) {
|
|
89
|
+
const tools = [];
|
|
90
|
+
const owners = new Map();
|
|
91
|
+
for (const provider of providers) {
|
|
92
|
+
let provided;
|
|
93
|
+
try {
|
|
94
|
+
provided = await provider.getTools();
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
logger.error("MCP tool provider '%s' failed: %s", provider.name, err?.message ?? err);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
for (const tool of provided ?? []) {
|
|
101
|
+
if (!tool || typeof tool.name !== 'string' || !mcp_types_1.MCP_TOOL_NAME_RE.test(tool.name)) {
|
|
102
|
+
warnOnce(`invalid|${provider.name}|${tool?.name}`, "MCP tool '%s' of provider '%s' has an invalid name and is skipped", tool?.name, provider.name);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const owner = owners.get(tool.name);
|
|
106
|
+
if (owner !== undefined) {
|
|
107
|
+
warnOnce(`dup|${tool.name}|${provider.name}`, "MCP tool name collision: '%s' from provider '%s' is skipped ('%s' wins)", tool.name, provider.name, owner);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
owners.set(tool.name, provider.name);
|
|
111
|
+
tools.push(tool);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return tools;
|
|
115
|
+
}
|
|
116
|
+
// JSON-RPC error codes
|
|
117
|
+
const PARSE_ERROR = -32700;
|
|
118
|
+
const INVALID_REQUEST = -32600;
|
|
119
|
+
const METHOD_NOT_FOUND = -32601;
|
|
120
|
+
const INVALID_PARAMS = -32602;
|
|
121
|
+
const INTERNAL_ERROR = -32603;
|
|
122
|
+
class JsonRpcError extends Error {
|
|
123
|
+
code;
|
|
124
|
+
constructor(code, message) {
|
|
125
|
+
super(message);
|
|
126
|
+
this.code = code;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function sha256(value) {
|
|
130
|
+
return (0, crypto_1.createHash)('sha256').update(value, 'utf8').digest();
|
|
131
|
+
}
|
|
132
|
+
/** Constant-time comparison of a presented bearer token with the configured one. */
|
|
133
|
+
function tokenMatches(presented, expected) {
|
|
134
|
+
if (presented === undefined)
|
|
135
|
+
return false;
|
|
136
|
+
return (0, crypto_1.timingSafeEqual)(sha256(presented), sha256(expected));
|
|
137
|
+
}
|
|
138
|
+
function bearerToken(req) {
|
|
139
|
+
const header = req.headers['authorization'];
|
|
140
|
+
if (typeof header !== 'string' || !header.startsWith('Bearer '))
|
|
141
|
+
return undefined;
|
|
142
|
+
const token = header.slice(7).trim();
|
|
143
|
+
return token || undefined;
|
|
144
|
+
}
|
|
145
|
+
function isPlainObject(value) {
|
|
146
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Checks done before the server auth gate: the `Origin` (DNS-rebinding
|
|
150
|
+
* protection: allowed or same-origin, else 403) and the method (`POST` only,
|
|
151
|
+
* else 405 with `Allow: POST`).
|
|
152
|
+
*/
|
|
153
|
+
function createMcpPreGate(options) {
|
|
154
|
+
return (req, res, next) => {
|
|
155
|
+
if (req.path !== '/' && req.path !== '') {
|
|
156
|
+
next();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const origin = req.headers.origin;
|
|
160
|
+
if (origin !== undefined && !(0, cli_server_auth_1.isOriginAllowed)(origin, options.allowedOrigins) && !(0, cli_server_auth_1.isSameOrigin)(origin, req, options.trustProxy)) {
|
|
161
|
+
res.status(403).json({ error: 'forbidden: origin not allowed' });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const method = req.method.toUpperCase();
|
|
165
|
+
if (method === 'OPTIONS' || method === 'POST') {
|
|
166
|
+
next();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
res.setHeader('Allow', 'POST');
|
|
170
|
+
res.status(405).json({ error: 'method not allowed' });
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* MCP "Streamable HTTP" endpoint, stateless and JSON-only: `POST` a JSON-RPC
|
|
175
|
+
* 2.0 message, get a JSON response (`202` for notifications). Tools are the
|
|
176
|
+
* registry's commands, built on every request and filtered by the caller's
|
|
177
|
+
* permissions; calls run through the same executor as `/execute`.
|
|
178
|
+
*/
|
|
179
|
+
function createMcpController(options) {
|
|
180
|
+
const { mcp, getAuth } = options;
|
|
181
|
+
const router = (0, express_1.Router)();
|
|
182
|
+
router.post('/', express_1.default.text({ type: () => true, limit: '1mb' }), async (req, res) => {
|
|
183
|
+
const auth = getAuth();
|
|
184
|
+
const protectedServer = !!auth?.protectServer;
|
|
185
|
+
let ctx;
|
|
186
|
+
if (protectedServer) {
|
|
187
|
+
// Authenticated (and `commands:execute` checked) by the server auth gate
|
|
188
|
+
ctx = req.qcliServerAuth;
|
|
189
|
+
if (!ctx) {
|
|
190
|
+
res.status(401).json({ error: 'unauthorized' });
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else if (mcp.token && !tokenMatches(bearerToken(req), mcp.token)) {
|
|
195
|
+
res.status(401).json({ error: 'unauthorized' });
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const raw = typeof req.body === 'string' ? req.body : '';
|
|
199
|
+
let message;
|
|
200
|
+
try {
|
|
201
|
+
message = JSON.parse(raw);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
sendRpc(res, null, undefined, new JsonRpcError(PARSE_ERROR, 'Parse error'));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (!isPlainObject(message)) {
|
|
208
|
+
sendRpc(res, null, undefined, new JsonRpcError(INVALID_REQUEST, 'Invalid Request'));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const hasId = Object.prototype.hasOwnProperty.call(message, 'id');
|
|
212
|
+
const rawId = message.id;
|
|
213
|
+
const validId = typeof rawId === 'string' || (typeof rawId === 'number' && Number.isFinite(rawId));
|
|
214
|
+
const id = validId ? rawId : null;
|
|
215
|
+
if (message.jsonrpc !== '2.0') {
|
|
216
|
+
sendRpc(res, id, undefined, new JsonRpcError(INVALID_REQUEST, 'Invalid Request'));
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (message.method === undefined && hasId && ('result' in message || 'error' in message)) {
|
|
220
|
+
// A JSON-RPC response from the client: nothing to answer
|
|
221
|
+
res.status(202).end();
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (typeof message.method !== 'string' || (hasId && !validId)) {
|
|
225
|
+
sendRpc(res, id, undefined, new JsonRpcError(INVALID_REQUEST, 'Invalid Request'));
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (!hasId) {
|
|
229
|
+
// Notification (e.g. notifications/initialized): accepted, no body
|
|
230
|
+
res.status(202).end();
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const params = message.params;
|
|
234
|
+
if (params !== undefined && !isPlainObject(params)) {
|
|
235
|
+
sendRpc(res, id, undefined, new JsonRpcError(INVALID_PARAMS, 'Invalid params: params must be an object'));
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const abortController = new AbortController();
|
|
239
|
+
res.on('close', () => {
|
|
240
|
+
if (!res.writableEnded)
|
|
241
|
+
abortController.abort();
|
|
242
|
+
});
|
|
243
|
+
try {
|
|
244
|
+
const result = await dispatch(message.method, (params ?? {}), ctx, abortController.signal, req);
|
|
245
|
+
sendRpc(res, id, result);
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
if (err instanceof JsonRpcError) {
|
|
249
|
+
sendRpc(res, id, undefined, err);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
logger.error('MCP request failed: %s', err?.message ?? err);
|
|
253
|
+
sendRpc(res, id, undefined, new JsonRpcError(INTERNAL_ERROR, 'Internal error'));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
// Body too large / unreadable: plain HTTP errors
|
|
258
|
+
router.use((err, _req, res, next) => {
|
|
259
|
+
if (err && (err.type === 'entity.too.large' || typeof err.status === 'number')) {
|
|
260
|
+
const status = err.type === 'entity.too.large' ? 413 : err.status;
|
|
261
|
+
res.status(status).json({ error: status === 413 ? 'request body too large' : 'bad request' });
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
next(err);
|
|
265
|
+
});
|
|
266
|
+
/** Tools visible to the caller: allow/deny lists, then the tool's permissions (when protected). */
|
|
267
|
+
const visibleTools = async (ctx) => {
|
|
268
|
+
const auth = getAuth();
|
|
269
|
+
const tools = await collectMcpTools(options.providers());
|
|
270
|
+
return tools.filter((tool) => {
|
|
271
|
+
if (!isMcpToolAllowed(tool.name, mcp.tools, mcp.exclude))
|
|
272
|
+
return false;
|
|
273
|
+
if (!auth?.protectServer)
|
|
274
|
+
return true;
|
|
275
|
+
if (!ctx)
|
|
276
|
+
return false;
|
|
277
|
+
return (tool.requiredPermissions ?? []).every((p) => auth.hasPermission(ctx, p));
|
|
278
|
+
});
|
|
279
|
+
};
|
|
280
|
+
const dispatch = async (method, params, ctx, signal, req) => {
|
|
281
|
+
switch (method) {
|
|
282
|
+
case 'initialize': {
|
|
283
|
+
const requested = params.protocolVersion;
|
|
284
|
+
if (typeof requested !== 'string') {
|
|
285
|
+
throw new JsonRpcError(INVALID_PARAMS, 'Invalid params: protocolVersion is required');
|
|
286
|
+
}
|
|
287
|
+
const protocolVersion = exports.MCP_PROTOCOL_VERSIONS.includes(requested)
|
|
288
|
+
? requested
|
|
289
|
+
: exports.MCP_PROTOCOL_VERSIONS[0];
|
|
290
|
+
return {
|
|
291
|
+
protocolVersion,
|
|
292
|
+
capabilities: { tools: { listChanged: false } },
|
|
293
|
+
serverInfo: { name: exports.MCP_SERVER_NAME, version: exports.MCP_SERVER_VERSION },
|
|
294
|
+
...(mcp.instructions ? { instructions: mcp.instructions } : {}),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
case 'ping':
|
|
298
|
+
return {};
|
|
299
|
+
case 'tools/list':
|
|
300
|
+
return {
|
|
301
|
+
tools: (await visibleTools(ctx)).map((t) => ({
|
|
302
|
+
name: t.name,
|
|
303
|
+
description: t.description,
|
|
304
|
+
inputSchema: t.inputSchema,
|
|
305
|
+
...(t.annotations ? { annotations: t.annotations } : {}),
|
|
306
|
+
})),
|
|
307
|
+
};
|
|
308
|
+
case 'tools/call':
|
|
309
|
+
return callTool(params, ctx, signal, req);
|
|
310
|
+
default:
|
|
311
|
+
throw new JsonRpcError(METHOD_NOT_FOUND, `Method not found: ${method}`);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
const callTool = async (params, ctx, signal, req) => {
|
|
315
|
+
const name = params.name;
|
|
316
|
+
if (typeof name !== 'string' || !name) {
|
|
317
|
+
throw new JsonRpcError(INVALID_PARAMS, 'Invalid params: name is required');
|
|
318
|
+
}
|
|
319
|
+
const args = params.arguments ?? {};
|
|
320
|
+
if (!isPlainObject(args)) {
|
|
321
|
+
throw new JsonRpcError(INVALID_PARAMS, 'Invalid params: arguments must be an object');
|
|
322
|
+
}
|
|
323
|
+
const tool = (await visibleTools(ctx)).find((t) => t.name === name);
|
|
324
|
+
if (!tool) {
|
|
325
|
+
throw new JsonRpcError(INVALID_PARAMS, `Unknown tool: ${name}`);
|
|
326
|
+
}
|
|
327
|
+
const invalid = (0, mcp_schema_1.validateMcpArguments)(tool.inputSchema, args);
|
|
328
|
+
if (invalid) {
|
|
329
|
+
throw new JsonRpcError(INVALID_PARAMS, `Invalid arguments for tool ${name}: ${invalid}`);
|
|
330
|
+
}
|
|
331
|
+
logger.debug('MCP tool call: %s (user=%s)', tool.name, ctx?.userName ?? '-');
|
|
332
|
+
let result;
|
|
333
|
+
try {
|
|
334
|
+
result = await tool.call(args, { auth: ctx, signal, request: req });
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
result = { text: `Error executing tool: ${err?.message ?? err}`, isError: true };
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
content: [{ type: 'text', text: result?.text ?? '' }],
|
|
341
|
+
isError: !!result?.isError,
|
|
342
|
+
...(result?.structured && typeof result.structured === 'object' && !Array.isArray(result.structured)
|
|
343
|
+
? { structuredContent: result.structured }
|
|
344
|
+
: {}),
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
return router;
|
|
348
|
+
}
|
|
349
|
+
function sendRpc(res, id, result, error) {
|
|
350
|
+
res.status(200).type('application/json');
|
|
351
|
+
if (error) {
|
|
352
|
+
res.send(JSON.stringify({ jsonrpc: '2.0', id, error: { code: error.code, message: error.message } }));
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
res.send(JSON.stringify({ jsonrpc: '2.0', id, result }));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=mcp-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-controller.js","sourceRoot":"","sources":["../../../src/mcp/mcp-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CliStructuredOutput } from '../abstractions';
|
|
2
|
+
import { CliServerResponse } from '../models';
|
|
3
|
+
import { McpToolResult } from './mcp-types';
|
|
4
|
+
/** Renders command outputs as plain text (text as-is, tables `a | b`, lists one per line, json pretty, key-value `k: v`). */
|
|
5
|
+
export declare function renderOutputsAsText(outputs: readonly CliStructuredOutput[]): string;
|
|
6
|
+
/** Tool result of a command response (`structured` when the outputs are exactly one json object). */
|
|
7
|
+
export declare function commandResult(response: CliServerResponse): McpToolResult;
|
|
8
|
+
/** Renders rows (arrays or objects) as `a | b` lines under a header. */
|
|
9
|
+
export declare function renderRows(columns: string[] | null, rows: unknown[]): string;
|
|
10
|
+
//# sourceMappingURL=mcp-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-render.d.ts","sourceRoot":"","sources":["../../../src/mcp/mcp-render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,6HAA6H;AAC7H,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,GAAG,MAAM,CAwBnF;AAED,qGAAqG;AACrG,wBAAgB,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,aAAa,CAUxE;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAkB5E"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderOutputsAsText = renderOutputsAsText;
|
|
4
|
+
exports.commandResult = commandResult;
|
|
5
|
+
exports.renderRows = renderRows;
|
|
6
|
+
/** Renders command outputs as plain text (text as-is, tables `a | b`, lists one per line, json pretty, key-value `k: v`). */
|
|
7
|
+
function renderOutputsAsText(outputs) {
|
|
8
|
+
const blocks = [];
|
|
9
|
+
for (const output of outputs ?? []) {
|
|
10
|
+
switch (output?.type) {
|
|
11
|
+
case 'text':
|
|
12
|
+
blocks.push(output.value ?? '');
|
|
13
|
+
break;
|
|
14
|
+
case 'table':
|
|
15
|
+
blocks.push([(output.headers ?? []).join(' | '), ...(output.rows ?? []).map((r) => (r ?? []).join(' | '))].join('\n'));
|
|
16
|
+
break;
|
|
17
|
+
case 'list':
|
|
18
|
+
blocks.push((output.items ?? []).join('\n'));
|
|
19
|
+
break;
|
|
20
|
+
case 'json':
|
|
21
|
+
blocks.push(JSON.stringify(output.value, null, 2) ?? 'null');
|
|
22
|
+
break;
|
|
23
|
+
case 'key-value':
|
|
24
|
+
blocks.push((output.entries ?? []).map((e) => `${e.key}: ${e.value}`).join('\n'));
|
|
25
|
+
break;
|
|
26
|
+
default:
|
|
27
|
+
blocks.push(JSON.stringify(output));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return blocks.join('\n');
|
|
31
|
+
}
|
|
32
|
+
/** Tool result of a command response (`structured` when the outputs are exactly one json object). */
|
|
33
|
+
function commandResult(response) {
|
|
34
|
+
const outputs = response.outputs ?? [];
|
|
35
|
+
const result = { text: renderOutputsAsText(outputs), isError: response.exitCode !== 0 };
|
|
36
|
+
if (outputs.length === 1 && outputs[0].type === 'json') {
|
|
37
|
+
const value = outputs[0].value;
|
|
38
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
39
|
+
result.structured = value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
/** Renders rows (arrays or objects) as `a | b` lines under a header. */
|
|
45
|
+
function renderRows(columns, rows) {
|
|
46
|
+
const cell = (v) => (v === null || v === undefined ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v));
|
|
47
|
+
let headers = columns ?? [];
|
|
48
|
+
if (headers.length === 0 && rows.length > 0 && rows[0] && typeof rows[0] === 'object' && !Array.isArray(rows[0])) {
|
|
49
|
+
headers = Object.keys(rows[0]);
|
|
50
|
+
}
|
|
51
|
+
const lines = headers.length > 0 ? [headers.join(' | ')] : [];
|
|
52
|
+
for (const row of rows) {
|
|
53
|
+
if (Array.isArray(row)) {
|
|
54
|
+
lines.push(row.map(cell).join(' | '));
|
|
55
|
+
}
|
|
56
|
+
else if (row && typeof row === 'object') {
|
|
57
|
+
const obj = row;
|
|
58
|
+
lines.push((headers.length > 0 ? headers : Object.keys(obj)).map((h) => cell(obj[h])).join(' | '));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
lines.push(cell(row));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return lines.join('\n');
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=mcp-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-render.js","sourceRoot":"","sources":["../../../src/mcp/mcp-render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { McpInputSchema } from './mcp-types';
|
|
2
|
+
/**
|
|
3
|
+
* Validates tool arguments against an input schema (types of the declared
|
|
4
|
+
* properties, array item types, unknown properties, required properties).
|
|
5
|
+
* Returns the reason when invalid. `null` counts as absent.
|
|
6
|
+
*/
|
|
7
|
+
export declare function validateMcpArguments(schema: McpInputSchema, args: Record<string, unknown>): string | undefined;
|
|
8
|
+
//# sourceMappingURL=mcp-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-schema.d.ts","sourceRoot":"","sources":["../../../src/mcp/mcp-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAqB,MAAM,aAAa,CAAC;AAyChE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAa9G"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateMcpArguments = validateMcpArguments;
|
|
4
|
+
function typeMatches(type, value) {
|
|
5
|
+
switch (type) {
|
|
6
|
+
case 'string':
|
|
7
|
+
return typeof value === 'string';
|
|
8
|
+
case 'number':
|
|
9
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
10
|
+
case 'integer':
|
|
11
|
+
return typeof value === 'number' && Number.isInteger(value);
|
|
12
|
+
case 'boolean':
|
|
13
|
+
return typeof value === 'boolean';
|
|
14
|
+
case 'object':
|
|
15
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
16
|
+
case 'array':
|
|
17
|
+
return Array.isArray(value);
|
|
18
|
+
default:
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const TYPE_LABEL = {
|
|
23
|
+
string: 'a string',
|
|
24
|
+
number: 'a number',
|
|
25
|
+
integer: 'an integer',
|
|
26
|
+
boolean: 'a boolean',
|
|
27
|
+
object: 'an object',
|
|
28
|
+
array: 'an array',
|
|
29
|
+
};
|
|
30
|
+
function checkProperty(key, prop, value) {
|
|
31
|
+
if (!typeMatches(prop.type, value)) {
|
|
32
|
+
if (prop.type === 'array' && prop.items?.type)
|
|
33
|
+
return `argument '${key}' must be an array of ${prop.items.type}s`;
|
|
34
|
+
return `argument '${key}' must be ${TYPE_LABEL[prop.type] ?? prop.type}`;
|
|
35
|
+
}
|
|
36
|
+
if (prop.type === 'array' && prop.items?.type && value.some((v) => !typeMatches(prop.items.type, v))) {
|
|
37
|
+
return `argument '${key}' must be an array of ${prop.items.type}s`;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validates tool arguments against an input schema (types of the declared
|
|
43
|
+
* properties, array item types, unknown properties, required properties).
|
|
44
|
+
* Returns the reason when invalid. `null` counts as absent.
|
|
45
|
+
*/
|
|
46
|
+
function validateMcpArguments(schema, args) {
|
|
47
|
+
const properties = schema.properties ?? {};
|
|
48
|
+
for (const [key, value] of Object.entries(args)) {
|
|
49
|
+
const prop = Object.prototype.hasOwnProperty.call(properties, key) ? properties[key] : undefined;
|
|
50
|
+
if (!prop)
|
|
51
|
+
return `unknown argument '${key}'`;
|
|
52
|
+
if (value === null || value === undefined)
|
|
53
|
+
continue;
|
|
54
|
+
const reason = checkProperty(key, prop, value);
|
|
55
|
+
if (reason)
|
|
56
|
+
return reason;
|
|
57
|
+
}
|
|
58
|
+
for (const key of schema.required ?? []) {
|
|
59
|
+
if (args[key] === undefined || args[key] === null)
|
|
60
|
+
return `missing required argument '${key}'`;
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=mcp-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-schema.js","sourceRoot":"","sources":["../../../src/mcp/mcp-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
import type { CliServerAuthContext } from '../auth/cli-server-auth';
|
|
3
|
+
/** JSON Schema of a property in a tool's input schema (the subset validated by the server). */
|
|
4
|
+
export interface McpPropertySchema {
|
|
5
|
+
type: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object';
|
|
6
|
+
items?: {
|
|
7
|
+
type: 'string' | 'number' | 'integer' | 'boolean';
|
|
8
|
+
};
|
|
9
|
+
description?: string;
|
|
10
|
+
default?: unknown;
|
|
11
|
+
[keyword: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
/** JSON Schema of a tool's arguments: always an object without additional properties. */
|
|
14
|
+
export interface McpInputSchema {
|
|
15
|
+
type: 'object';
|
|
16
|
+
properties: Record<string, McpPropertySchema>;
|
|
17
|
+
required: string[];
|
|
18
|
+
additionalProperties: false;
|
|
19
|
+
}
|
|
20
|
+
/** MCP tool annotations (hints for clients). */
|
|
21
|
+
export interface McpToolAnnotations {
|
|
22
|
+
readOnlyHint?: boolean;
|
|
23
|
+
destructiveHint?: boolean;
|
|
24
|
+
idempotentHint?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Context of a tool call. */
|
|
27
|
+
export interface McpToolCallContext {
|
|
28
|
+
/** The caller (when an auth provider protects the server). */
|
|
29
|
+
auth?: CliServerAuthContext;
|
|
30
|
+
/** Aborted when the client disconnects. */
|
|
31
|
+
signal: AbortSignal;
|
|
32
|
+
/** The HTTP request carrying the call. */
|
|
33
|
+
request: Request;
|
|
34
|
+
}
|
|
35
|
+
/** Result of a tool call: `text` becomes the text content, `structured` the `structuredContent`. */
|
|
36
|
+
export interface McpToolResult {
|
|
37
|
+
text: string;
|
|
38
|
+
structured?: Record<string, unknown>;
|
|
39
|
+
isError: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** A tool exposed by the MCP endpoint. */
|
|
42
|
+
export interface McpTool {
|
|
43
|
+
/** `[a-z0-9_-]`, at most 64 characters. */
|
|
44
|
+
name: string;
|
|
45
|
+
description: string;
|
|
46
|
+
inputSchema: McpInputSchema;
|
|
47
|
+
/** Checked for `tools/list` and `tools/call` when an auth provider protects the server. */
|
|
48
|
+
requiredPermissions: string[];
|
|
49
|
+
annotations?: McpToolAnnotations;
|
|
50
|
+
/** Called with arguments already validated against `inputSchema`. */
|
|
51
|
+
call(args: Record<string, unknown>, context: McpToolCallContext): Promise<McpToolResult>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Supplies MCP tools. Providers are asked for their tools on every request, so
|
|
55
|
+
* registrations, enabled features and permissions are always current.
|
|
56
|
+
*/
|
|
57
|
+
export interface McpToolProvider {
|
|
58
|
+
/** Provider name (used in logs). */
|
|
59
|
+
readonly name: string;
|
|
60
|
+
getTools(): McpTool[] | Promise<McpTool[]>;
|
|
61
|
+
}
|
|
62
|
+
/** MCP tool name rule: `[a-z0-9_-]`, 1-64 characters. */
|
|
63
|
+
export declare const MCP_TOOL_NAME_RE: RegExp;
|
|
64
|
+
/** Builds an input schema from properties and required names. */
|
|
65
|
+
export declare function mcpObjectSchema(properties?: Record<string, McpPropertySchema>, required?: string[]): McpInputSchema;
|
|
66
|
+
/** Error result with a message. */
|
|
67
|
+
export declare function mcpError(message: string): McpToolResult;
|
|
68
|
+
/** Success result with a structured object rendered as pretty JSON text. */
|
|
69
|
+
export declare function mcpJson(value: Record<string, unknown>, text?: string): McpToolResult;
|
|
70
|
+
//# sourceMappingURL=mcp-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-types.d.ts","sourceRoot":"","sources":["../../../src/mcp/mcp-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,+FAA+F;AAC/F,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IACvE,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAA;KAAE,CAAC;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CAC9B;AAED,yFAAyF;AACzF,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,oBAAoB,EAAE,KAAK,CAAC;CAC/B;AAED,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,8BAA8B;AAC9B,MAAM,WAAW,kBAAkB;IAC/B,8DAA8D;IAC9D,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,2CAA2C;IAC3C,MAAM,EAAE,WAAW,CAAC;IACpB,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,oGAAoG;AACpG,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,0CAA0C;AAC1C,MAAM,WAAW,OAAO;IACpB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,cAAc,CAAC;IAC5B,2FAA2F;IAC3F,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC5F;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,IAAI,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CAC9C;AAED,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,QAAuB,CAAC;AAErD,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAM,EAAE,QAAQ,GAAE,MAAM,EAAO,GAAG,cAAc,CAE3H;AAED,mCAAmC;AACnC,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAEvD;AAED,4EAA4E;AAC5E,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAEpF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MCP_TOOL_NAME_RE = void 0;
|
|
4
|
+
exports.mcpObjectSchema = mcpObjectSchema;
|
|
5
|
+
exports.mcpError = mcpError;
|
|
6
|
+
exports.mcpJson = mcpJson;
|
|
7
|
+
/** MCP tool name rule: `[a-z0-9_-]`, 1-64 characters. */
|
|
8
|
+
exports.MCP_TOOL_NAME_RE = /^[a-z0-9_-]{1,64}$/;
|
|
9
|
+
/** Builds an input schema from properties and required names. */
|
|
10
|
+
function mcpObjectSchema(properties = {}, required = []) {
|
|
11
|
+
return { type: 'object', properties, required, additionalProperties: false };
|
|
12
|
+
}
|
|
13
|
+
/** Error result with a message. */
|
|
14
|
+
function mcpError(message) {
|
|
15
|
+
return { text: message, isError: true };
|
|
16
|
+
}
|
|
17
|
+
/** Success result with a structured object rendered as pretty JSON text. */
|
|
18
|
+
function mcpJson(value, text) {
|
|
19
|
+
return { text: text ?? JSON.stringify(value, null, 2), structured: value, isError: false };
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=mcp-types.js.map
|