sopo-mcp 1.0.0
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/.dockerignore +10 -0
- package/.env +7 -0
- package/.ghaymah.json +20 -0
- package/Dockerfile +37 -0
- package/GUIDE.md +311 -0
- package/README.md +143 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/sopo.prompts.d.ts +8 -0
- package/dist/prompts/sopo.prompts.d.ts.map +1 -0
- package/dist/prompts/sopo.prompts.js +102 -0
- package/dist/prompts/sopo.prompts.js.map +1 -0
- package/dist/resources/platform.resources.d.ts +9 -0
- package/dist/resources/platform.resources.d.ts.map +1 -0
- package/dist/resources/platform.resources.js +143 -0
- package/dist/resources/platform.resources.js.map +1 -0
- package/dist/sopo-client.d.ts +51 -0
- package/dist/sopo-client.d.ts.map +1 -0
- package/dist/sopo-client.js +145 -0
- package/dist/sopo-client.js.map +1 -0
- package/dist/tools/aggregate-request.tools.d.ts +8 -0
- package/dist/tools/aggregate-request.tools.d.ts.map +1 -0
- package/dist/tools/aggregate-request.tools.js +57 -0
- package/dist/tools/aggregate-request.tools.js.map +1 -0
- package/dist/tools/auth.tools.d.ts +12 -0
- package/dist/tools/auth.tools.d.ts.map +1 -0
- package/dist/tools/auth.tools.js +152 -0
- package/dist/tools/auth.tools.js.map +1 -0
- package/dist/tools/collection.tools.d.ts +8 -0
- package/dist/tools/collection.tools.d.ts.map +1 -0
- package/dist/tools/collection.tools.js +54 -0
- package/dist/tools/collection.tools.js.map +1 -0
- package/dist/tools/gateway-plugin.tools.d.ts +8 -0
- package/dist/tools/gateway-plugin.tools.d.ts.map +1 -0
- package/dist/tools/gateway-plugin.tools.js +64 -0
- package/dist/tools/gateway-plugin.tools.js.map +1 -0
- package/dist/tools/gateway-route.tools.d.ts +8 -0
- package/dist/tools/gateway-route.tools.d.ts.map +1 -0
- package/dist/tools/gateway-route.tools.js +68 -0
- package/dist/tools/gateway-route.tools.js.map +1 -0
- package/dist/tools/gateway.tools.d.ts +8 -0
- package/dist/tools/gateway.tools.d.ts.map +1 -0
- package/dist/tools/gateway.tools.js +56 -0
- package/dist/tools/gateway.tools.js.map +1 -0
- package/dist/tools/observability.tools.d.ts +9 -0
- package/dist/tools/observability.tools.d.ts.map +1 -0
- package/dist/tools/observability.tools.js +54 -0
- package/dist/tools/observability.tools.js.map +1 -0
- package/dist/tools/service-target.tools.d.ts +8 -0
- package/dist/tools/service-target.tools.d.ts.map +1 -0
- package/dist/tools/service-target.tools.js +52 -0
- package/dist/tools/service-target.tools.js.map +1 -0
- package/dist/tools/service.tools.d.ts +8 -0
- package/dist/tools/service.tools.d.ts.map +1 -0
- package/dist/tools/service.tools.js +67 -0
- package/dist/tools/service.tools.js.map +1 -0
- package/dist/tools/user-profile.tools.d.ts +8 -0
- package/dist/tools/user-profile.tools.d.ts.map +1 -0
- package/dist/tools/user-profile.tools.js +46 -0
- package/dist/tools/user-profile.tools.js.map +1 -0
- package/package.json +33 -0
- package/src/index.ts +115 -0
- package/src/prompts/sopo.prompts.ts +128 -0
- package/src/resources/platform.resources.ts +163 -0
- package/src/sopo-client.ts +180 -0
- package/src/tools/aggregate-request.tools.ts +83 -0
- package/src/tools/auth.tools.ts +187 -0
- package/src/tools/collection.tools.ts +80 -0
- package/src/tools/gateway-plugin.tools.ts +90 -0
- package/src/tools/gateway-route.tools.ts +94 -0
- package/src/tools/gateway.tools.ts +82 -0
- package/src/tools/observability.tools.ts +87 -0
- package/src/tools/service-target.tools.ts +78 -0
- package/src/tools/service.tools.ts +93 -0
- package/src/tools/user-profile.tools.ts +72 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sopo MCP Server — Service Target Tools
|
|
3
|
+
*
|
|
4
|
+
* CRUD tools for managing Service Targets (upstream URLs / load balancing endpoints).
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { sopoGet, sopoPost, sopoPatch, sopoDelete } from '../sopo-client.js';
|
|
8
|
+
export function registerServiceTargetTools(server) {
|
|
9
|
+
// ── List Service Targets ──────────────────────────────────────
|
|
10
|
+
server.tool('list_service_targets', 'List all service targets (upstream URLs). Returns id, service_id, url, and weight for each target.', {}, async () => {
|
|
11
|
+
const result = await sopoGet('/api/v1/service-targets');
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true };
|
|
14
|
+
}
|
|
15
|
+
return { content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }] };
|
|
16
|
+
});
|
|
17
|
+
// ── Create Service Target ─────────────────────────────────────
|
|
18
|
+
server.tool('create_service_target', 'Add a new upstream URL target to a service. Requires url and service_id. The service_id MUST reference an existing service.', {
|
|
19
|
+
url: z.string().describe('The upstream URL (e.g. "https://api.example.com")'),
|
|
20
|
+
service_id: z.string().uuid().describe('UUID of the parent service (must exist)'),
|
|
21
|
+
weight: z.number().optional().default(1).describe('Load balancing weight (default 1)'),
|
|
22
|
+
}, async (args) => {
|
|
23
|
+
const result = await sopoPost('/api/v1/service-targets', args);
|
|
24
|
+
if (!result.success) {
|
|
25
|
+
return { content: [{ type: 'text', text: `Error creating service target: ${result.error}` }], isError: true };
|
|
26
|
+
}
|
|
27
|
+
return { content: [{ type: 'text', text: `Service target created:\n${JSON.stringify(result.data, null, 2)}` }] };
|
|
28
|
+
});
|
|
29
|
+
// ── Update Service Target ─────────────────────────────────────
|
|
30
|
+
server.tool('update_service_target', 'Update a service target by UUID. You can change the url or weight.', {
|
|
31
|
+
id: z.string().uuid().describe('UUID of the service target'),
|
|
32
|
+
url: z.string().describe('New upstream URL'),
|
|
33
|
+
}, async (args) => {
|
|
34
|
+
const { id, ...body } = args;
|
|
35
|
+
const result = await sopoPatch(`/api/v1/service-targets/${id}`, body);
|
|
36
|
+
if (!result.success) {
|
|
37
|
+
return { content: [{ type: 'text', text: `Error updating target: ${result.error}` }], isError: true };
|
|
38
|
+
}
|
|
39
|
+
return { content: [{ type: 'text', text: `Service target updated:\n${JSON.stringify(result.data, null, 2)}` }] };
|
|
40
|
+
});
|
|
41
|
+
// ── Delete Service Target ─────────────────────────────────────
|
|
42
|
+
server.tool('delete_service_target', 'Delete a service target by its UUID.', {
|
|
43
|
+
id: z.string().uuid().describe('UUID of the service target to delete'),
|
|
44
|
+
}, async (args) => {
|
|
45
|
+
const result = await sopoDelete(`/api/v1/service-targets/${args.id}`);
|
|
46
|
+
if (!result.success) {
|
|
47
|
+
return { content: [{ type: 'text', text: `Error deleting target: ${result.error}` }], isError: true };
|
|
48
|
+
}
|
|
49
|
+
return { content: [{ type: 'text', text: `Service target deleted successfully.` }] };
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=service-target.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-target.tools.js","sourceRoot":"","sources":["../../src/tools/service-target.tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sopo MCP Server — Service Tools
|
|
3
|
+
*
|
|
4
|
+
* CRUD tools for managing Services (upstream backends) within a Gateway.
|
|
5
|
+
*/
|
|
6
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
export declare function registerServiceTools(server: McpServer): void;
|
|
8
|
+
//# sourceMappingURL=service.tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.tools.d.ts","sourceRoot":"","sources":["../../src/tools/service.tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkF5D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sopo MCP Server — Service Tools
|
|
3
|
+
*
|
|
4
|
+
* CRUD tools for managing Services (upstream backends) within a Gateway.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { sopoGet, sopoPost, sopoPatch, sopoDelete } from '../sopo-client.js';
|
|
8
|
+
export function registerServiceTools(server) {
|
|
9
|
+
// ── List Services ─────────────────────────────────────────────
|
|
10
|
+
server.tool('list_services', 'List all services (upstream backends) across all gateways. Returns id, name, gateway_id, protocol, lb_policy, and health check settings.', {}, async () => {
|
|
11
|
+
const result = await sopoGet('/api/v1/services');
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true };
|
|
14
|
+
}
|
|
15
|
+
return { content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }] };
|
|
16
|
+
});
|
|
17
|
+
// ── Create Service ────────────────────────────────────────────
|
|
18
|
+
server.tool('create_service', 'Create a new service under a gateway. Requires name, gateway_id, protocol, and lb_policy. The gateway_id MUST reference an existing gateway.', {
|
|
19
|
+
name: z.string().describe('Name of the service'),
|
|
20
|
+
gateway_id: z.string().uuid().describe('UUID of the parent gateway (must exist)'),
|
|
21
|
+
protocol: z.string().describe('Protocol: "http" or "https"'),
|
|
22
|
+
lb_policy: z.string().describe('Load balancing policy: "round_robin", "weighted", or "random"'),
|
|
23
|
+
hc_path: z.string().optional().describe('Health check path (e.g. "/health")'),
|
|
24
|
+
hc_interval: z.string().optional().describe('Health check interval'),
|
|
25
|
+
hc_timeout: z.string().optional().describe('Health check timeout'),
|
|
26
|
+
hc_fail_threshold: z.number().optional().describe('Number of failures before marking unhealthy'),
|
|
27
|
+
hc_pass_threshold: z.number().optional().describe('Number of passes before marking healthy'),
|
|
28
|
+
collection_id: z.string().uuid().optional().describe('Optional collection ID (Pro mode)'),
|
|
29
|
+
}, async (args) => {
|
|
30
|
+
const result = await sopoPost('/api/v1/services', args);
|
|
31
|
+
if (!result.success) {
|
|
32
|
+
return { content: [{ type: 'text', text: `Error creating service: ${result.error}` }], isError: true };
|
|
33
|
+
}
|
|
34
|
+
return { content: [{ type: 'text', text: `Service created successfully:\n${JSON.stringify(result.data, null, 2)}` }] };
|
|
35
|
+
});
|
|
36
|
+
// ── Update Service ────────────────────────────────────────────
|
|
37
|
+
server.tool('update_service', 'Update an existing service by its UUID. You can change name, protocol, lb_policy, health check settings, or collection_id.', {
|
|
38
|
+
id: z.string().uuid().describe('UUID of the service to update'),
|
|
39
|
+
name: z.string().optional().describe('New name'),
|
|
40
|
+
protocol: z.string().optional().describe('New protocol'),
|
|
41
|
+
lb_policy: z.string().optional().describe('New load balancing policy'),
|
|
42
|
+
hc_path: z.string().optional().describe('Health check path'),
|
|
43
|
+
hc_interval: z.string().optional().describe('Health check interval'),
|
|
44
|
+
hc_timeout: z.string().optional().describe('Health check timeout'),
|
|
45
|
+
hc_fail_threshold: z.number().optional().describe('Failures before unhealthy'),
|
|
46
|
+
hc_pass_threshold: z.number().optional().describe('Passes before healthy'),
|
|
47
|
+
collection_id: z.string().uuid().optional().describe('Collection ID (Pro mode)'),
|
|
48
|
+
}, async (args) => {
|
|
49
|
+
const { id, ...body } = args;
|
|
50
|
+
const result = await sopoPatch(`/api/v1/services/${id}`, body);
|
|
51
|
+
if (!result.success) {
|
|
52
|
+
return { content: [{ type: 'text', text: `Error updating service: ${result.error}` }], isError: true };
|
|
53
|
+
}
|
|
54
|
+
return { content: [{ type: 'text', text: `Service updated successfully:\n${JSON.stringify(result.data, null, 2)}` }] };
|
|
55
|
+
});
|
|
56
|
+
// ── Delete Service ────────────────────────────────────────────
|
|
57
|
+
server.tool('delete_service', 'Delete a service by its UUID.', {
|
|
58
|
+
id: z.string().uuid().describe('UUID of the service to delete'),
|
|
59
|
+
}, async (args) => {
|
|
60
|
+
const result = await sopoDelete(`/api/v1/services/${args.id}`);
|
|
61
|
+
if (!result.success) {
|
|
62
|
+
return { content: [{ type: 'text', text: `Error deleting service: ${result.error}` }], isError: true };
|
|
63
|
+
}
|
|
64
|
+
return { content: [{ type: 'text', text: `Service deleted successfully.` }] };
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=service.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.tools.js","sourceRoot":"","sources":["../../src/tools/service.tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sopo MCP Server — User Profile Tools
|
|
3
|
+
*
|
|
4
|
+
* CRUD tools for managing User Profiles (user slug/namespace).
|
|
5
|
+
*/
|
|
6
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
export declare function registerUserProfileTools(server: McpServer): void;
|
|
8
|
+
//# sourceMappingURL=user-profile.tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-profile.tools.d.ts","sourceRoot":"","sources":["../../src/tools/user-profile.tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6DhE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sopo MCP Server — User Profile Tools
|
|
3
|
+
*
|
|
4
|
+
* CRUD tools for managing User Profiles (user slug/namespace).
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { sopoGet, sopoPost, sopoPatch, sopoDelete } from '../sopo-client.js';
|
|
8
|
+
export function registerUserProfileTools(server) {
|
|
9
|
+
// ── Get User Profile ──────────────────────────────────────────
|
|
10
|
+
server.tool('get_user_profile', 'Get the current authenticated user\'s profile, including their slug (URL namespace).', {}, async () => {
|
|
11
|
+
const result = await sopoGet('/api/v1/user-profiles');
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
return { content: [{ type: 'text', text: `Error: ${result.error}` }], isError: true };
|
|
14
|
+
}
|
|
15
|
+
return { content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }] };
|
|
16
|
+
});
|
|
17
|
+
// ── Create User Profile ───────────────────────────────────────
|
|
18
|
+
server.tool('create_user_profile', 'Create a profile for the authenticated user with a unique slug (URL namespace). Each user can only have one profile.', {
|
|
19
|
+
slug: z.string().describe('Unique slug for the user (e.g. "abdo")'),
|
|
20
|
+
}, async (args) => {
|
|
21
|
+
const result = await sopoPost('/api/v1/user-profiles', args);
|
|
22
|
+
if (!result.success) {
|
|
23
|
+
return { content: [{ type: 'text', text: `Error creating profile: ${result.error}` }], isError: true };
|
|
24
|
+
}
|
|
25
|
+
return { content: [{ type: 'text', text: `User profile created:\n${JSON.stringify(result.data, null, 2)}` }] };
|
|
26
|
+
});
|
|
27
|
+
// ── Update User Profile ───────────────────────────────────────
|
|
28
|
+
server.tool('update_user_profile', 'Update the authenticated user\'s slug.', {
|
|
29
|
+
slug: z.string().describe('New unique slug'),
|
|
30
|
+
}, async (args) => {
|
|
31
|
+
const result = await sopoPatch('/api/v1/user-profiles', args);
|
|
32
|
+
if (!result.success) {
|
|
33
|
+
return { content: [{ type: 'text', text: `Error updating profile: ${result.error}` }], isError: true };
|
|
34
|
+
}
|
|
35
|
+
return { content: [{ type: 'text', text: `User profile updated:\n${JSON.stringify(result.data, null, 2)}` }] };
|
|
36
|
+
});
|
|
37
|
+
// ── Delete User Profile ───────────────────────────────────────
|
|
38
|
+
server.tool('delete_user_profile', 'Delete the authenticated user\'s profile.', {}, async () => {
|
|
39
|
+
const result = await sopoDelete('/api/v1/user-profiles');
|
|
40
|
+
if (!result.success) {
|
|
41
|
+
return { content: [{ type: 'text', text: `Error deleting profile: ${result.error}` }], isError: true };
|
|
42
|
+
}
|
|
43
|
+
return { content: [{ type: 'text', text: `User profile deleted successfully.` }] };
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=user-profile.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-profile.tools.js","sourceRoot":"","sources":["../../src/tools/user-profile.tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sopo-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP (Model Context Protocol) Server for Sopo API Gateway Platform",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"sopo-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "tsx src/index.ts",
|
|
14
|
+
"inspect": "npx @modelcontextprotocol/inspector node dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"mcp",
|
|
18
|
+
"sopo",
|
|
19
|
+
"api-gateway"
|
|
20
|
+
],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
25
|
+
"dotenv": "^17.4.2",
|
|
26
|
+
"zod": "^3.25.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^22.15.0",
|
|
30
|
+
"tsx": "^4.19.0",
|
|
31
|
+
"typescript": "^5.8.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import 'dotenv/config';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ╔═══════════════════════════════════════════════════════════════╗
|
|
7
|
+
* ║ Sopo MCP Server ║
|
|
8
|
+
* ║ ║
|
|
9
|
+
* ║ Model Context Protocol server for the Sopo API Gateway ║
|
|
10
|
+
* ║ platform. Enables AI models (Claude, etc.) to manage ║
|
|
11
|
+
* ║ gateways, services, routes, plugins, and monitor metrics. ║
|
|
12
|
+
* ╚═══════════════════════════════════════════════════════════════╝
|
|
13
|
+
*
|
|
14
|
+
* Transport: stdio (for Claude Desktop / local AI clients)
|
|
15
|
+
*
|
|
16
|
+
* Environment Variables:
|
|
17
|
+
* SOPO_BACKEND_URL — Base URL of the Sopo Backend (default: http://localhost:4000)
|
|
18
|
+
* SOPO_ACCESS_TOKEN — JWT access token for authentication
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
22
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
23
|
+
import { configureSopoClient } from './sopo-client.js';
|
|
24
|
+
|
|
25
|
+
// ── Tool Registrations ──────────────────────────────────────────
|
|
26
|
+
import { registerAuthTools } from './tools/auth.tools.js';
|
|
27
|
+
import { registerGatewayTools } from './tools/gateway.tools.js';
|
|
28
|
+
import { registerServiceTools } from './tools/service.tools.js';
|
|
29
|
+
import { registerServiceTargetTools } from './tools/service-target.tools.js';
|
|
30
|
+
import { registerGatewayRouteTools } from './tools/gateway-route.tools.js';
|
|
31
|
+
import { registerGatewayPluginTools } from './tools/gateway-plugin.tools.js';
|
|
32
|
+
import { registerAggregateRequestTools } from './tools/aggregate-request.tools.js';
|
|
33
|
+
import { registerCollectionTools } from './tools/collection.tools.js';
|
|
34
|
+
import { registerUserProfileTools } from './tools/user-profile.tools.js';
|
|
35
|
+
import { registerObservabilityTools } from './tools/observability.tools.js';
|
|
36
|
+
|
|
37
|
+
// ── Resource Registrations ──────────────────────────────────────
|
|
38
|
+
import { registerResources } from './resources/platform.resources.js';
|
|
39
|
+
|
|
40
|
+
// ── Prompt Registrations ────────────────────────────────────────
|
|
41
|
+
import { registerPrompts } from './prompts/sopo.prompts.js';
|
|
42
|
+
|
|
43
|
+
// ═══════════════════════════════════════════════════════════════
|
|
44
|
+
// Configuration
|
|
45
|
+
// ═══════════════════════════════════════════════════════════════
|
|
46
|
+
|
|
47
|
+
const BACKEND_URL = process.env.SOPO_BACKEND_URL || 'http://localhost:4000';
|
|
48
|
+
const ACCESS_TOKEN = process.env.SOPO_ACCESS_TOKEN || '';
|
|
49
|
+
|
|
50
|
+
if (!ACCESS_TOKEN) {
|
|
51
|
+
console.error(
|
|
52
|
+
'⚠️ Warning: SOPO_ACCESS_TOKEN is not set. All API calls will fail with 401 Unauthorized.\n' +
|
|
53
|
+
' Set it via environment variable or .env file.\n' +
|
|
54
|
+
' See .env.example for reference.'
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ═══════════════════════════════════════════════════════════════
|
|
59
|
+
// Initialize
|
|
60
|
+
// ═══════════════════════════════════════════════════════════════
|
|
61
|
+
|
|
62
|
+
// Configure the HTTP client
|
|
63
|
+
configureSopoClient({
|
|
64
|
+
backendUrl: BACKEND_URL,
|
|
65
|
+
accessToken: ACCESS_TOKEN,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Create the MCP Server
|
|
69
|
+
const server = new McpServer({
|
|
70
|
+
name: 'sopo-mcp-server',
|
|
71
|
+
version: '1.0.0',
|
|
72
|
+
description: 'MCP Server for the Sopo API Gateway Platform — manage gateways, services, routes, plugins, and monitor metrics via AI.',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// ═══════════════════════════════════════════════════════════════
|
|
76
|
+
// Register All Capabilities
|
|
77
|
+
// ═══════════════════════════════════════════════════════════════
|
|
78
|
+
|
|
79
|
+
// Tools — Authentication (login + refresh)
|
|
80
|
+
registerAuthTools(server); // 2 tools: login, refresh_token
|
|
81
|
+
|
|
82
|
+
// Tools (30 tools covering full CRUD for all entities + observability)
|
|
83
|
+
registerGatewayTools(server); // 4 tools: list, create, update, delete
|
|
84
|
+
registerServiceTools(server); // 4 tools: list, create, update, delete
|
|
85
|
+
registerServiceTargetTools(server); // 4 tools: list, create, update, delete
|
|
86
|
+
registerGatewayRouteTools(server); // 4 tools: list, create, update, delete
|
|
87
|
+
registerGatewayPluginTools(server); // 4 tools: list, create, update, delete
|
|
88
|
+
registerAggregateRequestTools(server); // 4 tools: list, create, update, delete
|
|
89
|
+
registerCollectionTools(server); // 4 tools: list, create, update, delete
|
|
90
|
+
registerUserProfileTools(server); // 4 tools: get, create, update, delete
|
|
91
|
+
registerObservabilityTools(server); // 5 tools: health, stats, logs, metrics, metrics-mv
|
|
92
|
+
|
|
93
|
+
// Resources (3 resources: platform overview, live config, live stats)
|
|
94
|
+
registerResources(server);
|
|
95
|
+
|
|
96
|
+
// Prompts (4 prompts: setup gateway, diagnose, full report, add plugin)
|
|
97
|
+
registerPrompts(server);
|
|
98
|
+
|
|
99
|
+
// ═══════════════════════════════════════════════════════════════
|
|
100
|
+
// Start Server
|
|
101
|
+
// ═══════════════════════════════════════════════════════════════
|
|
102
|
+
|
|
103
|
+
async function main() {
|
|
104
|
+
const transport = new StdioServerTransport();
|
|
105
|
+
await server.connect(transport);
|
|
106
|
+
console.error('🚀 Sopo MCP Server started successfully');
|
|
107
|
+
console.error(` Backend URL: ${BACKEND_URL}`);
|
|
108
|
+
console.error(` Token: ${ACCESS_TOKEN ? '✅ configured' : '❌ missing'}`);
|
|
109
|
+
console.error(` Tools: 39 | Resources: 3 | Prompts: 4`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
main().catch((error) => {
|
|
113
|
+
console.error('Fatal error starting Sopo MCP Server:', error);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sopo MCP Server — Prompts
|
|
3
|
+
*
|
|
4
|
+
* Predefined prompt templates that guide the AI for common Sopo operations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
9
|
+
|
|
10
|
+
export function registerPrompts(server: McpServer): void {
|
|
11
|
+
|
|
12
|
+
// ── Setup New Gateway (Guided Workflow) ───────────────────────
|
|
13
|
+
server.prompt(
|
|
14
|
+
'setup_new_gateway',
|
|
15
|
+
'Guided workflow to set up a complete API gateway from scratch — creates gateway, service, service target, and route.',
|
|
16
|
+
{
|
|
17
|
+
gateway_name: z.string().describe('Name for the new gateway'),
|
|
18
|
+
upstream_url: z.string().describe('URL of the upstream backend to route to'),
|
|
19
|
+
route_path: z.string().describe('The incoming request path to handle'),
|
|
20
|
+
},
|
|
21
|
+
async (args) => ({
|
|
22
|
+
messages: [{
|
|
23
|
+
role: 'user',
|
|
24
|
+
content: {
|
|
25
|
+
type: 'text',
|
|
26
|
+
text: `I want to set up a new API gateway in Sopo. Please execute these steps in order:
|
|
27
|
+
|
|
28
|
+
1. **Create a gateway** named "${args.gateway_name}" in "single" mode (active).
|
|
29
|
+
2. **Create a service** named "${args.gateway_name}-service" under the new gateway with protocol "http" and lb_policy "round_robin".
|
|
30
|
+
3. **Create a service target** with URL "${args.upstream_url}" pointing to the new service.
|
|
31
|
+
4. **Create a route** with path "${args.route_path}" on the new gateway pointing to the new service.
|
|
32
|
+
|
|
33
|
+
After each step, confirm the ID of the created resource. If any step fails, stop and report the error.`,
|
|
34
|
+
},
|
|
35
|
+
}],
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// ── Diagnose Gateway ──────────────────────────────────────────
|
|
40
|
+
server.prompt(
|
|
41
|
+
'diagnose_gateway',
|
|
42
|
+
'Diagnose the health and configuration of a specific gateway by reviewing its resources, routes, plugins, and recent metrics.',
|
|
43
|
+
{
|
|
44
|
+
gateway_name: z.string().describe('Name of the gateway to diagnose'),
|
|
45
|
+
},
|
|
46
|
+
async (args) => ({
|
|
47
|
+
messages: [{
|
|
48
|
+
role: 'user',
|
|
49
|
+
content: {
|
|
50
|
+
type: 'text',
|
|
51
|
+
text: `Please diagnose the gateway "${args.gateway_name}" in Sopo. Do the following:
|
|
52
|
+
|
|
53
|
+
1. **List all gateways** and find the one named "${args.gateway_name}".
|
|
54
|
+
2. **List all services** and filter those belonging to this gateway.
|
|
55
|
+
3. **List all service targets** and check if the services have healthy upstream URLs.
|
|
56
|
+
4. **List all routes** belonging to this gateway.
|
|
57
|
+
5. **List all plugins** attached to this gateway or its routes.
|
|
58
|
+
6. **Get resource stats** for an overview.
|
|
59
|
+
7. **Fetch recent request logs** and look for errors or high latency.
|
|
60
|
+
8. **Get hourly metrics** to check traffic trends.
|
|
61
|
+
|
|
62
|
+
Provide a summary with:
|
|
63
|
+
- ✅ Things that look good
|
|
64
|
+
- ⚠️ Potential issues or misconfigurations
|
|
65
|
+
- 🔧 Recommended actions`,
|
|
66
|
+
},
|
|
67
|
+
}],
|
|
68
|
+
})
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// ── Full Platform Report ──────────────────────────────────────
|
|
72
|
+
server.prompt(
|
|
73
|
+
'platform_report',
|
|
74
|
+
'Generate a comprehensive report of the entire Sopo platform — all resources, configuration, and metrics.',
|
|
75
|
+
{},
|
|
76
|
+
async () => ({
|
|
77
|
+
messages: [{
|
|
78
|
+
role: 'user',
|
|
79
|
+
content: {
|
|
80
|
+
type: 'text',
|
|
81
|
+
text: `Generate a complete Sopo platform report. Please:
|
|
82
|
+
|
|
83
|
+
1. **Check system health** (call check_health).
|
|
84
|
+
2. **Get resource stats** for overall counts.
|
|
85
|
+
3. **List all gateways** with their details.
|
|
86
|
+
4. **List all services** with health check configs.
|
|
87
|
+
5. **List all service targets** with their URLs and weights.
|
|
88
|
+
6. **List all routes** with their path mappings.
|
|
89
|
+
7. **List all plugins** with their configs.
|
|
90
|
+
8. **List all collections** if any exist.
|
|
91
|
+
9. **Get user profile** to show the current user's slug.
|
|
92
|
+
10. **Fetch hourly metrics** to show recent traffic.
|
|
93
|
+
|
|
94
|
+
Format everything as a structured, readable report with sections for each resource type.`,
|
|
95
|
+
},
|
|
96
|
+
}],
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
// ── Add Plugin to Gateway ─────────────────────────────────────
|
|
101
|
+
server.prompt(
|
|
102
|
+
'add_plugin_to_gateway',
|
|
103
|
+
'Attach a middleware plugin (like API key auth, rate limiting, or CORS) to a gateway.',
|
|
104
|
+
{
|
|
105
|
+
gateway_name: z.string().describe('Name of the gateway'),
|
|
106
|
+
plugin_type: z.string().describe('Plugin type (e.g. "apikey", "rate_limit", "cors")'),
|
|
107
|
+
},
|
|
108
|
+
async (args) => ({
|
|
109
|
+
messages: [{
|
|
110
|
+
role: 'user',
|
|
111
|
+
content: {
|
|
112
|
+
type: 'text',
|
|
113
|
+
text: `I want to add a "${args.plugin_type}" plugin to the gateway "${args.gateway_name}". Please:
|
|
114
|
+
|
|
115
|
+
1. **List all gateways** and find the one named "${args.gateway_name}" to get its ID.
|
|
116
|
+
2. **Create a gateway plugin** with:
|
|
117
|
+
- name: "${args.plugin_type}"
|
|
118
|
+
- phase: "access" (or the appropriate phase for this plugin type)
|
|
119
|
+
- gateway_id: (the ID found above)
|
|
120
|
+
- enabled: true
|
|
121
|
+
- A sensible default plugin_config for "${args.plugin_type}"
|
|
122
|
+
|
|
123
|
+
Explain what the plugin does and what its configuration means.`,
|
|
124
|
+
},
|
|
125
|
+
}],
|
|
126
|
+
})
|
|
127
|
+
);
|
|
128
|
+
}
|