@enfyra/mcp-server 0.0.60 → 0.0.61
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/package.json
CHANGED
package/src/lib/mcp-examples.js
CHANGED
|
@@ -497,11 +497,11 @@ return @DATA\`
|
|
|
497
497
|
tableName: "route_definition",
|
|
498
498
|
id: "<route_id>",
|
|
499
499
|
data: {
|
|
500
|
-
publishedMethods: [{ id:
|
|
500
|
+
publishedMethods: [{ id: "<GET_method_id_from_list_methods>" }]
|
|
501
501
|
}
|
|
502
502
|
})`,
|
|
503
503
|
notes: [
|
|
504
|
-
'Method
|
|
504
|
+
'Method ids are instance data. Use list_methods or inspect_route output to resolve the GET method id first.',
|
|
505
505
|
'publishedMethods controls anonymous route access. Route permissions are not for public access.',
|
|
506
506
|
'Route permissions apply when the method is not public.',
|
|
507
507
|
],
|
|
@@ -802,6 +802,7 @@ update_method({
|
|
|
802
802
|
})`,
|
|
803
803
|
notes: [
|
|
804
804
|
'Use dedicated method tools instead of generic CRUD on method_definition.',
|
|
805
|
+
'The backend stores the method label in method_definition.name; do not send or filter a method_definition.method field.',
|
|
805
806
|
'buttonColor is the badge background and textColor is the badge text color.',
|
|
806
807
|
'The eApp management UI is /settings/methods.',
|
|
807
808
|
'delete_method is preview-first and should only be used for unused custom methods.',
|
|
@@ -114,9 +114,10 @@ export function buildMcpServerInstructions(apiBaseUrl) {
|
|
|
114
114
|
'- **mainTable warning:** do not set `mainTable` on custom routes. It is reserved for canonical table routes only.',
|
|
115
115
|
' - **Many-to-one:** `"someRelation": {"id": 4}` (single object with id)',
|
|
116
116
|
' - **One-to-many / many-to-many:** `"publishedMethods": [{"id": 1}, {"id": 2}]` (array of objects with id)',
|
|
117
|
-
'- **Method IDs**
|
|
117
|
+
'- **Method IDs** are instance data, not a stable contract. Query `method_definition` or use method names through MCP route helpers before setting `publishedMethods`, `availableMethods`, `skipRoleGuardMethods`, hook methods, handler methods, or route permissions. Default CRUD records are `GET`, `POST`, `PATCH`, and `DELETE`; create extra records such as `PUT` through method tools when a route needs them.',
|
|
118
|
+
'- `method_definition.name` is the unique backend field for the HTTP method label. Do not filter, create, or update a `method_definition.method` field. MCP method tools accept an input named `method` for usability, but they write/read `name` on the server.',
|
|
118
119
|
'- **Wrong:** `"publishedMethods": ["GET"]` or `"publishedMethods": [{"method": "GET"}]` — rejected or silently ignored.',
|
|
119
|
-
'- **Right:**
|
|
120
|
+
'- **Right:** first query method records, then pass their ids, for example `"publishedMethods": [{"id": <GET_METHOD_ID>}]`. Multiple methods use multiple id objects.',
|
|
120
121
|
'- **To unset:** pass empty array `"publishedMethods": []`.',
|
|
121
122
|
'',
|
|
122
123
|
'### Dynamic script `$repos` mutation return shape',
|
|
@@ -298,6 +299,7 @@ export function buildMcpServerInstructions(apiBaseUrl) {
|
|
|
298
299
|
'- **Operational list data loading:** do not use arbitrary fixed limits such as `limit=50` as the whole data strategy for admin pages. Use pagination, expose result count when the API supports `meta=filterCount`, and add search/filter controls for natural lookup keys such as id, name, slug, status, email, or external reference.',
|
|
299
300
|
'- **ESV aggregate contract:** aggregate query must be an object keyed by a real field or relation, for example `aggregate: { id: { count: true }, status: { count: { _eq: "failed" } }, amount: { sum: true } }`. Results are returned in `response.meta.aggregate`. Time windows and cross-field conditions belong in top-level `filter`, not inside a field aggregate condition. Field aggregate conditions only support operators on that same field; relation aggregates use `countRecords`.',
|
|
300
301
|
'- **Aggregate numeric rule:** `sum` and `avg` require a numeric field in ESV. Do not aggregate money stored as varchar/text. Use a numeric money field such as `amount_usd` with type `float`, `amount_cents`, or `amount` for revenue stats, or build a dedicated stats route that normalizes legacy values explicitly. If metadata says `float` but SQL aggregate still fails with `sum(character varying)`, the Enfyra Server physical schema is stale or missing the SQL float DDL mapping and must be redeployed/healed before relying on aggregate.',
|
|
302
|
+
'- **Snapshot migrations:** backend metadata/physical schema renames belong in `data/snapshot-migration.json` via table-driven `columnsToModify` entries. The server migration/self-heal path should read table name plus `oldName`/`newName` dynamically; do not hard-code one-off table repairs when the snapshot migration contract can express the change.',
|
|
301
303
|
'- **Partial reload default:** ESV/ASV automatically triggers partial reloads for metadata, routes, menus, extensions, flows, handlers, and related caches after successful writes. Do not reflexively call `/admin/reload`, `/admin/reload/metadata`, or `/admin/reload/routes` after each change. Verify naturally first; use manual reload only when verification shows stale behavior, a reload event failed, or a concrete error indicates the partial reload did not apply.',
|
|
302
304
|
'- **Menu/extension realtime reload contract:** `menu_definition` and `extension_definition` writes are runtime UI changes, not plain CRUD. The server cache orchestrator must emit `$system:reload` through the admin Socket.IO channel with identifiers that eApp handles; eApp must refetch menus/rebuild the menu registry for menu reloads and invalidate dynamic extension caches for extension reloads. Menu reloads can change route-to-extension mapping, so they should also invalidate extension cache. If an open admin tab does not reflect menu/extension changes, debug this two-sided reload contract before telling the user to refresh.',
|
|
303
305
|
'- **Dashboard stats:** time range buttons must change the query filter and reload stats. Dashboards should summarize actionable errors and high-level activity; successful/no-error background runs usually do not need a standalone page unless there is a real workflow to manage.',
|
|
@@ -306,7 +308,7 @@ export function buildMcpServerInstructions(apiBaseUrl) {
|
|
|
306
308
|
'- **Do not misuse PageHeader stats:** `PageHeader.stats` renders prominent stat cards inside the shell header. Do not put normal operational KPIs, capacity totals, billing totals, or detail metrics there by default; keep those as body cards/tables where the operator can scan them with the page content. Only use PageHeader stats for a deliberately compact overview page where the stats are truly header-level context.',
|
|
307
309
|
'- **Page actions belong in registries:** Move page-level buttons into `useHeaderActionRegistry` or `useSubHeaderActionRegistry`; keep the extension body for operational content only. Sensitive registry actions must include a `permission` condition, for example `{ id: "create", label: "Create report", permission: { and: [{ route: "/report_definition", methods: ["POST"] }] }, onClick }`.',
|
|
308
310
|
'- **Header action button variants:** choose the button variant by intent. Use `color: "primary", variant: "solid"` for the main page action. Use `color: "neutral", variant: "ghost"` for back/navigation actions and `color: "neutral", variant: "outline"` for visible secondary actions. `variant: "soft"` is only for low-emphasis secondary/chrome actions; do not use soft for critical or primary header actions just because it looks acceptable in dark mode.',
|
|
309
|
-
'- **HTTP method management:** use the dedicated MCP tools `list_methods`, `create_method`, `update_method`, and preview-first `delete_method` for `method_definition`. The eApp UI for the same records is `/settings/methods`. Method color fields are `buttonColor` for badge background and `textColor` for badge text, both full hex colors. Do not use generic `create_record` on `method_definition` unless the dedicated tool is unavailable.',
|
|
311
|
+
'- **HTTP method management:** use the dedicated MCP tools `list_methods`, `create_method`, `update_method`, and preview-first `delete_method` for `method_definition`. The backend field is `method_definition.name`, unique per method; do not send `method_definition.method`. The eApp UI for the same records is `/settings/methods`. Method color fields are `buttonColor` for badge background and `textColor` for badge text, both full hex colors. Do not use generic `create_record` on `method_definition` unless the dedicated tool is unavailable.',
|
|
310
312
|
'- **Extension navigation:** prefer `NuxtLink` or Nuxt UI components with `:to` for visible navigation links and drill-down cards/buttons. Use `navigateTo(...)` only for imperative navigation after submit, confirm, mutation, or another side effect.',
|
|
311
313
|
'- **Extension runtime scope:** eApp exposes Vue APIs and injected Nuxt/Enfyra composables both to script global scope and Vue app `globalProperties`. Template expressions may call injected helpers directly, for example after a save handler can call `navigateTo("/data/report_definition")`, because Vue compiles template helpers to `_ctx.*`.',
|
|
312
314
|
'- **Extension CSS affects shell utility ordering:** dynamic extension CSS is injected after the app shell CSS. Shell/page-header code must not put conflicting plain Tailwind utilities on the same element, such as `flex-col` plus `flex-row`, `items-start` plus `items-center`, or `text-left` plus `text-center`. Choose one mutually exclusive class per state; otherwise extension CSS can change which utility wins and shift shell layout.',
|
package/src/mcp-server-entry.mjs
CHANGED
|
@@ -34,7 +34,7 @@ const CAPABILITY_AREAS = [
|
|
|
34
34
|
{
|
|
35
35
|
area: 'Dynamic REST API',
|
|
36
36
|
tables: ['route_definition', 'route_handler_definition', 'pre_hook_definition', 'post_hook_definition', 'route_permission_definition', 'method_definition'],
|
|
37
|
-
workflow: 'Create custom paths with create_route without mainTableId, then add handlers/hooks. mainTableId is only for canonical table routes like /table_name.
|
|
37
|
+
workflow: 'Create custom paths with create_route without mainTableId, then add handlers/hooks. mainTableId is only for canonical table routes like /table_name. Query method_definition before assigning route methods.',
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
area: 'Auth, roles, sessions, OAuth',
|
|
@@ -197,8 +197,8 @@ function summarizeRoutes(routesResult) {
|
|
|
197
197
|
id: route.id ?? route._id,
|
|
198
198
|
path: route.path,
|
|
199
199
|
mainTable: route.mainTable?.name || route.mainTableName || null,
|
|
200
|
-
availableMethods: (route.availableMethods || []).map((method) => method.
|
|
201
|
-
publishedMethods: (route.publishedMethods || []).map((method) => method.
|
|
200
|
+
availableMethods: (route.availableMethods || []).map((method) => method.name).filter(Boolean),
|
|
201
|
+
publishedMethods: (route.publishedMethods || []).map((method) => method.name).filter(Boolean),
|
|
202
202
|
isEnabled: route.isEnabled,
|
|
203
203
|
}));
|
|
204
204
|
}
|
|
@@ -376,8 +376,8 @@ function normalizeHexColorInput(value, fieldName) {
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
async function findMethodRecordByName(method) {
|
|
379
|
-
const filter = encodeURIComponent(JSON.stringify({
|
|
380
|
-
const result = await fetchAPI(ENFYRA_API_URL, `/method_definition?filter=${filter}&limit=1&fields=id,_id,
|
|
379
|
+
const filter = encodeURIComponent(JSON.stringify({ name: { _eq: method } }));
|
|
380
|
+
const result = await fetchAPI(ENFYRA_API_URL, `/method_definition?filter=${filter}&limit=1&fields=id,_id,name,buttonColor,textColor,isSystem`);
|
|
381
381
|
return unwrapData(result)[0] || null;
|
|
382
382
|
}
|
|
383
383
|
|
|
@@ -476,7 +476,7 @@ server.tool(
|
|
|
476
476
|
routes: routes.length,
|
|
477
477
|
methods: methodsResult?.data?.length || 0,
|
|
478
478
|
},
|
|
479
|
-
methods: (methodsResult?.data || []).map((method) => ({ id: method.id || method._id,
|
|
479
|
+
methods: (methodsResult?.data || []).map((method) => ({ id: method.id || method._id, name: method.name, method: method.name })),
|
|
480
480
|
capabilityAreas: CAPABILITY_AREAS.map((item) => ({
|
|
481
481
|
...item,
|
|
482
482
|
presentTables: item.tables.filter((table) => tableNames.includes(table)),
|
|
@@ -579,7 +579,7 @@ server.tool(
|
|
|
579
579
|
storageConfigs: storageResult?.data?.length || 0,
|
|
580
580
|
settings: settingsResult?.data?.length || 0,
|
|
581
581
|
},
|
|
582
|
-
methods: (methodsResult?.data || []).map((method) => ({ id: method.id || method._id,
|
|
582
|
+
methods: (methodsResult?.data || []).map((method) => ({ id: method.id || method._id, name: method.name, method: method.name })),
|
|
583
583
|
routeRuntime: {
|
|
584
584
|
routePattern: 'GET/POST /<route-path>; PATCH/DELETE /<route-path>/:id; no dynamic GET /<route-path>/:id.',
|
|
585
585
|
adminRoutes: adminRoutes.map((route) => route.path).sort(),
|
|
@@ -1050,10 +1050,11 @@ server.tool(
|
|
|
1050
1050
|
'List method_definition records with their UI colors. Use this before creating route methods or method-colored UI.',
|
|
1051
1051
|
{},
|
|
1052
1052
|
async () => {
|
|
1053
|
-
const result = await fetchAPI(ENFYRA_API_URL, '/method_definition?fields=id,_id,
|
|
1053
|
+
const result = await fetchAPI(ENFYRA_API_URL, '/method_definition?fields=id,_id,name,buttonColor,textColor,isSystem&sort=name&limit=0');
|
|
1054
1054
|
const methods = unwrapData(result).map((method) => ({
|
|
1055
1055
|
id: getId(method),
|
|
1056
|
-
|
|
1056
|
+
name: method.name,
|
|
1057
|
+
method: method.name,
|
|
1057
1058
|
buttonColor: method.buttonColor,
|
|
1058
1059
|
textColor: method.textColor,
|
|
1059
1060
|
isSystem: method.isSystem === true,
|
|
@@ -1082,7 +1083,7 @@ server.tool(
|
|
|
1082
1083
|
throw new Error(`Method ${normalizedMethod} already exists with id ${getId(existing)}. Use update_method to change colors.`);
|
|
1083
1084
|
}
|
|
1084
1085
|
const body = {
|
|
1085
|
-
|
|
1086
|
+
name: normalizedMethod,
|
|
1086
1087
|
buttonColor: normalizeHexColorInput(buttonColor, 'buttonColor'),
|
|
1087
1088
|
textColor: normalizeHexColorInput(textColor, 'textColor'),
|
|
1088
1089
|
isSystem: isSystem === true,
|
|
@@ -1094,6 +1095,7 @@ server.tool(
|
|
|
1094
1095
|
_methodMap = null;
|
|
1095
1096
|
return { content: [{ type: 'text', text: JSON.stringify({
|
|
1096
1097
|
...summarizeMutationResult(result, 'created', 'method_definition'),
|
|
1098
|
+
name: normalizedMethod,
|
|
1097
1099
|
method: normalizedMethod,
|
|
1098
1100
|
appUi: '/settings/methods',
|
|
1099
1101
|
}, null, 2) }] };
|
|
@@ -1128,7 +1130,7 @@ server.tool(
|
|
|
1128
1130
|
body.textColor = normalizeHexColorInput(textColor, 'textColor');
|
|
1129
1131
|
}
|
|
1130
1132
|
if (method !== undefined && id) {
|
|
1131
|
-
body.
|
|
1133
|
+
body.name = normalizeMethodNameInput(method);
|
|
1132
1134
|
}
|
|
1133
1135
|
if (Object.keys(body).length === 0) {
|
|
1134
1136
|
throw new Error('Provide buttonColor, textColor, or a new method name.');
|
|
@@ -1168,13 +1170,14 @@ server.tool(
|
|
|
1168
1170
|
if (!target) {
|
|
1169
1171
|
const primaryKey = await getPrimaryFieldName('method_definition');
|
|
1170
1172
|
const filter = encodeURIComponent(JSON.stringify({ [primaryKey]: { _eq: targetId } }));
|
|
1171
|
-
const result = await fetchAPI(ENFYRA_API_URL, `/method_definition?filter=${filter}&limit=1&fields=id,_id,
|
|
1173
|
+
const result = await fetchAPI(ENFYRA_API_URL, `/method_definition?filter=${filter}&limit=1&fields=id,_id,name,buttonColor,textColor,isSystem`);
|
|
1172
1174
|
target = unwrapData(result)[0] || null;
|
|
1173
1175
|
}
|
|
1174
1176
|
return { content: [{ type: 'text', text: JSON.stringify({
|
|
1175
1177
|
action: 'delete_method_preview',
|
|
1176
1178
|
id: targetId,
|
|
1177
|
-
|
|
1179
|
+
name: target?.name,
|
|
1180
|
+
method: target?.name,
|
|
1178
1181
|
isSystem: target?.isSystem === true,
|
|
1179
1182
|
destructive: true,
|
|
1180
1183
|
warning: 'Only delete unused custom methods. Deleting a method can affect route method relations.',
|
|
@@ -1265,7 +1268,7 @@ async function getMethodMap() {
|
|
|
1265
1268
|
const result = await fetchAPI(ENFYRA_API_URL, '/method_definition?limit=0');
|
|
1266
1269
|
_methodMap = {};
|
|
1267
1270
|
for (const m of result.data) {
|
|
1268
|
-
_methodMap[m.
|
|
1271
|
+
_methodMap[m.name] = m.id || m._id;
|
|
1269
1272
|
}
|
|
1270
1273
|
return _methodMap;
|
|
1271
1274
|
}
|
|
@@ -1289,7 +1292,8 @@ function withMethodNames(records, methodIdNameMap, field = 'methods') {
|
|
|
1289
1292
|
[field]: Array.isArray(record?.[field])
|
|
1290
1293
|
? record[field].map((item) => ({
|
|
1291
1294
|
...item,
|
|
1292
|
-
|
|
1295
|
+
name: item.name || methodIdNameMap[String(getId(item))] || null,
|
|
1296
|
+
method: item.name || methodIdNameMap[String(getId(item))] || null,
|
|
1293
1297
|
}))
|
|
1294
1298
|
: record?.[field],
|
|
1295
1299
|
}));
|
|
@@ -1344,7 +1348,11 @@ function enrichRoute(route, state) {
|
|
|
1344
1348
|
.filter((item) => sameId(refId(item.route), routeId))
|
|
1345
1349
|
.map((item) => pickCodeSummary({
|
|
1346
1350
|
...item,
|
|
1347
|
-
method: item.method ? {
|
|
1351
|
+
method: item.method ? {
|
|
1352
|
+
...item.method,
|
|
1353
|
+
name: state.methodIdNameMap[String(getId(item.method))] || item.method.name || null,
|
|
1354
|
+
method: state.methodIdNameMap[String(getId(item.method))] || item.method.name || null,
|
|
1355
|
+
} : item.method,
|
|
1348
1356
|
}, 'sourceCode'));
|
|
1349
1357
|
const routePreHooks = withMethodNames(
|
|
1350
1358
|
state.preHooks.filter((item) => item.isGlobal || sameId(refId(item.route), routeId)),
|
|
@@ -1369,13 +1377,25 @@ function enrichRoute(route, state) {
|
|
|
1369
1377
|
return {
|
|
1370
1378
|
...route,
|
|
1371
1379
|
availableMethods: Array.isArray(route.availableMethods)
|
|
1372
|
-
? route.availableMethods.map((method) => ({
|
|
1380
|
+
? route.availableMethods.map((method) => ({
|
|
1381
|
+
...method,
|
|
1382
|
+
name: method.name || state.methodIdNameMap[String(getId(method))] || null,
|
|
1383
|
+
method: method.name || state.methodIdNameMap[String(getId(method))] || null,
|
|
1384
|
+
}))
|
|
1373
1385
|
: route.availableMethods,
|
|
1374
1386
|
publishedMethods: Array.isArray(route.publishedMethods)
|
|
1375
|
-
? route.publishedMethods.map((method) => ({
|
|
1387
|
+
? route.publishedMethods.map((method) => ({
|
|
1388
|
+
...method,
|
|
1389
|
+
name: method.name || state.methodIdNameMap[String(getId(method))] || null,
|
|
1390
|
+
method: method.name || state.methodIdNameMap[String(getId(method))] || null,
|
|
1391
|
+
}))
|
|
1376
1392
|
: route.publishedMethods,
|
|
1377
1393
|
skipRoleGuardMethods: Array.isArray(route.skipRoleGuardMethods)
|
|
1378
|
-
? route.skipRoleGuardMethods.map((method) => ({
|
|
1394
|
+
? route.skipRoleGuardMethods.map((method) => ({
|
|
1395
|
+
...method,
|
|
1396
|
+
name: method.name || state.methodIdNameMap[String(getId(method))] || null,
|
|
1397
|
+
method: method.name || state.methodIdNameMap[String(getId(method))] || null,
|
|
1398
|
+
}))
|
|
1379
1399
|
: route.skipRoleGuardMethods,
|
|
1380
1400
|
handlers: routeHandlers,
|
|
1381
1401
|
preHooks: routePreHooks,
|
|
@@ -1536,7 +1556,7 @@ server.tool(
|
|
|
1536
1556
|
'Use this after inspecting a route or changing handlers/hooks/guards. Pass paths like /table_definition?limit=1, not external URLs.',
|
|
1537
1557
|
].join(' '),
|
|
1538
1558
|
{
|
|
1539
|
-
method: z.
|
|
1559
|
+
method: z.string().optional().default('GET').describe('HTTP method name. Must exist in method_definition.name for Enfyra route-backed calls.'),
|
|
1540
1560
|
path: z.string().describe('Enfyra API path, e.g. /route_definition?limit=1'),
|
|
1541
1561
|
query: z.string().optional().describe('Optional query params JSON object, merged onto path query string'),
|
|
1542
1562
|
body: z.string().optional().describe('Optional JSON request body string'),
|
|
@@ -1544,6 +1564,7 @@ server.tool(
|
|
|
1544
1564
|
useAuth: z.boolean().optional().default(true).describe('Attach MCP admin Bearer token. Set false to test published/public access.'),
|
|
1545
1565
|
},
|
|
1546
1566
|
async ({ method, path, query, body, headers, useAuth }) => {
|
|
1567
|
+
const httpMethod = normalizeMethodNameInput(method || 'GET');
|
|
1547
1568
|
const restPath = normalizeRestPath(path);
|
|
1548
1569
|
const url = new URL(`${ENFYRA_API_URL.replace(/\/$/, '')}${restPath}`);
|
|
1549
1570
|
const queryObj = parseJsonArg(query, {});
|
|
@@ -1561,9 +1582,9 @@ server.tool(
|
|
|
1561
1582
|
|
|
1562
1583
|
const started = Date.now();
|
|
1563
1584
|
const response = await fetch(url, {
|
|
1564
|
-
method,
|
|
1585
|
+
method: httpMethod,
|
|
1565
1586
|
headers: requestHeaders,
|
|
1566
|
-
...(body !== undefined && body !== null &&
|
|
1587
|
+
...(body !== undefined && body !== null && httpMethod !== 'GET' ? { body } : {}),
|
|
1567
1588
|
});
|
|
1568
1589
|
const contentType = response.headers.get('content-type') || '';
|
|
1569
1590
|
const responseText = await response.text();
|
|
@@ -1574,7 +1595,7 @@ server.tool(
|
|
|
1574
1595
|
|
|
1575
1596
|
const payload = {
|
|
1576
1597
|
request: {
|
|
1577
|
-
method,
|
|
1598
|
+
method: httpMethod,
|
|
1578
1599
|
url: url.toString(),
|
|
1579
1600
|
authenticated: !!useAuth,
|
|
1580
1601
|
},
|
|
@@ -1641,9 +1662,9 @@ server.tool(
|
|
|
1641
1662
|
{
|
|
1642
1663
|
path: z.string().describe('URL path, must start with / (e.g., "/my-endpoint")'),
|
|
1643
1664
|
mainTableId: z.union([z.string(), z.number()]).optional().describe('Only set for the canonical table route `/<table_name>`. Omit for every custom route.'),
|
|
1644
|
-
methods: z.array(z.
|
|
1645
|
-
.describe('HTTP
|
|
1646
|
-
publishedMethods: z.array(z.
|
|
1665
|
+
methods: z.array(z.string())
|
|
1666
|
+
.describe('HTTP method names this route supports (availableMethods). Each value must exist in method_definition.name. Common: ["GET","POST","PATCH","DELETE"].'),
|
|
1667
|
+
publishedMethods: z.array(z.string()).optional()
|
|
1647
1668
|
.describe('Methods accessible WITHOUT auth token. Omit = all methods require auth.'),
|
|
1648
1669
|
isEnabled: z.boolean().optional().default(true).describe('Enable route immediately'),
|
|
1649
1670
|
description: z.string().optional().describe('Route description'),
|
|
@@ -1687,7 +1708,7 @@ server.tool(
|
|
|
1687
1708
|
publishedMethods: publishedMethods || [],
|
|
1688
1709
|
},
|
|
1689
1710
|
routesReloaded: true,
|
|
1690
|
-
next: `Use create_handler({ routeId: ${JSON.stringify(getId(created))}, method: "GET"
|
|
1711
|
+
next: `Use create_handler({ routeId: ${JSON.stringify(getId(created))}, method: "GET", sourceCode }) for custom code. Create extra method_definition.name rows first for custom methods such as PUT.`,
|
|
1691
1712
|
}, null, 2) }] };
|
|
1692
1713
|
},
|
|
1693
1714
|
);
|
|
@@ -1704,9 +1725,9 @@ server.tool(
|
|
|
1704
1725
|
].join(' '),
|
|
1705
1726
|
{
|
|
1706
1727
|
routeId: z.union([z.string(), z.number()]).describe('Route definition ID'),
|
|
1707
|
-
method: z.
|
|
1708
|
-
.describe('Single
|
|
1709
|
-
methods: z.array(z.
|
|
1728
|
+
method: z.string().optional()
|
|
1729
|
+
.describe('Single method_definition.name to create. Prefer this for one handler.'),
|
|
1730
|
+
methods: z.array(z.string()).optional()
|
|
1710
1731
|
.describe('Batch create multiple handlers. Use only when the same sourceCode applies to every method.'),
|
|
1711
1732
|
sourceCode: z.string().describe('Handler JavaScript sourceCode. Do not use logic; backend CRUD rejects logic.'),
|
|
1712
1733
|
scriptLanguage: z.enum(['javascript', 'typescript']).optional().default('javascript').describe('Script language for compiler. Default javascript.'),
|
|
@@ -1768,8 +1789,8 @@ server.tool(
|
|
|
1768
1789
|
name: z.string().describe('Hook name (unique per route)'),
|
|
1769
1790
|
code: z.string().describe('Hook JavaScript sourceCode. MCP stores it as sourceCode and lets Enfyra compile compiledCode.'),
|
|
1770
1791
|
scriptLanguage: z.enum(['javascript', 'typescript']).optional().default('javascript').describe('Script language for compiler. Default javascript.'),
|
|
1771
|
-
methods: z.array(z.
|
|
1772
|
-
.describe('
|
|
1792
|
+
methods: z.array(z.string()).optional()
|
|
1793
|
+
.describe('Method names this hook applies to. Default: built-in REST methods GET, POST, PATCH, DELETE.'),
|
|
1773
1794
|
priority: z.number().optional().default(0).describe('Execution order (lower = first)'),
|
|
1774
1795
|
isEnabled: z.boolean().optional().default(true).describe('Enable hook immediately'),
|
|
1775
1796
|
},
|
|
@@ -1822,8 +1843,8 @@ server.tool(
|
|
|
1822
1843
|
name: z.string().describe('Hook name (unique per route)'),
|
|
1823
1844
|
code: z.string().describe('Hook JavaScript sourceCode. MCP stores it as sourceCode and lets Enfyra compile compiledCode.'),
|
|
1824
1845
|
scriptLanguage: z.enum(['javascript', 'typescript']).optional().default('javascript').describe('Script language for compiler. Default javascript.'),
|
|
1825
|
-
methods: z.array(z.
|
|
1826
|
-
.describe('
|
|
1846
|
+
methods: z.array(z.string()).optional()
|
|
1847
|
+
.describe('Method names this hook applies to. Default: built-in REST methods GET, POST, PATCH, DELETE.'),
|
|
1827
1848
|
priority: z.number().optional().default(0).describe('Execution order (lower = first)'),
|
|
1828
1849
|
isEnabled: z.boolean().optional().default(true).describe('Enable hook immediately'),
|
|
1829
1850
|
},
|
|
@@ -1954,7 +1975,7 @@ server.tool(
|
|
|
1954
1975
|
{
|
|
1955
1976
|
path: z.string().optional().describe('Route path, e.g. /user_definition'),
|
|
1956
1977
|
routeId: z.union([z.string(), z.number()]).optional().describe('Route id. Use either path or routeId.'),
|
|
1957
|
-
methods: z.array(z.
|
|
1978
|
+
methods: z.array(z.string()).describe('REST method names this permission allows. Each value must exist in method_definition.name.'),
|
|
1958
1979
|
roleId: z.union([z.string(), z.number()]).optional().describe('Role id scope'),
|
|
1959
1980
|
allowedUserIds: z.array(z.union([z.string(), z.number()])).optional().describe('Specific user ids scope'),
|
|
1960
1981
|
description: z.string().optional().describe('Admin note'),
|
|
@@ -1999,7 +2020,7 @@ server.tool(
|
|
|
1999
2020
|
position: z.enum(['pre_auth', 'post_auth']).default('pre_auth').describe('Execution position for root guard'),
|
|
2000
2021
|
routeId: z.union([z.string(), z.number()]).optional().describe('Optional route id'),
|
|
2001
2022
|
path: z.string().optional().describe('Optional route path'),
|
|
2002
|
-
methods: z.array(z.
|
|
2023
|
+
methods: z.array(z.string()).optional().describe('Method names this guard applies to. Empty means all configured behavior for route/global.'),
|
|
2003
2024
|
combinator: z.enum(['and', 'or']).default('and').describe('How child guards/rules combine'),
|
|
2004
2025
|
priority: z.number().optional().default(0).describe('Lower runs first'),
|
|
2005
2026
|
isGlobal: z.boolean().optional().default(false).describe('Apply globally instead of one route'),
|