@enfyra/mcp-server 0.0.6 → 0.0.8
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
|
@@ -65,6 +65,13 @@ export function buildMcpServerInstructions(apiBaseUrl) {
|
|
|
65
65
|
'- **Error handling:** If redirected with `?error=`, show message to user.',
|
|
66
66
|
'- **Do not confuse:** Google’s **Authorized redirect URI** = Enfyra **`redirectUri`** = `{ENFYRA_API_URL}/auth/google/callback`. **`appCallbackUrl`** = your SPA only (Enfyra redirects there *after* processing Google’s callback).',
|
|
67
67
|
'',
|
|
68
|
+
'### System tables — which have REST routes',
|
|
69
|
+
'- **Not all system tables have a REST route.** `query_table`, `find_one_record`, `create_record`, etc. all go through the dynamic REST API and will return **404** if the table has no registered route.',
|
|
70
|
+
'- **`column_definition` has NO route** — do NOT call `query_table("column_definition", …)`. It will always 404.',
|
|
71
|
+
'- To check which tables are accessible via MCP tools, call `get_all_routes` and look for the route whose `mainTable.id` matches the table you need, or `get_all_metadata` to see all table names.',
|
|
72
|
+
'- **Tables confirmed to have REST routes (system):** `table_definition`, `route_definition`, `user_definition`, `setting_definition`, `ai_config_definition`, `role_definition`, `menu_definition`, `extension_definition`, `folder_definition`, `file_definition`, `file_permission_definition`, `package_definition`, `bootstrap_script_definition`, `storage_config_definition`, `ai_conversation_definition`, `ai_message_definition`, `websocket_definition`, `websocket_event_definition`, `oauth_config_definition`, `oauth_account_definition`, `method_definition`, `pre_hook_definition`, `post_hook_definition`, `route_handler_definition`, `route_permission_definition`.',
|
|
73
|
+
'- **Tables without REST routes (internal/system only):** `column_definition`, `relation_definition` — these are managed indirectly via `create_column`, `create_table`, or admin sync endpoints.',
|
|
74
|
+
'',
|
|
68
75
|
'### Schema / table migration (sequential only)',
|
|
69
76
|
'- When creating, updating, or deleting tables (or columns), run operations **one at a time**. The migration process locks the DB per operation.',
|
|
70
77
|
'- Do NOT batch multiple schema changes (e.g. create 3 tables in parallel, or create table + add columns simultaneously). Execute each `create_table`, `create_column`, sync, or drop sequentially; wait for completion before the next.',
|
package/src/lib/table-tools.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Table & Column tools for Enfyra MCP Server
|
|
3
3
|
*/
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { fetchAPI
|
|
5
|
+
import { fetchAPI } from './fetch.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Register table tools with MCP server
|
|
@@ -24,7 +24,8 @@ export function registerTableTools(server, ENFYRA_API_URL) {
|
|
|
24
24
|
server.tool(
|
|
25
25
|
'create_table',
|
|
26
26
|
[
|
|
27
|
-
'Create a new table definition
|
|
27
|
+
'Create a new table definition with an auto-included `id` primary key column.',
|
|
28
|
+
'Use create_column to add more columns after creation.',
|
|
28
29
|
'Schema operations (create/update/delete table, add column) must run one at a time — migration locks DB; parallel calls will fail.',
|
|
29
30
|
'Enfyra auto-creates a REST route at path `/<table_name>` (same segment as `name`, not alias).',
|
|
30
31
|
'REST surface for that route (matches server route engine): 4 HTTP operations — GET `/<table>` (list/filter), POST `/<table>` (create), PATCH `/<table>/:id` (update), DELETE `/<table>/:id` (delete).',
|
|
@@ -39,9 +40,10 @@ export function registerTableTools(server, ENFYRA_API_URL) {
|
|
|
39
40
|
isEnabled: z.boolean().optional().default(true).describe('Enable table. Set to false to disable.'),
|
|
40
41
|
},
|
|
41
42
|
async ({ name, alias, description, isEnabled }) => {
|
|
43
|
+
const idColumn = { name: 'id', type: 'int', isPrimary: true, isGenerated: true, isNullable: false };
|
|
42
44
|
const result = await fetchAPI(ENFYRA_API_URL, '/table_definition', {
|
|
43
45
|
method: 'POST',
|
|
44
|
-
body: JSON.stringify({ name, alias, description, isEnabled }),
|
|
46
|
+
body: JSON.stringify({ name, alias, description, isEnabled, columns: [idColumn] }),
|
|
45
47
|
});
|
|
46
48
|
const base = ENFYRA_API_URL.replace(/\/$/, '');
|
|
47
49
|
const routePath = `/${name}`;
|
|
@@ -55,6 +57,34 @@ export function registerTableTools(server, ENFYRA_API_URL) {
|
|
|
55
57
|
}
|
|
56
58
|
);
|
|
57
59
|
|
|
60
|
+
server.tool(
|
|
61
|
+
'create_relation',
|
|
62
|
+
[
|
|
63
|
+
'Create a relation between two tables (many-to-one, one-to-many, one-to-one, many-to-many).',
|
|
64
|
+
'For many-to-one: a FK column is created on the source table. For one-to-many: the FK is on the target (inverse relation).',
|
|
65
|
+
'Run sequentially — DB migration locks per operation.',
|
|
66
|
+
].join(' '),
|
|
67
|
+
{
|
|
68
|
+
sourceTableId: z.string().describe('Source table ID (the table that owns the FK for many-to-one).'),
|
|
69
|
+
targetTableId: z.string().describe('Target table ID.'),
|
|
70
|
+
type: z.enum(['many-to-one', 'one-to-many', 'one-to-one', 'many-to-many']).describe('Relation type.'),
|
|
71
|
+
propertyName: z.string().describe('Property name on source table (e.g., "customer", "items").'),
|
|
72
|
+
inversePropertyName: z.string().optional().describe('Property name on target table for bidirectional relation (e.g., "orders").'),
|
|
73
|
+
isNullable: z.boolean().optional().default(true).describe('Whether the relation is nullable.'),
|
|
74
|
+
onDelete: z.enum(['CASCADE', 'SET NULL', 'RESTRICT', 'NO ACTION']).optional().default('SET NULL').describe('On delete behavior.'),
|
|
75
|
+
},
|
|
76
|
+
async ({ sourceTableId, targetTableId, type, propertyName, inversePropertyName, isNullable, onDelete }) => {
|
|
77
|
+
const relation = { type, propertyName, inversePropertyName: inversePropertyName || null, isNullable, onDelete };
|
|
78
|
+
const result = await fetchAPI(ENFYRA_API_URL, `/table_definition/${sourceTableId}`, {
|
|
79
|
+
method: 'PATCH',
|
|
80
|
+
body: JSON.stringify({ relations: [{ targetTableId, ...relation }] }),
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
content: [{ type: 'text', text: `Relation created: ${propertyName} (${type}) from table ${sourceTableId} → ${targetTableId}.\n\nFull result:\n${JSON.stringify(result, null, 2)}` }],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
58
88
|
server.tool(
|
|
59
89
|
'create_column',
|
|
60
90
|
'Create a column for an existing table. Columns cascade through table_definition. Run schema changes sequentially — migration locks DB per operation.',
|