@socketsecurity/mcp 0.0.2
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/LICENSE +21 -0
- package/README.md +197 -0
- package/build/index.js +155 -0
- package/package.json +33 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Socket Inc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Socket MCP Server
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server for Socket integration, allowing AI assistants to efficiently check dependency vulnerability scores and security information.
|
|
4
|
+
|
|
5
|
+
🛠️ This project is in early development and rapidly evolving.
|
|
6
|
+
|
|
7
|
+
## Tools
|
|
8
|
+
|
|
9
|
+
### depscore
|
|
10
|
+
|
|
11
|
+
The `depscore` tool allows AI assistants to query the Socket API for dependency scoring information. It provides security and quality metrics for packages across different ecosystems.
|
|
12
|
+
|
|
13
|
+
**Parameters:**
|
|
14
|
+
|
|
15
|
+
- `ecosystem`: The package ecosystem (e.g., npm, PyPI). Defaults to "npm".
|
|
16
|
+
- `depname`: The name of the dependency.
|
|
17
|
+
- `version`: The version of the dependency. Defaults to "unknown".
|
|
18
|
+
|
|
19
|
+
## Configuration
|
|
20
|
+
|
|
21
|
+
### Getting an API key
|
|
22
|
+
|
|
23
|
+
To use the Socket MCP Server, you need to create an API key. You can do this by following [these steps](https://docs.socket.dev/reference/creating-and-managing-api-tokens).
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Usage with Claude Desktop
|
|
27
|
+
|
|
28
|
+
> [!NOTE]
|
|
29
|
+
> Custom integrations are not available to all paid versions of Claude. Check [here](https://support.anthropic.com/en/articles/11175166-about-custom-integrations-using-remote-mcp) for more information.
|
|
30
|
+
|
|
31
|
+
To use this MCP server with Claude Desktop:
|
|
32
|
+
|
|
33
|
+
1. Install the Socket MCP server:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g @socketsecurity/mcp
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
2. Set the API key in your environment:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
export SOCKET_API_KEY=your_api_key_here
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
3. In Claude Desktop, go to Settings > Developer > Edit Config.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
{
|
|
50
|
+
"mcpServers": {
|
|
51
|
+
"socket-mcp": {
|
|
52
|
+
"command": "socket-mcp",
|
|
53
|
+
"args": [],
|
|
54
|
+
"env": {
|
|
55
|
+
"SOCKET_API_KEY": "your-api-key"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
4. Enter the following:
|
|
63
|
+
- Name: Socket
|
|
64
|
+
- Command: `socket-mcp`
|
|
65
|
+
- Save the configuration.
|
|
66
|
+
|
|
67
|
+
5. Now you can ask Claude questions like "Check the security score for express version 4.18.2".
|
|
68
|
+
|
|
69
|
+
The process is similar for Claude Code. See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/tutorials#set-up-model-context-protocol-mcp) for more details.
|
|
70
|
+
|
|
71
|
+
### Usage with VS Code
|
|
72
|
+
|
|
73
|
+
For quick installation, you can use the following link to install the Socket MCP server in VS Code:
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
[](https://vscode.dev/redirect/mcp/install?name=socket-mcp&inputs=[{"type":"promptString","id":"socket_api_key","description":"Socket%20API%20key","password":true}]&config={"command":"depscore","type":"stdio","env":{"SOCKET_API_KEY":"${input:socket_api_key}"}})
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
To use this MCP server in VS Code:
|
|
80
|
+
|
|
81
|
+
1. Set the API key in your environment:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
export SOCKET_API_KEY=your_api_key_here
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
2. In VS Code settings, add the Socket MCP server to your configuration `.vscode/mcp.json` file:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"inputs": [
|
|
92
|
+
{
|
|
93
|
+
"type": "promptString",
|
|
94
|
+
"id": "socket_api_key",
|
|
95
|
+
"description": "Socket API Key",
|
|
96
|
+
"password": true
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"servers": {
|
|
100
|
+
"socket-mcp": {
|
|
101
|
+
"type": "stdio",
|
|
102
|
+
"command": "socket-mcp",
|
|
103
|
+
"args": [],
|
|
104
|
+
"env": {
|
|
105
|
+
"SOCKET_API_KEY": "${input:socket_api_key}"
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
3. Now you can ask questions about dependency security within your VS Code environment.
|
|
113
|
+
4. Feel free to add the following to your `.github/copilot-instructions.md` file to control better how the tools is used by your agent:
|
|
114
|
+
|
|
115
|
+
```markdown
|
|
116
|
+
## Socket MCP Server
|
|
117
|
+
Always check the dependencies scores with the depscore tool when you add a new dependency. If the score is low, consider using an alternative library or writing the code yourself. If you decide to use a library with a low score, make sure to document the reasons for your choice. If you are unsure about the score, ask for a review from someone with more experience.
|
|
118
|
+
|
|
119
|
+
When checking dependencies, make sure to also check the imports not just the pyproject.toml/package.json/dependency file.
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Development
|
|
123
|
+
|
|
124
|
+
### Prerequisites
|
|
125
|
+
|
|
126
|
+
- Node.js v16 or higher
|
|
127
|
+
- npm or yarn
|
|
128
|
+
|
|
129
|
+
### Installation
|
|
130
|
+
|
|
131
|
+
Clone the repository and install dependencies:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
git clone https://github.com/SocketDev/socket-mcp.git
|
|
135
|
+
cd socket-mcp
|
|
136
|
+
npm install
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Build
|
|
140
|
+
|
|
141
|
+
To build the project:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npm run build
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This compiles the TypeScript files and makes the binary executable called `socket-mcp`.
|
|
148
|
+
|
|
149
|
+
## Run
|
|
150
|
+
|
|
151
|
+
To run the Socket MCP server locally:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
export SOCKET_API_KEY=your_api_key_here
|
|
155
|
+
node build/index.js
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
After installing globally, you can run the executable directly:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
export SOCKET_API_KEY=your_api_key_here
|
|
162
|
+
socket-mcp
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Global Installation
|
|
166
|
+
|
|
167
|
+
To install the tool globally and make the `socket-mcp` command available system-wide:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npm install -g .
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
After global installation, you can use the `socket-mcp` command from anywhere:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
export SOCKET_API_KEY=your_api_key_here
|
|
177
|
+
socket-mcp
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Adjust tool usage with custom rules
|
|
181
|
+
|
|
182
|
+
You can further customize how the Socket MCP server interacts with your AI assistant by modifying your client rules. The rules are usually a markdown file and its location depends on the AI assistant you are using.
|
|
183
|
+
|
|
184
|
+
| MCP Client | Rules File Location |
|
|
185
|
+
|---|---|
|
|
186
|
+
| Claude Desktop/Code | `CLAUDE.md` |
|
|
187
|
+
| VSCode Copilot | `.github/copilot-instructions.md` |
|
|
188
|
+
| Cursor | `.cursor/rules` |
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
Rules that can be added to the client rules file include the following:
|
|
192
|
+
|
|
193
|
+
```md
|
|
194
|
+
Always check dependency scores with the debscore tool when you add a new dependency. If the score is low, consider using an alternative library or writing the code yourself. If you are unsure about the score, ask for a review from someone with more experience. When checking dependencies, make sure to also check the imports not just the pyproject.toml file.
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
You can adjust the rules to fit your needs. For example, you can add rules to include specific manifest files, or guide the AI assistant on how to handle low scores. The rules are flexible and can be tailored to your workflow.
|
package/build/index.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import fetch from 'node-fetch';
|
|
6
|
+
import winston from 'winston';
|
|
7
|
+
const VERSION = "0.0.1"; // Version of the MCP server
|
|
8
|
+
// Configure winston logger
|
|
9
|
+
const logger = winston.createLogger({
|
|
10
|
+
level: 'info',
|
|
11
|
+
format: winston.format.combine(winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.json()),
|
|
12
|
+
transports: [
|
|
13
|
+
new winston.transports.File({ filename: 'socket-mcp-error.log', level: 'error' }),
|
|
14
|
+
new winston.transports.File({ filename: 'socket-mcp.log' })
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
const SOCKET_API_URL = "https://api.socket.dev/v0/purl?alerts=false&compact=false&fixable=false&licenseattrib=false&licensedetails=false";
|
|
18
|
+
const SOCKET_API_KEY = process.env.SOCKET_API_KEY || "";
|
|
19
|
+
if (!SOCKET_API_KEY) {
|
|
20
|
+
logger.error("SOCKET_API_KEY environment variable is not set");
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const SOCKET_HEADERS = {
|
|
24
|
+
"user-agent": `socket-mcp/${VERSION}`,
|
|
25
|
+
"accept": "application/x-ndjson",
|
|
26
|
+
"content-type": "application/json",
|
|
27
|
+
"authorization": `Bearer ${SOCKET_API_KEY}`
|
|
28
|
+
};
|
|
29
|
+
// Create server instance
|
|
30
|
+
const server = new McpServer({
|
|
31
|
+
name: "socket",
|
|
32
|
+
version: VERSION,
|
|
33
|
+
description: "Socket MCP server",
|
|
34
|
+
capabilities: {
|
|
35
|
+
resources: {},
|
|
36
|
+
tools: {},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
server.tool("depscore", "Get the dependency score of a package 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).", {
|
|
40
|
+
ecosystem: z.string().describe("The package ecosystem (e.g., npm, pypi)").default("npm"),
|
|
41
|
+
depname: z.string().describe("The name of the dependency"),
|
|
42
|
+
version: z.string().describe("The version of the dependency, use 'unknown' if not known").default("unknown"),
|
|
43
|
+
}, async ({ ecosystem, depname, version }) => {
|
|
44
|
+
logger.info(`Received request for ${depname} (${version}) in ${ecosystem} ecosystem`);
|
|
45
|
+
// cleanup version
|
|
46
|
+
let purl;
|
|
47
|
+
const cleanedVersion = version.replace(/[\^~]/g, ''); // Remove ^ and ~ from version
|
|
48
|
+
if (cleanedVersion === "1.0.0" || cleanedVersion === "unknown" || !cleanedVersion) {
|
|
49
|
+
purl = `pkg:${ecosystem}/${depname}`;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
logger.info(`Using version ${cleanedVersion} for ${depname}`);
|
|
53
|
+
purl = `pkg:${ecosystem}/${depname}@${cleanedVersion}`;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
// Make a POST request to the Socket API
|
|
57
|
+
const response = await fetch(SOCKET_API_URL, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: SOCKET_HEADERS,
|
|
60
|
+
body: JSON.stringify({ components: [{ purl }] })
|
|
61
|
+
});
|
|
62
|
+
const responseText = await response.text();
|
|
63
|
+
if (response.status !== 200) {
|
|
64
|
+
const errorMsg = `Error processing ${purl}: [${response.status}] ${responseText}`;
|
|
65
|
+
logger.error(errorMsg);
|
|
66
|
+
return {
|
|
67
|
+
content: [{ type: "text", text: errorMsg }],
|
|
68
|
+
isError: false
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
else if (!responseText.trim()) {
|
|
72
|
+
const errorMsg = `${purl} was not found.`;
|
|
73
|
+
logger.error(errorMsg);
|
|
74
|
+
return {
|
|
75
|
+
content: [{ type: "text", text: errorMsg }],
|
|
76
|
+
isError: false
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
// Handle NDJSON (multiple JSON objects, one per line)
|
|
81
|
+
let jsonData;
|
|
82
|
+
if ((response.headers.get('content-type') || '').includes('x-ndjson')) {
|
|
83
|
+
const jsonLines = responseText.split('\n')
|
|
84
|
+
.filter(line => line.trim())
|
|
85
|
+
.map(line => JSON.parse(line));
|
|
86
|
+
if (!jsonLines.length) {
|
|
87
|
+
const errorMsg = `No valid JSON objects found in NDJSON response for ${purl}`;
|
|
88
|
+
return {
|
|
89
|
+
content: [{ type: "text", text: errorMsg }],
|
|
90
|
+
isError: true
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
jsonData = jsonLines[0];
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
jsonData = JSON.parse(responseText);
|
|
97
|
+
}
|
|
98
|
+
if (jsonData.score && jsonData.score.overall !== undefined) {
|
|
99
|
+
// Unroll the jsonData.score object into key-value pairs
|
|
100
|
+
const scoreEntries = Object.entries(jsonData.score)
|
|
101
|
+
.filter(([key]) => key !== "overall" && key !== "uuid")
|
|
102
|
+
.map(([key, value]) => `${key}: ${value}`)
|
|
103
|
+
.join(', ');
|
|
104
|
+
return {
|
|
105
|
+
content: [
|
|
106
|
+
{
|
|
107
|
+
type: "text",
|
|
108
|
+
text: `Dependency scores for ${purl}: ${scoreEntries}`
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: "text",
|
|
118
|
+
text: `No score found for ${purl}`
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
const error = e;
|
|
126
|
+
const errorMsg = `JSON parsing error for ${purl}: ${error.message} -- Response: ${responseText}`;
|
|
127
|
+
logger.error(errorMsg);
|
|
128
|
+
const llmResponse = `Package ${purl} not found.`;
|
|
129
|
+
return {
|
|
130
|
+
content: [{ type: "text", text: llmResponse }],
|
|
131
|
+
isError: true
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
const error = e;
|
|
137
|
+
const errorMsg = `Error processing ${purl}: ${error.message}`;
|
|
138
|
+
logger.error(errorMsg);
|
|
139
|
+
const llmResponse = `Package ${purl} not found.`;
|
|
140
|
+
return {
|
|
141
|
+
content: [{ type: "text", text: llmResponse }],
|
|
142
|
+
isError: true
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// Create a stdio transport and start the server
|
|
147
|
+
const transport = new StdioServerTransport();
|
|
148
|
+
server.connect(transport)
|
|
149
|
+
.then(() => {
|
|
150
|
+
logger.info("Socket MCP server started successfully");
|
|
151
|
+
})
|
|
152
|
+
.catch((error) => {
|
|
153
|
+
logger.error(`Failed to start Socket MCP server: ${error.message}`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@socketsecurity/mcp",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./build/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"socket-mcp": "./build/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && chmod 755 ./build/index.js",
|
|
11
|
+
"postinstall": "npm run build"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"build"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [],
|
|
17
|
+
"author": "Alexandros Kapravelos",
|
|
18
|
+
"description": "Socket MCP server for scanning dependencies",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@modelcontextprotocol/sdk": "^1.11.3",
|
|
21
|
+
"@types/node-fetch": "^2.6.12",
|
|
22
|
+
"node-fetch": "^3.3.2",
|
|
23
|
+
"semver": "^7.7.2",
|
|
24
|
+
"winston": "^3.17.0",
|
|
25
|
+
"zod": "^3.24.4"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^22.15.19",
|
|
29
|
+
"@types/semver": "^7.7.0",
|
|
30
|
+
"@types/triple-beam": "^1.3.5",
|
|
31
|
+
"typescript": "^5.8.3"
|
|
32
|
+
}
|
|
33
|
+
}
|