@gxp-dev/tools 2.0.11 → 2.0.13
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/bin/lib/cli.js +42 -0
- package/bin/lib/commands/extract-config.js +186 -0
- package/bin/lib/commands/index.js +2 -0
- package/bin/lib/commands/init.js +446 -180
- package/bin/lib/tui/App.tsx +158 -41
- package/bin/lib/tui/components/CommandInput.tsx +100 -95
- package/bin/lib/tui/components/LogPanel.tsx +30 -17
- package/bin/lib/tui/components/TabBar.tsx +1 -1
- package/bin/lib/utils/ai-scaffold.js +877 -0
- package/bin/lib/utils/extract-config.js +468 -0
- package/bin/lib/utils/files.js +43 -2
- package/bin/lib/utils/index.js +4 -0
- package/bin/lib/utils/prompts.js +352 -0
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +134 -40
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/components/CommandInput.d.ts.map +1 -1
- package/dist/tui/components/CommandInput.js +87 -89
- package/dist/tui/components/CommandInput.js.map +1 -1
- package/dist/tui/components/LogPanel.d.ts +4 -2
- package/dist/tui/components/LogPanel.d.ts.map +1 -1
- package/dist/tui/components/LogPanel.js +25 -15
- package/dist/tui/components/LogPanel.js.map +1 -1
- package/dist/tui/components/TabBar.js +1 -1
- package/dist/tui/components/TabBar.js.map +1 -1
- package/mcp/gxp-api-server.js +524 -0
- package/package.json +4 -2
- package/runtime/stores/gxpPortalConfigStore.js +9 -0
- package/template/.claude/agents/gxp-developer.md +335 -0
- package/template/.claude/settings.json +9 -0
- package/template/AGENTS.md +125 -0
- package/template/GEMINI.md +80 -0
- package/template/app-manifest.json +1 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GxP API Specs MCP Server
|
|
5
|
+
*
|
|
6
|
+
* Provides API documentation (OpenAPI, AsyncAPI, Webhooks) to AI coding assistants
|
|
7
|
+
* via the Model Context Protocol (MCP).
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Fetches specs based on VITE_API_ENV environment variable
|
|
11
|
+
* - Caches specs in memory for performance
|
|
12
|
+
* - Provides tools for fetching full specs or searching endpoints
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* node mcp/gxp-api-server.js
|
|
16
|
+
*
|
|
17
|
+
* Configure in your AI tool's MCP settings to enable API-aware assistance.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const readline = require("readline");
|
|
21
|
+
const fs = require("fs");
|
|
22
|
+
const path = require("path");
|
|
23
|
+
|
|
24
|
+
// Environment URL configuration (matches constants.js)
|
|
25
|
+
const ENVIRONMENT_URLS = {
|
|
26
|
+
production: {
|
|
27
|
+
apiBaseUrl: "https://api.gramercy.cloud",
|
|
28
|
+
openApiSpec: "https://api.gramercy.cloud/api-specs/openapi.json",
|
|
29
|
+
asyncApiSpec: "https://api.gramercy.cloud/api-specs/asyncapi.json",
|
|
30
|
+
webhookSpec: "https://api.gramercy.cloud/api-specs/webhooks.json",
|
|
31
|
+
},
|
|
32
|
+
staging: {
|
|
33
|
+
apiBaseUrl: "https://api.efz-staging.env.eventfinity.app",
|
|
34
|
+
openApiSpec:
|
|
35
|
+
"https://api.efz-staging.env.eventfinity.app/api-specs/openapi.json",
|
|
36
|
+
asyncApiSpec:
|
|
37
|
+
"https://api.efz-staging.env.eventfinity.app/api-specs/asyncapi.json",
|
|
38
|
+
webhookSpec:
|
|
39
|
+
"https://api.efz-staging.env.eventfinity.app/api-specs/webhooks.json",
|
|
40
|
+
},
|
|
41
|
+
testing: {
|
|
42
|
+
apiBaseUrl: "https://api.zenith-develop-testing.env.eventfinity.app",
|
|
43
|
+
openApiSpec:
|
|
44
|
+
"https://api.zenith-develop-testing.env.eventfinity.app/api-specs/openapi.json",
|
|
45
|
+
asyncApiSpec:
|
|
46
|
+
"https://api.zenith-develop-testing.env.eventfinity.app/api-specs/asyncapi.json",
|
|
47
|
+
webhookSpec:
|
|
48
|
+
"https://api.zenith-develop-testing.env.eventfinity.app/api-specs/webhooks.json",
|
|
49
|
+
},
|
|
50
|
+
develop: {
|
|
51
|
+
apiBaseUrl: "https://api.zenith-develop.env.eventfinity.app",
|
|
52
|
+
openApiSpec:
|
|
53
|
+
"https://api.zenith-develop.env.eventfinity.app/api-specs/openapi.json",
|
|
54
|
+
asyncApiSpec:
|
|
55
|
+
"https://api.zenith-develop.env.eventfinity.app/api-specs/asyncapi.json",
|
|
56
|
+
webhookSpec:
|
|
57
|
+
"https://api.zenith-develop.env.eventfinity.app/api-specs/webhooks.json",
|
|
58
|
+
},
|
|
59
|
+
local: {
|
|
60
|
+
apiBaseUrl: "https://dashboard.eventfinity.test",
|
|
61
|
+
openApiSpec: "https://api.eventfinity.test/api-specs/openapi.json",
|
|
62
|
+
asyncApiSpec: "https://api.eventfinity.test/api-specs/asyncapi.json",
|
|
63
|
+
webhookSpec: "https://api.eventfinity.test/api-specs/webhooks.json",
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Cache for fetched specs
|
|
68
|
+
const specCache = {
|
|
69
|
+
openapi: null,
|
|
70
|
+
asyncapi: null,
|
|
71
|
+
webhooks: null,
|
|
72
|
+
lastFetch: null,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get current environment from .env file or default
|
|
79
|
+
*/
|
|
80
|
+
function getEnvironment() {
|
|
81
|
+
// Try to read from .env file in current directory
|
|
82
|
+
const envPath = path.join(process.cwd(), ".env");
|
|
83
|
+
if (fs.existsSync(envPath)) {
|
|
84
|
+
const envContent = fs.readFileSync(envPath, "utf-8");
|
|
85
|
+
const match = envContent.match(/VITE_API_ENV=(\w+)/);
|
|
86
|
+
if (match) {
|
|
87
|
+
return match[1];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Fall back to environment variable or default
|
|
92
|
+
return process.env.VITE_API_ENV || process.env.API_ENV || "develop";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get URLs for current environment
|
|
97
|
+
*/
|
|
98
|
+
function getEnvUrls() {
|
|
99
|
+
const env = getEnvironment();
|
|
100
|
+
return ENVIRONMENT_URLS[env] || ENVIRONMENT_URLS.develop;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Fetch a spec with caching
|
|
105
|
+
*/
|
|
106
|
+
async function fetchSpec(specType) {
|
|
107
|
+
const urls = getEnvUrls();
|
|
108
|
+
const urlMap = {
|
|
109
|
+
openapi: urls.openApiSpec,
|
|
110
|
+
asyncapi: urls.asyncApiSpec,
|
|
111
|
+
webhooks: urls.webhookSpec,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const url = urlMap[specType];
|
|
115
|
+
if (!url) {
|
|
116
|
+
throw new Error(`Unknown spec type: ${specType}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Check cache
|
|
120
|
+
const now = Date.now();
|
|
121
|
+
if (
|
|
122
|
+
specCache[specType] &&
|
|
123
|
+
specCache.lastFetch &&
|
|
124
|
+
now - specCache.lastFetch < CACHE_TTL
|
|
125
|
+
) {
|
|
126
|
+
return specCache[specType];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Fetch fresh
|
|
130
|
+
try {
|
|
131
|
+
const response = await fetch(url);
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
134
|
+
}
|
|
135
|
+
const data = await response.json();
|
|
136
|
+
specCache[specType] = data;
|
|
137
|
+
specCache.lastFetch = now;
|
|
138
|
+
return data;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
throw new Error(`Failed to fetch ${specType} spec from ${url}: ${error.message}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Search OpenAPI spec for endpoints matching a query
|
|
146
|
+
*/
|
|
147
|
+
function searchEndpoints(spec, query) {
|
|
148
|
+
const results = [];
|
|
149
|
+
const queryLower = query.toLowerCase();
|
|
150
|
+
|
|
151
|
+
if (spec.paths) {
|
|
152
|
+
for (const [path, methods] of Object.entries(spec.paths)) {
|
|
153
|
+
for (const [method, details] of Object.entries(methods)) {
|
|
154
|
+
if (
|
|
155
|
+
typeof details === "object" &&
|
|
156
|
+
(path.toLowerCase().includes(queryLower) ||
|
|
157
|
+
details.summary?.toLowerCase().includes(queryLower) ||
|
|
158
|
+
details.description?.toLowerCase().includes(queryLower) ||
|
|
159
|
+
details.operationId?.toLowerCase().includes(queryLower) ||
|
|
160
|
+
details.tags?.some((t) => t.toLowerCase().includes(queryLower)))
|
|
161
|
+
) {
|
|
162
|
+
results.push({
|
|
163
|
+
path,
|
|
164
|
+
method: method.toUpperCase(),
|
|
165
|
+
summary: details.summary || "",
|
|
166
|
+
description: details.description || "",
|
|
167
|
+
operationId: details.operationId || "",
|
|
168
|
+
tags: details.tags || [],
|
|
169
|
+
parameters: details.parameters || [],
|
|
170
|
+
requestBody: details.requestBody || null,
|
|
171
|
+
responses: Object.keys(details.responses || {}),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return results;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Search AsyncAPI spec for channels/events matching a query
|
|
183
|
+
*/
|
|
184
|
+
function searchEvents(spec, query) {
|
|
185
|
+
const results = [];
|
|
186
|
+
const queryLower = query.toLowerCase();
|
|
187
|
+
|
|
188
|
+
if (spec.channels) {
|
|
189
|
+
for (const [channel, details] of Object.entries(spec.channels)) {
|
|
190
|
+
if (
|
|
191
|
+
channel.toLowerCase().includes(queryLower) ||
|
|
192
|
+
details.description?.toLowerCase().includes(queryLower)
|
|
193
|
+
) {
|
|
194
|
+
const operations = [];
|
|
195
|
+
if (details.publish) {
|
|
196
|
+
operations.push({
|
|
197
|
+
type: "publish",
|
|
198
|
+
summary: details.publish.summary || "",
|
|
199
|
+
message: details.publish.message || null,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
if (details.subscribe) {
|
|
203
|
+
operations.push({
|
|
204
|
+
type: "subscribe",
|
|
205
|
+
summary: details.subscribe.summary || "",
|
|
206
|
+
message: details.subscribe.message || null,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
results.push({
|
|
211
|
+
channel,
|
|
212
|
+
description: details.description || "",
|
|
213
|
+
operations,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return results;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Get endpoint details by path and method
|
|
224
|
+
*/
|
|
225
|
+
function getEndpointDetails(spec, path, method) {
|
|
226
|
+
const methodLower = method.toLowerCase();
|
|
227
|
+
const endpoint = spec.paths?.[path]?.[methodLower];
|
|
228
|
+
|
|
229
|
+
if (!endpoint) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
path,
|
|
235
|
+
method: method.toUpperCase(),
|
|
236
|
+
summary: endpoint.summary || "",
|
|
237
|
+
description: endpoint.description || "",
|
|
238
|
+
operationId: endpoint.operationId || "",
|
|
239
|
+
tags: endpoint.tags || [],
|
|
240
|
+
parameters: endpoint.parameters || [],
|
|
241
|
+
requestBody: endpoint.requestBody || null,
|
|
242
|
+
responses: endpoint.responses || {},
|
|
243
|
+
security: endpoint.security || spec.security || [],
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// MCP Server Implementation
|
|
248
|
+
const SERVER_INFO = {
|
|
249
|
+
name: "gxp-api-server",
|
|
250
|
+
version: "1.0.0",
|
|
251
|
+
description: "GxP API documentation server for AI coding assistants",
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const TOOLS = [
|
|
255
|
+
{
|
|
256
|
+
name: "get_openapi_spec",
|
|
257
|
+
description:
|
|
258
|
+
"Fetch the full OpenAPI specification for the GxP API. Returns the complete spec including all endpoints, schemas, and documentation.",
|
|
259
|
+
inputSchema: {
|
|
260
|
+
type: "object",
|
|
261
|
+
properties: {},
|
|
262
|
+
required: [],
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "get_asyncapi_spec",
|
|
267
|
+
description:
|
|
268
|
+
"Fetch the AsyncAPI specification for GxP WebSocket events. Returns channel definitions, message schemas, and event documentation.",
|
|
269
|
+
inputSchema: {
|
|
270
|
+
type: "object",
|
|
271
|
+
properties: {},
|
|
272
|
+
required: [],
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: "search_api_endpoints",
|
|
277
|
+
description:
|
|
278
|
+
"Search for API endpoints matching a query. Searches path, summary, description, operation ID, and tags.",
|
|
279
|
+
inputSchema: {
|
|
280
|
+
type: "object",
|
|
281
|
+
properties: {
|
|
282
|
+
query: {
|
|
283
|
+
type: "string",
|
|
284
|
+
description:
|
|
285
|
+
"Search term to find matching endpoints (e.g., 'attendee', 'check-in', 'event')",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
required: ["query"],
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: "search_websocket_events",
|
|
293
|
+
description:
|
|
294
|
+
"Search for WebSocket channels/events matching a query. Searches channel names and descriptions.",
|
|
295
|
+
inputSchema: {
|
|
296
|
+
type: "object",
|
|
297
|
+
properties: {
|
|
298
|
+
query: {
|
|
299
|
+
type: "string",
|
|
300
|
+
description:
|
|
301
|
+
"Search term to find matching events (e.g., 'message', 'created', 'updated')",
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
required: ["query"],
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
name: "get_endpoint_details",
|
|
309
|
+
description:
|
|
310
|
+
"Get detailed information about a specific API endpoint including parameters, request body, and responses.",
|
|
311
|
+
inputSchema: {
|
|
312
|
+
type: "object",
|
|
313
|
+
properties: {
|
|
314
|
+
path: {
|
|
315
|
+
type: "string",
|
|
316
|
+
description: "API endpoint path (e.g., '/api/v1/attendees')",
|
|
317
|
+
},
|
|
318
|
+
method: {
|
|
319
|
+
type: "string",
|
|
320
|
+
description: "HTTP method (GET, POST, PUT, PATCH, DELETE)",
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
required: ["path", "method"],
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
name: "get_api_environment",
|
|
328
|
+
description:
|
|
329
|
+
"Get the current API environment configuration including base URL and spec URLs.",
|
|
330
|
+
inputSchema: {
|
|
331
|
+
type: "object",
|
|
332
|
+
properties: {},
|
|
333
|
+
required: [],
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
];
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Handle MCP tool calls
|
|
340
|
+
*/
|
|
341
|
+
async function handleToolCall(name, args) {
|
|
342
|
+
switch (name) {
|
|
343
|
+
case "get_openapi_spec": {
|
|
344
|
+
const spec = await fetchSpec("openapi");
|
|
345
|
+
return {
|
|
346
|
+
content: [
|
|
347
|
+
{
|
|
348
|
+
type: "text",
|
|
349
|
+
text: JSON.stringify(spec, null, 2),
|
|
350
|
+
},
|
|
351
|
+
],
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
case "get_asyncapi_spec": {
|
|
356
|
+
const spec = await fetchSpec("asyncapi");
|
|
357
|
+
return {
|
|
358
|
+
content: [
|
|
359
|
+
{
|
|
360
|
+
type: "text",
|
|
361
|
+
text: JSON.stringify(spec, null, 2),
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
case "search_api_endpoints": {
|
|
368
|
+
const spec = await fetchSpec("openapi");
|
|
369
|
+
const results = searchEndpoints(spec, args.query);
|
|
370
|
+
return {
|
|
371
|
+
content: [
|
|
372
|
+
{
|
|
373
|
+
type: "text",
|
|
374
|
+
text:
|
|
375
|
+
results.length > 0
|
|
376
|
+
? JSON.stringify(results, null, 2)
|
|
377
|
+
: `No endpoints found matching "${args.query}"`,
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
case "search_websocket_events": {
|
|
384
|
+
const spec = await fetchSpec("asyncapi");
|
|
385
|
+
const results = searchEvents(spec, args.query);
|
|
386
|
+
return {
|
|
387
|
+
content: [
|
|
388
|
+
{
|
|
389
|
+
type: "text",
|
|
390
|
+
text:
|
|
391
|
+
results.length > 0
|
|
392
|
+
? JSON.stringify(results, null, 2)
|
|
393
|
+
: `No events found matching "${args.query}"`,
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
case "get_endpoint_details": {
|
|
400
|
+
const spec = await fetchSpec("openapi");
|
|
401
|
+
const details = getEndpointDetails(spec, args.path, args.method);
|
|
402
|
+
return {
|
|
403
|
+
content: [
|
|
404
|
+
{
|
|
405
|
+
type: "text",
|
|
406
|
+
text: details
|
|
407
|
+
? JSON.stringify(details, null, 2)
|
|
408
|
+
: `Endpoint not found: ${args.method} ${args.path}`,
|
|
409
|
+
},
|
|
410
|
+
],
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
case "get_api_environment": {
|
|
415
|
+
const env = getEnvironment();
|
|
416
|
+
const urls = getEnvUrls();
|
|
417
|
+
return {
|
|
418
|
+
content: [
|
|
419
|
+
{
|
|
420
|
+
type: "text",
|
|
421
|
+
text: JSON.stringify(
|
|
422
|
+
{
|
|
423
|
+
environment: env,
|
|
424
|
+
...urls,
|
|
425
|
+
},
|
|
426
|
+
null,
|
|
427
|
+
2
|
|
428
|
+
),
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
default:
|
|
435
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Process MCP JSON-RPC request
|
|
441
|
+
*/
|
|
442
|
+
async function processRequest(request) {
|
|
443
|
+
const { method, params, id } = request;
|
|
444
|
+
|
|
445
|
+
try {
|
|
446
|
+
let result;
|
|
447
|
+
|
|
448
|
+
switch (method) {
|
|
449
|
+
case "initialize":
|
|
450
|
+
result = {
|
|
451
|
+
protocolVersion: "2024-11-05",
|
|
452
|
+
capabilities: {
|
|
453
|
+
tools: {},
|
|
454
|
+
},
|
|
455
|
+
serverInfo: SERVER_INFO,
|
|
456
|
+
};
|
|
457
|
+
break;
|
|
458
|
+
|
|
459
|
+
case "tools/list":
|
|
460
|
+
result = { tools: TOOLS };
|
|
461
|
+
break;
|
|
462
|
+
|
|
463
|
+
case "tools/call":
|
|
464
|
+
result = await handleToolCall(params.name, params.arguments || {});
|
|
465
|
+
break;
|
|
466
|
+
|
|
467
|
+
case "notifications/initialized":
|
|
468
|
+
// No response needed for notifications
|
|
469
|
+
return null;
|
|
470
|
+
|
|
471
|
+
default:
|
|
472
|
+
throw new Error(`Unknown method: ${method}`);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return { jsonrpc: "2.0", id, result };
|
|
476
|
+
} catch (error) {
|
|
477
|
+
return {
|
|
478
|
+
jsonrpc: "2.0",
|
|
479
|
+
id,
|
|
480
|
+
error: {
|
|
481
|
+
code: -32603,
|
|
482
|
+
message: error.message,
|
|
483
|
+
},
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Main server loop
|
|
490
|
+
*/
|
|
491
|
+
async function main() {
|
|
492
|
+
const rl = readline.createInterface({
|
|
493
|
+
input: process.stdin,
|
|
494
|
+
output: process.stdout,
|
|
495
|
+
terminal: false,
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
for await (const line of rl) {
|
|
499
|
+
if (!line.trim()) continue;
|
|
500
|
+
|
|
501
|
+
try {
|
|
502
|
+
const request = JSON.parse(line);
|
|
503
|
+
const response = await processRequest(request);
|
|
504
|
+
|
|
505
|
+
if (response) {
|
|
506
|
+
console.log(JSON.stringify(response));
|
|
507
|
+
}
|
|
508
|
+
} catch (error) {
|
|
509
|
+
console.log(
|
|
510
|
+
JSON.stringify({
|
|
511
|
+
jsonrpc: "2.0",
|
|
512
|
+
id: null,
|
|
513
|
+
error: {
|
|
514
|
+
code: -32700,
|
|
515
|
+
message: `Parse error: ${error.message}`,
|
|
516
|
+
},
|
|
517
|
+
})
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Run server
|
|
524
|
+
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gxp-dev/tools",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.13",
|
|
4
4
|
"description": "Dev tools to create platform plugins",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"publishConfig": {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"bin",
|
|
11
11
|
"dist/tui",
|
|
12
|
+
"mcp",
|
|
12
13
|
"README.md",
|
|
13
14
|
"runtime",
|
|
14
15
|
"template",
|
|
@@ -34,7 +35,8 @@
|
|
|
34
35
|
"url": "git+ssh://git@github.com/GramercyTech/gx-devtools.git"
|
|
35
36
|
},
|
|
36
37
|
"bin": {
|
|
37
|
-
"gxdev": "bin/gx-devtools.js"
|
|
38
|
+
"gxdev": "bin/gx-devtools.js",
|
|
39
|
+
"gxp-api-server": "mcp/gxp-api-server.js"
|
|
38
40
|
},
|
|
39
41
|
"keywords": [
|
|
40
42
|
"tunnel",
|
|
@@ -375,6 +375,14 @@ export const useGxpStore = defineStore("gxp-portal-app", () => {
|
|
|
375
375
|
throw new Error(`DELETE ${endpoint}: ${error.message}`);
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
|
+
async function callApi(endpoint, method, data = {}) {
|
|
379
|
+
try {
|
|
380
|
+
const response = await apiClient[method](endpoint, data);
|
|
381
|
+
return response.data;
|
|
382
|
+
} catch (error) {
|
|
383
|
+
throw new Error(`${method} ${endpoint}: ${error.message}`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
378
386
|
|
|
379
387
|
// Utility methods
|
|
380
388
|
function getString(key, fallback = "") {
|
|
@@ -523,6 +531,7 @@ export const useGxpStore = defineStore("gxp-portal-app", () => {
|
|
|
523
531
|
apiPatch,
|
|
524
532
|
apiPut,
|
|
525
533
|
apiDelete,
|
|
534
|
+
callApi,
|
|
526
535
|
|
|
527
536
|
// Utility methods
|
|
528
537
|
getString,
|