@enfyra/mcp-server 0.0.1 → 0.0.2
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 +15 -86
- package/package.json +1 -1
- package/src/index.mjs +74 -18
- package/src/lib/mcp-instructions.js +73 -0
- package/src/lib/table-tools.js +16 -2
package/README.md
CHANGED
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
# Enfyra MCP Server
|
|
2
2
|
|
|
3
|
-
MCP
|
|
3
|
+
MCP server for managing Enfyra instances from **Claude Code** (and other MCP clients). All operations go through Enfyra's REST API.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**LLM rules (REST, GraphQL, auth, URL, mutation `create_{tableName}`, etc.):** not in this README — see **`src/lib/mcp-instructions.js`** (content sent via MCP `instructions`) and tool descriptions in **`src/index.mjs`**. This README only covers **MCP installation and configuration** for users/devs.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Metadata Management**: Query tables, columns, relations, routes, hooks
|
|
9
|
-
- **CRUD Operations**: Create, read, update, delete records in any table
|
|
10
|
-
- **Route & Handler Management**: Create routes, handlers, pre/post hooks
|
|
11
|
-
- **Table Management**: Create tables and columns
|
|
12
|
-
- **Cache Control**: Reload metadata, routes, Swagger, GraphQL
|
|
13
|
-
- **Log Access**: View and tail log files
|
|
7
|
+
## Install in Claude Code
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
### Method 1: Global Configuration (Recommended)
|
|
18
|
-
|
|
19
|
-
Edit `~/.claude.json` and add to the `mcpServers` section:
|
|
9
|
+
Edit `~/.claude.json` and add to `mcpServers`:
|
|
20
10
|
|
|
21
11
|
```json
|
|
22
12
|
{
|
|
@@ -34,82 +24,21 @@ Edit `~/.claude.json` and add to the `mcpServers` section:
|
|
|
34
24
|
}
|
|
35
25
|
```
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
27
|
+
- `-y`: auto-confirm package install without prompting.
|
|
28
|
+
- **Restart Claude Code** after updating config.
|
|
29
|
+
|
|
30
|
+
**Local dev (running this repo):** use `node` with path to `src/index.mjs`; see `.mcp.json` in the project.
|
|
40
31
|
|
|
41
32
|
| Variable | Description | Default |
|
|
42
33
|
|----------|-------------|---------|
|
|
43
|
-
| `ENFYRA_API_URL` |
|
|
44
|
-
| `ENFYRA_EMAIL` | Admin email
|
|
45
|
-
| `ENFYRA_PASSWORD` | Admin password
|
|
46
|
-
|
|
47
|
-
## Available Tools
|
|
48
|
-
|
|
49
|
-
### Authentication
|
|
50
|
-
- `login` - Login and get new access token
|
|
51
|
-
|
|
52
|
-
### Metadata
|
|
53
|
-
- `get_all_metadata` - Get all system metadata
|
|
54
|
-
- `get_table_metadata` - Get metadata for a specific table
|
|
55
|
-
- `query_table` - Query any table with filters
|
|
56
|
-
- `find_one_record` - Find a single record
|
|
57
|
-
|
|
58
|
-
### CRUD
|
|
59
|
-
- `create_record` - Create a new record
|
|
60
|
-
- `update_record` - Update a record
|
|
61
|
-
- `delete_record` - Delete a record
|
|
62
|
-
|
|
63
|
-
### Routes & Handlers
|
|
64
|
-
- `get_all_routes` - Get all route definitions
|
|
65
|
-
- `create_route` - Create a new route
|
|
66
|
-
- `create_handler` - Create a handler for a route
|
|
67
|
-
- `create_pre_hook` - Create a pre-hook
|
|
68
|
-
- `create_post_hook` - Create a post-hook
|
|
69
|
-
|
|
70
|
-
### Tables
|
|
71
|
-
- `get_all_tables` - Get all table definitions
|
|
72
|
-
- `create_table` - Create a new table
|
|
73
|
-
- `create_column` - Create a column
|
|
74
|
-
- `sync_table_schema` - Sync DB schema with metadata
|
|
34
|
+
| `ENFYRA_API_URL` | API base URL (usually includes `/api`) | `http://localhost:3000/api` |
|
|
35
|
+
| `ENFYRA_EMAIL` | Admin email | — |
|
|
36
|
+
| `ENFYRA_PASSWORD` | Admin password | — |
|
|
75
37
|
|
|
76
|
-
|
|
77
|
-
- `reload_all` - Reload all caches
|
|
78
|
-
- `reload_metadata` - Reload metadata only
|
|
79
|
-
- `reload_routes` - Reload routes only
|
|
80
|
-
- `reload_swagger` - Reload Swagger spec
|
|
81
|
-
- `reload_graphql` - Reload GraphQL schema
|
|
38
|
+
## Tools (summary)
|
|
82
39
|
|
|
83
|
-
|
|
84
|
-
- `get_log_files` - List available log files
|
|
85
|
-
- `get_log_content` - Get log file content
|
|
86
|
-
- `tail_log` - Get last N lines from log
|
|
87
|
-
|
|
88
|
-
### Auth
|
|
89
|
-
- `get_current_user` - Get current user info
|
|
90
|
-
- `get_all_roles` - Get all roles
|
|
91
|
-
|
|
92
|
-
## Usage Examples
|
|
93
|
-
|
|
94
|
-
After configuring in Claude Code:
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
"Query all users"
|
|
98
|
-
→ Uses query_table with tableName="user_definition"
|
|
99
|
-
|
|
100
|
-
"Create a new API route for /api/tasks"
|
|
101
|
-
→ Uses create_route, then create_handler
|
|
102
|
-
|
|
103
|
-
"Debug the error logs"
|
|
104
|
-
→ Uses tail_log with filename="error.log"
|
|
105
|
-
|
|
106
|
-
"Deploy my metadata changes"
|
|
107
|
-
→ Uses reload_all
|
|
108
|
-
```
|
|
40
|
+
Metadata, query/CRUD, route/handler/hook, tables/columns, reload cache, logs, user/roles, login, menu/extension, `get_enfyra_api_context`. For full tool list and behavior, see the app after enabling MCP or the source in `src/index.mjs`.
|
|
109
41
|
|
|
110
|
-
## Security
|
|
42
|
+
## Security
|
|
111
43
|
|
|
112
|
-
-
|
|
113
|
-
- Authentication is required (JWT token with auto-refresh)
|
|
114
|
-
- Permissions are enforced by Enfyra's auth system
|
|
115
|
-
- Pre/Post hooks and RLS are applied to all queries
|
|
44
|
+
API calls use JWT (MCP auto-refreshes). Permissions are enforced by Enfyra.
|
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -21,16 +21,22 @@ const ENFYRA_PASSWORD = process.env.ENFYRA_PASSWORD || '';
|
|
|
21
21
|
// Import modules
|
|
22
22
|
import { login, refreshAccessToken, getValidToken, resetTokens, getTokenExpiry, initAuth } from './lib/auth.js';
|
|
23
23
|
import { fetchAPI, validateFilter, validateTableName } from './lib/fetch.js';
|
|
24
|
+
import { buildMcpServerInstructions, buildGraphqlUrls } from './lib/mcp-instructions.js';
|
|
24
25
|
import { registerTableTools } from './lib/table-tools.js';
|
|
25
26
|
|
|
26
27
|
// Initialize auth module
|
|
27
28
|
initAuth(ENFYRA_API_URL, ENFYRA_EMAIL, ENFYRA_PASSWORD);
|
|
28
29
|
|
|
29
|
-
// Create MCP server
|
|
30
|
-
const server = new McpServer(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
// Create MCP server — `instructions` is sent to the host (e.g. Claude Code) for the LLM; not README
|
|
31
|
+
const server = new McpServer(
|
|
32
|
+
{
|
|
33
|
+
name: 'enfyra-mcp',
|
|
34
|
+
version: '1.0.0',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
instructions: buildMcpServerInstructions(ENFYRA_API_URL),
|
|
38
|
+
},
|
|
39
|
+
);
|
|
34
40
|
|
|
35
41
|
// ============================================================================
|
|
36
42
|
// METADATA TOOLS
|
|
@@ -52,6 +58,40 @@ server.tool('get_table_metadata', 'Get metadata for a specific table by name', {
|
|
|
52
58
|
// QUERY TOOLS
|
|
53
59
|
// ============================================================================
|
|
54
60
|
|
|
61
|
+
server.tool(
|
|
62
|
+
'get_enfyra_api_context',
|
|
63
|
+
[
|
|
64
|
+
'Returns the resolved API base URL for this MCP session (env ENFYRA_API_URL).',
|
|
65
|
+
'Use when the user asks which HTTP endpoint or full URL applies: combine enfyraApiUrl with paths from server instructions (GET/POST /{table}, PATCH/DELETE /{table}/{id}, no GET /{table}/{id}).',
|
|
66
|
+
'Auth: publishedMethods on a route can allow a method without Bearer; otherwise JWT + routePermissions — see server instructions.',
|
|
67
|
+
'If path might differ from table name, use get_all_routes before asserting a URL.',
|
|
68
|
+
'Same mapping as MCP tool → HTTP: query_table=GET /table?..., create_record=POST /table, update_record=PATCH /table/id, delete_record=DELETE /table/id.',
|
|
69
|
+
'GraphQL: see graphqlHttpUrl / graphqlSchemaUrl in response; GQL_QUERY vs GQL_MUTATION in publishedMethods — server instructions.',
|
|
70
|
+
].join(' '),
|
|
71
|
+
{},
|
|
72
|
+
async () => {
|
|
73
|
+
const base = ENFYRA_API_URL.replace(/\/$/, '');
|
|
74
|
+
const gql = buildGraphqlUrls(ENFYRA_API_URL);
|
|
75
|
+
const payload = {
|
|
76
|
+
enfyraApiUrl: base,
|
|
77
|
+
graphqlHttpUrl: gql.graphqlHttpUrl,
|
|
78
|
+
graphqlSchemaUrl: gql.graphqlSchemaUrl,
|
|
79
|
+
examples: {
|
|
80
|
+
listOrCreate: `${base}/<table_name>`,
|
|
81
|
+
updateOrDelete: `${base}/<table_name>/<id>`,
|
|
82
|
+
oneRowById: `${base}/<table_name>?filter={"id":{"_eq":"<id>"}}&limit=1`,
|
|
83
|
+
},
|
|
84
|
+
auth: {
|
|
85
|
+
publishedMethods: 'If the HTTP method is published for that route, no Bearer required; else Bearer JWT and routePermissions apply.',
|
|
86
|
+
mcp: 'This server uses admin credentials from env for tools (fetchAPI).',
|
|
87
|
+
},
|
|
88
|
+
pathResolution: 'Confirm route path with get_all_routes or metadata — path may not equal table name.',
|
|
89
|
+
note: 'Full tool→HTTP mapping is in MCP server instructions (shown to the model at connect).',
|
|
90
|
+
};
|
|
91
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
92
|
+
},
|
|
93
|
+
);
|
|
94
|
+
|
|
55
95
|
server.tool('query_table', 'Query any table in Enfyra with filters, sorting, and pagination', {
|
|
56
96
|
tableName: z.string().describe('Table name to query'),
|
|
57
97
|
filter: z.string().optional().describe('Filter object as JSON string. Examples: \'{"status": {"_eq": "active"}}\''),
|
|
@@ -75,19 +115,35 @@ server.tool('query_table', 'Query any table in Enfyra with filters, sorting, and
|
|
|
75
115
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
76
116
|
});
|
|
77
117
|
|
|
78
|
-
server.tool(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
});
|
|
118
|
+
server.tool(
|
|
119
|
+
'find_one_record',
|
|
120
|
+
'Find a single record by ID or filter. By ID uses GET with filter (Enfyra has no GET /table/:id route).',
|
|
121
|
+
{
|
|
122
|
+
tableName: z.string().describe('Table name'),
|
|
123
|
+
id: z.string().optional().describe('Record ID'),
|
|
124
|
+
filter: z.string().optional().describe('Filter as JSON string to find by'),
|
|
125
|
+
},
|
|
126
|
+
async ({ tableName, id, filter }) => {
|
|
127
|
+
validateTableName(tableName);
|
|
128
|
+
if (id) {
|
|
129
|
+
// Enfyra route engine does not register GET /<table>/:id (only PATCH/DELETE use /:id). Use list + filter.
|
|
130
|
+
const filterObj = JSON.stringify({ id: { _eq: id } });
|
|
131
|
+
const result = await fetchAPI(
|
|
132
|
+
ENFYRA_API_URL,
|
|
133
|
+
`/${tableName}?filter=${encodeURIComponent(filterObj)}&limit=1`,
|
|
134
|
+
);
|
|
135
|
+
const one = result.data?.[0] ?? null;
|
|
136
|
+
return { content: [{ type: 'text', text: JSON.stringify(one, null, 2) }] };
|
|
137
|
+
}
|
|
138
|
+
if (!filter) throw new Error('Provide id or filter');
|
|
139
|
+
validateFilter(filter);
|
|
140
|
+
const result = await fetchAPI(
|
|
141
|
+
ENFYRA_API_URL,
|
|
142
|
+
`/${tableName}?filter=${encodeURIComponent(filter)}&limit=1`,
|
|
143
|
+
);
|
|
144
|
+
return { content: [{ type: 'text', text: JSON.stringify(result.data?.[0] || null, null, 2) }] };
|
|
145
|
+
},
|
|
146
|
+
);
|
|
91
147
|
|
|
92
148
|
// ============================================================================
|
|
93
149
|
// CRUD TOOLS
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server `instructions` — surfaced to the host (e.g. Claude Code) for the LLM.
|
|
3
|
+
* Single source of truth for API/REST/GraphQL/auth/mutation naming; README does NOT feed the model.
|
|
4
|
+
* Maintain all assistant-facing rules here (and tool descriptions in index.mjs).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** GraphQL shares the same URL prefix as REST: `{ENFYRA_API_URL}/graphql` and `{ENFYRA_API_URL}/graphql-schema`. */
|
|
8
|
+
export function buildGraphqlUrls(apiBaseUrl) {
|
|
9
|
+
const base = String(apiBaseUrl || '').replace(/\/$/, '');
|
|
10
|
+
return {
|
|
11
|
+
graphqlHttpUrl: `${base}/graphql`,
|
|
12
|
+
graphqlSchemaUrl: `${base}/graphql-schema`,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function buildMcpServerInstructions(apiBaseUrl) {
|
|
17
|
+
const base = String(apiBaseUrl || '').replace(/\/$/, '');
|
|
18
|
+
const { graphqlHttpUrl, graphqlSchemaUrl } = buildGraphqlUrls(apiBaseUrl);
|
|
19
|
+
const getList = `${base}/<table_name>`;
|
|
20
|
+
const getOneById = `${base}/<table_name>?filter={"id":{"_eq":"<id>"}}&limit=1`;
|
|
21
|
+
const patchOne = `${base}/<table_name>/<id>`;
|
|
22
|
+
const delOne = `${base}/<table_name>/<id>`;
|
|
23
|
+
const examplePost = `${base}/post`;
|
|
24
|
+
|
|
25
|
+
return [
|
|
26
|
+
'## Enfyra API endpoints (answer user questions with these rules)',
|
|
27
|
+
'',
|
|
28
|
+
`**API base for this session:** \`${base}\` (from env ENFYRA_API_URL, no trailing slash).`,
|
|
29
|
+
`**Full URL:** base + path segment. Example for table \`post\`: \`${examplePost}\`.`,
|
|
30
|
+
'',
|
|
31
|
+
'### After a new table is created',
|
|
32
|
+
'- Enfyra creates a route at `/{table_name}` using the table **name** from `create_table` (not the alias).',
|
|
33
|
+
'- **Four REST HTTP operations** on that resource:',
|
|
34
|
+
` - **GET** \`${getList}\` — list / filter (query: filter, sort, page, limit, fields, meta).`,
|
|
35
|
+
` - **POST** \`${getList}\` — create (JSON body).`,
|
|
36
|
+
` - **PATCH** \`${patchOne}\` — update one row.`,
|
|
37
|
+
` - **DELETE** \`${delOne}\` — delete one row.`,
|
|
38
|
+
`- **No** **GET** \`${base}/<table_name>/<id>\`. For one row by id use **GET** \`${getOneById}\` or MCP \`query_table\` / \`find_one_record\`.`,
|
|
39
|
+
'',
|
|
40
|
+
'### Auth and publishedMethods (Enfyra server)',
|
|
41
|
+
'- Each route has **publishedMethods** (which HTTP verbs are “public”) and **routePermissions** (roles/users for protected access).',
|
|
42
|
+
'- If the **current request method** is listed in **publishedMethods** for that route, the server allows the call **without** a Bearer token (`RoleGuard`).',
|
|
43
|
+
'- Otherwise the client must send an **Authorization** header with **Bearer** JWT from login. Then the user must satisfy **routePermissions** (unless root admin).',
|
|
44
|
+
'- MCP tools that use `fetchAPI` authenticate with the configured admin credentials; explain to users that **direct HTTP** calls need a token unless the route/method is published.',
|
|
45
|
+
'',
|
|
46
|
+
'### Resolving the real REST path',
|
|
47
|
+
'- Do **not** assume `route_definition.path` always equals `table_definition.name`. Paths are data-driven (custom prefixes, renames, multiple routes per table).',
|
|
48
|
+
'- When unsure of the URL path, use MCP **`get_all_routes`** (or **`get_all_metadata`**) to read each route’s **path** and **mainTable** before stating a full URL.',
|
|
49
|
+
'',
|
|
50
|
+
'### MongoDB vs SQL primary key',
|
|
51
|
+
'- On **SQL**, filters often use **`id`**. On **MongoDB**, documents may use **`_id`** — a filter for one row might be `{"_id":{"_eq":"..."}}` instead of `id`, depending on metadata.',
|
|
52
|
+
'',
|
|
53
|
+
'### GraphQL (same prefix as REST / ENFYRA_API_URL)',
|
|
54
|
+
`- **POST** \`${graphqlHttpUrl}\` — GraphQL endpoint (body: GraphQL query). Example with default base: \`http://localhost:3000/api/graphql\`.`,
|
|
55
|
+
`- **GET** \`${graphqlSchemaUrl}\` — current schema SDL (text), e.g. \`.../api/graphql-schema\`.`,
|
|
56
|
+
'- A table appears in the schema only if its route has **both** `GQL_QUERY` and `GQL_MUTATION` in `availableMethods`, `path` = `/<table_name>`, and `mainTable` set.',
|
|
57
|
+
'- **Query** field = same string as `table_definition.name`. **Mutations** are literal concat: `create_`+tableName, `update_`+tableName, `delete_`+tableName (e.g. tableName `post` → `create_post`, input type `postInput`). See `generate-type-defs.ts`. No mutations if no non-PK columns for input.',
|
|
58
|
+
'- **Auth:** `publishedMethods` may include `GQL_QUERY` and/or `GQL_MUTATION` **separately** — each controls anonymous access for queries vs mutations. Otherwise Bearer JWT + `routePermissions` must list the same method key (`GQL_QUERY` / `GQL_MUTATION`).',
|
|
59
|
+
'- MCP does not wrap GraphQL; use REST tools or tell users the URLs above.',
|
|
60
|
+
'',
|
|
61
|
+
'### MCP tool → HTTP',
|
|
62
|
+
`- \`get_all_metadata\` → GET \`${base}/metadata\``,
|
|
63
|
+
`- \`get_table_metadata\` → GET \`${base}/metadata/<tableName>\``,
|
|
64
|
+
`- \`query_table\` → GET \`${base}/<tableName>?…\` (query string from tool args)`,
|
|
65
|
+
`- \`find_one_record\` (by id) → GET \`${base}/<tableName>?filter=…&limit=1\``,
|
|
66
|
+
`- \`create_record\` → POST \`${base}/<tableName>\``,
|
|
67
|
+
`- \`update_record\` → PATCH \`${base}/<tableName>/<id>\``,
|
|
68
|
+
`- \`delete_record\` → DELETE \`${base}/<tableName>/<id>\``,
|
|
69
|
+
`- Other admin paths include \`${base}/route_definition\`, \`${base}/admin/reload\`, etc.`,
|
|
70
|
+
'',
|
|
71
|
+
'When asked which endpoint the API calls, respond with **HTTP method + full URL** using this base. Call `get_enfyra_api_context` to confirm the resolved base if needed.',
|
|
72
|
+
].join('\n');
|
|
73
|
+
}
|
package/src/lib/table-tools.js
CHANGED
|
@@ -8,6 +8,7 @@ import { fetchAPI, validateTableName } from './fetch.js';
|
|
|
8
8
|
* Register table tools with MCP server
|
|
9
9
|
*/
|
|
10
10
|
export function registerTableTools(server, ENFYRA_API_URL) {
|
|
11
|
+
const apiBase = ENFYRA_API_URL.replace(/\/$/, '');
|
|
11
12
|
server.tool(
|
|
12
13
|
'get_all_tables',
|
|
13
14
|
'Get all table definitions in the system',
|
|
@@ -22,7 +23,14 @@ export function registerTableTools(server, ENFYRA_API_URL) {
|
|
|
22
23
|
|
|
23
24
|
server.tool(
|
|
24
25
|
'create_table',
|
|
25
|
-
|
|
26
|
+
[
|
|
27
|
+
'Create a new table definition. After creating a table, use create_column to add columns.',
|
|
28
|
+
'Enfyra auto-creates a REST route at path `/<table_name>` (same segment as `name`, not alias).',
|
|
29
|
+
'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).',
|
|
30
|
+
'There is NO `GET /<table>/:id`. To fetch one row by id, use GET `/<table>?filter={"id":{"_eq":"<id>"}}&limit=1` or tool query_table / find_one_record.',
|
|
31
|
+
`Full URLs: ${apiBase}/<table_name> (example table post: ${apiBase}/post).`,
|
|
32
|
+
'GraphQL (GQL_QUERY / GQL_MUTATION) may also be enabled on the route; that is separate from REST paths above.',
|
|
33
|
+
].join(' '),
|
|
26
34
|
{
|
|
27
35
|
name: z.string().describe('Table name (e.g., "user_definition", "my_custom_table"). Must be unique, lowercase with underscores.'),
|
|
28
36
|
alias: z.string().optional().describe('Table alias for API. If not provided, the table name will be used.'),
|
|
@@ -34,8 +42,14 @@ export function registerTableTools(server, ENFYRA_API_URL) {
|
|
|
34
42
|
method: 'POST',
|
|
35
43
|
body: JSON.stringify({ name, alias, description, isEnabled }),
|
|
36
44
|
});
|
|
45
|
+
const base = ENFYRA_API_URL.replace(/\/$/, '');
|
|
46
|
+
const routePath = `/${name}`;
|
|
47
|
+
const restHint = [
|
|
48
|
+
`Auto route path: ${routePath} → full base for REST: ${base}${routePath}`,
|
|
49
|
+
`REST: GET+POST on ${routePath}; PATCH+DELETE on ${routePath}/:id only. No GET ${routePath}/:id.`,
|
|
50
|
+
].join('\n');
|
|
37
51
|
return {
|
|
38
|
-
content: [{ type: 'text', text: `Table created successfully with ID: ${result.id}. Next step: use create_column to add columns (tableId: ${result.id}).\n\nFull result:\n${JSON.stringify(result, null, 2)}` }],
|
|
52
|
+
content: [{ type: 'text', text: `Table created successfully with ID: ${result.id}. Next step: use create_column to add columns (tableId: ${result.id}).\n${restHint}\n\nFull result:\n${JSON.stringify(result, null, 2)}` }],
|
|
39
53
|
};
|
|
40
54
|
}
|
|
41
55
|
);
|