@socketsecurity/mcp 0.0.6 → 0.0.8
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 +276 -103
- package/build/index.js +161 -23
- package/build/index.js.map +1 -0
- package/build/mock-client/debug-client.js +138 -0
- package/build/mock-client/debug-client.js.map +1 -0
- package/build/mock-client/http-client.js +153 -0
- package/build/mock-client/http-client.js.map +1 -0
- package/build/mock-client/stdio-client.js +53 -0
- package/build/mock-client/stdio-client.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,132 +1,311 @@
|
|
|
1
1
|
# Socket MCP Server
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/js/@socketsecurity%2Fmcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://socket.dev/npm/package/@socketsecurity/mcp)
|
|
6
|
+
|
|
3
7
|
A Model Context Protocol (MCP) server for Socket integration, allowing AI assistants to efficiently check dependency vulnerability scores and security information.
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
## ✨ Features
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
- 🔍 **Dependency Security Scanning** - Get comprehensive security scores for npm, PyPI, and other package ecosystems
|
|
12
|
+
- 🌐 **Public Hosted Service** - Use our public server at `https://mcp.socket.dev/` with no setup required
|
|
13
|
+
- 🚀 **Multiple Deployment Options** - Run locally via stdio, HTTP, or use our service
|
|
14
|
+
- 🤖 **AI Assistant Integration** - Works seamlessly with Claude, VS Code Copilot, Cursor, and other MCP clients
|
|
15
|
+
- 📊 **Batch Processing** - Check multiple dependencies in a single request
|
|
16
|
+
- 🔒 **No Authentication Required** - Public server requires no API keys or registration
|
|
8
17
|
|
|
9
|
-
|
|
18
|
+
🛠️ This project is in early development and rapidly evolving.
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
## 🚀 Quick Start
|
|
12
21
|
|
|
13
|
-
|
|
22
|
+
### Option 1: Use the Public Socket MCP Server (Recommended)
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
- `depname`: The name of the dependency.
|
|
17
|
-
- `version`: The version of the dependency. Defaults to "unknown".
|
|
24
|
+
The easiest way to get started is to use our public Socket MCP server. **No API key or authentication required!** Click a button below to install the public server in your favorite AI assistant.
|
|
18
25
|
|
|
19
|
-
## Configuration
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
[](https://vscode.dev/redirect/mcp/install?name=socket-mcp&config={"url":"https://mcp.socket.dev/","type":"http"})
|
|
28
|
+
[](https://cursor.com/install-mcp?name=socket-mcp&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vbWNwLnNvY2tldC5kZXYifQ%3D%3D)
|
|
22
29
|
|
|
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). The only required permission scope is `packages:list`, which allows the MCP server to query package metadata for dependency scores.
|
|
24
30
|
|
|
31
|
+
<details><summary><b>Manual Installation Instructions & more MCP Clients</b></summary>
|
|
25
32
|
|
|
26
|
-
|
|
33
|
+
<details><summary><b>Install in Claude Desktop or Claude Code</b></summary>
|
|
27
34
|
|
|
28
35
|
> [!NOTE]
|
|
29
36
|
> 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
37
|
|
|
31
|
-
To use
|
|
38
|
+
To use the public Socket MCP server with Claude Desktop:
|
|
32
39
|
|
|
33
|
-
1.
|
|
40
|
+
1. In Claude Desktop, go to Settings > Developer > Edit Config.
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
npm install -g @socketsecurity/mcp
|
|
37
|
-
```
|
|
42
|
+
2. Add the Socket MCP server configuration:
|
|
38
43
|
|
|
39
|
-
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"socket-mcp": {
|
|
48
|
+
"type": "http",
|
|
49
|
+
"url": "https://mcp.socket.dev/"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
export SOCKET_API_KEY=your_api_key_here
|
|
43
|
-
```
|
|
55
|
+
3. Save the configuration and restart Claude Desktop.
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
4. Now you can ask Claude questions like "Check the security score for express version 4.18.2".
|
|
46
58
|
|
|
59
|
+
The process is similar for Claude Code. See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/mcp) for more details. Here's an example command to add the Socket MCP server:
|
|
47
60
|
|
|
48
|
-
```
|
|
61
|
+
```bash
|
|
62
|
+
claude mcp add --transport http socket-mcp https://mcp.socket.dev/
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
</details>
|
|
66
|
+
|
|
67
|
+
<details><summary><b>Install in VS Code</b></summary>
|
|
68
|
+
|
|
69
|
+
You can install the Socket MCP server using the VS Code CLI:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# For VS Code with GitHub Copilot
|
|
73
|
+
code --add-mcp '{"name":"socket-mcp","type":"http","url":"https://mcp.socket.dev/}'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
After installation, the Socket MCP server will be available for use with your GitHub Copilot agent in VS Code.
|
|
77
|
+
|
|
78
|
+
Alternatively, you can manually add it to your VS Code MCP configuration in `.vscode/mcp.json`:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"servers": {
|
|
83
|
+
"socket-mcp": {
|
|
84
|
+
"type": "http",
|
|
85
|
+
"url": "https://mcp.socket.dev/"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
</details>
|
|
92
|
+
|
|
93
|
+
<details><summary><b>Install in Cursor</b></summary>
|
|
94
|
+
|
|
95
|
+
Go to `Cursor Settings` -> `MCP` -> `Add new MCP Server`. Name it "socket-mcp", use `http` type with URL `https://mcp.socket.dev/`.
|
|
96
|
+
|
|
97
|
+
```json
|
|
49
98
|
{
|
|
50
99
|
"mcpServers": {
|
|
51
100
|
"socket-mcp": {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"env": {
|
|
55
|
-
"SOCKET_API_KEY": "your-api-key"
|
|
56
|
-
}
|
|
101
|
+
"type": "http",
|
|
102
|
+
"url": "https://mcp.socket.dev/"
|
|
57
103
|
}
|
|
58
104
|
}
|
|
59
105
|
}
|
|
60
106
|
```
|
|
61
107
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
108
|
+
</details>
|
|
109
|
+
|
|
110
|
+
<details><summary><b>Install in Windsurf</b></summary>
|
|
111
|
+
|
|
112
|
+
> [!WARNING]
|
|
113
|
+
> Windsurf does not support `http` type MCP servers yet. Use the `stdio` configuration [below](#option-2a-stdio-mode-default).
|
|
114
|
+
|
|
115
|
+
To use the Socket MCP server in Windsurf:
|
|
116
|
+
|
|
117
|
+
1. Open Windsurf Settings
|
|
118
|
+
2. Navigate to MCP Servers section
|
|
119
|
+
3. Add a new server with the following configuration:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"mcpServers": {
|
|
124
|
+
"socket-mcp": {
|
|
125
|
+
"serverUrl": "https://mcp.socket.dev/mcp"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
4. Save the configuration and restart Windsurf if needed.
|
|
132
|
+
|
|
133
|
+
</details>
|
|
134
|
+
|
|
135
|
+
</details>
|
|
136
|
+
|
|
137
|
+
### Option 2: Deploy Socket MCP Server on your machine
|
|
138
|
+
|
|
139
|
+
If you prefer to run your own instance, you can deploy the Socket MCP server locally using either stdio or HTTP modes.
|
|
66
140
|
|
|
67
|
-
|
|
141
|
+
### Getting an API key
|
|
142
|
+
|
|
143
|
+
To use a local 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). The only required permission scope is `packages:list`, which allows the MCP server to query package metadata for dependency scores.
|
|
144
|
+
|
|
145
|
+
For local deployment, you have two options:
|
|
68
146
|
|
|
69
|
-
|
|
147
|
+
##### Option 2a: Stdio Mode (Default)
|
|
70
148
|
|
|
71
|
-
|
|
149
|
+
Click a button below to install the self-hosted stdio server in your favorite AI assistant.
|
|
72
150
|
|
|
73
|
-
|
|
151
|
+
[](https://vscode.dev/redirect/mcp/install?name=socket-mcp&config={"command":"npx","args":["@socketsecurity/mcp@latest"],"type":"stdio"})
|
|
152
|
+
[](https://cursor.com/install-mcp?name=socket-mcp-stdio&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyJAc29ja2V0c2VjdXJpdHkvbWNwQGxhdGVzdCJdLCJlbnYiOnsiU09DS0VUX0FQSV9LRVkiOiJ5b3VyLWFwaS1rZXktaGVyZSJ9fQ==)
|
|
74
153
|
|
|
154
|
+
Claude Code (stdio mode) can be set up with the following command:
|
|
75
155
|
|
|
76
|
-
|
|
156
|
+
```bash
|
|
157
|
+
claude mcp add socket-mcp -e SOCKET_API_KEY="your-api-key-here" -- npx -y @socketsecurity/mcp@latest
|
|
158
|
+
```
|
|
159
|
+
This is how the configuration looks like on most MCP clients:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"mcpServers": {
|
|
164
|
+
"socket-mcp": {
|
|
165
|
+
"command": "npx",
|
|
166
|
+
"args": ["@socketsecurity/mcp@latest"],
|
|
167
|
+
"env": {
|
|
168
|
+
"SOCKET_API_KEY": "your-api-key-here"
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
77
174
|
|
|
175
|
+
This approach automatically uses the latest version without requiring global installation.
|
|
78
176
|
|
|
79
|
-
To use this MCP server in VS Code:
|
|
80
177
|
|
|
81
|
-
|
|
178
|
+
##### Option 2b: HTTP Mode
|
|
82
179
|
|
|
180
|
+
1. Run the server in HTTP mode using npx:
|
|
83
181
|
```bash
|
|
84
|
-
|
|
182
|
+
MCP_HTTP_MODE=true SOCKET_API_KEY=your-api-key npx @socketsecurity/mcp@latest --http
|
|
85
183
|
```
|
|
86
184
|
|
|
87
|
-
2.
|
|
88
|
-
|
|
185
|
+
2. Configure your MCP client to connect to the HTTP server:
|
|
89
186
|
```json
|
|
187
|
+
{
|
|
188
|
+
"mcpServers": {
|
|
189
|
+
"socket-mcp": {
|
|
190
|
+
"type": "http",
|
|
191
|
+
"url": "http://localhost:3000"
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Tools exposed by the Socket MCP Server
|
|
198
|
+
|
|
199
|
+
### depscore
|
|
200
|
+
|
|
201
|
+
The `depscore` tool allows AI assistants to query the Socket API for dependency scoring information. It provides comprehensive security and quality metrics for packages across different ecosystems.
|
|
202
|
+
|
|
203
|
+
**Parameters:**
|
|
204
|
+
|
|
205
|
+
| Parameter | Type | Required | Default | Description |
|
|
206
|
+
|-----------|------|----------|---------|-------------|
|
|
207
|
+
| `packages` | Array | ✅ Yes | - | Array of package objects to analyze |
|
|
208
|
+
| `packages[].ecosystem` | String | No | `"npm"` | Package ecosystem (`npm`, `pypi`, `cargo`, etc.) |
|
|
209
|
+
| `packages[].depname` | String | ✅ Yes | - | Name of the dependency/package |
|
|
210
|
+
| `packages[].version` | String | No | `"unknown"` | Version of the dependency |
|
|
211
|
+
|
|
212
|
+
**Example Usage:**
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"packages": [
|
|
90
217
|
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
}
|
|
218
|
+
"ecosystem": "npm",
|
|
219
|
+
"depname": "express",
|
|
220
|
+
"version": "4.18.2"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"ecosystem": "pypi",
|
|
224
|
+
"depname": "fastapi",
|
|
225
|
+
"version": "0.100.0"
|
|
109
226
|
}
|
|
110
|
-
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
```
|
|
111
230
|
|
|
112
|
-
|
|
113
|
-
|
|
231
|
+
**Sample Response:**
|
|
232
|
+
```
|
|
233
|
+
pkg:npm/express@4.18.2: supply_chain: 1.0, quality: 0.9, maintenance: 1.0, vulnerability: 1.0, license: 1.0
|
|
234
|
+
pkg:pypi/fastapi@0.100.0: supply_chain: 1.0, quality: 0.95, maintenance: 0.98, vulnerability: 1.0, license: 1.0
|
|
235
|
+
```
|
|
114
236
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
237
|
+
### How to Use the Socket MCP Server
|
|
238
|
+
|
|
239
|
+
1. **Ask your AI assistant** to check dependencies:
|
|
240
|
+
- "Check the security score for express version 4.18.2"
|
|
241
|
+
- "Analyze the security of my package.json dependencies"
|
|
242
|
+
- "What are the vulnerability scores for react, lodash, and axios?"
|
|
243
|
+
|
|
244
|
+
2. **Get comprehensive security insights** including supply chain, quality, maintenance, vulnerability, and license scores.
|
|
245
|
+
|
|
246
|
+
### Adjust tool usage with custom rules
|
|
247
|
+
|
|
248
|
+
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.
|
|
249
|
+
|
|
250
|
+
| MCP Client | Rules File Location |
|
|
251
|
+
|---|---|
|
|
252
|
+
| Claude Desktop/Code | `CLAUDE.md` |
|
|
253
|
+
| VSCode Copilot | `.github/copilot-instructions.md` |
|
|
254
|
+
| Cursor | `.cursor/rules` |
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
Rules that can be added to the client rules file include the following:
|
|
258
|
+
|
|
259
|
+
```md
|
|
260
|
+
Always check dependency 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 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/package.json/dependency file.
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
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.
|
|
118
264
|
|
|
119
|
-
When checking dependencies, make sure to also check the imports not just the pyproject.toml/package.json/dependency file.
|
|
120
|
-
```
|
|
121
265
|
|
|
122
266
|
## Development
|
|
123
267
|
|
|
124
|
-
###
|
|
268
|
+
### For End Users
|
|
269
|
+
|
|
270
|
+
For most users, we recommend using either:
|
|
271
|
+
1. **Public server**: `https://mcp.socket.dev/` (no setup required)
|
|
272
|
+
2. **NPX command**: `npx @socketsecurity/mcp@latest` (always latest version)
|
|
273
|
+
|
|
274
|
+
### For Contributors
|
|
275
|
+
|
|
276
|
+
If you want to contribute to the Socket MCP server development:
|
|
277
|
+
|
|
278
|
+
### Health Check Endpoint
|
|
279
|
+
|
|
280
|
+
When running in HTTP mode, the server provides a health check endpoint for Kubernetes and Docker deployments:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
GET /health
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Response:**
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"status": "healthy",
|
|
290
|
+
"service": "socket-mcp",
|
|
291
|
+
"version": "0.0.3",
|
|
292
|
+
"timestamp": "2025-06-17T20:45:22.059Z"
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
This endpoint can be used for:
|
|
297
|
+
- Kubernetes liveness and readiness probes
|
|
298
|
+
- Docker health checks
|
|
299
|
+
- Load balancer health monitoring
|
|
300
|
+
- General service monitoring
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
#### Prerequisites
|
|
125
304
|
|
|
126
305
|
- Node.js v16 or higher
|
|
127
306
|
- npm or yarn
|
|
128
307
|
|
|
129
|
-
|
|
308
|
+
#### Installation
|
|
130
309
|
|
|
131
310
|
Clone the repository and install dependencies:
|
|
132
311
|
|
|
@@ -136,7 +315,7 @@ cd socket-mcp
|
|
|
136
315
|
npm install
|
|
137
316
|
```
|
|
138
317
|
|
|
139
|
-
|
|
318
|
+
#### Build
|
|
140
319
|
|
|
141
320
|
To build the project:
|
|
142
321
|
|
|
@@ -144,54 +323,48 @@ To build the project:
|
|
|
144
323
|
npm run build
|
|
145
324
|
```
|
|
146
325
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
## Run
|
|
326
|
+
#### Run from Source
|
|
150
327
|
|
|
151
|
-
To run the Socket MCP server
|
|
328
|
+
To run the Socket MCP server from source:
|
|
152
329
|
|
|
153
330
|
```bash
|
|
154
331
|
export SOCKET_API_KEY=your_api_key_here
|
|
155
332
|
node build/index.js
|
|
156
333
|
```
|
|
157
334
|
|
|
158
|
-
|
|
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:
|
|
335
|
+
Or in HTTP mode:
|
|
168
336
|
|
|
169
337
|
```bash
|
|
170
|
-
|
|
338
|
+
MCP_HTTP_MODE=true SOCKET_API_KEY=your_api_key_here node build/index.js --http
|
|
171
339
|
```
|
|
172
340
|
|
|
173
|
-
|
|
341
|
+
## 🔧 Troubleshooting
|
|
174
342
|
|
|
175
|
-
|
|
176
|
-
export SOCKET_API_KEY=your_api_key_here
|
|
177
|
-
socket-mcp
|
|
178
|
-
```
|
|
343
|
+
### Common Issues
|
|
179
344
|
|
|
180
|
-
|
|
345
|
+
**Q: The public server isn't responding**
|
|
346
|
+
- Check that you're using the correct URL: `https://mcp.socket.dev/`
|
|
347
|
+
- Verify your MCP client configuration is correct
|
|
348
|
+
- Try restarting your MCP client
|
|
181
349
|
|
|
182
|
-
|
|
350
|
+
**Q: Local server fails to start**
|
|
351
|
+
- Ensure you have Node.js v16+ installed
|
|
352
|
+
- Check that your `SOCKET_API_KEY` environment variable is set
|
|
353
|
+
- Verify the API key has `packages:list` permission
|
|
183
354
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
| Cursor | `.cursor/rules` |
|
|
355
|
+
**Q: Getting authentication errors with local server**
|
|
356
|
+
- Double-check your Socket API key is valid
|
|
357
|
+
- Ensure the key has the required `packages:list` scope
|
|
358
|
+
- Try regenerating your API key from the Socket dashboard
|
|
189
359
|
|
|
360
|
+
**Q: AI assistant can't find the depscore tool**
|
|
361
|
+
- Restart your MCP client after configuration changes
|
|
362
|
+
- Verify the server configuration is saved correctly
|
|
363
|
+
- Check that the MCP server is running (for local deployments)
|
|
190
364
|
|
|
191
|
-
|
|
365
|
+
### Getting Help
|
|
192
366
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
367
|
+
- 📖 [Socket Documentation](https://docs.socket.dev)
|
|
368
|
+
- 🐛 [Report Issues](https://github.com/SocketDev/socket-mcp/issues)
|
|
369
|
+
- 💬 [Community Support](https://github.com/SocketDev/socket-mcp/discussions)
|
|
196
370
|
|
|
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
CHANGED
|
@@ -79,6 +79,12 @@ server.tool("depscore", "Get the dependency score of packages with the `depscore
|
|
|
79
79
|
})).describe("Array of packages to check"),
|
|
80
80
|
}, async ({ packages }) => {
|
|
81
81
|
logger.info(`Received request for ${packages.length} packages`);
|
|
82
|
+
const SOCKET_HEADERS = {
|
|
83
|
+
"user-agent": `socket-mcp/${VERSION}`,
|
|
84
|
+
"accept": "application/x-ndjson",
|
|
85
|
+
"content-type": "application/json",
|
|
86
|
+
"authorization": `Bearer ${SOCKET_API_KEY}`
|
|
87
|
+
};
|
|
82
88
|
// Build components array for the API request
|
|
83
89
|
const components = packages.map(pkg => {
|
|
84
90
|
const cleanedVersion = pkg.version.replace(/[\^~]/g, ''); // Remove ^ and ~ from version
|
|
@@ -105,7 +111,7 @@ server.tool("depscore", "Get the dependency score of packages with the `depscore
|
|
|
105
111
|
logger.error(errorMsg);
|
|
106
112
|
return {
|
|
107
113
|
content: [{ type: "text", text: errorMsg }],
|
|
108
|
-
isError:
|
|
114
|
+
isError: true
|
|
109
115
|
};
|
|
110
116
|
}
|
|
111
117
|
else if (!responseText.trim()) {
|
|
@@ -113,7 +119,7 @@ server.tool("depscore", "Get the dependency score of packages with the `depscore
|
|
|
113
119
|
logger.error(errorMsg);
|
|
114
120
|
return {
|
|
115
121
|
content: [{ type: "text", text: errorMsg }],
|
|
116
|
-
isError:
|
|
122
|
+
isError: true
|
|
117
123
|
};
|
|
118
124
|
}
|
|
119
125
|
try {
|
|
@@ -204,21 +210,39 @@ if (!SOCKET_API_KEY) {
|
|
|
204
210
|
process.exit(1);
|
|
205
211
|
}
|
|
206
212
|
}
|
|
207
|
-
// Now that we have the API key, set up the headers
|
|
208
|
-
const SOCKET_HEADERS = {
|
|
209
|
-
"user-agent": `socket-mcp/${VERSION}`,
|
|
210
|
-
"accept": "application/x-ndjson",
|
|
211
|
-
"content-type": "application/json",
|
|
212
|
-
"authorization": `Bearer ${SOCKET_API_KEY}`
|
|
213
|
-
};
|
|
214
213
|
if (useHttp) {
|
|
215
214
|
// HTTP mode with Server-Sent Events
|
|
216
215
|
logger.info(`Starting HTTP server on port ${port}`);
|
|
217
216
|
const httpServer = createServer(async (req, res) => {
|
|
218
|
-
//
|
|
219
|
-
|
|
217
|
+
// Validate Origin header as required by MCP spec
|
|
218
|
+
const origin = req.headers.origin;
|
|
219
|
+
const allowedOrigins = [
|
|
220
|
+
'http://localhost:3000',
|
|
221
|
+
'http://127.0.0.1:3000',
|
|
222
|
+
'https://mcp.socket.dev',
|
|
223
|
+
'https://mcp.socket-staging.dev'
|
|
224
|
+
];
|
|
225
|
+
const isValidOrigin = !origin || allowedOrigins.includes(origin);
|
|
226
|
+
if (origin && !isValidOrigin) {
|
|
227
|
+
logger.warn(`Rejected request from invalid origin: ${origin}`);
|
|
228
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
229
|
+
res.end(JSON.stringify({
|
|
230
|
+
jsonrpc: '2.0',
|
|
231
|
+
error: { code: -32000, message: 'Forbidden: Invalid origin' },
|
|
232
|
+
id: null
|
|
233
|
+
}));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
// Set CORS headers for valid origins
|
|
237
|
+
if (origin && isValidOrigin) {
|
|
238
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
|
|
242
|
+
}
|
|
220
243
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
221
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, mcp-session-id');
|
|
244
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, mcp-session-id, Accept, Last-Event-ID');
|
|
245
|
+
res.setHeader('Access-Control-Expose-Headers', 'mcp-session-id');
|
|
222
246
|
if (req.method === 'OPTIONS') {
|
|
223
247
|
res.writeHead(200);
|
|
224
248
|
res.end();
|
|
@@ -236,8 +260,20 @@ if (useHttp) {
|
|
|
236
260
|
}));
|
|
237
261
|
return;
|
|
238
262
|
}
|
|
239
|
-
if (url.pathname === '/
|
|
263
|
+
if (url.pathname === '/') {
|
|
240
264
|
if (req.method === 'POST') {
|
|
265
|
+
// Validate Accept header as required by MCP spec
|
|
266
|
+
const acceptHeader = req.headers.accept;
|
|
267
|
+
if (!acceptHeader || (!acceptHeader.includes('application/json') && !acceptHeader.includes('text/event-stream'))) {
|
|
268
|
+
logger.warn(`Invalid Accept header: ${acceptHeader}`);
|
|
269
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
270
|
+
res.end(JSON.stringify({
|
|
271
|
+
jsonrpc: '2.0',
|
|
272
|
+
error: { code: -32000, message: 'Bad Request: Accept header must include application/json or text/event-stream' },
|
|
273
|
+
id: null
|
|
274
|
+
}));
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
241
277
|
// Handle JSON-RPC messages
|
|
242
278
|
let body = '';
|
|
243
279
|
req.on('data', chunk => body += chunk);
|
|
@@ -245,18 +281,39 @@ if (useHttp) {
|
|
|
245
281
|
try {
|
|
246
282
|
const jsonData = JSON.parse(body);
|
|
247
283
|
const sessionId = req.headers['mcp-session-id'];
|
|
284
|
+
// Validate session ID format if provided (must contain only visible ASCII characters)
|
|
285
|
+
if (sessionId && !/^[\x21-\x7E]+$/.test(sessionId)) {
|
|
286
|
+
logger.warn(`Invalid session ID format: ${sessionId}`);
|
|
287
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
288
|
+
res.end(JSON.stringify({
|
|
289
|
+
jsonrpc: '2.0',
|
|
290
|
+
error: { code: -32000, message: 'Bad Request: Session ID must contain only visible ASCII characters' },
|
|
291
|
+
id: jsonData.id || null
|
|
292
|
+
}));
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
248
295
|
let transport;
|
|
249
296
|
if (sessionId && transports[sessionId]) {
|
|
250
297
|
// Reuse existing transport
|
|
251
298
|
transport = transports[sessionId];
|
|
252
299
|
}
|
|
253
|
-
else if (!sessionId
|
|
254
|
-
//
|
|
300
|
+
else if (!sessionId) {
|
|
301
|
+
// Create new session (either for initialize request or fallback)
|
|
302
|
+
const newSessionId = randomUUID();
|
|
303
|
+
const isInit = isInitializeRequest(jsonData);
|
|
304
|
+
if (isInit) {
|
|
305
|
+
logger.info(`Creating new session for initialize request: ${newSessionId}`);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
logger.warn(`Creating fallback session for non-initialize request: ${newSessionId}`);
|
|
309
|
+
}
|
|
255
310
|
transport = new StreamableHTTPServerTransport({
|
|
256
|
-
sessionIdGenerator: () =>
|
|
311
|
+
sessionIdGenerator: () => newSessionId,
|
|
257
312
|
onsessioninitialized: (id) => {
|
|
258
313
|
transports[id] = transport;
|
|
259
314
|
logger.info(`Session initialized: ${id}`);
|
|
315
|
+
// Set session ID in response headers as required by MCP spec
|
|
316
|
+
res.setHeader('mcp-session-id', id);
|
|
260
317
|
}
|
|
261
318
|
});
|
|
262
319
|
transport.onclose = () => {
|
|
@@ -271,12 +328,16 @@ if (useHttp) {
|
|
|
271
328
|
return;
|
|
272
329
|
}
|
|
273
330
|
else {
|
|
274
|
-
// Invalid request
|
|
331
|
+
// Invalid request - session ID provided but not found
|
|
332
|
+
logger.error(`Invalid session ID: ${sessionId}. Active sessions count: ${Object.keys(transports).length}`);
|
|
275
333
|
res.writeHead(400);
|
|
276
334
|
res.end(JSON.stringify({
|
|
277
335
|
jsonrpc: '2.0',
|
|
278
|
-
error: {
|
|
279
|
-
|
|
336
|
+
error: {
|
|
337
|
+
code: -32000,
|
|
338
|
+
message: `Bad Request: Invalid session ID. Please initialize a new session first.`
|
|
339
|
+
},
|
|
340
|
+
id: jsonData.id || null
|
|
280
341
|
}));
|
|
281
342
|
return;
|
|
282
343
|
}
|
|
@@ -297,15 +358,92 @@ if (useHttp) {
|
|
|
297
358
|
});
|
|
298
359
|
}
|
|
299
360
|
else if (req.method === 'GET') {
|
|
361
|
+
// Validate Accept header for SSE as required by MCP spec
|
|
362
|
+
const acceptHeader = req.headers.accept;
|
|
363
|
+
if (!acceptHeader || !acceptHeader.includes('text/event-stream')) {
|
|
364
|
+
logger.warn(`GET request without text/event-stream Accept header: ${acceptHeader}`);
|
|
365
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
366
|
+
res.end(JSON.stringify({
|
|
367
|
+
jsonrpc: '2.0',
|
|
368
|
+
error: { code: -32000, message: 'Method Not Allowed: GET requires Accept: text/event-stream' },
|
|
369
|
+
id: null
|
|
370
|
+
}));
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
300
373
|
// Handle SSE streams
|
|
301
374
|
const sessionId = req.headers['mcp-session-id'];
|
|
375
|
+
// Validate session ID format
|
|
376
|
+
if (sessionId && !/^[\x21-\x7E]+$/.test(sessionId)) {
|
|
377
|
+
logger.warn(`Invalid session ID format in GET request: ${sessionId}`);
|
|
378
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
379
|
+
res.end(JSON.stringify({
|
|
380
|
+
jsonrpc: '2.0',
|
|
381
|
+
error: { code: -32000, message: 'Bad Request: Session ID must contain only visible ASCII characters' },
|
|
382
|
+
id: null
|
|
383
|
+
}));
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
302
386
|
if (!sessionId || !transports[sessionId]) {
|
|
303
|
-
|
|
304
|
-
res.
|
|
387
|
+
logger.warn(`SSE request with invalid session ID: ${sessionId}`);
|
|
388
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
389
|
+
res.end(JSON.stringify({
|
|
390
|
+
jsonrpc: '2.0',
|
|
391
|
+
error: { code: -32000, message: 'Bad Request: Invalid or missing session ID for SSE stream' },
|
|
392
|
+
id: null
|
|
393
|
+
}));
|
|
305
394
|
return;
|
|
306
395
|
}
|
|
396
|
+
// Check for Last-Event-ID header for resumability (optional MCP feature)
|
|
397
|
+
const lastEventId = req.headers['last-event-id'];
|
|
398
|
+
if (lastEventId) {
|
|
399
|
+
logger.info(`SSE resumability requested with Last-Event-ID: ${lastEventId}`);
|
|
400
|
+
// Note: Actual resumability implementation would require message storage
|
|
401
|
+
// For now, we log the request but don't implement full resumability
|
|
402
|
+
}
|
|
403
|
+
logger.info(`Opening SSE stream for session: ${sessionId}`);
|
|
404
|
+
// Prevent connection timeout and keep it alive
|
|
405
|
+
req.socket?.setTimeout(0);
|
|
406
|
+
req.socket?.setKeepAlive(true, 30000);
|
|
407
|
+
let streamClosed = false;
|
|
408
|
+
// Handle client disconnection gracefully
|
|
409
|
+
req.on('close', () => {
|
|
410
|
+
streamClosed = true;
|
|
411
|
+
logger.info(`Client disconnected SSE stream for session: ${sessionId}`);
|
|
412
|
+
});
|
|
413
|
+
req.on('aborted', () => {
|
|
414
|
+
streamClosed = true;
|
|
415
|
+
logger.info(`Client aborted SSE stream for session: ${sessionId}`);
|
|
416
|
+
});
|
|
417
|
+
// Let the MCP transport handle the SSE stream completely
|
|
307
418
|
const transport = transports[sessionId];
|
|
308
|
-
|
|
419
|
+
try {
|
|
420
|
+
await transport.handleRequest(req, res);
|
|
421
|
+
// If the transport completes without the client disconnecting,
|
|
422
|
+
// it might have closed the stream prematurely. Keep it open with heartbeat.
|
|
423
|
+
if (!streamClosed && !res.destroyed) {
|
|
424
|
+
logger.info(`Transport completed, maintaining SSE stream for session: ${sessionId}`);
|
|
425
|
+
// Send periodic heartbeat to keep connection alive
|
|
426
|
+
const heartbeat = setInterval(() => {
|
|
427
|
+
if (streamClosed || res.destroyed) {
|
|
428
|
+
clearInterval(heartbeat);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
try {
|
|
432
|
+
res.write(': heartbeat\n\n');
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
logger.error(`Heartbeat error for session ${sessionId}:`, error);
|
|
436
|
+
clearInterval(heartbeat);
|
|
437
|
+
}
|
|
438
|
+
}, 30000);
|
|
439
|
+
// Clean up heartbeat when connection closes
|
|
440
|
+
req.on('close', () => clearInterval(heartbeat));
|
|
441
|
+
res.on('close', () => clearInterval(heartbeat));
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
logger.error(`SSE transport error for session ${sessionId}:`, error);
|
|
446
|
+
}
|
|
309
447
|
}
|
|
310
448
|
else if (req.method === 'DELETE') {
|
|
311
449
|
// Handle session termination
|
|
@@ -330,7 +468,7 @@ if (useHttp) {
|
|
|
330
468
|
});
|
|
331
469
|
httpServer.listen(port, () => {
|
|
332
470
|
logger.info(`Socket MCP HTTP server version ${VERSION} started successfully on port ${port}`);
|
|
333
|
-
logger.info(`Connect to: http://localhost:${port}
|
|
471
|
+
logger.info(`Connect to: http://localhost:${port}/`);
|
|
334
472
|
});
|
|
335
473
|
}
|
|
336
474
|
else {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
import readline from 'readline';
|
|
4
|
+
// Simple JSON-RPC client for testing MCP server
|
|
5
|
+
class SimpleJSONRPCClient {
|
|
6
|
+
process;
|
|
7
|
+
rl;
|
|
8
|
+
requestId = 1;
|
|
9
|
+
pendingRequests = new Map();
|
|
10
|
+
constructor(command, args = [], env = {}) {
|
|
11
|
+
this.process = spawn(command, args, {
|
|
12
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
13
|
+
env: { ...process.env, ...env }
|
|
14
|
+
});
|
|
15
|
+
this.rl = readline.createInterface({
|
|
16
|
+
input: this.process.stdout,
|
|
17
|
+
crlfDelay: Infinity
|
|
18
|
+
});
|
|
19
|
+
this.rl.on('line', (line) => {
|
|
20
|
+
try {
|
|
21
|
+
const response = JSON.parse(line);
|
|
22
|
+
if (response.id && this.pendingRequests.has(response.id)) {
|
|
23
|
+
const { resolve, reject } = this.pendingRequests.get(response.id);
|
|
24
|
+
this.pendingRequests.delete(response.id);
|
|
25
|
+
if (response.error) {
|
|
26
|
+
reject(response.error);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
resolve(response.result);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (response.method) {
|
|
33
|
+
console.log('Notification:', response);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
console.error('Failed to parse response:', line);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
this.process.stderr.on('data', (data) => {
|
|
41
|
+
console.error('Server stderr:', data.toString());
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async sendRequest(method, params = {}) {
|
|
45
|
+
const id = this.requestId++;
|
|
46
|
+
const request = {
|
|
47
|
+
jsonrpc: '2.0',
|
|
48
|
+
id,
|
|
49
|
+
method,
|
|
50
|
+
params
|
|
51
|
+
};
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
this.pendingRequests.set(id, { resolve, reject });
|
|
54
|
+
this.process.stdin.write(JSON.stringify(request) + '\n');
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
close() {
|
|
58
|
+
this.rl.close();
|
|
59
|
+
this.process.kill();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function main() {
|
|
63
|
+
const apiKey = process.env.SOCKET_API_KEY;
|
|
64
|
+
if (!apiKey) {
|
|
65
|
+
console.error('Error: SOCKET_API_KEY environment variable is required');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
console.log('Starting MCP server debug client...');
|
|
69
|
+
const client = new SimpleJSONRPCClient('./build/index.js', [], {
|
|
70
|
+
SOCKET_API_KEY: apiKey
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
// Initialize the connection
|
|
74
|
+
console.log('\n1. Initializing connection...');
|
|
75
|
+
const initResult = await client.sendRequest('initialize', {
|
|
76
|
+
protocolVersion: '0.1.0',
|
|
77
|
+
capabilities: {},
|
|
78
|
+
clientInfo: {
|
|
79
|
+
name: 'debug-client',
|
|
80
|
+
version: '1.0.0'
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
console.log('Initialize response:', JSON.stringify(initResult, null, 2));
|
|
84
|
+
// List available tools
|
|
85
|
+
console.log('\n2. Listing available tools...');
|
|
86
|
+
const toolsResult = await client.sendRequest('tools/list', {});
|
|
87
|
+
console.log('Available tools:', JSON.stringify(toolsResult, null, 2));
|
|
88
|
+
// Call the depscore tool
|
|
89
|
+
console.log('\n3. Calling depscore tool...');
|
|
90
|
+
const depscoreResult = await client.sendRequest('tools/call', {
|
|
91
|
+
name: 'depscore',
|
|
92
|
+
arguments: {
|
|
93
|
+
packages: [
|
|
94
|
+
{ depname: 'express', ecosystem: 'npm', version: '5.0.1' },
|
|
95
|
+
{ depname: 'lodash', ecosystem: 'npm', version: '4.17.21' },
|
|
96
|
+
{ depname: 'react', ecosystem: 'npm', version: '18.2.0' },
|
|
97
|
+
{ depname: 'flask', ecosystem: 'pypi', version: '2.3.2' },
|
|
98
|
+
{ depname: 'unknown-package', ecosystem: 'npm', version: 'unknown' }
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
console.log('Depscore result:', JSON.stringify(depscoreResult, null, 2));
|
|
103
|
+
// Test with minimal input
|
|
104
|
+
console.log('\n4. Testing with minimal input (default to npm)...');
|
|
105
|
+
const minimalResult = await client.sendRequest('tools/call', {
|
|
106
|
+
name: 'depscore',
|
|
107
|
+
arguments: {
|
|
108
|
+
packages: [
|
|
109
|
+
{ depname: 'axios' },
|
|
110
|
+
{ depname: 'typescript' }
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
console.log('Minimal input result:', JSON.stringify(minimalResult, null, 2));
|
|
115
|
+
// Test error handling
|
|
116
|
+
console.log('\n5. Testing error handling (empty packages)...');
|
|
117
|
+
try {
|
|
118
|
+
await client.sendRequest('tools/call', {
|
|
119
|
+
name: 'depscore',
|
|
120
|
+
arguments: {
|
|
121
|
+
packages: []
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.log('Expected error:', error);
|
|
127
|
+
}
|
|
128
|
+
console.log('\nDebug session complete!');
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.error('Client error:', error);
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
client.close();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
main().catch(console.error);
|
|
138
|
+
//# sourceMappingURL=debug-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-client.js","sourceRoot":"","sources":["../../mock-client/debug-client.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,gDAAgD;AAChD,MAAM,mBAAmB;IACf,OAAO,CAAM;IACb,EAAE,CAAqB;IACvB,SAAS,GAAG,CAAC,CAAC;IACd,eAAe,GAAG,IAAI,GAAG,EAAE,CAAC;IAEpC,YAAY,OAAe,EAAE,OAAiB,EAAE,EAAE,MAAW,EAAE;QAC7D,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YAClC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YACjC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC1B,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAClC,IAAI,QAAQ,CAAC,EAAE,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;oBACzD,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;oBAClE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;oBAEzC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;wBACnB,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;oBAC3B,CAAC;gBACH,CAAC;qBAAM,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;oBAC3B,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,IAAI,CAAC,CAAC;YACnD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC9C,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,SAAc,EAAE;QAChD,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG;YACd,OAAO,EAAE,KAAK;YACd,EAAE;YACF,MAAM;YACN,MAAM;SACP,CAAC;QAEF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;CACF;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAG,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,EAAE,EAAE;QAC7D,cAAc,EAAE,MAAM;KACvB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,4BAA4B;QAC5B,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE;YACxD,eAAe,EAAE,OAAO;YACxB,YAAY,EAAE,EAAE;YAChB,UAAU,EAAE;gBACV,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,OAAO;aACjB;SACF,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEzE,uBAAuB;QACvB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEtE,yBAAyB;QACzB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE;YAC5D,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE;gBACT,QAAQ,EAAE;oBACR,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE;oBAC1D,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE;oBAC3D,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE;oBACzD,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE;oBACzD,EAAE,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE;iBACrE;aACF;SACF,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEzE,0BAA0B;QAC1B,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QACnE,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE;YAC3D,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE;gBACT,QAAQ,EAAE;oBACR,EAAE,OAAO,EAAE,OAAO,EAAE;oBACpB,EAAE,OAAO,EAAE,YAAY,EAAE;iBAC1B;aACF;SACF,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAE7E,sBAAsB;QACtB,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAC/D,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE;gBACrC,IAAI,EAAE,UAAU;gBAChB,SAAS,EAAE;oBACT,QAAQ,EAAE,EAAE;iBACb;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fetch from 'node-fetch';
|
|
3
|
+
// Helper function to parse SSE or JSON response
|
|
4
|
+
async function parseResponse(response) {
|
|
5
|
+
const contentType = response.headers.get('content-type');
|
|
6
|
+
const text = await response.text();
|
|
7
|
+
if (contentType?.includes('text/event-stream')) {
|
|
8
|
+
// Parse SSE format: "event: message\ndata: {json}\n"
|
|
9
|
+
const dataMatch = text.match(/data: (.+)/);
|
|
10
|
+
if (dataMatch) {
|
|
11
|
+
return JSON.parse(dataMatch[1]);
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return JSON.parse(text);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Simple HTTP client for testing MCP server in HTTP mode
|
|
20
|
+
async function testHTTPMode() {
|
|
21
|
+
const baseUrl = (process.env.MCP_URL || 'http://localhost:3000').replace(/\/$/, ''); // Remove trailing slash
|
|
22
|
+
const sessionId = `test-session-${Date.now()}`;
|
|
23
|
+
console.log('Testing Socket MCP in HTTP mode...');
|
|
24
|
+
console.log(`Server URL: ${baseUrl}`);
|
|
25
|
+
console.log(`Session ID: ${sessionId}`);
|
|
26
|
+
try {
|
|
27
|
+
// 1. Initialize connection
|
|
28
|
+
console.log('\n1. Initializing connection...');
|
|
29
|
+
const initRequest = {
|
|
30
|
+
jsonrpc: '2.0',
|
|
31
|
+
id: 1,
|
|
32
|
+
method: 'initialize',
|
|
33
|
+
params: {
|
|
34
|
+
protocolVersion: '0.1.0',
|
|
35
|
+
capabilities: {},
|
|
36
|
+
clientInfo: {
|
|
37
|
+
name: 'http-debug-client',
|
|
38
|
+
version: '1.0.0'
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const initResponse = await fetch(`${baseUrl}/`, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'Accept': 'application/json, text/event-stream',
|
|
47
|
+
'User-Agent': 'socket-mcp-debug-client/1.0.0'
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify(initRequest)
|
|
50
|
+
});
|
|
51
|
+
const initResult = await parseResponse(initResponse);
|
|
52
|
+
console.log('Initialize response:', JSON.stringify(initResult, null, 2));
|
|
53
|
+
// Extract session ID from response headers
|
|
54
|
+
const serverSessionId = initResponse.headers.get('mcp-session-id');
|
|
55
|
+
const actualSessionId = serverSessionId || sessionId;
|
|
56
|
+
console.log('Session ID:', actualSessionId);
|
|
57
|
+
// 2. List tools
|
|
58
|
+
console.log('\n2. Listing available tools...');
|
|
59
|
+
const toolsRequest = {
|
|
60
|
+
jsonrpc: '2.0',
|
|
61
|
+
id: 2,
|
|
62
|
+
method: 'tools/list',
|
|
63
|
+
params: {}
|
|
64
|
+
};
|
|
65
|
+
const toolsResponse = await fetch(`${baseUrl}/`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
'Accept': 'application/json, text/event-stream',
|
|
70
|
+
'mcp-session-id': actualSessionId
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify(toolsRequest)
|
|
73
|
+
});
|
|
74
|
+
const toolsResult = await parseResponse(toolsResponse);
|
|
75
|
+
console.log('Available tools:', JSON.stringify(toolsResult, null, 2));
|
|
76
|
+
// 3. Call depscore
|
|
77
|
+
console.log('\n3. Calling depscore tool...');
|
|
78
|
+
const depscoreRequest = {
|
|
79
|
+
jsonrpc: '2.0',
|
|
80
|
+
id: 3,
|
|
81
|
+
method: 'tools/call',
|
|
82
|
+
params: {
|
|
83
|
+
name: 'depscore',
|
|
84
|
+
arguments: {
|
|
85
|
+
packages: [
|
|
86
|
+
{ depname: 'express', ecosystem: 'npm', version: '4.18.2' },
|
|
87
|
+
{ depname: 'fastapi', ecosystem: 'pypi', version: '0.100.0' },
|
|
88
|
+
{ depname: 'react', ecosystem: 'npm', version: '18.2.0' }
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const depscoreResponse = await fetch(`${baseUrl}/`, {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: {
|
|
96
|
+
'Content-Type': 'application/json',
|
|
97
|
+
'Accept': 'application/json, text/event-stream',
|
|
98
|
+
'mcp-session-id': actualSessionId
|
|
99
|
+
},
|
|
100
|
+
body: JSON.stringify(depscoreRequest)
|
|
101
|
+
});
|
|
102
|
+
const depscoreResult = await parseResponse(depscoreResponse);
|
|
103
|
+
console.log('Depscore result:', JSON.stringify(depscoreResult, null, 2));
|
|
104
|
+
// 4. Test SSE stream (optional)
|
|
105
|
+
console.log('\n4. Testing SSE stream connection...');
|
|
106
|
+
const sseResponse = await fetch(`${baseUrl}/`, {
|
|
107
|
+
method: 'GET',
|
|
108
|
+
headers: {
|
|
109
|
+
'mcp-session-id': actualSessionId,
|
|
110
|
+
'Accept': 'text/event-stream'
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
if (sseResponse.ok) {
|
|
114
|
+
console.log('SSE stream connected successfully');
|
|
115
|
+
// Note: In a real implementation, you'd parse the SSE stream
|
|
116
|
+
}
|
|
117
|
+
// 5. Clean up session
|
|
118
|
+
console.log('\n5. Cleaning up session...');
|
|
119
|
+
const cleanupResponse = await fetch(`${baseUrl}/`, {
|
|
120
|
+
method: 'DELETE',
|
|
121
|
+
headers: {
|
|
122
|
+
'mcp-session-id': actualSessionId
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
console.log('Session cleanup:', cleanupResponse.status === 200 ? 'Success' : 'Failed');
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
console.error('Error:', error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Usage instructions
|
|
132
|
+
if (process.argv.includes('--help')) {
|
|
133
|
+
console.log(`
|
|
134
|
+
Socket MCP HTTP Client Debugger
|
|
135
|
+
|
|
136
|
+
Usage:
|
|
137
|
+
# Start the MCP server in HTTP mode first:
|
|
138
|
+
MCP_HTTP_MODE=true SOCKET_API_KEY=your-api-key ./build/index.js
|
|
139
|
+
|
|
140
|
+
# Then run this client:
|
|
141
|
+
npm run build
|
|
142
|
+
node ./build/http-client.js
|
|
143
|
+
|
|
144
|
+
Environment variables:
|
|
145
|
+
MCP_URL - Server URL (default: http://localhost:3000)
|
|
146
|
+
|
|
147
|
+
Example:
|
|
148
|
+
MCP_URL=http://localhost:8080 node ./build/http-client.js
|
|
149
|
+
`);
|
|
150
|
+
process.exit(0);
|
|
151
|
+
}
|
|
152
|
+
testHTTPMode().catch(console.error);
|
|
153
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../mock-client/http-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
3
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
4
|
+
async function main() {
|
|
5
|
+
const transport = new StdioClientTransport({
|
|
6
|
+
command: './build/index.js',
|
|
7
|
+
args: [],
|
|
8
|
+
env: {
|
|
9
|
+
...process.env,
|
|
10
|
+
SOCKET_API_KEY: process.env.SOCKET_API_KEY || ''
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
const client = new Client({
|
|
14
|
+
name: 'test-mcp-client',
|
|
15
|
+
version: '1.0.0'
|
|
16
|
+
}, {
|
|
17
|
+
capabilities: {}
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
await client.connect(transport);
|
|
21
|
+
console.log('Connected to MCP server');
|
|
22
|
+
// List available tools
|
|
23
|
+
const tools = await client.listTools();
|
|
24
|
+
console.log('Available tools:', tools.tools.map(t => t.name));
|
|
25
|
+
// Test the depscore tool
|
|
26
|
+
const testPackages = [
|
|
27
|
+
{ depname: 'express', ecosystem: 'npm', version: '4.18.2' },
|
|
28
|
+
{ depname: 'lodash', ecosystem: 'npm', version: '4.17.21' },
|
|
29
|
+
{ depname: 'react', ecosystem: 'npm', version: '18.2.0' },
|
|
30
|
+
{ depname: 'requests', ecosystem: 'pypi', version: '2.31.0' },
|
|
31
|
+
{ depname: 'unknown-package', ecosystem: 'npm', version: 'unknown' }
|
|
32
|
+
];
|
|
33
|
+
console.log('\nTesting depscore with packages:', testPackages);
|
|
34
|
+
const result = await client.callTool({
|
|
35
|
+
name: 'depscore',
|
|
36
|
+
arguments: {
|
|
37
|
+
packages: testPackages
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
console.log('\nDepscore results:');
|
|
41
|
+
console.log(JSON.stringify(result, null, 2));
|
|
42
|
+
await client.close();
|
|
43
|
+
console.log('\nClient closed successfully');
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error('Error:', error);
|
|
47
|
+
await client.close();
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Run the client
|
|
52
|
+
main().catch(console.error);
|
|
53
|
+
//# sourceMappingURL=stdio-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio-client.js","sourceRoot":"","sources":["../../mock-client/stdio-client.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;QACzC,OAAO,EAAE,kBAAkB;QAC3B,IAAI,EAAE,EAAE;QACR,GAAG,EAAE;YACH,GAAG,OAAO,CAAC,GAAG;YACd,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE;SACjD;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;QACxB,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,OAAO;KACjB,EAAE;QACD,YAAY,EAAE,EAAE;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAEvC,uBAAuB;QACvB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAE9D,yBAAyB;QACzB,MAAM,YAAY,GAAG;YACnB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE;YAC3D,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE;YAC3D,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE;YACzD,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;YAC7D,EAAE,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE;SACrE,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,YAAY,CAAC,CAAC;QAE/D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;YACnC,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE;gBACT,QAAQ,EAAE,YAAY;aACvB;SACF,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAE7C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,iBAAiB;AACjB,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
|