@gxp-dev/tools 2.0.70 → 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.
@@ -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
+ }
@@ -18,130 +18,12 @@
18
18
  */
19
19
 
20
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(
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: "1.0.0",
253
- description: "GxP API documentation server for AI coding assistants",
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 TOOLS = [
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")