@enfyra/mcp-server 0.0.68 → 0.0.70
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
|
@@ -890,6 +890,24 @@ return order && order.total > 1000`,
|
|
|
890
890
|
'Children run according to branch true/false.',
|
|
891
891
|
],
|
|
892
892
|
},
|
|
893
|
+
{
|
|
894
|
+
name: 'Split a provisioning workflow into focused steps',
|
|
895
|
+
code: `[
|
|
896
|
+
{ "key": "load_project", "stepOrder": 10, "type": "script" },
|
|
897
|
+
{ "key": "reserve_capacity", "stepOrder": 20, "type": "script" },
|
|
898
|
+
{ "key": "create_database_user", "stepOrder": 30, "type": "script" },
|
|
899
|
+
{ "key": "apply_database_guardrails", "stepOrder": 40, "type": "script" },
|
|
900
|
+
{ "key": "start_container", "stepOrder": 50, "type": "script" },
|
|
901
|
+
{ "key": "apply_container_guardrails", "stepOrder": 60, "type": "script" },
|
|
902
|
+
{ "key": "check_health", "stepOrder": 70, "type": "script" },
|
|
903
|
+
{ "key": "finalize_project", "stepOrder": 80, "type": "script" }
|
|
904
|
+
]`,
|
|
905
|
+
notes: [
|
|
906
|
+
'Prefer operation-sized flow steps with clear keys over one large script that performs SSH, Docker, DB, API, email, and finalization work together.',
|
|
907
|
+
'Each step should return only ids, booleans, status keys, or small counters that later steps need.',
|
|
908
|
+
'When refactoring an existing flow, add or extract adjacent focused flow_step_definition rows instead of making an oversized sourceCode block longer.',
|
|
909
|
+
],
|
|
910
|
+
},
|
|
893
911
|
{
|
|
894
912
|
name: 'Flow query step config',
|
|
895
913
|
code: `{
|
|
@@ -48,7 +48,7 @@ export function buildMcpServerInstructions(apiBaseUrl) {
|
|
|
48
48
|
'- **GraphQL:** `gql_definition` enables tables in GraphQL. GraphQL endpoint and schema share `ENFYRA_API_URL`; GraphQL requires Bearer auth.',
|
|
49
49
|
'- **Files/storage/assets:** `file_definition`, `file_permission_definition`, `folder_definition`, `storage_config_definition` plus upload/assets routes and file helpers.',
|
|
50
50
|
'- **WebSocket:** `websocket_definition` and `websocket_event_definition` define Socket.IO gateways/events. Use `run_admin_test` for websocket scripts.',
|
|
51
|
-
'- **Flows:** `flow_definition`, `flow_step_definition`, `flow_execution_definition`; use `test_flow_step`, `run_admin_test`, and `trigger_flow` for runtime checks.',
|
|
51
|
+
'- **Flows:** `flow_definition`, `flow_step_definition`, `flow_execution_definition`; compose workflows from small operation-sized steps, use `test_flow_step`, `run_admin_test`, and `trigger_flow` for runtime checks.',
|
|
52
52
|
'- **Extensions/packages/menus:** `extension_definition`, `menu_definition`, `package_definition`, `bootstrap_script_definition`; extensions are Vue SFC only, and packages should be installed with `install_package`.',
|
|
53
53
|
'- **Platform config:** `setting_definition`, `cors_origin_definition`, reload endpoints, logs, and metadata endpoints.',
|
|
54
54
|
'',
|
|
@@ -288,8 +288,10 @@ export function buildMcpServerInstructions(apiBaseUrl) {
|
|
|
288
288
|
'- **Execution history** (`flow_execution_definition`): `flow` → flow id, `status`, `payload`, `completedSteps`, `currentStep`, `error`, `startedAt`, `completedAt`, `duration`. There is no persisted `context` column; failed executions store diagnostics in `error`. Query separately — NOT nested under flow_definition.',
|
|
289
289
|
'- **triggerConfig examples**: schedule: `{"cron":"0 2 * * *","timezone":"UTC"}`, manual: `{}`. For event/webhook use cases, create a handler/hook with `@TRIGGER("flow-name", payload)` instead.',
|
|
290
290
|
'- **Step config examples**: script: `{"code":"return #user_definition.find({limit:10})"}`, condition: `{"code":"return @FLOW_LAST?.data?.length > 0"}` (uses JS truthy/falsy: `return user` = truthy if exists, `return null` = falsy), query: `{"table":"user_definition","filter":{"status":{"_eq":"active"}},"limit":10}`, http: `{"url":"https://api.example.com","method":"POST","body":{}}` (auto Content-Type: application/json; **http `url` must be public-safe**—see Safety), sleep: `{"ms":5000}`, trigger_flow: `{"flowId":2}`.',
|
|
291
|
+
'- **Flow step sizing:** prefer many small, named steps over one large script. Split workflows at real operation boundaries such as load context, reserve capacity, create remote resource, apply DB/user guardrails, start container, check health, write final state, and send notifications. A script step that mixes unrelated SSH/Docker/DB/API/email/reconciliation work, returns huge objects, or grows beyond roughly 100-150 lines should be split before saving.',
|
|
291
292
|
'- **Data chain**: Steps access previous results via `@FLOW.<stepKey>` and `@FLOW_LAST`. Input payload via `@FLOW_PAYLOAD`. Repos via `#table_name`.',
|
|
292
293
|
'- **Flow step output discipline:** Script/condition steps must return only the small values that later steps genuinely need, such as ids, booleans, status keys, or counters. Do not return full records, host objects, package objects, DB URLs, SSH keys, API tokens, generated passwords, or other secrets. Later steps should re-query the records they need from ids/payload. Flow execution history already records errors; successful runs do not need full success snapshots.',
|
|
294
|
+
'- **Flow refactor rule:** when changing an existing oversized flow step, prefer adding or extracting adjacent focused `flow_step_definition` rows with clear keys and `stepOrder` instead of making the original `sourceCode` longer. Keep branch `parent`/`branch` relationships explicit, and re-read saved steps after mutation to verify order and executable source.',
|
|
293
295
|
'- **Template syntax (flows)**: `@FLOW_PAYLOAD` → `$ctx.$flow.$payload` (input data), `@FLOW_LAST` → `$ctx.$flow.$last`, `@FLOW` → `$ctx.$flow`, `@FLOW_META` → `$ctx.$flow.$meta`, `#table_name` → `$ctx.$repos.table_name`, `@HELPERS` → `$ctx.$helpers`, `@THROW400`–`@THROW503` / `@THROW` → `$ctx.$throw[...]`. Trigger other flows in handlers via `@TRIGGER(name, payload)` or `$ctx.$trigger(name, payload)`.',
|
|
294
296
|
'- **Condition branching**: Condition step uses JavaScript truthy/falsy evaluation (e.g. `return user` → truthy if exists, falsy if null/0/undefined). Children with matching `parent: {id: conditionStepId}` and `branch: "true"/"false"` execute. Root steps (no parent) always execute sequentially.',
|
|
295
297
|
'- **Safety**: Max nesting depth 10 (flow triggering flow). Circular flow detection prevents A→B→A loops. HTTP steps: **SSRF hardening** — only `http`/`https`; blocks `localhost`, private IPs, and hostnames resolving to private IPs (use internet-facing URLs like `https://api.example.com`, not internal services, unless server policy changes). Default HTTP timeout 30s (AbortController). `$trigger()` available inside flow steps.',
|
package/src/lib/table-tools.js
CHANGED
|
@@ -34,6 +34,12 @@ export function resolveTableFromMetadata(metadata, tableId) {
|
|
|
34
34
|
.find((table) => String(getId(table)) === String(tableId)) || null;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
export function resolveTableFromMetadataByName(metadata, tableName) {
|
|
38
|
+
if (!tableName) return null;
|
|
39
|
+
return normalizeTablesFromMetadata(metadata)
|
|
40
|
+
.find((table) => table?.name === tableName || table?.alias === tableName) || null;
|
|
41
|
+
}
|
|
42
|
+
|
|
37
43
|
/**
|
|
38
44
|
* Helper: fetch table with full columns and relations.
|
|
39
45
|
* Dynamic table_definition relation fields can be paginated/truncated, so schema
|
|
@@ -46,7 +52,9 @@ export async function fetchTableWithDetails(ENFYRA_API_URL, tableId) {
|
|
|
46
52
|
fetchAPI(ENFYRA_API_URL, '/metadata'),
|
|
47
53
|
]);
|
|
48
54
|
const tableData = tableResult?.data?.[0] || tableResult?.[0] || null;
|
|
49
|
-
const metadataTable =
|
|
55
|
+
const metadataTable =
|
|
56
|
+
resolveTableFromMetadata(metadata, tableId) ||
|
|
57
|
+
resolveTableFromMetadataByName(metadata, tableData?.name);
|
|
50
58
|
if (!metadataTable) {
|
|
51
59
|
throw new Error(`Full metadata for table ${tableId} was not found; refusing schema cascade patch.`);
|
|
52
60
|
}
|
package/src/mcp-server-entry.mjs
CHANGED
|
@@ -64,7 +64,7 @@ const CAPABILITY_AREAS = [
|
|
|
64
64
|
{
|
|
65
65
|
area: 'Flows',
|
|
66
66
|
tables: ['flow_definition', 'flow_step_definition', 'flow_execution_definition'],
|
|
67
|
-
workflow: 'Create flows
|
|
67
|
+
workflow: 'Create flows as small operation-sized steps via CRUD, test steps with test_flow_step/run_admin_test, trigger with trigger_flow. Split oversized scripts instead of adding more work to one step.',
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
70
|
area: 'Extensions, menus, packages',
|