Skip to content

Commit 59b080c

Browse files
committed
new debug capabilities with new mock clients
1 parent ce4344b commit 59b080c

File tree

9 files changed

+506
-7
lines changed

9 files changed

+506
-7
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
node_modules/
22
*.log
33
.vscode/
4-
build/index.js.map
4+
build/

DEBUG.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Socket MCP Mock Client Tools
2+
3+
The `mock-client` directory contains debug clients for testing the Socket MCP server.
4+
5+
## Prerequisites
6+
7+
1. Build the project:
8+
9+
```bash
10+
npm run build
11+
```
12+
13+
2. Set your Socket API key:
14+
15+
```bash
16+
export SOCKET_API_KEY="your-api-key-here"
17+
```
18+
19+
## Debug Clients
20+
21+
### 1. Simple JSON-RPC Client (`mock-client/debug-client.ts`)
22+
23+
Direct stdio communication using JSON-RPC protocol:
24+
25+
```bash
26+
npm run debug:stdio
27+
```
28+
29+
This client:
30+
31+
- Sends raw JSON-RPC messages to the MCP server
32+
- Tests initialization, tool listing, and depscore calls
33+
- Useful for debugging protocol-level issues
34+
35+
### 2. MCP SDK Client (`mock-client/stdio-client.ts`)
36+
37+
Uses the official MCP SDK client library:
38+
39+
```bash
40+
npm run debug:sdk
41+
```
42+
43+
This client:
44+
45+
- Uses the same SDK that real MCP clients use
46+
- Tests the server's compatibility with the SDK
47+
- Good for integration testing
48+
49+
### 3. HTTP Mode Client (`mock-client/http-client.ts`)
50+
51+
Tests the HTTP/SSE transport mode:
52+
53+
```bash
54+
# First, start the server in HTTP mode:
55+
npm run server:http
56+
57+
# In another terminal:
58+
npm run debug:http
59+
```
60+
61+
This client:
62+
63+
- Tests HTTP POST requests and SSE streams
64+
- Verifies session management
65+
- Tests CORS and HTTP-specific features
66+
67+
## What Each Client Tests
68+
69+
All clients test the following scenarios:
70+
71+
1. **Connection initialization** - MCP protocol handshake
72+
2. **Tool discovery** - Lists available tools
73+
3. **Basic depscore call** - Tests with npm and PyPI packages
74+
4. **Error handling** - Tests with invalid inputs
75+
5. **Edge cases** - Unknown packages, minimal inputs
76+
77+
## Interpreting Results
78+
79+
### Successful Response
80+
81+
```json
82+
{
83+
"content": [
84+
{
85+
"type": "text",
86+
"text": "Package: [email protected]\nScore: 0.85\n..."
87+
}
88+
]
89+
}
90+
```
91+
92+
### Error Response
93+
94+
```json
95+
{
96+
"error": {
97+
"code": -32602,
98+
"message": "Invalid params",
99+
"data": "Expected array with at least 1 element"
100+
}
101+
}
102+
```
103+
104+
## Common Issues
105+
106+
1. **API Key Missing**: Set `SOCKET_API_KEY` environment variable
107+
2. **Build Errors**: Run `npm run build` first
108+
3. **Permission Denied**: Check file permissions (should be executable)
109+
4. **Connection Refused**: For HTTP mode, ensure server is running
110+
111+
## Advanced Usage
112+
113+
### Custom API Endpoint
114+
115+
To test against a local Socket API:
116+
117+
```bash
118+
# Edit src/index.ts and change SOCKET_API_URL
119+
# Then rebuild and test
120+
```
121+
122+
### Verbose Logging
123+
124+
Check logs at:
125+
126+
- `/tmp/socket-mcp.log` - Info logs
127+
- `/tmp/socket-mcp-error.log` - Error logs
128+
129+
### Testing Specific Packages
130+
131+
Edit the test clients to modify the `testPackages` array with your specific packages to test.

build/index.js

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mock-client/debug-client.ts

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/usr/bin/env node
2+
import { spawn } from 'child_process';
3+
import readline from 'readline';
4+
5+
// Simple JSON-RPC client for testing MCP server
6+
class SimpleJSONRPCClient {
7+
private process: any;
8+
private rl: readline.Interface;
9+
private requestId = 1;
10+
private pendingRequests = new Map();
11+
12+
constructor(command: string, args: string[] = [], env: any = {}) {
13+
this.process = spawn(command, args, {
14+
stdio: ['pipe', 'pipe', 'pipe'],
15+
env: { ...process.env, ...env }
16+
});
17+
18+
this.rl = readline.createInterface({
19+
input: this.process.stdout,
20+
crlfDelay: Infinity
21+
});
22+
23+
this.rl.on('line', (line) => {
24+
try {
25+
const response = JSON.parse(line);
26+
if (response.id && this.pendingRequests.has(response.id)) {
27+
const { resolve, reject } = this.pendingRequests.get(response.id);
28+
this.pendingRequests.delete(response.id);
29+
30+
if (response.error) {
31+
reject(response.error);
32+
} else {
33+
resolve(response.result);
34+
}
35+
} else if (response.method) {
36+
console.log('Notification:', response);
37+
}
38+
} catch (e) {
39+
console.error('Failed to parse response:', line);
40+
}
41+
});
42+
43+
this.process.stderr.on('data', (data: Buffer) => {
44+
console.error('Server stderr:', data.toString());
45+
});
46+
}
47+
48+
async sendRequest(method: string, params: any = {}) {
49+
const id = this.requestId++;
50+
const request = {
51+
jsonrpc: '2.0',
52+
id,
53+
method,
54+
params
55+
};
56+
57+
return new Promise((resolve, reject) => {
58+
this.pendingRequests.set(id, { resolve, reject });
59+
this.process.stdin.write(JSON.stringify(request) + '\n');
60+
});
61+
}
62+
63+
close() {
64+
this.rl.close();
65+
this.process.kill();
66+
}
67+
}
68+
69+
async function main() {
70+
const apiKey = process.env.SOCKET_API_KEY;
71+
if (!apiKey) {
72+
console.error('Error: SOCKET_API_KEY environment variable is required');
73+
process.exit(1);
74+
}
75+
76+
console.log('Starting MCP server debug client...');
77+
78+
const client = new SimpleJSONRPCClient('./build/index.js', [], {
79+
SOCKET_API_KEY: apiKey
80+
});
81+
82+
try {
83+
// Initialize the connection
84+
console.log('\n1. Initializing connection...');
85+
const initResult = await client.sendRequest('initialize', {
86+
protocolVersion: '0.1.0',
87+
capabilities: {},
88+
clientInfo: {
89+
name: 'debug-client',
90+
version: '1.0.0'
91+
}
92+
});
93+
console.log('Initialize response:', JSON.stringify(initResult, null, 2));
94+
95+
// List available tools
96+
console.log('\n2. Listing available tools...');
97+
const toolsResult = await client.sendRequest('tools/list', {});
98+
console.log('Available tools:', JSON.stringify(toolsResult, null, 2));
99+
100+
// Call the depscore tool
101+
console.log('\n3. Calling depscore tool...');
102+
const depscoreResult = await client.sendRequest('tools/call', {
103+
name: 'depscore',
104+
arguments: {
105+
packages: [
106+
{ depname: 'express', ecosystem: 'npm', version: '5.0.1' },
107+
{ depname: 'lodash', ecosystem: 'npm', version: '4.17.21' },
108+
{ depname: 'react', ecosystem: 'npm', version: '18.2.0' },
109+
{ depname: 'flask', ecosystem: 'pypi', version: '2.3.2' },
110+
{ depname: 'unknown-package', ecosystem: 'npm', version: 'unknown' }
111+
]
112+
}
113+
});
114+
console.log('Depscore result:', JSON.stringify(depscoreResult, null, 2));
115+
116+
// Test with minimal input
117+
console.log('\n4. Testing with minimal input (default to npm)...');
118+
const minimalResult = await client.sendRequest('tools/call', {
119+
name: 'depscore',
120+
arguments: {
121+
packages: [
122+
{ depname: 'axios' },
123+
{ depname: 'typescript' }
124+
]
125+
}
126+
});
127+
console.log('Minimal input result:', JSON.stringify(minimalResult, null, 2));
128+
129+
// Test error handling
130+
console.log('\n5. Testing error handling (empty packages)...');
131+
try {
132+
await client.sendRequest('tools/call', {
133+
name: 'depscore',
134+
arguments: {
135+
packages: []
136+
}
137+
});
138+
} catch (error) {
139+
console.log('Expected error:', error);
140+
}
141+
142+
console.log('\nDebug session complete!');
143+
} catch (error) {
144+
console.error('Client error:', error);
145+
} finally {
146+
client.close();
147+
}
148+
}
149+
150+
main().catch(console.error);

0 commit comments

Comments
 (0)