Skip to content

Commit de7362e

Browse files
Copilot0xrinegade
andcommitted
Fix MCP Inspector workflow to use correct package name and testing approach
Co-authored-by: 0xrinegade <[email protected]>
1 parent e94d2db commit de7362e

File tree

1 file changed

+115
-75
lines changed

1 file changed

+115
-75
lines changed

.github/workflows/mcp-inspector.yml

Lines changed: 115 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ env:
1111
CARGO_TERM_COLOR: always
1212
RUST_BACKTRACE: full
1313
NODE_VERSION: '18'
14-
# Note: The inspector package name is different in your example. Adjust as needed.
15-
INSPECTOR_PACKAGE: '@open-svm/[email protected]'
16-
MCP_HOST: '127.0.0.1'
17-
MCP_PORT: 31902
14+
# Use the official MCP Inspector package
15+
INSPECTOR_PACKAGE: '@modelcontextprotocol/[email protected]'
1816

1917
jobs:
2018
mcp-inspector-test:
@@ -42,7 +40,7 @@ jobs:
4240
- name: Build solana-mcp-server
4341
run: cargo build --release
4442

45-
- name: Install MCP Inspector CLI and Zod
43+
- name: Install MCP Inspector and Zod
4644
run: |
4745
npm install -g ${{ env.INSPECTOR_PACKAGE }}
4846
npm install zod
@@ -52,82 +50,126 @@ jobs:
5250
mkdir -p test-config
5351
cat <<EOF > test-config/mcp-config.json
5452
{
55-
"network": "devnet",
56-
"rpc_url": "https://api.devnet.solana.com",
57-
"mcp_port": ${{ env.MCP_PORT }},
58-
"mcp_host": "${{ env.MCP_HOST }}",
59-
"mcp_token": ""
53+
"mcpServers": {
54+
"solana": {
55+
"command": "./target/release/solana-mcp-server",
56+
"args": ["stdio"],
57+
"env": {
58+
"SOLANA_RPC_URL": "https://api.devnet.solana.com",
59+
"SOLANA_COMMITMENT": "confirmed",
60+
"RUST_LOG": "debug"
61+
}
62+
}
63+
}
6064
}
6165
EOF
6266
63-
- name: Start Server and Wait for it to be Ready
67+
- name: Test MCP Protocol Communication
6468
run: |
65-
echo "Starting server in the background..."
66-
./target/release/solana-mcp-server --config test-config/mcp-config.json > server.log 2>&1 &
69+
echo "Testing MCP protocol communication with Solana server..."
6770
68-
echo "Waiting for server to become available..."
69-
timeout=120
70-
for i in $(seq 1 $timeout); do
71-
if mcp-inspector ping --host ${{ env.MCP_HOST }} --port ${{ env.MCP_PORT }}; then
72-
echo "✅ Server is up and running!"
73-
exit 0
74-
fi
75-
echo "Still waiting for server... (${i}s)"
76-
sleep 1
77-
done
71+
# Test the server directly using Node.js to verify MCP protocol
72+
node <<'EOF'
73+
const { spawn } = require('child_process');
74+
const readline = require('readline');
7875
79-
echo "❌ Server did not start within $timeout seconds."
80-
echo "--- Server Log ---"
81-
cat server.log
82-
exit 1
83-
84-
- name: Run Inspector CLI Tests and Validate Schema
85-
run: |
86-
echo "--- Testing 'initialize' method ---"
87-
mcp-inspector call --host ${{ env.MCP_HOST }} --port ${{ env.MCP_PORT }} --method "initialize" --params '{}' --json > initialize_response.json
88-
cat initialize_response.json
76+
// Start the server
77+
const server = spawn('./target/release/solana-mcp-server', ['stdio'], {
78+
env: {
79+
...process.env,
80+
SOLANA_RPC_URL: 'https://api.devnet.solana.com',
81+
SOLANA_COMMITMENT: 'confirmed',
82+
RUST_LOG: 'debug'
83+
}
84+
});
8985
90-
echo "--- Testing 'tools/list' method ---"
91-
mcp-inspector call --host ${{ env.MCP_HOST }} --port ${{ env.MCP_PORT }} --method "tools/list" --params '{}' --json > tools_list_response.json
92-
cat tools_list_response.json
93-
94-
echo "--- Validating response schemas ---"
95-
node <<EOF
96-
const { z } = require('zod');
97-
const fs = require('fs');
86+
let testResults = {
87+
initialize: false,
88+
toolsList: false
89+
};
9890
99-
try {
100-
const initResp = JSON.parse(fs.readFileSync('initialize_response.json', 'utf8'));
101-
const toolsResp = JSON.parse(fs.readFileSync('tools_list_response.json', 'utf8'));
102-
103-
// Define schemas based on the MCP spec
104-
const initializeResultSchema = z.object({
105-
protocolVersion: z.string(),
106-
serverInfo: z.object({ name: z.string(), version: z.string() }),
107-
}).passthrough();
108-
109-
const toolSchema = z.object({
110-
name: z.string(),
111-
description: z.string().optional(),
112-
inputSchema: z.any()
113-
});
114-
115-
const toolsListResultSchema = z.object({
116-
tools: z.array(toolSchema),
117-
});
118-
119-
// Validate 'initialize'
120-
initializeResultSchema.parse(initResp.result);
121-
console.log("✅ 'initialize' response schema is valid.");
122-
123-
// Validate 'tools/list'
124-
toolsListResultSchema.parse(toolsResp.result);
125-
console.log("✅ 'tools/list' response schema is valid.");
126-
127-
} catch (error) {
128-
console.error("❌ Schema validation failed:", error.message);
91+
// Handle server output
92+
server.stdout.on('data', (data) => {
93+
const response = data.toString();
94+
console.log('Server response:', response);
95+
96+
try {
97+
const jsonResponse = JSON.parse(response);
98+
99+
if (jsonResponse.result && jsonResponse.result.protocolVersion) {
100+
console.log('✅ Initialize response received with protocol version:', jsonResponse.result.protocolVersion);
101+
testResults.initialize = true;
102+
103+
// Send tools/list request
104+
const toolsListRequest = {
105+
jsonrpc: "2.0",
106+
id: 2,
107+
method: "tools/list",
108+
params: {}
109+
};
110+
server.stdin.write(JSON.stringify(toolsListRequest) + '\n');
111+
}
112+
113+
if (jsonResponse.result && jsonResponse.result.tools) {
114+
console.log('✅ Tools list response received with', jsonResponse.result.tools.length, 'tools');
115+
testResults.toolsList = true;
116+
117+
// Check if we have the expected Solana RPC methods
118+
const toolNames = jsonResponse.result.tools.map(tool => tool.name);
119+
const expectedMethods = ['getAccountInfo', 'getBalance', 'sendTransaction'];
120+
const hasExpectedMethods = expectedMethods.every(method => toolNames.includes(method));
121+
122+
if (hasExpectedMethods) {
123+
console.log('✅ Expected Solana RPC methods found in tools list');
124+
} else {
125+
console.log('❌ Some expected Solana RPC methods missing from tools list');
126+
process.exit(1);
127+
}
128+
129+
// Test passed
130+
console.log('✅ All MCP protocol tests passed');
131+
server.kill();
132+
process.exit(0);
133+
}
134+
} catch (e) {
135+
// Ignore non-JSON output
136+
}
137+
});
138+
139+
server.stderr.on('data', (data) => {
140+
console.error('Server error:', data.toString());
141+
});
142+
143+
server.on('close', (code) => {
144+
if (!testResults.initialize || !testResults.toolsList) {
145+
console.log('❌ MCP protocol test failed - missing required responses');
146+
process.exit(1);
147+
}
148+
});
149+
150+
// Send initialize request
151+
const initializeRequest = {
152+
jsonrpc: "2.0",
153+
id: 1,
154+
method: "initialize",
155+
params: {
156+
protocolVersion: "2024-11-05",
157+
capabilities: {},
158+
clientInfo: {
159+
name: "test-client",
160+
version: "1.0.0"
161+
}
162+
}
163+
};
164+
165+
server.stdin.write(JSON.stringify(initializeRequest) + '\n');
166+
167+
// Timeout after 30 seconds
168+
setTimeout(() => {
169+
console.log('❌ Test timeout');
170+
server.kill();
129171
process.exit(1);
130-
}
172+
}, 30000);
131173
EOF
132174
133175
- name: Upload Test Artifacts
@@ -136,7 +178,5 @@ jobs:
136178
with:
137179
name: mcp-test-artifacts
138180
path: |
139-
server.log
140-
initialize_response.json
141-
tools_list_response.json
181+
test-config/mcp-config.json
142182
retention-days: 7

0 commit comments

Comments
 (0)