@socketsecurity/mcp 0.0.15 → 0.0.17
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/index.js +241 -132
- package/package.json +13 -3
package/index.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
4
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
5
|
+
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
+
import { randomUUID } from 'node:crypto';
|
|
5
7
|
import { z } from 'zod';
|
|
6
8
|
import pino from 'pino';
|
|
7
9
|
import readline from 'readline';
|
|
@@ -58,75 +60,92 @@ function buildSocketHeaders() {
|
|
|
58
60
|
authorization: `Bearer ${SOCKET_API_KEY}`
|
|
59
61
|
};
|
|
60
62
|
}
|
|
61
|
-
|
|
62
|
-
name: 'socket',
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
purl
|
|
90
|
-
}
|
|
91
|
-
return { purl };
|
|
92
|
-
});
|
|
93
|
-
try {
|
|
94
|
-
const response = await fetch(SOCKET_API_URL, {
|
|
95
|
-
method: 'POST',
|
|
96
|
-
headers: buildSocketHeaders(),
|
|
97
|
-
body: JSON.stringify({ components })
|
|
63
|
+
function createConfiguredServer() {
|
|
64
|
+
const srv = new McpServer({ name: 'socket', version: VERSION });
|
|
65
|
+
srv.registerTool('depscore', {
|
|
66
|
+
title: 'Dependency Score Tool',
|
|
67
|
+
description: "Get the dependency score of packages with the `depscore` tool from Socket. Use 'unknown' for version if not known. Use this tool to scan dependencies for their quality and security on existing code or when code is generated. Stop generating code and ask the user how to proceed when any of the scores are low. When checking dependencies, make sure to also check the imports in the code, not just the manifest files (pyproject.toml, package.json, etc).",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
packages: z.array(z.object({
|
|
70
|
+
ecosystem: z.string().describe('The package ecosystem (e.g., npm, pypi)').default('npm'),
|
|
71
|
+
depname: z.string().describe('The name of the dependency'),
|
|
72
|
+
version: z.string().describe("The version of the dependency, use 'unknown' if not known").default('unknown'),
|
|
73
|
+
})).describe('Array of packages to check'),
|
|
74
|
+
},
|
|
75
|
+
annotations: {
|
|
76
|
+
readOnlyHint: true,
|
|
77
|
+
},
|
|
78
|
+
}, async ({ packages }) => {
|
|
79
|
+
logger.info(`Received request for ${packages.length} packages`);
|
|
80
|
+
const components = packages.map((pkg) => {
|
|
81
|
+
const cleanedVersion = (pkg.version ?? 'unknown').replace(/[\^~]/g, '');
|
|
82
|
+
const ecosystem = pkg.ecosystem ?? 'npm';
|
|
83
|
+
let purl;
|
|
84
|
+
if (cleanedVersion === '1.0.0' || cleanedVersion === 'unknown' || !cleanedVersion) {
|
|
85
|
+
purl = `pkg:${ecosystem}/${pkg.depname}`;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
logger.info(`Using version ${cleanedVersion} for ${pkg.depname}`);
|
|
89
|
+
purl = `pkg:${ecosystem}/${pkg.depname}@${cleanedVersion}`;
|
|
90
|
+
}
|
|
91
|
+
return { purl };
|
|
98
92
|
});
|
|
99
|
-
const responseText = await response.text();
|
|
100
|
-
if (response.status !== 200) {
|
|
101
|
-
const errorMsg = `Error processing packages: [${response.status}] ${responseText}`;
|
|
102
|
-
logger.error(errorMsg);
|
|
103
|
-
return {
|
|
104
|
-
content: [{ type: 'text', text: errorMsg }],
|
|
105
|
-
isError: true
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
else if (!responseText.trim()) {
|
|
109
|
-
const errorMsg = 'No packages were found.';
|
|
110
|
-
logger.error(errorMsg);
|
|
111
|
-
return {
|
|
112
|
-
content: [{ type: 'text', text: errorMsg }],
|
|
113
|
-
isError: true
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
93
|
try {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
94
|
+
const response = await fetch(SOCKET_API_URL, {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
headers: buildSocketHeaders(),
|
|
97
|
+
body: JSON.stringify({ components })
|
|
98
|
+
});
|
|
99
|
+
const responseText = await response.text();
|
|
100
|
+
if (response.status !== 200) {
|
|
101
|
+
const errorMsg = `Error processing packages: [${response.status}] ${responseText}`;
|
|
102
|
+
logger.error(errorMsg);
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: 'text', text: errorMsg }],
|
|
105
|
+
isError: true
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
else if (!responseText.trim()) {
|
|
109
|
+
const errorMsg = 'No packages were found.';
|
|
110
|
+
logger.error(errorMsg);
|
|
111
|
+
return {
|
|
112
|
+
content: [{ type: 'text', text: errorMsg }],
|
|
113
|
+
isError: true
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const results = [];
|
|
118
|
+
if ((response.headers.get('content-type') || '').includes('x-ndjson')) {
|
|
119
|
+
const jsonLines = responseText.split('\n')
|
|
120
|
+
.filter(line => line.trim())
|
|
121
|
+
.map(line => JSON.parse(line));
|
|
122
|
+
if (!jsonLines.length) {
|
|
123
|
+
const errorMsg = 'No valid JSON objects found in NDJSON response';
|
|
124
|
+
return {
|
|
125
|
+
content: [{ type: 'text', text: errorMsg }],
|
|
126
|
+
isError: true
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
for (const jsonData of jsonLines) {
|
|
130
|
+
const purl = `pkg:${jsonData.type || 'unknown'}/${jsonData.name || 'unknown'}@${jsonData.version || 'unknown'}`;
|
|
131
|
+
if (jsonData.score && jsonData.score.overall !== undefined) {
|
|
132
|
+
const scoreEntries = Object.entries(jsonData.score)
|
|
133
|
+
.filter(([key]) => key !== 'overall' && key !== 'uuid')
|
|
134
|
+
.map(([key, value]) => {
|
|
135
|
+
const numValue = Number(value);
|
|
136
|
+
const displayValue = numValue <= 1 ? Math.round(numValue * 100) : numValue;
|
|
137
|
+
return `${key}: ${displayValue}`;
|
|
138
|
+
})
|
|
139
|
+
.join(', ');
|
|
140
|
+
results.push(`${purl}: ${scoreEntries}`);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
results.push(`${purl}: No score found`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
128
146
|
}
|
|
129
|
-
|
|
147
|
+
else {
|
|
148
|
+
const jsonData = JSON.parse(responseText);
|
|
130
149
|
const purl = `pkg:${jsonData.type || 'unknown'}/${jsonData.name || 'unknown'}@${jsonData.version || 'unknown'}`;
|
|
131
150
|
if (jsonData.score && jsonData.score.overall !== undefined) {
|
|
132
151
|
const scoreEntries = Object.entries(jsonData.score)
|
|
@@ -143,56 +162,39 @@ server.registerTool('depscore', {
|
|
|
143
162
|
results.push(`${purl}: No score found`);
|
|
144
163
|
}
|
|
145
164
|
}
|
|
165
|
+
return {
|
|
166
|
+
content: [
|
|
167
|
+
{
|
|
168
|
+
type: 'text',
|
|
169
|
+
text: results.length > 0
|
|
170
|
+
? `Dependency scores:\n${results.join('\n')}`
|
|
171
|
+
: 'No scores found for the provided packages'
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
};
|
|
146
175
|
}
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const displayValue = numValue <= 1 ? Math.round(numValue * 100) : numValue;
|
|
156
|
-
return `${key}: ${displayValue}`;
|
|
157
|
-
})
|
|
158
|
-
.join(', ');
|
|
159
|
-
results.push(`${purl}: ${scoreEntries}`);
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
results.push(`${purl}: No score found`);
|
|
163
|
-
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
const error = e;
|
|
178
|
+
const errorMsg = `JSON parsing error: ${error.message} -- Response: ${responseText}`;
|
|
179
|
+
logger.error(errorMsg);
|
|
180
|
+
return {
|
|
181
|
+
content: [{ type: 'text', text: 'Error parsing response from Socket API' }],
|
|
182
|
+
isError: true
|
|
183
|
+
};
|
|
164
184
|
}
|
|
165
|
-
return {
|
|
166
|
-
content: [
|
|
167
|
-
{
|
|
168
|
-
type: 'text',
|
|
169
|
-
text: results.length > 0
|
|
170
|
-
? `Dependency scores:\n${results.join('\n')}`
|
|
171
|
-
: 'No scores found for the provided packages'
|
|
172
|
-
}
|
|
173
|
-
]
|
|
174
|
-
};
|
|
175
185
|
}
|
|
176
186
|
catch (e) {
|
|
177
187
|
const error = e;
|
|
178
|
-
const errorMsg = `
|
|
188
|
+
const errorMsg = `Error processing packages: ${error.message}`;
|
|
179
189
|
logger.error(errorMsg);
|
|
180
190
|
return {
|
|
181
|
-
content: [{ type: 'text', text: 'Error
|
|
191
|
+
content: [{ type: 'text', text: 'Error connecting to Socket API' }],
|
|
182
192
|
isError: true
|
|
183
193
|
};
|
|
184
194
|
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const errorMsg = `Error processing packages: ${error.message}`;
|
|
189
|
-
logger.error(errorMsg);
|
|
190
|
-
return {
|
|
191
|
-
content: [{ type: 'text', text: 'Error connecting to Socket API' }],
|
|
192
|
-
isError: true
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
});
|
|
195
|
+
});
|
|
196
|
+
return srv;
|
|
197
|
+
}
|
|
196
198
|
const useHttp = process.env['MCP_HTTP_MODE'] === 'true' || process.argv.includes('--http');
|
|
197
199
|
const port = parseInt(process.env['MCP_PORT'] || '3000', 10);
|
|
198
200
|
if (!SOCKET_API_KEY) {
|
|
@@ -208,7 +210,30 @@ if (!SOCKET_API_KEY) {
|
|
|
208
210
|
}
|
|
209
211
|
if (useHttp) {
|
|
210
212
|
logger.info(`Starting HTTP server on port ${port}`);
|
|
211
|
-
|
|
213
|
+
const sessions = new Map();
|
|
214
|
+
function destroySession(id) {
|
|
215
|
+
const s = sessions.get(id);
|
|
216
|
+
if (!s)
|
|
217
|
+
return;
|
|
218
|
+
sessions.delete(id);
|
|
219
|
+
try {
|
|
220
|
+
s.transport.close();
|
|
221
|
+
}
|
|
222
|
+
catch { }
|
|
223
|
+
s.server.close().catch(() => { });
|
|
224
|
+
logger.info(`Session ${id} destroyed`);
|
|
225
|
+
}
|
|
226
|
+
const SESSION_TTL_MS = 30 * 60 * 1000;
|
|
227
|
+
const reapInterval = setInterval(() => {
|
|
228
|
+
const now = Date.now();
|
|
229
|
+
for (const [id, session] of sessions.entries()) {
|
|
230
|
+
if (now - session.lastActivity > SESSION_TTL_MS) {
|
|
231
|
+
logger.info(`Reaping idle session ${id}`);
|
|
232
|
+
destroySession(id);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}, 60_000);
|
|
236
|
+
reapInterval.unref();
|
|
212
237
|
const httpServer = createServer(async (req, res) => {
|
|
213
238
|
let url;
|
|
214
239
|
try {
|
|
@@ -249,13 +274,15 @@ if (useHttp) {
|
|
|
249
274
|
'https://mcp.socket-staging.dev'
|
|
250
275
|
];
|
|
251
276
|
const host = req.headers.host || '';
|
|
252
|
-
const
|
|
277
|
+
const allowedHosts = allowedOrigins.map(o => new URL(o).hostname);
|
|
278
|
+
const isAllowedHost = host === `localhost:${port}` ||
|
|
253
279
|
host === `127.0.0.1:${port}` ||
|
|
254
280
|
host === 'localhost' ||
|
|
255
|
-
host === '127.0.0.1'
|
|
281
|
+
host === '127.0.0.1' ||
|
|
282
|
+
allowedHosts.includes(host);
|
|
256
283
|
const isValidOrigin = origin
|
|
257
284
|
? (isLocalhostOrigin(origin) || allowedOrigins.includes(origin))
|
|
258
|
-
:
|
|
285
|
+
: isAllowedHost;
|
|
259
286
|
if (!isValidOrigin) {
|
|
260
287
|
logger.warn(`Rejected request from invalid origin: ${origin || 'missing'} (host: ${host})`);
|
|
261
288
|
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
@@ -268,8 +295,9 @@ if (useHttp) {
|
|
|
268
295
|
}
|
|
269
296
|
if (origin) {
|
|
270
297
|
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
271
|
-
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
272
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept');
|
|
298
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
299
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept, Mcp-Session-Id');
|
|
300
|
+
res.setHeader('Access-Control-Expose-Headers', 'Mcp-Session-Id');
|
|
273
301
|
}
|
|
274
302
|
if (req.method === 'OPTIONS') {
|
|
275
303
|
res.writeHead(200);
|
|
@@ -277,37 +305,62 @@ if (useHttp) {
|
|
|
277
305
|
return;
|
|
278
306
|
}
|
|
279
307
|
if (url.pathname === '/') {
|
|
308
|
+
const accept = req.headers.accept || '';
|
|
309
|
+
if (!accept.includes('application/json') || !accept.includes('text/event-stream')) {
|
|
310
|
+
const requiredAccept = 'application/json, text/event-stream';
|
|
311
|
+
req.headers.accept = requiredAccept;
|
|
312
|
+
const idx = req.rawHeaders.findIndex(h => h.toLowerCase() === 'accept');
|
|
313
|
+
if (idx !== -1) {
|
|
314
|
+
req.rawHeaders[idx + 1] = requiredAccept;
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
req.rawHeaders.push('Accept', requiredAccept);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
280
320
|
if (req.method === 'POST') {
|
|
281
321
|
let body = '';
|
|
282
|
-
req.on('data', chunk =>
|
|
322
|
+
req.on('data', (chunk) => { body += chunk; });
|
|
283
323
|
req.on('end', async () => {
|
|
284
324
|
try {
|
|
285
325
|
const jsonData = JSON.parse(body);
|
|
286
|
-
|
|
326
|
+
const sessionId = req.headers['mcp-session-id'] || undefined;
|
|
327
|
+
const session = sessionId ? sessions.get(sessionId) : undefined;
|
|
328
|
+
let transport = session?.transport;
|
|
329
|
+
if (!transport && isInitializeRequest(jsonData)) {
|
|
287
330
|
const clientInfo = jsonData.params?.clientInfo;
|
|
288
331
|
logger.info(`Client connected: ${clientInfo?.name || 'unknown'} v${clientInfo?.version || 'unknown'} from ${origin || host}`);
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
enableJsonResponse: true
|
|
332
|
+
const server = createConfiguredServer();
|
|
333
|
+
const newTransport = new StreamableHTTPServerTransport({
|
|
334
|
+
enableJsonResponse: true,
|
|
335
|
+
sessionIdGenerator: () => randomUUID(),
|
|
336
|
+
onsessioninitialized: (id) => {
|
|
337
|
+
sessions.set(id, { transport: newTransport, server, lastActivity: Date.now() });
|
|
338
|
+
},
|
|
339
|
+
onsessionclosed: (id) => { destroySession(id); }
|
|
298
340
|
});
|
|
299
|
-
|
|
300
|
-
|
|
341
|
+
newTransport.onclose = () => {
|
|
342
|
+
const id = newTransport.sessionId;
|
|
343
|
+
if (id)
|
|
344
|
+
destroySession(id);
|
|
345
|
+
};
|
|
346
|
+
transport = newTransport;
|
|
347
|
+
await server.connect(transport);
|
|
348
|
+
}
|
|
349
|
+
if (!transport) {
|
|
350
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
351
|
+
res.end(JSON.stringify({
|
|
352
|
+
jsonrpc: '2.0',
|
|
353
|
+
error: { code: -32000, message: 'Bad Request: No valid session. Send initialize first.' },
|
|
354
|
+
id: null
|
|
355
|
+
}));
|
|
301
356
|
return;
|
|
302
357
|
}
|
|
303
|
-
if (
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
});
|
|
308
|
-
await server.connect(httpTransport);
|
|
358
|
+
if (sessionId) {
|
|
359
|
+
const activeSession = sessions.get(sessionId);
|
|
360
|
+
if (activeSession)
|
|
361
|
+
activeSession.lastActivity = Date.now();
|
|
309
362
|
}
|
|
310
|
-
await
|
|
363
|
+
await transport.handleRequest(req, res, jsonData);
|
|
311
364
|
}
|
|
312
365
|
catch (error) {
|
|
313
366
|
logger.error(`Error processing POST request: ${error}`);
|
|
@@ -322,6 +375,61 @@ if (useHttp) {
|
|
|
322
375
|
}
|
|
323
376
|
});
|
|
324
377
|
}
|
|
378
|
+
else if (req.method === 'GET') {
|
|
379
|
+
const sessionId = req.headers['mcp-session-id'] || undefined;
|
|
380
|
+
const session = sessionId ? sessions.get(sessionId) : undefined;
|
|
381
|
+
if (!session) {
|
|
382
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
383
|
+
res.end(JSON.stringify({
|
|
384
|
+
jsonrpc: '2.0',
|
|
385
|
+
error: { code: -32000, message: 'Not Found: Invalid or expired session. Re-initialize.' },
|
|
386
|
+
id: null
|
|
387
|
+
}));
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
session.lastActivity = Date.now();
|
|
392
|
+
await session.transport.handleRequest(req, res);
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
logger.error(`Error processing GET request: ${error}`);
|
|
396
|
+
if (!res.headersSent) {
|
|
397
|
+
res.writeHead(500);
|
|
398
|
+
res.end(JSON.stringify({
|
|
399
|
+
jsonrpc: '2.0',
|
|
400
|
+
error: { code: -32603, message: 'Internal server error' },
|
|
401
|
+
id: null
|
|
402
|
+
}));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
else if (req.method === 'DELETE') {
|
|
407
|
+
const sessionId = req.headers['mcp-session-id'] || undefined;
|
|
408
|
+
const transport = sessionId ? sessions.get(sessionId)?.transport : undefined;
|
|
409
|
+
if (!transport) {
|
|
410
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
411
|
+
res.end(JSON.stringify({
|
|
412
|
+
jsonrpc: '2.0',
|
|
413
|
+
error: { code: -32000, message: 'Not Found: Invalid or expired session.' },
|
|
414
|
+
id: null
|
|
415
|
+
}));
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
try {
|
|
419
|
+
await transport.handleRequest(req, res);
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
logger.error(`Error processing DELETE request: ${error}`);
|
|
423
|
+
if (!res.headersSent) {
|
|
424
|
+
res.writeHead(500);
|
|
425
|
+
res.end(JSON.stringify({
|
|
426
|
+
jsonrpc: '2.0',
|
|
427
|
+
error: { code: -32603, message: 'Internal server error' },
|
|
428
|
+
id: null
|
|
429
|
+
}));
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
325
433
|
else {
|
|
326
434
|
res.writeHead(405);
|
|
327
435
|
res.end('Method not allowed');
|
|
@@ -339,6 +447,7 @@ if (useHttp) {
|
|
|
339
447
|
}
|
|
340
448
|
else {
|
|
341
449
|
logger.info('Starting in stdio mode');
|
|
450
|
+
const server = createConfiguredServer();
|
|
342
451
|
const transport = new StdioServerTransport();
|
|
343
452
|
server.connect(transport)
|
|
344
453
|
.then(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socketsecurity/mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"bin": {
|
|
@@ -50,11 +50,21 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@anthropic-ai/mcpb": "^1.1.0",
|
|
53
|
-
"@modelcontextprotocol/sdk": "
|
|
53
|
+
"@modelcontextprotocol/sdk": "1.26.0",
|
|
54
54
|
"pino": "^10.0.0",
|
|
55
55
|
"pino-pretty": "^13.0.0",
|
|
56
56
|
"semver": "^7.7.2",
|
|
57
|
-
"zod": "
|
|
57
|
+
"zod": "3.25.76"
|
|
58
|
+
},
|
|
59
|
+
"overrides": {
|
|
60
|
+
"zod": "3.25.76",
|
|
61
|
+
"zod-to-json-schema": "3.25.1"
|
|
62
|
+
},
|
|
63
|
+
"pnpm": {
|
|
64
|
+
"overrides": {
|
|
65
|
+
"zod": "3.25.76",
|
|
66
|
+
"zod-to-json-schema": "3.25.1"
|
|
67
|
+
}
|
|
58
68
|
},
|
|
59
69
|
"devDependencies": {
|
|
60
70
|
"@types/node": "^24.0.7",
|