@gxp-dev/tools 2.0.71 → 2.0.72
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 +108 -81
- package/bin/lib/cli.js +18 -0
- package/bin/lib/commands/index.js +2 -0
- package/bin/lib/commands/init.js +23 -0
- package/bin/lib/commands/lint.js +77 -0
- package/bin/lib/constants.js +12 -0
- package/bin/lib/lint/formatter.js +91 -0
- package/bin/lib/lint/index.js +284 -0
- package/bin/lib/lint/schemas/app-manifest.schema.json +124 -0
- package/bin/lib/lint/schemas/card.schema.json +165 -0
- package/bin/lib/lint/schemas/common.schema.json +62 -0
- package/bin/lib/lint/schemas/configuration.schema.json +19 -0
- package/bin/lib/lint/schemas/field.schema.json +230 -0
- package/mcp/gxp-api-server.js +56 -127
- package/mcp/lib/api-tools.js +456 -0
- package/mcp/lib/config-ops.js +234 -0
- package/mcp/lib/config-tools.js +549 -0
- package/mcp/lib/docs-tools.js +142 -0
- package/mcp/lib/docs.js +263 -0
- package/mcp/lib/specs.js +135 -0
- package/mcp/lib/test-tools.js +358 -0
- package/package.json +3 -1
- package/runtime/vite.config.js +5 -3
- package/template/.prettierrc +10 -0
- package/template/README.md +205 -240
- package/template/app-instructions.md +91 -0
- package/template/eslint.config.js +32 -0
- package/template/githooks/pre-commit +37 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "https://gxp.dev/schemas/field.schema.json",
|
|
3
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
"title": "GxP Form Field",
|
|
5
|
+
"description": "A single form field descriptor used inside a fields_list card.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["type"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"type": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"enum": [
|
|
12
|
+
"hidden",
|
|
13
|
+
"html",
|
|
14
|
+
"live-html",
|
|
15
|
+
"heading",
|
|
16
|
+
"heading-large",
|
|
17
|
+
"small-heading",
|
|
18
|
+
"description",
|
|
19
|
+
"image",
|
|
20
|
+
"video",
|
|
21
|
+
"icon",
|
|
22
|
+
"icon-selector",
|
|
23
|
+
"clipboard",
|
|
24
|
+
"timestamp",
|
|
25
|
+
"button",
|
|
26
|
+
"external_link",
|
|
27
|
+
"text",
|
|
28
|
+
"number",
|
|
29
|
+
"email",
|
|
30
|
+
"password",
|
|
31
|
+
"phone_number",
|
|
32
|
+
"textarea",
|
|
33
|
+
"select",
|
|
34
|
+
"pill_select",
|
|
35
|
+
"multi_select",
|
|
36
|
+
"autocomplete",
|
|
37
|
+
"asyncSelect",
|
|
38
|
+
"radio",
|
|
39
|
+
"checkbox",
|
|
40
|
+
"boolean",
|
|
41
|
+
"boolean_icon",
|
|
42
|
+
"file",
|
|
43
|
+
"selectAsset",
|
|
44
|
+
"selectPagePlugin",
|
|
45
|
+
"selectProjectPlan",
|
|
46
|
+
"keyValuePair",
|
|
47
|
+
"codeEditor",
|
|
48
|
+
"htmlEditor",
|
|
49
|
+
"render_markdown",
|
|
50
|
+
"colorPicker",
|
|
51
|
+
"tag_list",
|
|
52
|
+
"savedSearchBuilder",
|
|
53
|
+
"date",
|
|
54
|
+
"datetime",
|
|
55
|
+
"time",
|
|
56
|
+
"timezone_picker",
|
|
57
|
+
"data_table",
|
|
58
|
+
"integration_connector",
|
|
59
|
+
"form-builder",
|
|
60
|
+
"object-builder"
|
|
61
|
+
],
|
|
62
|
+
"description": "Field type. Determines which extra properties are required."
|
|
63
|
+
},
|
|
64
|
+
"name": { "type": ["string", "null"] },
|
|
65
|
+
"label": { "type": ["string", "null"] },
|
|
66
|
+
"default": {
|
|
67
|
+
"type": ["string", "number", "boolean", "array", "object", "null"]
|
|
68
|
+
},
|
|
69
|
+
"placeholder": { "type": ["string", "null"] },
|
|
70
|
+
"disabled": { "type": "boolean" },
|
|
71
|
+
"readonly": { "type": "boolean" },
|
|
72
|
+
"required": { "type": "boolean" },
|
|
73
|
+
"multiple": { "type": "boolean" },
|
|
74
|
+
"classList": {
|
|
75
|
+
"type": "array",
|
|
76
|
+
"items": { "type": "string" }
|
|
77
|
+
},
|
|
78
|
+
"columnClass": { "type": ["string", "null"] },
|
|
79
|
+
"cols": {
|
|
80
|
+
"$ref": "common.schema.json#/$defs/gridCols"
|
|
81
|
+
},
|
|
82
|
+
"colsSm": { "$ref": "common.schema.json#/$defs/gridCols" },
|
|
83
|
+
"colsMd": { "$ref": "common.schema.json#/$defs/gridCols" },
|
|
84
|
+
"colsLg": { "$ref": "common.schema.json#/$defs/gridCols" },
|
|
85
|
+
"condition": { "type": ["string", "null"] },
|
|
86
|
+
"conditionParams": {
|
|
87
|
+
"$ref": "common.schema.json#/$defs/conditionParams"
|
|
88
|
+
},
|
|
89
|
+
"content": { "type": ["string", "null"] },
|
|
90
|
+
"text": { "type": ["string", "null"] },
|
|
91
|
+
"href": { "type": ["string", "null"] },
|
|
92
|
+
"icon": { "type": ["string", "null"] },
|
|
93
|
+
"options": {
|
|
94
|
+
"$ref": "common.schema.json#/$defs/options"
|
|
95
|
+
},
|
|
96
|
+
"accept": {
|
|
97
|
+
"type": "array",
|
|
98
|
+
"items": { "type": "string" }
|
|
99
|
+
},
|
|
100
|
+
"format": { "type": ["string", "null"] },
|
|
101
|
+
"prepend": { "type": ["string", "null"] },
|
|
102
|
+
"append": { "type": ["string", "null"] },
|
|
103
|
+
"method": {
|
|
104
|
+
"type": ["string", "null"],
|
|
105
|
+
"enum": ["GET", "POST", "PUT", "PATCH", "DELETE", null]
|
|
106
|
+
},
|
|
107
|
+
"query_parameter": { "type": ["string", "null"] },
|
|
108
|
+
"refresh": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"properties": {
|
|
111
|
+
"only": { "type": "string" },
|
|
112
|
+
"key": { "type": "string" }
|
|
113
|
+
},
|
|
114
|
+
"additionalProperties": true
|
|
115
|
+
},
|
|
116
|
+
"validation_rules": {
|
|
117
|
+
"type": "array",
|
|
118
|
+
"items": { "type": "string" }
|
|
119
|
+
},
|
|
120
|
+
"custom_settings": { "type": "object" }
|
|
121
|
+
},
|
|
122
|
+
"allOf": [
|
|
123
|
+
{
|
|
124
|
+
"if": {
|
|
125
|
+
"properties": {
|
|
126
|
+
"type": {
|
|
127
|
+
"enum": [
|
|
128
|
+
"select",
|
|
129
|
+
"pill_select",
|
|
130
|
+
"multi_select",
|
|
131
|
+
"radio",
|
|
132
|
+
"checkbox"
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"required": ["type"]
|
|
137
|
+
},
|
|
138
|
+
"then": {
|
|
139
|
+
"required": ["options"],
|
|
140
|
+
"properties": {
|
|
141
|
+
"options": {
|
|
142
|
+
"$ref": "common.schema.json#/$defs/options",
|
|
143
|
+
"minItems": 1
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"if": {
|
|
150
|
+
"properties": {
|
|
151
|
+
"type": {
|
|
152
|
+
"enum": [
|
|
153
|
+
"text",
|
|
154
|
+
"number",
|
|
155
|
+
"email",
|
|
156
|
+
"password",
|
|
157
|
+
"phone_number",
|
|
158
|
+
"textarea",
|
|
159
|
+
"select",
|
|
160
|
+
"pill_select",
|
|
161
|
+
"multi_select",
|
|
162
|
+
"autocomplete",
|
|
163
|
+
"asyncSelect",
|
|
164
|
+
"radio",
|
|
165
|
+
"checkbox",
|
|
166
|
+
"boolean",
|
|
167
|
+
"boolean_icon",
|
|
168
|
+
"file",
|
|
169
|
+
"selectAsset",
|
|
170
|
+
"keyValuePair",
|
|
171
|
+
"codeEditor",
|
|
172
|
+
"htmlEditor",
|
|
173
|
+
"colorPicker",
|
|
174
|
+
"tag_list",
|
|
175
|
+
"date",
|
|
176
|
+
"datetime",
|
|
177
|
+
"time",
|
|
178
|
+
"timezone_picker"
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"required": ["type"]
|
|
183
|
+
},
|
|
184
|
+
"then": {
|
|
185
|
+
"required": ["name"],
|
|
186
|
+
"properties": {
|
|
187
|
+
"name": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"minLength": 1
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"if": {
|
|
196
|
+
"properties": { "type": { "const": "asyncSelect" } },
|
|
197
|
+
"required": ["type"]
|
|
198
|
+
},
|
|
199
|
+
"then": {
|
|
200
|
+
"required": ["href", "method"]
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"if": {
|
|
205
|
+
"properties": { "type": { "const": "external_link" } },
|
|
206
|
+
"required": ["type"]
|
|
207
|
+
},
|
|
208
|
+
"then": {
|
|
209
|
+
"required": ["href"]
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"if": {
|
|
214
|
+
"properties": { "type": { "const": "colorPicker" } },
|
|
215
|
+
"required": ["type"]
|
|
216
|
+
},
|
|
217
|
+
"then": {
|
|
218
|
+
"properties": {
|
|
219
|
+
"default": {
|
|
220
|
+
"oneOf": [
|
|
221
|
+
{ "$ref": "common.schema.json#/$defs/colorHex" },
|
|
222
|
+
{ "type": "null" }
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
],
|
|
229
|
+
"additionalProperties": true
|
|
230
|
+
}
|
package/mcp/gxp-api-server.js
CHANGED
|
@@ -18,130 +18,12 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
const readline = require("readline")
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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(
|
|
141
|
-
`Failed to fetch ${specType} spec from ${url}: ${error.message}`,
|
|
142
|
-
)
|
|
143
|
-
}
|
|
144
|
-
}
|
|
21
|
+
const {
|
|
22
|
+
ENVIRONMENT_URLS,
|
|
23
|
+
getEnvironment,
|
|
24
|
+
getEnvUrls,
|
|
25
|
+
fetchSpec,
|
|
26
|
+
} = require("./lib/specs")
|
|
145
27
|
|
|
146
28
|
/**
|
|
147
29
|
* Search OpenAPI spec for endpoints matching a query
|
|
@@ -247,13 +129,38 @@ function getEndpointDetails(spec, path, method) {
|
|
|
247
129
|
}
|
|
248
130
|
|
|
249
131
|
// MCP Server Implementation
|
|
132
|
+
const {
|
|
133
|
+
CONFIG_TOOLS,
|
|
134
|
+
handleConfigToolCall,
|
|
135
|
+
isConfigTool,
|
|
136
|
+
} = require("./lib/config-tools")
|
|
137
|
+
|
|
138
|
+
const {
|
|
139
|
+
EXT_API_TOOLS,
|
|
140
|
+
handleExtApiToolCall,
|
|
141
|
+
isExtApiTool,
|
|
142
|
+
} = require("./lib/api-tools")
|
|
143
|
+
|
|
144
|
+
const {
|
|
145
|
+
DOCS_TOOLS,
|
|
146
|
+
handleDocsToolCall,
|
|
147
|
+
isDocsTool,
|
|
148
|
+
} = require("./lib/docs-tools")
|
|
149
|
+
|
|
150
|
+
const {
|
|
151
|
+
TEST_TOOLS,
|
|
152
|
+
handleTestToolCall,
|
|
153
|
+
isTestTool,
|
|
154
|
+
} = require("./lib/test-tools")
|
|
155
|
+
|
|
250
156
|
const SERVER_INFO = {
|
|
251
157
|
name: "gxp-api-server",
|
|
252
|
-
version: "
|
|
253
|
-
description:
|
|
158
|
+
version: "2.0.0",
|
|
159
|
+
description:
|
|
160
|
+
"GxP toolkit MCP server: API specs, config/manifest editing, documentation search, and plugin test helpers for AI coding assistants.",
|
|
254
161
|
}
|
|
255
162
|
|
|
256
|
-
const
|
|
163
|
+
const API_TOOLS = [
|
|
257
164
|
{
|
|
258
165
|
name: "get_openapi_spec",
|
|
259
166
|
description:
|
|
@@ -337,10 +244,32 @@ const TOOLS = [
|
|
|
337
244
|
},
|
|
338
245
|
]
|
|
339
246
|
|
|
247
|
+
// Final tool set surfaced to MCP clients: API spec tools + extended API tools
|
|
248
|
+
// + config-editor tools + doc-search tools + test tools.
|
|
249
|
+
const TOOLS = [
|
|
250
|
+
...API_TOOLS,
|
|
251
|
+
...EXT_API_TOOLS,
|
|
252
|
+
...CONFIG_TOOLS,
|
|
253
|
+
...DOCS_TOOLS,
|
|
254
|
+
...TEST_TOOLS,
|
|
255
|
+
]
|
|
256
|
+
|
|
340
257
|
/**
|
|
341
258
|
* Handle MCP tool calls
|
|
342
259
|
*/
|
|
343
260
|
async function handleToolCall(name, args) {
|
|
261
|
+
if (isConfigTool(name)) {
|
|
262
|
+
return handleConfigToolCall(name, args)
|
|
263
|
+
}
|
|
264
|
+
if (isExtApiTool(name)) {
|
|
265
|
+
return handleExtApiToolCall(name, args)
|
|
266
|
+
}
|
|
267
|
+
if (isDocsTool(name)) {
|
|
268
|
+
return handleDocsToolCall(name, args)
|
|
269
|
+
}
|
|
270
|
+
if (isTestTool(name)) {
|
|
271
|
+
return handleTestToolCall(name, args)
|
|
272
|
+
}
|
|
344
273
|
switch (name) {
|
|
345
274
|
case "get_openapi_spec": {
|
|
346
275
|
const spec = await fetchSpec("openapi")
|