@socketsecurity/mcp 0.0.12 → 0.0.14
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 +55 -53
- package/mock-client/stdio-client.js +1 -1
- package/package.json +10 -7
package/index.js
CHANGED
|
@@ -50,46 +50,50 @@ async function getApiKeyInteractively() {
|
|
|
50
50
|
return apiKey;
|
|
51
51
|
}
|
|
52
52
|
let SOCKET_API_KEY = process.env['SOCKET_API_KEY'] || '';
|
|
53
|
+
function buildSocketHeaders() {
|
|
54
|
+
return {
|
|
55
|
+
'user-agent': `socket-mcp/${VERSION}`,
|
|
56
|
+
accept: 'application/x-ndjson',
|
|
57
|
+
'content-type': 'application/json',
|
|
58
|
+
authorization: `Bearer ${SOCKET_API_KEY}`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
53
61
|
const server = new McpServer({
|
|
54
62
|
name: 'socket',
|
|
55
63
|
version: VERSION,
|
|
56
|
-
description: 'Socket MCP server',
|
|
57
|
-
capabilities: {
|
|
58
|
-
resources: {},
|
|
59
|
-
tools: {},
|
|
60
|
-
streaming: {}
|
|
61
|
-
},
|
|
62
64
|
});
|
|
63
|
-
server.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
server.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: z.object({
|
|
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
|
+
},
|
|
69
78
|
}, async ({ packages }) => {
|
|
70
79
|
logger.info(`Received request for ${packages.length} packages`);
|
|
71
|
-
const SOCKET_HEADERS = {
|
|
72
|
-
'user-agent': `socket-mcp/${VERSION}`,
|
|
73
|
-
accept: 'application/x-ndjson',
|
|
74
|
-
'content-type': 'application/json',
|
|
75
|
-
authorization: `Bearer ${SOCKET_API_KEY}`
|
|
76
|
-
};
|
|
77
80
|
const components = packages.map(pkg => {
|
|
78
|
-
const cleanedVersion = pkg.version.replace(/[\^~]/g, '');
|
|
81
|
+
const cleanedVersion = (pkg.version ?? 'unknown').replace(/[\^~]/g, '');
|
|
82
|
+
const ecosystem = pkg.ecosystem ?? 'npm';
|
|
79
83
|
let purl;
|
|
80
84
|
if (cleanedVersion === '1.0.0' || cleanedVersion === 'unknown' || !cleanedVersion) {
|
|
81
|
-
purl = `pkg:${
|
|
85
|
+
purl = `pkg:${ecosystem}/${pkg.depname}`;
|
|
82
86
|
}
|
|
83
87
|
else {
|
|
84
88
|
logger.info(`Using version ${cleanedVersion} for ${pkg.depname}`);
|
|
85
|
-
purl = `pkg:${
|
|
89
|
+
purl = `pkg:${ecosystem}/${pkg.depname}@${cleanedVersion}`;
|
|
86
90
|
}
|
|
87
91
|
return { purl };
|
|
88
92
|
});
|
|
89
93
|
try {
|
|
90
94
|
const response = await fetch(SOCKET_API_URL, {
|
|
91
95
|
method: 'POST',
|
|
92
|
-
headers:
|
|
96
|
+
headers: buildSocketHeaders(),
|
|
93
97
|
body: JSON.stringify({ components })
|
|
94
98
|
});
|
|
95
99
|
const responseText = await response.text();
|
|
@@ -154,6 +158,9 @@ server.tool('depscore', "Get the dependency score of packages with the `depscore
|
|
|
154
158
|
.join(', ');
|
|
155
159
|
results.push(`${purl}: ${scoreEntries}`);
|
|
156
160
|
}
|
|
161
|
+
else {
|
|
162
|
+
results.push(`${purl}: No score found`);
|
|
163
|
+
}
|
|
157
164
|
}
|
|
158
165
|
return {
|
|
159
166
|
content: [
|
|
@@ -203,37 +210,6 @@ if (useHttp) {
|
|
|
203
210
|
logger.info(`Starting HTTP server on port ${port}`);
|
|
204
211
|
let httpTransport = null;
|
|
205
212
|
const httpServer = createServer(async (req, res) => {
|
|
206
|
-
const origin = req.headers.origin;
|
|
207
|
-
const allowedOrigins = [
|
|
208
|
-
'http://localhost:3000',
|
|
209
|
-
'http://127.0.0.1:3000',
|
|
210
|
-
'https://mcp.socket.dev',
|
|
211
|
-
'https://mcp.socket-staging.dev'
|
|
212
|
-
];
|
|
213
|
-
const isValidOrigin = !origin || allowedOrigins.includes(origin);
|
|
214
|
-
if (origin && !isValidOrigin) {
|
|
215
|
-
logger.warn(`Rejected request from invalid origin: ${origin}`);
|
|
216
|
-
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
217
|
-
res.end(JSON.stringify({
|
|
218
|
-
jsonrpc: '2.0',
|
|
219
|
-
error: { code: -32000, message: 'Forbidden: Invalid origin' },
|
|
220
|
-
id: null
|
|
221
|
-
}));
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
if (origin && isValidOrigin) {
|
|
225
|
-
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
|
|
229
|
-
}
|
|
230
|
-
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
231
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept');
|
|
232
|
-
if (req.method === 'OPTIONS') {
|
|
233
|
-
res.writeHead(200);
|
|
234
|
-
res.end();
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
213
|
let url;
|
|
238
214
|
try {
|
|
239
215
|
url = new URL(req.url, `http://localhost:${port}`);
|
|
@@ -258,6 +234,32 @@ if (useHttp) {
|
|
|
258
234
|
}));
|
|
259
235
|
return;
|
|
260
236
|
}
|
|
237
|
+
const origin = req.headers.origin;
|
|
238
|
+
const allowedOrigins = [
|
|
239
|
+
'http://localhost:3000',
|
|
240
|
+
'http://127.0.0.1:3000',
|
|
241
|
+
'https://mcp.socket.dev',
|
|
242
|
+
'https://mcp.socket-staging.dev'
|
|
243
|
+
];
|
|
244
|
+
const isValidOrigin = origin && allowedOrigins.includes(origin);
|
|
245
|
+
if (!isValidOrigin) {
|
|
246
|
+
logger.warn(`Rejected request from invalid origin: ${origin}`);
|
|
247
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
248
|
+
res.end(JSON.stringify({
|
|
249
|
+
jsonrpc: '2.0',
|
|
250
|
+
error: { code: -32000, message: 'Forbidden: Invalid origin' },
|
|
251
|
+
id: null
|
|
252
|
+
}));
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
256
|
+
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
257
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept');
|
|
258
|
+
if (req.method === 'OPTIONS') {
|
|
259
|
+
res.writeHead(200);
|
|
260
|
+
res.end();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
261
263
|
if (url.pathname === '/') {
|
|
262
264
|
if (req.method === 'POST') {
|
|
263
265
|
let body = '';
|
|
@@ -9,7 +9,7 @@ async function main() {
|
|
|
9
9
|
command: 'node',
|
|
10
10
|
args: ['--experimental-strip-types', serverPath],
|
|
11
11
|
env: {
|
|
12
|
-
...process.env,
|
|
12
|
+
...Object.fromEntries(Object.entries(process.env).filter(([, value]) => value !== undefined)),
|
|
13
13
|
SOCKET_API_KEY: process.env['SOCKET_API_KEY'] || ''
|
|
14
14
|
}
|
|
15
15
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socketsecurity/mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"bin": {
|
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
"build": "npm run clean && run-s build:*",
|
|
21
21
|
"build:types": "tsc -p tsconfig.declaration.json",
|
|
22
22
|
"build:permissions": "chmod +x ./index.js && (chmod +x ./mock-client/*.js 2>/dev/null || true)",
|
|
23
|
-
"build-
|
|
24
|
-
"build-
|
|
25
|
-
"build-
|
|
26
|
-
"build-
|
|
23
|
+
"build-mcpb": "run-s build build-mcpb:*",
|
|
24
|
+
"build-mcpb:versions_match": "node --experimental-strip-types scripts/check-versions.ts",
|
|
25
|
+
"build-mcpb:validate": "npx mcpb validate ./",
|
|
26
|
+
"build-mcpb:ensure-deps": "npm install --production --ignore-scripts",
|
|
27
|
+
"build-mcpb:mcpb-pack": "npx mcpb pack ./",
|
|
27
28
|
"clean": "./scripts/clean.sh",
|
|
28
29
|
"debug-stdio": "node --experimental-strip-types ./mock-client/debug-client.ts",
|
|
29
30
|
"debug-sdk": "node --experimental-strip-types ./mock-client/stdio-client.ts",
|
|
@@ -33,6 +34,8 @@
|
|
|
33
34
|
},
|
|
34
35
|
"keywords": [],
|
|
35
36
|
"files": [
|
|
37
|
+
"package.json",
|
|
38
|
+
"package-lock.json",
|
|
36
39
|
"index.js",
|
|
37
40
|
"index.d.ts",
|
|
38
41
|
"index.d.ts.map",
|
|
@@ -46,14 +49,14 @@
|
|
|
46
49
|
"url": "https://github.com/SocketDev/socket-mcp"
|
|
47
50
|
},
|
|
48
51
|
"dependencies": {
|
|
52
|
+
"@anthropic-ai/mcpb": "^1.1.0",
|
|
49
53
|
"@modelcontextprotocol/sdk": "^1.18.0",
|
|
50
|
-
"pino": "^
|
|
54
|
+
"pino": "^10.0.0",
|
|
51
55
|
"pino-pretty": "^13.0.0",
|
|
52
56
|
"semver": "^7.7.2",
|
|
53
57
|
"zod": "^3.24.4"
|
|
54
58
|
},
|
|
55
59
|
"devDependencies": {
|
|
56
|
-
"@anthropic-ai/dxt": "^0.2.0",
|
|
57
60
|
"@types/node": "^24.0.7",
|
|
58
61
|
"@types/semver": "^7.7.0",
|
|
59
62
|
"@types/triple-beam": "^1.3.5",
|