Skip to content

Commit 0627ad8

Browse files
Better organization
1 parent ed3da8e commit 0627ad8

6 files changed

Lines changed: 98 additions & 71 deletions

File tree

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,33 @@ Created for use with NeuroPilot and NeuroMCP, meant for anyone and everyone to u
66
## Usage
77

88
You can find the docs at [our GitHub Pages link](https://vsc-neuropilot.github.io/neuro-mcp-relay-registry) or start the docs preview server included in the container build.
9+
10+
## API Endpoints
11+
12+
### MCP Protocol
13+
- `POST /mcp` - Main MCP endpoint for tool calls and communication with downstream clients
14+
15+
### Permission Management
16+
- `GET /api/permissions` - List all tool permissions and configurations
17+
- `PUT /api/permissions/:toolName` - Update permission for a specific tool
18+
- Request body: `{ "mode": "auto" | "copilot" | "disabled" }`
19+
- `POST /api/permissions/batch` - Update permissions for multiple tools
20+
- Request body: `{ "updates": { "toolName": "mode" } }`
21+
- `GET /api/permissions/stats` - Get permission system statistics
22+
23+
### Approval Queue
24+
- `GET /api/approvals/pending` - List pending approval requests
25+
- `POST /api/approvals/:approvalId/approve` - Approve a pending request
26+
- Request body: `{ "message": "optional approval message" }`
27+
- `POST /api/approvals/:approvalId/reject` - Reject a pending request
28+
- Request body: `{ "message": "optional rejection message" }`
29+
- `GET /api/approvals/history` - Get approval history
30+
31+
### Server Management
32+
- `POST /api/servers/register` - Register a new upstream server
33+
- Request body: `{ "serverId": "server1", "clientConfig": { "transport": "http", "serverUrl": "http://127.0.0.1:3001", "name": "Server 1" } }`
34+
- `GET /api/servers` - List all registered upstream servers
35+
36+
### Health & Monitoring
37+
- `GET /health` - Health check and server information
38+
- `GET /stats` - Detailed server statistics and connection information

server/package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
"start": "node ./output/server/index.mjs",
77
"build": "vite build",
88
"dev": "vite dev",
9-
"preview": "vite preview",
10-
"test:relay": "tsx test-relay-server.ts",
11-
"test:cli": "tsx test-cli.ts",
12-
"test:permissions": "tsx test-permission-cli.ts"
9+
"preview": "vite preview"
1310
},
1411
"keywords": [],
1512
"author": "",

server/routes/mcp/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@
3838
// ===== Client Module =====
3939

4040
// Base client and factory
41-
export { BaseMcpClient } from './clients/base-client';
42-
export { McpClientFactory } from './clients/factory';
41+
export {BaseMcpClient} from './clients/base-client';
42+
export {McpClientFactory} from './clients/factory';
4343

4444
// Concrete implementations
45-
export { StreamableHttpMcpClient } from './clients/http';
45+
export {StreamableHttpMcpClient} from './clients/http';
4646

4747
// Client types
4848
export type {
@@ -87,7 +87,7 @@ export type {
8787

8888
// ===== Server Module =====
8989

90-
export { McpRelayServer } from './server/index';
90+
export {McpRelayServer} from './server/index';
9191

9292
export type {
9393
McpRelayServerConfig,

server/test-cli.ts renamed to server/src/examples/example-mcp-tool-call-cli.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/**
22
* Interactive CLI to test the relay server by calling tools
33
*
4-
* Usage: tsx test-cli.ts [relay-server-url]
5-
* Example: tsx test-cli.ts http://127.0.0.1:3100
4+
* Usage: tsx example-mcp-tool-call-cli.ts [relay-server-url]
5+
* Example: tsx example-mcp-tool-call-cli.ts http://127.0.0.1:3100
66
*/
77

8-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
9-
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
8+
import {Client} from "@modelcontextprotocol/sdk/client/index.js";
9+
import {StreamableHTTPClientTransport} from "@modelcontextprotocol/sdk/client/streamableHttp.js";
1010
import * as readline from "readline";
1111

1212
const DEFAULT_RELAY_URL = "http://localhost:3100";
@@ -21,7 +21,7 @@ interface Tool {
2121
};
2222
}
2323

24-
class TestCLI {
24+
class ExampleMcpToolCallCli {
2525
private readonly client: Client;
2626
private transport: StreamableHTTPClientTransport | null = null;
2727
private tools: Tool[] = [];
@@ -152,12 +152,6 @@ class TestCLI {
152152
}
153153
}
154154

155-
private question(prompt: string): Promise<string> {
156-
return new Promise((resolve) => {
157-
this.rl.question(prompt, resolve);
158-
});
159-
}
160-
161155
async interactiveMode(): Promise<void> {
162156
console.log("\n=== Interactive Mode ===");
163157
console.log("Commands:");
@@ -240,14 +234,20 @@ class TestCLI {
240234
close(): void {
241235
this.rl.close();
242236
}
237+
238+
private question(prompt: string): Promise<string> {
239+
return new Promise((resolve) => {
240+
this.rl.question(prompt, resolve);
241+
});
242+
}
243243
}
244244

245245
async function main() {
246246
const relayUrl = process.argv[2] || DEFAULT_RELAY_URL;
247247

248248
console.log("=== MCP Relay Test CLI ===\n");
249249

250-
const cli = new TestCLI(relayUrl);
250+
const cli = new ExampleMcpToolCallCli(relayUrl);
251251

252252
try {
253253
await cli.connect();

server/test-permission-cli.ts renamed to server/src/examples/example-permission-control-cli.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/**
22
* Interactive CLI to test the permission system
33
*
4-
* Usage: tsx test-permission-cli.ts [relay-server-url]
5-
* Example: tsx test-permission-cli.ts http://127.0.0.1:3100
4+
* Usage: tsx example-permission-control-cli.ts [relay-server-url]
5+
* Example: tsx example-permission-control-cli.ts http://127.0.0.1:3100
66
*/
77

88
import * as readline from "readline";
@@ -48,16 +48,6 @@ class PermissionCLI {
4848
});
4949
}
5050

51-
private async fetch(path: string, options?: RequestInit): Promise<any> {
52-
const url = new URL(path, this.baseUrl);
53-
const response = await fetch(url.toString(), options);
54-
if (!response.ok) {
55-
const text = await response.text();
56-
throw new Error(`HTTP ${response.status}: ${text}`);
57-
}
58-
return response.json();
59-
}
60-
6151
async checkConnection(): Promise<void> {
6252
console.log(`[Permission CLI] Connecting to relay server: ${this.baseUrl}`);
6353
try {
@@ -115,8 +105,8 @@ class PermissionCLI {
115105
try {
116106
await this.fetch(`/api/permissions/${encodeURIComponent(toolName)}`, {
117107
method: 'PUT',
118-
headers: { 'Content-Type': 'application/json' },
119-
body: JSON.stringify({ mode })
108+
headers: {'Content-Type': 'application/json'},
109+
body: JSON.stringify({mode})
120110
});
121111
console.log(`✓ Updated ${toolName} to ${mode.toUpperCase()} mode`);
122112
} catch (error) {
@@ -171,8 +161,8 @@ class PermissionCLI {
171161
try {
172162
await this.fetch(`/api/approvals/${approvalId}/approve`, {
173163
method: 'POST',
174-
headers: { 'Content-Type': 'application/json' },
175-
body: JSON.stringify({ message: message || 'Approved via CLI' })
164+
headers: {'Content-Type': 'application/json'},
165+
body: JSON.stringify({message: message || 'Approved via CLI'})
176166
});
177167
console.log(`✓ Approved ${approvalId}`);
178168
} catch (error) {
@@ -184,8 +174,8 @@ class PermissionCLI {
184174
try {
185175
await this.fetch(`/api/approvals/${approvalId}/reject`, {
186176
method: 'POST',
187-
headers: { 'Content-Type': 'application/json' },
188-
body: JSON.stringify({ message: message || 'Rejected via CLI' })
177+
headers: {'Content-Type': 'application/json'},
178+
body: JSON.stringify({message: message || 'Rejected via CLI'})
189179
});
190180
console.log(`✓ Rejected ${approvalId}`);
191181
} catch (error) {
@@ -246,12 +236,6 @@ class PermissionCLI {
246236
}
247237
}
248238

249-
private question(prompt: string): Promise<string> {
250-
return new Promise((resolve) => {
251-
this.rl.question(prompt, resolve);
252-
});
253-
}
254-
255239
async interactiveMode(): Promise<void> {
256240
console.log("\n=== Interactive Permission Manager ===\n");
257241
console.log("Commands:");
@@ -370,6 +354,22 @@ class PermissionCLI {
370354
process.exit(1);
371355
}
372356
}
357+
358+
private async fetch(path: string, options?: RequestInit): Promise<any> {
359+
const url = new URL(path, this.baseUrl);
360+
const response = await fetch(url.toString(), options);
361+
if (!response.ok) {
362+
const text = await response.text();
363+
throw new Error(`HTTP ${response.status}: ${text}`);
364+
}
365+
return response.json();
366+
}
367+
368+
private question(prompt: string): Promise<string> {
369+
return new Promise((resolve) => {
370+
this.rl.question(prompt, resolve);
371+
});
372+
}
373373
}
374374

375375
async function main() {

0 commit comments

Comments
 (0)