@cloudverse/gridx-mcp 0.1.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/README.md +15 -0
- package/dist/apps/mcp-server/src/main.js +201 -0
- package/dist/main.js +201 -0
- package/dist/packages/contracts/src/api.js +1 -0
- package/dist/packages/contracts/src/domain.js +1 -0
- package/dist/packages/contracts/src/events.js +1 -0
- package/dist/packages/contracts/src/index.js +34 -0
- package/dist/packages/contracts/src/security.js +1 -0
- package/dist/packages/sdk/src/index.js +128 -0
- package/package.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## Gridx MCP Server
|
|
2
|
+
|
|
3
|
+
Small MCP server that exposes real GridX market and execution tools for AI agents.
|
|
4
|
+
|
|
5
|
+
Install:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @cloudverse/gridx-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Run:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
gridx-mcp --baseUrl http://127.0.0.1:4000 --key gx_sa_xxx
|
|
15
|
+
```
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { GridxClient } from "@gridx/sdk";
|
|
5
|
+
function parseArg(flag) {
|
|
6
|
+
const index = process.argv.indexOf(flag);
|
|
7
|
+
if (index === -1) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return process.argv[index + 1] ?? null;
|
|
11
|
+
}
|
|
12
|
+
function loadConfigFile() {
|
|
13
|
+
const configPath = resolve(parseArg("--config") ?? `${homedir()}/.gridx/config.json`);
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(readFileSync(configPath, "utf8"));
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const savedConfig = loadConfigFile();
|
|
22
|
+
const client = new GridxClient({
|
|
23
|
+
baseUrl: parseArg("--baseUrl") ??
|
|
24
|
+
process.env.GRIDX_BASE_URL ??
|
|
25
|
+
savedConfig.baseUrl ??
|
|
26
|
+
"http://127.0.0.1:4000",
|
|
27
|
+
serviceKey: parseArg("--key") ??
|
|
28
|
+
process.env.GRIDX_SERVICE_KEY ??
|
|
29
|
+
savedConfig.serviceKey ??
|
|
30
|
+
"",
|
|
31
|
+
});
|
|
32
|
+
const tools = [
|
|
33
|
+
{
|
|
34
|
+
name: "route_best_listing",
|
|
35
|
+
description: "Auto-route a workload intent to the best eligible GridX listing.",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
modelFamily: { type: "string" },
|
|
40
|
+
modelHint: { type: "string" },
|
|
41
|
+
executionMode: { type: "string" },
|
|
42
|
+
demandClass: { type: "string" },
|
|
43
|
+
latencyTargetMs: { type: "number" },
|
|
44
|
+
gpuClassPreference: { type: "string" },
|
|
45
|
+
regionPreference: { type: "string" },
|
|
46
|
+
fallbackPreference: { type: "string" },
|
|
47
|
+
trustBias: { type: "string" },
|
|
48
|
+
issueLease: { type: "boolean" },
|
|
49
|
+
preferredAccessMode: { type: "string" }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "route_specific_listing",
|
|
55
|
+
description: "Route a specific listing through GridX if it is eligible.",
|
|
56
|
+
inputSchema: {
|
|
57
|
+
type: "object",
|
|
58
|
+
required: ["listingId"],
|
|
59
|
+
properties: {
|
|
60
|
+
listingId: { type: "string" },
|
|
61
|
+
demandClass: { type: "string" },
|
|
62
|
+
issueLease: { type: "boolean" }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "list_marketplace_candidates",
|
|
68
|
+
description: "List active marketplace listings visible through the GridX API.",
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: "object",
|
|
71
|
+
properties: {
|
|
72
|
+
modelFamily: { type: "string" },
|
|
73
|
+
executionMode: { type: "string" }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{ name: "get_session", description: "Get GridX session truth.", inputSchema: { type: "object", required: ["sessionId"], properties: { sessionId: { type: "string" } } } },
|
|
78
|
+
{ name: "get_session_truth", description: "Get GridX session truth with execution metadata.", inputSchema: { type: "object", required: ["sessionId"], properties: { sessionId: { type: "string" } } } },
|
|
79
|
+
{ name: "get_session_lease", description: "Get a GridX session lease.", inputSchema: { type: "object", required: ["leaseId"], properties: { leaseId: { type: "string" } } } },
|
|
80
|
+
{ name: "execute_via_proxy", description: "Execute a lease-backed GridX session via proxy mode.", inputSchema: { type: "object", required: ["leaseToken"], properties: { leaseToken: { type: "string" }, prompt: { type: "string" }, outputText: { type: "string" }, completionTokens: { type: "number" }, runtimeSeconds: { type: "number" }, usageUnits: { type: "number" } } } },
|
|
81
|
+
{ name: "revoke_session_lease", description: "Revoke a GridX session lease.", inputSchema: { type: "object", required: ["leaseId"], properties: { leaseId: { type: "string" } } } },
|
|
82
|
+
{ name: "get_buyer_savings_insights", description: "Get buyer savings insight for the calling org.", inputSchema: { type: "object", properties: { sessionId: { type: "string" } } } },
|
|
83
|
+
{ name: "get_policy_tuning_suggestions", description: "Get policy tuning suggestions for the calling org.", inputSchema: { type: "object", properties: {} } },
|
|
84
|
+
{ name: "list_commitments", description: "List active buyer commitments.", inputSchema: { type: "object", properties: {} } },
|
|
85
|
+
{ name: "list_reservations", description: "List active buyer reservations.", inputSchema: { type: "object", properties: {} } },
|
|
86
|
+
{ name: "get_seller_pricing_insights", description: "Get seller pricing insights when the org has seller context.", inputSchema: { type: "object", properties: { listingId: { type: "string" } } } },
|
|
87
|
+
{ name: "get_seller_repricing_guardrails", description: "Get seller repricing guardrails when the org has seller context.", inputSchema: { type: "object", properties: { listingId: { type: "string" } } } },
|
|
88
|
+
{ name: "get_seller_allocation_summary", description: "Get seller allocation optimization summary.", inputSchema: { type: "object", properties: {} } },
|
|
89
|
+
{ name: "get_market_pricing_overview", description: "Get market pricing overview.", inputSchema: { type: "object", properties: {} } },
|
|
90
|
+
{ name: "explain_route_policy_impact", description: "Explain the pricing and policy impact for a specific session.", inputSchema: { type: "object", required: ["sessionId"], properties: { sessionId: { type: "string" } } } }
|
|
91
|
+
];
|
|
92
|
+
function writeMessage(payload) {
|
|
93
|
+
const body = JSON.stringify(payload);
|
|
94
|
+
process.stdout.write(`Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n${body}`);
|
|
95
|
+
}
|
|
96
|
+
function writeResult(id, result) {
|
|
97
|
+
writeMessage({ jsonrpc: "2.0", id, result });
|
|
98
|
+
}
|
|
99
|
+
function writeError(id, message) {
|
|
100
|
+
writeMessage({
|
|
101
|
+
jsonrpc: "2.0",
|
|
102
|
+
id,
|
|
103
|
+
error: { code: -32000, message },
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async function handleToolCall(name, args = {}) {
|
|
107
|
+
switch (name) {
|
|
108
|
+
case "route_best_listing":
|
|
109
|
+
return client.routeBestListing(args);
|
|
110
|
+
case "route_specific_listing":
|
|
111
|
+
return client.routeSpecificListing(String(args.listingId), args);
|
|
112
|
+
case "list_marketplace_candidates":
|
|
113
|
+
return client.listMarketplaceCandidates(args);
|
|
114
|
+
case "get_session":
|
|
115
|
+
case "get_session_truth":
|
|
116
|
+
return client.getSession(String(args.sessionId));
|
|
117
|
+
case "get_session_lease":
|
|
118
|
+
return client.getSessionLease(String(args.leaseId));
|
|
119
|
+
case "execute_via_proxy":
|
|
120
|
+
return client.executeWithLease(String(args.leaseToken), {
|
|
121
|
+
prompt: typeof args.prompt === "string" ? args.prompt : undefined,
|
|
122
|
+
outputText: typeof args.outputText === "string" ? args.outputText : undefined,
|
|
123
|
+
completionTokens: typeof args.completionTokens === "number" ? args.completionTokens : undefined,
|
|
124
|
+
runtimeSeconds: typeof args.runtimeSeconds === "number" ? args.runtimeSeconds : undefined,
|
|
125
|
+
usageUnits: typeof args.usageUnits === "number" ? args.usageUnits : undefined,
|
|
126
|
+
});
|
|
127
|
+
case "revoke_session_lease":
|
|
128
|
+
return client.revokeSessionLease(String(args.leaseId));
|
|
129
|
+
case "get_buyer_savings_insights":
|
|
130
|
+
return client.getBuyerSavingsInsights(typeof args.sessionId === "string" ? args.sessionId : undefined);
|
|
131
|
+
case "get_policy_tuning_suggestions":
|
|
132
|
+
return client.getPolicyTuningSuggestions();
|
|
133
|
+
case "list_commitments":
|
|
134
|
+
return client.listCommitments();
|
|
135
|
+
case "list_reservations":
|
|
136
|
+
return client.listReservations();
|
|
137
|
+
case "get_seller_pricing_insights":
|
|
138
|
+
return client.getSellerPricingInsights(typeof args.listingId === "string" ? args.listingId : undefined);
|
|
139
|
+
case "get_seller_repricing_guardrails":
|
|
140
|
+
return client.getSellerRepricingGuardrails(typeof args.listingId === "string" ? args.listingId : undefined);
|
|
141
|
+
case "get_seller_allocation_summary":
|
|
142
|
+
return client.getSellerAllocationSummary();
|
|
143
|
+
case "get_market_pricing_overview":
|
|
144
|
+
return client.getMarketPricingOverview();
|
|
145
|
+
case "explain_route_policy_impact":
|
|
146
|
+
return client.getBuyerSavingsInsights(String(args.sessionId));
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unknown tool '${name}'.`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
let buffer = "";
|
|
152
|
+
process.stdin.setEncoding("utf8");
|
|
153
|
+
process.stdin.on("data", async (chunk) => {
|
|
154
|
+
buffer += chunk;
|
|
155
|
+
while (true) {
|
|
156
|
+
const separatorIndex = buffer.indexOf("\r\n\r\n");
|
|
157
|
+
if (separatorIndex === -1) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const header = buffer.slice(0, separatorIndex);
|
|
161
|
+
const lengthMatch = header.match(/Content-Length:\s*(\d+)/i);
|
|
162
|
+
if (!lengthMatch) {
|
|
163
|
+
buffer = "";
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const length = Number(lengthMatch[1]);
|
|
167
|
+
const bodyStart = separatorIndex + 4;
|
|
168
|
+
if (buffer.length < bodyStart + length) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const body = buffer.slice(bodyStart, bodyStart + length);
|
|
172
|
+
buffer = buffer.slice(bodyStart + length);
|
|
173
|
+
const request = JSON.parse(body);
|
|
174
|
+
try {
|
|
175
|
+
if (request.method === "initialize") {
|
|
176
|
+
writeResult(request.id ?? null, {
|
|
177
|
+
protocolVersion: "2024-11-05",
|
|
178
|
+
capabilities: { tools: {} },
|
|
179
|
+
serverInfo: { name: "gridx-mcp", version: "0.1.0" },
|
|
180
|
+
});
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (request.method === "tools/list") {
|
|
184
|
+
writeResult(request.id ?? null, { tools });
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (request.method === "tools/call") {
|
|
188
|
+
const result = await handleToolCall(String(request.params?.name ?? ""), request.params?.arguments ?? {});
|
|
189
|
+
writeResult(request.id ?? null, {
|
|
190
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
191
|
+
structuredContent: result,
|
|
192
|
+
});
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
writeError(request.id ?? null, `Unsupported method '${request.method}'.`);
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
writeError(request.id ?? null, error instanceof Error ? error.message : "GridX MCP server failed.");
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
});
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { GridxClient } from "@gridx/sdk";
|
|
5
|
+
function parseArg(flag) {
|
|
6
|
+
const index = process.argv.indexOf(flag);
|
|
7
|
+
if (index === -1) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return process.argv[index + 1] ?? null;
|
|
11
|
+
}
|
|
12
|
+
function loadConfigFile() {
|
|
13
|
+
const configPath = resolve(parseArg("--config") ?? `${homedir()}/.gridx/config.json`);
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(readFileSync(configPath, "utf8"));
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const savedConfig = loadConfigFile();
|
|
22
|
+
const client = new GridxClient({
|
|
23
|
+
baseUrl: parseArg("--baseUrl") ??
|
|
24
|
+
process.env.GRIDX_BASE_URL ??
|
|
25
|
+
savedConfig.baseUrl ??
|
|
26
|
+
"http://127.0.0.1:4000",
|
|
27
|
+
serviceKey: parseArg("--key") ??
|
|
28
|
+
process.env.GRIDX_SERVICE_KEY ??
|
|
29
|
+
savedConfig.serviceKey ??
|
|
30
|
+
"",
|
|
31
|
+
});
|
|
32
|
+
const tools = [
|
|
33
|
+
{
|
|
34
|
+
name: "route_best_listing",
|
|
35
|
+
description: "Auto-route a workload intent to the best eligible GridX listing.",
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
modelFamily: { type: "string" },
|
|
40
|
+
modelHint: { type: "string" },
|
|
41
|
+
executionMode: { type: "string" },
|
|
42
|
+
demandClass: { type: "string" },
|
|
43
|
+
latencyTargetMs: { type: "number" },
|
|
44
|
+
gpuClassPreference: { type: "string" },
|
|
45
|
+
regionPreference: { type: "string" },
|
|
46
|
+
fallbackPreference: { type: "string" },
|
|
47
|
+
trustBias: { type: "string" },
|
|
48
|
+
issueLease: { type: "boolean" },
|
|
49
|
+
preferredAccessMode: { type: "string" }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "route_specific_listing",
|
|
55
|
+
description: "Route a specific listing through GridX if it is eligible.",
|
|
56
|
+
inputSchema: {
|
|
57
|
+
type: "object",
|
|
58
|
+
required: ["listingId"],
|
|
59
|
+
properties: {
|
|
60
|
+
listingId: { type: "string" },
|
|
61
|
+
demandClass: { type: "string" },
|
|
62
|
+
issueLease: { type: "boolean" }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "list_marketplace_candidates",
|
|
68
|
+
description: "List active marketplace listings visible through the GridX API.",
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: "object",
|
|
71
|
+
properties: {
|
|
72
|
+
modelFamily: { type: "string" },
|
|
73
|
+
executionMode: { type: "string" }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{ name: "get_session", description: "Get GridX session truth.", inputSchema: { type: "object", required: ["sessionId"], properties: { sessionId: { type: "string" } } } },
|
|
78
|
+
{ name: "get_session_truth", description: "Get GridX session truth with execution metadata.", inputSchema: { type: "object", required: ["sessionId"], properties: { sessionId: { type: "string" } } } },
|
|
79
|
+
{ name: "get_session_lease", description: "Get a GridX session lease.", inputSchema: { type: "object", required: ["leaseId"], properties: { leaseId: { type: "string" } } } },
|
|
80
|
+
{ name: "execute_via_proxy", description: "Execute a lease-backed GridX session via proxy mode.", inputSchema: { type: "object", required: ["leaseToken"], properties: { leaseToken: { type: "string" }, prompt: { type: "string" }, outputText: { type: "string" }, completionTokens: { type: "number" }, runtimeSeconds: { type: "number" }, usageUnits: { type: "number" } } } },
|
|
81
|
+
{ name: "revoke_session_lease", description: "Revoke a GridX session lease.", inputSchema: { type: "object", required: ["leaseId"], properties: { leaseId: { type: "string" } } } },
|
|
82
|
+
{ name: "get_buyer_savings_insights", description: "Get buyer savings insight for the calling org.", inputSchema: { type: "object", properties: { sessionId: { type: "string" } } } },
|
|
83
|
+
{ name: "get_policy_tuning_suggestions", description: "Get policy tuning suggestions for the calling org.", inputSchema: { type: "object", properties: {} } },
|
|
84
|
+
{ name: "list_commitments", description: "List active buyer commitments.", inputSchema: { type: "object", properties: {} } },
|
|
85
|
+
{ name: "list_reservations", description: "List active buyer reservations.", inputSchema: { type: "object", properties: {} } },
|
|
86
|
+
{ name: "get_seller_pricing_insights", description: "Get seller pricing insights when the org has seller context.", inputSchema: { type: "object", properties: { listingId: { type: "string" } } } },
|
|
87
|
+
{ name: "get_seller_repricing_guardrails", description: "Get seller repricing guardrails when the org has seller context.", inputSchema: { type: "object", properties: { listingId: { type: "string" } } } },
|
|
88
|
+
{ name: "get_seller_allocation_summary", description: "Get seller allocation optimization summary.", inputSchema: { type: "object", properties: {} } },
|
|
89
|
+
{ name: "get_market_pricing_overview", description: "Get market pricing overview.", inputSchema: { type: "object", properties: {} } },
|
|
90
|
+
{ name: "explain_route_policy_impact", description: "Explain the pricing and policy impact for a specific session.", inputSchema: { type: "object", required: ["sessionId"], properties: { sessionId: { type: "string" } } } }
|
|
91
|
+
];
|
|
92
|
+
function writeMessage(payload) {
|
|
93
|
+
const body = JSON.stringify(payload);
|
|
94
|
+
process.stdout.write(`Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n${body}`);
|
|
95
|
+
}
|
|
96
|
+
function writeResult(id, result) {
|
|
97
|
+
writeMessage({ jsonrpc: "2.0", id, result });
|
|
98
|
+
}
|
|
99
|
+
function writeError(id, message) {
|
|
100
|
+
writeMessage({
|
|
101
|
+
jsonrpc: "2.0",
|
|
102
|
+
id,
|
|
103
|
+
error: { code: -32000, message },
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async function handleToolCall(name, args = {}) {
|
|
107
|
+
switch (name) {
|
|
108
|
+
case "route_best_listing":
|
|
109
|
+
return client.routeBestListing(args);
|
|
110
|
+
case "route_specific_listing":
|
|
111
|
+
return client.routeSpecificListing(String(args.listingId), args);
|
|
112
|
+
case "list_marketplace_candidates":
|
|
113
|
+
return client.listMarketplaceCandidates(args);
|
|
114
|
+
case "get_session":
|
|
115
|
+
case "get_session_truth":
|
|
116
|
+
return client.getSession(String(args.sessionId));
|
|
117
|
+
case "get_session_lease":
|
|
118
|
+
return client.getSessionLease(String(args.leaseId));
|
|
119
|
+
case "execute_via_proxy":
|
|
120
|
+
return client.executeWithLease(String(args.leaseToken), {
|
|
121
|
+
prompt: typeof args.prompt === "string" ? args.prompt : undefined,
|
|
122
|
+
outputText: typeof args.outputText === "string" ? args.outputText : undefined,
|
|
123
|
+
completionTokens: typeof args.completionTokens === "number" ? args.completionTokens : undefined,
|
|
124
|
+
runtimeSeconds: typeof args.runtimeSeconds === "number" ? args.runtimeSeconds : undefined,
|
|
125
|
+
usageUnits: typeof args.usageUnits === "number" ? args.usageUnits : undefined,
|
|
126
|
+
});
|
|
127
|
+
case "revoke_session_lease":
|
|
128
|
+
return client.revokeSessionLease(String(args.leaseId));
|
|
129
|
+
case "get_buyer_savings_insights":
|
|
130
|
+
return client.getBuyerSavingsInsights(typeof args.sessionId === "string" ? args.sessionId : undefined);
|
|
131
|
+
case "get_policy_tuning_suggestions":
|
|
132
|
+
return client.getPolicyTuningSuggestions();
|
|
133
|
+
case "list_commitments":
|
|
134
|
+
return client.listCommitments();
|
|
135
|
+
case "list_reservations":
|
|
136
|
+
return client.listReservations();
|
|
137
|
+
case "get_seller_pricing_insights":
|
|
138
|
+
return client.getSellerPricingInsights(typeof args.listingId === "string" ? args.listingId : undefined);
|
|
139
|
+
case "get_seller_repricing_guardrails":
|
|
140
|
+
return client.getSellerRepricingGuardrails(typeof args.listingId === "string" ? args.listingId : undefined);
|
|
141
|
+
case "get_seller_allocation_summary":
|
|
142
|
+
return client.getSellerAllocationSummary();
|
|
143
|
+
case "get_market_pricing_overview":
|
|
144
|
+
return client.getMarketPricingOverview();
|
|
145
|
+
case "explain_route_policy_impact":
|
|
146
|
+
return client.getBuyerSavingsInsights(String(args.sessionId));
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unknown tool '${name}'.`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
let buffer = "";
|
|
152
|
+
process.stdin.setEncoding("utf8");
|
|
153
|
+
process.stdin.on("data", async (chunk) => {
|
|
154
|
+
buffer += chunk;
|
|
155
|
+
while (true) {
|
|
156
|
+
const separatorIndex = buffer.indexOf("\r\n\r\n");
|
|
157
|
+
if (separatorIndex === -1) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const header = buffer.slice(0, separatorIndex);
|
|
161
|
+
const lengthMatch = header.match(/Content-Length:\s*(\d+)/i);
|
|
162
|
+
if (!lengthMatch) {
|
|
163
|
+
buffer = "";
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const length = Number(lengthMatch[1]);
|
|
167
|
+
const bodyStart = separatorIndex + 4;
|
|
168
|
+
if (buffer.length < bodyStart + length) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const body = buffer.slice(bodyStart, bodyStart + length);
|
|
172
|
+
buffer = buffer.slice(bodyStart + length);
|
|
173
|
+
const request = JSON.parse(body);
|
|
174
|
+
try {
|
|
175
|
+
if (request.method === "initialize") {
|
|
176
|
+
writeResult(request.id ?? null, {
|
|
177
|
+
protocolVersion: "2024-11-05",
|
|
178
|
+
capabilities: { tools: {} },
|
|
179
|
+
serverInfo: { name: "gridx-mcp", version: "0.1.0" },
|
|
180
|
+
});
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (request.method === "tools/list") {
|
|
184
|
+
writeResult(request.id ?? null, { tools });
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (request.method === "tools/call") {
|
|
188
|
+
const result = await handleToolCall(String(request.params?.name ?? ""), request.params?.arguments ?? {});
|
|
189
|
+
writeResult(request.id ?? null, {
|
|
190
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
191
|
+
structuredContent: result,
|
|
192
|
+
});
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
writeError(request.id ?? null, `Unsupported method '${request.method}'.`);
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
writeError(request.id ?? null, error instanceof Error ? error.message : "GridX MCP server failed.");
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const productContext = {
|
|
2
|
+
name: "GridX",
|
|
3
|
+
positioning: "Federated AI compute exchange",
|
|
4
|
+
runtimeBoundary: "Managed AI services only"
|
|
5
|
+
};
|
|
6
|
+
export const platformPrinciples = [
|
|
7
|
+
"Policy before economics",
|
|
8
|
+
"Zero inbound ports",
|
|
9
|
+
"Zero-trust execution envelopes",
|
|
10
|
+
"Session continuity above the provider runtime",
|
|
11
|
+
"Ledger-grade telemetry"
|
|
12
|
+
];
|
|
13
|
+
export const applicationAreas = [
|
|
14
|
+
{
|
|
15
|
+
name: "Marketplace Dashboard",
|
|
16
|
+
summary: "Supply, pricing, utilization, and provider health overview."
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: "Provider Console",
|
|
20
|
+
summary: "Service SKUs, runtime state, trust posture, and revenue visibility."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: "Execution Explorer",
|
|
24
|
+
summary: "Session timelines, checkpoints, failovers, and cost breakdowns."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "Trust and Ops Console",
|
|
28
|
+
summary: "Quarantines, canary failures, tunnel instability, and settlement holds."
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
export * from "./api.js";
|
|
32
|
+
export * from "./domain.js";
|
|
33
|
+
export * from "./events.js";
|
|
34
|
+
export * from "./security.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export class GridxSdkError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
details;
|
|
4
|
+
constructor(message, status, details) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.details = details;
|
|
8
|
+
this.name = "GridxSdkError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class GridxClient {
|
|
12
|
+
baseUrl;
|
|
13
|
+
serviceKey;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
16
|
+
this.serviceKey = options.serviceKey;
|
|
17
|
+
}
|
|
18
|
+
whoAmI() {
|
|
19
|
+
return this.get("/v1/service-accounts/whoami");
|
|
20
|
+
}
|
|
21
|
+
routeBestListing(body) {
|
|
22
|
+
return this.post("/v1/routes/auto-execute", body);
|
|
23
|
+
}
|
|
24
|
+
routeSpecificListing(listingId, body) {
|
|
25
|
+
return this.post("/v1/routes/execute", {
|
|
26
|
+
...body,
|
|
27
|
+
listingId,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
getSession(sessionId) {
|
|
31
|
+
return this.get(`/v1/sessions/${sessionId}`);
|
|
32
|
+
}
|
|
33
|
+
listMarketplaceCandidates(filters) {
|
|
34
|
+
return this.post("/v1/routes/candidates", filters ?? {});
|
|
35
|
+
}
|
|
36
|
+
getBuyerSavingsInsights(sessionId) {
|
|
37
|
+
return this.get(sessionId ? `/v1/buyer/savings-insights/${sessionId}` : "/v1/buyer/savings-insights");
|
|
38
|
+
}
|
|
39
|
+
getPolicyTuningSuggestions() {
|
|
40
|
+
return this.get("/v1/buyer/policy-tuning");
|
|
41
|
+
}
|
|
42
|
+
listCommitments() {
|
|
43
|
+
return this.get("/v1/buyer/commitments");
|
|
44
|
+
}
|
|
45
|
+
listReservations() {
|
|
46
|
+
return this.get("/v1/buyer/reservations");
|
|
47
|
+
}
|
|
48
|
+
getSellerPricingInsights(listingId) {
|
|
49
|
+
return this.get(listingId ? `/v1/seller/pricing-insights/${listingId}` : "/v1/seller/pricing-insights");
|
|
50
|
+
}
|
|
51
|
+
getSellerRepricingGuardrails(listingId) {
|
|
52
|
+
return this.get(listingId
|
|
53
|
+
? `/v1/seller/repricing-guardrails/${listingId}`
|
|
54
|
+
: "/v1/seller/repricing-guardrails");
|
|
55
|
+
}
|
|
56
|
+
getSellerAllocationSummary() {
|
|
57
|
+
return this.get("/v1/seller/allocation-optimization");
|
|
58
|
+
}
|
|
59
|
+
getMarketPricingOverview() {
|
|
60
|
+
return this.get("/v1/market/pricing-overview");
|
|
61
|
+
}
|
|
62
|
+
getSessionLease(leaseId) {
|
|
63
|
+
return this.get(`/v1/session-leases/${leaseId}`);
|
|
64
|
+
}
|
|
65
|
+
revokeSessionLease(leaseId) {
|
|
66
|
+
return this.post(`/v1/session-leases/${leaseId}/revoke`, {});
|
|
67
|
+
}
|
|
68
|
+
executeWithLease(leaseToken, body) {
|
|
69
|
+
return this.request("/v1/execute", {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: {
|
|
72
|
+
"content-type": "application/json",
|
|
73
|
+
authorization: `Bearer ${leaseToken}`,
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify(body),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
listServiceAccounts() {
|
|
79
|
+
return this.get("/v1/service-accounts");
|
|
80
|
+
}
|
|
81
|
+
listWebhookEndpoints() {
|
|
82
|
+
return this.get("/v1/webhooks");
|
|
83
|
+
}
|
|
84
|
+
createWebhookEndpoint(body) {
|
|
85
|
+
return this.post("/v1/webhooks", body);
|
|
86
|
+
}
|
|
87
|
+
get(path, query) {
|
|
88
|
+
return this.request(path + this.toQueryString(query), { method: "GET" });
|
|
89
|
+
}
|
|
90
|
+
post(path, body) {
|
|
91
|
+
return this.request(path, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: {
|
|
94
|
+
"content-type": "application/json",
|
|
95
|
+
},
|
|
96
|
+
body: JSON.stringify(body),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
async request(path, init) {
|
|
100
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
101
|
+
...init,
|
|
102
|
+
headers: {
|
|
103
|
+
authorization: `Bearer ${this.serviceKey}`,
|
|
104
|
+
...(init.headers ?? {}),
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
const text = await response.text();
|
|
108
|
+
const payload = text ? JSON.parse(text) : null;
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
throw new GridxSdkError(payload?.error?.message ?? "GridX request failed.", response.status, payload);
|
|
111
|
+
}
|
|
112
|
+
return payload;
|
|
113
|
+
}
|
|
114
|
+
toQueryString(query) {
|
|
115
|
+
if (!query) {
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
const search = new URLSearchParams();
|
|
119
|
+
for (const [key, value] of Object.entries(query)) {
|
|
120
|
+
if (value === undefined || value === null || value === "") {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
search.set(key, String(value));
|
|
124
|
+
}
|
|
125
|
+
const rendered = search.toString();
|
|
126
|
+
return rendered ? `?${rendered}` : "";
|
|
127
|
+
}
|
|
128
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cloudverse/gridx-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"gridx-mcp": "dist/apps/mcp-server/src/main.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/apps/mcp-server/src/main.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.json",
|
|
19
|
+
"dev": "tsx src/main.ts",
|
|
20
|
+
"lint": "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@gridx/sdk": "workspace:*"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"tsx": "^4.20.5"
|
|
28
|
+
}
|
|
29
|
+
}
|