@nextblock-cms/cortex 0.14.4 → 0.14.6
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/index.cjs.js +1 -1
- package/index.d.ts +3 -0
- package/index.es.js +166 -121
- package/lib/ai-global-agent-db-tools.cjs.js +1 -1
- package/lib/ai-global-agent-db-tools.d.ts +8 -8
- package/lib/ai-global-agent-db-tools.es.js +154 -125
- package/lib/ai-global-agent-tools.cjs.js +2 -2
- package/lib/ai-global-agent-tools.d.ts +116 -97
- package/lib/ai-global-agent-tools.es.js +1223 -1181
- package/lib/mcp-server.cjs.js +1 -0
- package/lib/mcp-server.d.ts +76 -0
- package/lib/mcp-server.es.js +157 -0
- package/lib/mcp-tokens.cjs.js +1 -0
- package/lib/mcp-tokens.d.ts +95 -0
- package/lib/mcp-tokens.es.js +104 -0
- package/lib/mcp-tool-registry.cjs.js +4 -0
- package/lib/mcp-tool-registry.d.ts +234 -0
- package/lib/mcp-tool-registry.es.js +300 -0
- package/package.json +4 -4
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { createCortexGlobalAgentTools } from './ai-global-agent-tools';
|
|
2
|
+
import { CortexAiMcpScope } from './mcp-tokens';
|
|
3
|
+
/**
|
|
4
|
+
* Adapts the existing Cortex AI tool registry to the Model Context Protocol.
|
|
5
|
+
*
|
|
6
|
+
* This file deliberately owns NO business logic. Every tool exposed over MCP is the
|
|
7
|
+
* same executor the in-app global agent calls, reached through
|
|
8
|
+
* `createCortexGlobalAgentTools(context)` — so an external client (Claude Code,
|
|
9
|
+
* Cursor, …) and the dashboard chat cannot drift apart in validation, revision
|
|
10
|
+
* recording, or side effects. What this layer adds is only what MCP needs and the
|
|
11
|
+
* AI SDK path does not:
|
|
12
|
+
*
|
|
13
|
+
* 1. JSON Schema. MCP `tools/list` transmits raw JSON Schema; the registry stores Zod.
|
|
14
|
+
* 2. Scopes. A read-only token must not even *see* the mutating tools.
|
|
15
|
+
* 3. Aliases. The MCP contract names five tools that already exist here under
|
|
16
|
+
* different names (see CORTEX_MCP_TOOL_ALIASES).
|
|
17
|
+
* 4. MCP result envelopes (`content` / `isError` / `structuredContent`).
|
|
18
|
+
*/
|
|
19
|
+
export type CortexMcpToolContext = Parameters<typeof createCortexGlobalAgentTools>[0];
|
|
20
|
+
/**
|
|
21
|
+
* Read/write classification for every tool in the registry.
|
|
22
|
+
*
|
|
23
|
+
* Exhaustive by construction: `assertCortexMcpToolCoverage` (and a unit test) compares
|
|
24
|
+
* these keys against the live factory output, so adding a tool to the agent without
|
|
25
|
+
* classifying it here is a loud failure rather than a silent security hole. New tools
|
|
26
|
+
* are NOT defaulted to 'read' — an unclassified mutating tool handed to a read-only
|
|
27
|
+
* token is exactly the bug this table exists to prevent.
|
|
28
|
+
*/
|
|
29
|
+
export declare const CORTEX_MCP_TOOL_KINDS: {
|
|
30
|
+
readonly create_cms_page: "write";
|
|
31
|
+
readonly create_cms_post: "write";
|
|
32
|
+
readonly create_cms_product: "write";
|
|
33
|
+
readonly create_custom_block: "write";
|
|
34
|
+
readonly delete_cms_item: "write";
|
|
35
|
+
readonly delete_custom_block: "write";
|
|
36
|
+
readonly describe_database_schema: "read";
|
|
37
|
+
readonly execute_cms_action_plan: "write";
|
|
38
|
+
readonly execute_database_action_plan: "write";
|
|
39
|
+
readonly execute_database_mutation: "write";
|
|
40
|
+
readonly fetch_ecommerce_stats: "read";
|
|
41
|
+
readonly fetch_url_content: "read";
|
|
42
|
+
readonly insert_content_block: "write";
|
|
43
|
+
readonly list_custom_blocks: "read";
|
|
44
|
+
readonly prepare_delete_cms_item: "read";
|
|
45
|
+
readonly read_current_cms_item: "read";
|
|
46
|
+
readonly read_database_records: "read";
|
|
47
|
+
readonly rewrite_page_draft: "write";
|
|
48
|
+
readonly search_documentation: "read";
|
|
49
|
+
readonly search_stock_photos: "read";
|
|
50
|
+
readonly set_content_images: "write";
|
|
51
|
+
readonly translate_page: "write";
|
|
52
|
+
readonly update_cms_item_field: "write";
|
|
53
|
+
readonly update_content_block: "write";
|
|
54
|
+
readonly update_current_cms_fields: "write";
|
|
55
|
+
readonly update_custom_block: "write";
|
|
56
|
+
readonly update_footer: "write";
|
|
57
|
+
readonly update_navigation_bar: "write";
|
|
58
|
+
readonly update_section_column_block: "write";
|
|
59
|
+
};
|
|
60
|
+
export type CortexMcpCanonicalToolName = keyof typeof CORTEX_MCP_TOOL_KINDS;
|
|
61
|
+
/**
|
|
62
|
+
* MCP-contract tool names that map onto existing executors.
|
|
63
|
+
*
|
|
64
|
+
* These are the names the MCP integration promises to external clients. Rather than
|
|
65
|
+
* fork five 7000-line-file executors to rename them, each alias forwards to the
|
|
66
|
+
* canonical tool. The alias is what an external model sees first; the canonical name
|
|
67
|
+
* stays listed too, so nothing is hidden from a client that already knows the
|
|
68
|
+
* in-app vocabulary.
|
|
69
|
+
*/
|
|
70
|
+
export declare const CORTEX_MCP_TOOL_ALIASES: {
|
|
71
|
+
readonly generate_jsonb_layout: {
|
|
72
|
+
readonly canonical: "rewrite_page_draft";
|
|
73
|
+
readonly description: "Generate a complete, strictly-validated JSONB block layout and write it into a target page or post. Blocks are normalized and validated against the NextBlock block schema, then staged as a Live Draft on the target record — nothing goes live until an editor publishes the draft, and publishing snapshots a revision so the change is reversible. Use for whole-page builds and redesigns. Alias of `rewrite_page_draft`.";
|
|
74
|
+
readonly title: "Generate JSONB layout";
|
|
75
|
+
};
|
|
76
|
+
readonly get_database_schema: {
|
|
77
|
+
readonly canonical: "describe_database_schema";
|
|
78
|
+
readonly description: "Return the current CMS database structure: every table Cortex AI may read or mutate, its columns, primary keys, and whether it is read-only. Pair with `list_custom_blocks` for the active data-defined block definitions and with the `cortex://schema/blocks` resource for the built-in block types. Read-only. Alias of `describe_database_schema`.";
|
|
79
|
+
readonly title: "Get database schema";
|
|
80
|
+
};
|
|
81
|
+
readonly query_site_analytics: {
|
|
82
|
+
readonly canonical: "fetch_ecommerce_stats";
|
|
83
|
+
readonly description: "Query quantitative site analytics: revenue, order counts, order-status breakdowns, and top-selling products over a time range. Read-only. For inventory levels and post/page metrics that this report does not cover, use `read_database_records` against the `products`, `product_variants`, `posts`, or `pages` tables. Alias of `fetch_ecommerce_stats`.";
|
|
84
|
+
readonly title: "Query site analytics";
|
|
85
|
+
};
|
|
86
|
+
readonly search_stock_media: {
|
|
87
|
+
readonly canonical: "search_stock_photos";
|
|
88
|
+
readonly description: "Search free stock media (Pexels, then Unsplash) for contextually relevant imagery, returning direct image URLs with dimensions, alt text, and photographer attribution. Drop a returned `url` straight into an image block's `external_url` or a section background. Read-only and zero cost. Requires a stock provider key in CMS Settings → Cortex AI. Alias of `search_stock_photos`.";
|
|
89
|
+
readonly title: "Search stock media";
|
|
90
|
+
};
|
|
91
|
+
readonly update_site_navigation: {
|
|
92
|
+
readonly canonical: "update_navigation_bar";
|
|
93
|
+
readonly description: "Alter the public site navigation: header menu items and their nested child hierarchy, per locale. Use mode \"append\" to add links while preserving the existing menu, \"update\" to rename or re-point one link, and \"replace\" only when rebuilding the whole menu. For footer links and copyright use `update_footer`. Alias of `update_navigation_bar`.";
|
|
94
|
+
readonly title: "Update site navigation";
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
export type CortexMcpAliasToolName = keyof typeof CORTEX_MCP_TOOL_ALIASES;
|
|
98
|
+
export type CortexMcpToolName = CortexMcpAliasToolName | CortexMcpCanonicalToolName;
|
|
99
|
+
/** Resolve an alias to the executor that actually runs, or pass a canonical name through. */
|
|
100
|
+
export declare function resolveCortexMcpToolName(name: string): CortexMcpCanonicalToolName | null;
|
|
101
|
+
export declare function getCortexMcpToolKind(name: string): CortexAiMcpScope | null;
|
|
102
|
+
/** A token holding `write` implicitly holds `read`; there is no write-without-read tool. */
|
|
103
|
+
export declare function cortexMcpScopesAllow(scopes: readonly CortexAiMcpScope[], name: string): boolean;
|
|
104
|
+
export type CortexMcpToolDefinition = {
|
|
105
|
+
description: string;
|
|
106
|
+
inputSchema: Record<string, unknown>;
|
|
107
|
+
name: string;
|
|
108
|
+
title: string;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Guard against the registry and the scope table drifting apart.
|
|
112
|
+
*
|
|
113
|
+
* Returns the tools present in one but not the other. Called by the route on every
|
|
114
|
+
* `tools/list` (cheap — it is a key comparison) so an unclassified tool is dropped
|
|
115
|
+
* from the listing rather than being exposed with an unknown risk profile.
|
|
116
|
+
*/
|
|
117
|
+
export declare function assertCortexMcpToolCoverage(context?: CortexMcpToolContext): {
|
|
118
|
+
missingFromRegistry: string[];
|
|
119
|
+
unclassified: string[];
|
|
120
|
+
};
|
|
121
|
+
/** Build the `tools/list` payload, filtered to what the caller's scopes permit. */
|
|
122
|
+
export declare function buildCortexMcpToolDefinitions(params: {
|
|
123
|
+
context?: CortexMcpToolContext;
|
|
124
|
+
scopes: readonly CortexAiMcpScope[];
|
|
125
|
+
}): CortexMcpToolDefinition[];
|
|
126
|
+
export type CortexMcpToolCallResult = {
|
|
127
|
+
content: Array<{
|
|
128
|
+
text: string;
|
|
129
|
+
type: 'text';
|
|
130
|
+
}>;
|
|
131
|
+
isError: boolean;
|
|
132
|
+
structuredContent?: Record<string, unknown>;
|
|
133
|
+
};
|
|
134
|
+
export declare class CortexMcpUnknownToolError extends Error {
|
|
135
|
+
constructor(name: string);
|
|
136
|
+
}
|
|
137
|
+
export declare class CortexMcpForbiddenToolError extends Error {
|
|
138
|
+
constructor(name: string);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Execute one MCP `tools/call`.
|
|
142
|
+
*
|
|
143
|
+
* Throws only for *protocol* faults (unknown tool, forbidden scope), which the caller
|
|
144
|
+
* turns into JSON-RPC error objects. Everything else — validation failures, executor
|
|
145
|
+
* exceptions — comes back as a successful result carrying `isError: true`, because
|
|
146
|
+
* that is the encoding MCP defines for tool execution errors and the only one a model
|
|
147
|
+
* can read and self-correct from.
|
|
148
|
+
*/
|
|
149
|
+
export declare function callCortexMcpTool(params: {
|
|
150
|
+
args: unknown;
|
|
151
|
+
context?: CortexMcpToolContext;
|
|
152
|
+
name: string;
|
|
153
|
+
scopes: readonly CortexAiMcpScope[];
|
|
154
|
+
}): Promise<CortexMcpToolCallResult>;
|
|
155
|
+
export declare const CORTEX_MCP_RESOURCES: readonly [{
|
|
156
|
+
readonly description: "The CMS database structure Cortex AI can read and mutate: tables, columns, primary keys, and read-only flags.";
|
|
157
|
+
readonly mimeType: "application/json";
|
|
158
|
+
readonly name: "database-schema";
|
|
159
|
+
readonly title: "NextBlock database schema";
|
|
160
|
+
readonly uri: "cortex://schema/database";
|
|
161
|
+
}, {
|
|
162
|
+
readonly description: "The built-in NextBlock block types available when composing page, post, and product layouts.";
|
|
163
|
+
readonly mimeType: "application/json";
|
|
164
|
+
readonly name: "block-types";
|
|
165
|
+
readonly title: "NextBlock block types";
|
|
166
|
+
readonly uri: "cortex://schema/blocks";
|
|
167
|
+
}, {
|
|
168
|
+
readonly description: "Data-defined custom block definitions registered in this workspace, keyed by the slug used as a block instance `block_type`.";
|
|
169
|
+
readonly mimeType: "application/json";
|
|
170
|
+
readonly name: "custom-blocks";
|
|
171
|
+
readonly title: "NextBlock custom block definitions";
|
|
172
|
+
readonly uri: "cortex://schema/custom-blocks";
|
|
173
|
+
}];
|
|
174
|
+
export declare function readCortexMcpResource(params: {
|
|
175
|
+
context?: CortexMcpToolContext;
|
|
176
|
+
uri: string;
|
|
177
|
+
}): Promise<{
|
|
178
|
+
mimeType: string;
|
|
179
|
+
text: string;
|
|
180
|
+
uri: string;
|
|
181
|
+
} | null>;
|
|
182
|
+
export declare const CORTEX_MCP_PROMPTS: readonly [{
|
|
183
|
+
readonly arguments: readonly [{
|
|
184
|
+
readonly description: "What the page is for, and any brand or tone notes.";
|
|
185
|
+
readonly name: "brief";
|
|
186
|
+
readonly required: true;
|
|
187
|
+
}, {
|
|
188
|
+
readonly description: "Slug of the page or post to rewrite, e.g. \"home\".";
|
|
189
|
+
readonly name: "slug";
|
|
190
|
+
readonly required: true;
|
|
191
|
+
}];
|
|
192
|
+
readonly description: "Build or redesign a NextBlock page from a brief, following the section-based layout recipe, and stage it as a reviewable Live Draft.";
|
|
193
|
+
readonly name: "build-page";
|
|
194
|
+
readonly title: "Build a NextBlock page";
|
|
195
|
+
}, {
|
|
196
|
+
readonly arguments: readonly [{
|
|
197
|
+
readonly description: "Source URL to draw structure and copy from.";
|
|
198
|
+
readonly name: "url";
|
|
199
|
+
readonly required: true;
|
|
200
|
+
}, {
|
|
201
|
+
readonly description: "Slug of the page to write the result into.";
|
|
202
|
+
readonly name: "slug";
|
|
203
|
+
readonly required: true;
|
|
204
|
+
}];
|
|
205
|
+
readonly description: "Read an external page and rebuild an equivalent NextBlock page from it, reusing its imagery where available.";
|
|
206
|
+
readonly name: "clone-from-url";
|
|
207
|
+
readonly title: "Rebuild a page from a URL";
|
|
208
|
+
}, {
|
|
209
|
+
readonly arguments: readonly [{
|
|
210
|
+
readonly description: "Target language code, e.g. \"fr\".";
|
|
211
|
+
readonly name: "languageCode";
|
|
212
|
+
readonly required: true;
|
|
213
|
+
}, {
|
|
214
|
+
readonly description: "Slug of the page or post to translate.";
|
|
215
|
+
readonly name: "slug";
|
|
216
|
+
readonly required: true;
|
|
217
|
+
}];
|
|
218
|
+
readonly description: "Translate an existing page or post into another language, preserving its layout and imagery.";
|
|
219
|
+
readonly name: "translate-content";
|
|
220
|
+
readonly title: "Translate a page or post";
|
|
221
|
+
}];
|
|
222
|
+
export declare function getCortexMcpPrompt(params: {
|
|
223
|
+
args?: Record<string, string>;
|
|
224
|
+
name: string;
|
|
225
|
+
}): {
|
|
226
|
+
description: string;
|
|
227
|
+
messages: Array<{
|
|
228
|
+
content: {
|
|
229
|
+
text: string;
|
|
230
|
+
type: 'text';
|
|
231
|
+
};
|
|
232
|
+
role: 'user';
|
|
233
|
+
}>;
|
|
234
|
+
} | null;
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { availableCortexAiBlockTypes as b, createCortexGlobalAgentTools as y } from "./ai-global-agent-tools.es.js";
|
|
2
|
+
import "./zod-config.es.js";
|
|
3
|
+
import { z as k } from "zod";
|
|
4
|
+
const i = {
|
|
5
|
+
create_cms_page: "write",
|
|
6
|
+
create_cms_post: "write",
|
|
7
|
+
create_cms_product: "write",
|
|
8
|
+
create_custom_block: "write",
|
|
9
|
+
delete_cms_item: "write",
|
|
10
|
+
delete_custom_block: "write",
|
|
11
|
+
describe_database_schema: "read",
|
|
12
|
+
execute_cms_action_plan: "write",
|
|
13
|
+
execute_database_action_plan: "write",
|
|
14
|
+
execute_database_mutation: "write",
|
|
15
|
+
fetch_ecommerce_stats: "read",
|
|
16
|
+
fetch_url_content: "read",
|
|
17
|
+
insert_content_block: "write",
|
|
18
|
+
list_custom_blocks: "read",
|
|
19
|
+
prepare_delete_cms_item: "read",
|
|
20
|
+
read_current_cms_item: "read",
|
|
21
|
+
read_database_records: "read",
|
|
22
|
+
rewrite_page_draft: "write",
|
|
23
|
+
search_documentation: "read",
|
|
24
|
+
search_stock_photos: "read",
|
|
25
|
+
set_content_images: "write",
|
|
26
|
+
translate_page: "write",
|
|
27
|
+
update_cms_item_field: "write",
|
|
28
|
+
update_content_block: "write",
|
|
29
|
+
update_current_cms_fields: "write",
|
|
30
|
+
update_custom_block: "write",
|
|
31
|
+
update_footer: "write",
|
|
32
|
+
update_navigation_bar: "write",
|
|
33
|
+
update_section_column_block: "write"
|
|
34
|
+
}, u = {
|
|
35
|
+
generate_jsonb_layout: {
|
|
36
|
+
canonical: "rewrite_page_draft",
|
|
37
|
+
description: "Generate a complete, strictly-validated JSONB block layout and write it into a target page or post. Blocks are normalized and validated against the NextBlock block schema, then staged as a Live Draft on the target record — nothing goes live until an editor publishes the draft, and publishing snapshots a revision so the change is reversible. Use for whole-page builds and redesigns. Alias of `rewrite_page_draft`.",
|
|
38
|
+
title: "Generate JSONB layout"
|
|
39
|
+
},
|
|
40
|
+
get_database_schema: {
|
|
41
|
+
canonical: "describe_database_schema",
|
|
42
|
+
description: "Return the current CMS database structure: every table Cortex AI may read or mutate, its columns, primary keys, and whether it is read-only. Pair with `list_custom_blocks` for the active data-defined block definitions and with the `cortex://schema/blocks` resource for the built-in block types. Read-only. Alias of `describe_database_schema`.",
|
|
43
|
+
title: "Get database schema"
|
|
44
|
+
},
|
|
45
|
+
query_site_analytics: {
|
|
46
|
+
canonical: "fetch_ecommerce_stats",
|
|
47
|
+
description: "Query quantitative site analytics: revenue, order counts, order-status breakdowns, and top-selling products over a time range. Read-only. For inventory levels and post/page metrics that this report does not cover, use `read_database_records` against the `products`, `product_variants`, `posts`, or `pages` tables. Alias of `fetch_ecommerce_stats`.",
|
|
48
|
+
title: "Query site analytics"
|
|
49
|
+
},
|
|
50
|
+
search_stock_media: {
|
|
51
|
+
canonical: "search_stock_photos",
|
|
52
|
+
description: "Search free stock media (Pexels, then Unsplash) for contextually relevant imagery, returning direct image URLs with dimensions, alt text, and photographer attribution. Drop a returned `url` straight into an image block's `external_url` or a section background. Read-only and zero cost. Requires a stock provider key in CMS Settings → Cortex AI. Alias of `search_stock_photos`.",
|
|
53
|
+
title: "Search stock media"
|
|
54
|
+
},
|
|
55
|
+
update_site_navigation: {
|
|
56
|
+
canonical: "update_navigation_bar",
|
|
57
|
+
description: 'Alter the public site navigation: header menu items and their nested child hierarchy, per locale. Use mode "append" to add links while preserving the existing menu, "update" to rename or re-point one link, and "replace" only when rebuilding the whole menu. For footer links and copyright use `update_footer`. Alias of `update_navigation_bar`.',
|
|
58
|
+
title: "Update site navigation"
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function _(e) {
|
|
62
|
+
return e in u ? u[e].canonical : e in i ? e : null;
|
|
63
|
+
}
|
|
64
|
+
function x(e) {
|
|
65
|
+
const t = _(e);
|
|
66
|
+
return t ? i[t] : null;
|
|
67
|
+
}
|
|
68
|
+
function d(e, t) {
|
|
69
|
+
const o = x(t);
|
|
70
|
+
return o ? o === "read" ? e.length > 0 : e.includes("write") : !1;
|
|
71
|
+
}
|
|
72
|
+
function p(e) {
|
|
73
|
+
return e.split("_").map((o, r) => r === 0 ? o.charAt(0).toUpperCase() + o.slice(1) : o).join(" ");
|
|
74
|
+
}
|
|
75
|
+
function m(e) {
|
|
76
|
+
const t = { additionalProperties: !1, type: "object" };
|
|
77
|
+
if (!e || typeof e != "object")
|
|
78
|
+
return t;
|
|
79
|
+
try {
|
|
80
|
+
const o = k.toJSONSchema(e, {
|
|
81
|
+
cycles: "ref",
|
|
82
|
+
io: "input",
|
|
83
|
+
reused: "inline",
|
|
84
|
+
target: "draft-2020-12",
|
|
85
|
+
unrepresentable: "any"
|
|
86
|
+
});
|
|
87
|
+
return delete o.$schema, o.type === "object" ? o : t;
|
|
88
|
+
} catch {
|
|
89
|
+
return t;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function s(e) {
|
|
93
|
+
return y(e);
|
|
94
|
+
}
|
|
95
|
+
function j(e) {
|
|
96
|
+
const t = Object.keys(s(e)), o = Object.keys(i);
|
|
97
|
+
return {
|
|
98
|
+
missingFromRegistry: o.filter((r) => !t.includes(r)),
|
|
99
|
+
unclassified: t.filter((r) => !o.includes(r))
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function O(e) {
|
|
103
|
+
const t = s(e.context), o = [];
|
|
104
|
+
for (const [r, a] of Object.entries(t))
|
|
105
|
+
!(r in i) || !d(e.scopes, r) || o.push({
|
|
106
|
+
description: a.description ?? `Cortex AI ${p(r)} tool.`,
|
|
107
|
+
inputSchema: m(a.inputSchema),
|
|
108
|
+
name: r,
|
|
109
|
+
title: p(r)
|
|
110
|
+
});
|
|
111
|
+
for (const [r, a] of Object.entries(u)) {
|
|
112
|
+
const n = t[a.canonical];
|
|
113
|
+
!n || !d(e.scopes, r) || o.push({
|
|
114
|
+
description: a.description,
|
|
115
|
+
inputSchema: m(n.inputSchema),
|
|
116
|
+
name: r,
|
|
117
|
+
title: a.title
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return o.sort((r, a) => r.name.localeCompare(a.name));
|
|
121
|
+
}
|
|
122
|
+
function g(e, t) {
|
|
123
|
+
return { content: [{ text: e, type: "text" }], isError: t };
|
|
124
|
+
}
|
|
125
|
+
function w(e) {
|
|
126
|
+
return e.issues.map((t) => `${t.path.length > 0 ? t.path.join(".") : "(root)"}: ${t.message}`).join("; ");
|
|
127
|
+
}
|
|
128
|
+
class h extends Error {
|
|
129
|
+
constructor(t) {
|
|
130
|
+
super(`Unknown tool: ${t}`), this.name = "CortexMcpUnknownToolError";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
class v extends Error {
|
|
134
|
+
constructor(t) {
|
|
135
|
+
super(
|
|
136
|
+
`Tool "${t}" requires the "write" scope. This MCP token is read-only — mint a read+write token in CMS Settings → Cortex AI.`
|
|
137
|
+
), this.name = "CortexMcpForbiddenToolError";
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async function N(e) {
|
|
141
|
+
const t = _(e.name);
|
|
142
|
+
if (!t)
|
|
143
|
+
throw new h(e.name);
|
|
144
|
+
if (!d(e.scopes, e.name))
|
|
145
|
+
throw new v(e.name);
|
|
146
|
+
const r = s(e.context)[t];
|
|
147
|
+
if (!r || typeof r.execute != "function")
|
|
148
|
+
throw new h(e.name);
|
|
149
|
+
const a = e.args && typeof e.args == "object" ? e.args : {};
|
|
150
|
+
if (r.inputSchema && typeof r.inputSchema.safeParse == "function") {
|
|
151
|
+
const n = r.inputSchema.safeParse(a);
|
|
152
|
+
if (!n.success)
|
|
153
|
+
return g(
|
|
154
|
+
`Invalid arguments for "${e.name}": ${w(n.error)}`,
|
|
155
|
+
!0
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const n = await r.execute(a), c = JSON.stringify(n ?? { success: !0 }, null, 2), l = n && typeof n == "object" && !Array.isArray(n) ? n : null, f = l?.success === !1;
|
|
160
|
+
return {
|
|
161
|
+
content: [{ text: c, type: "text" }],
|
|
162
|
+
isError: f,
|
|
163
|
+
...l ? { structuredContent: l } : {}
|
|
164
|
+
};
|
|
165
|
+
} catch (n) {
|
|
166
|
+
const c = n instanceof Error ? n.message : String(n);
|
|
167
|
+
return g(`Tool "${e.name}" failed: ${c}`, !0);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const A = [
|
|
171
|
+
{
|
|
172
|
+
description: "The CMS database structure Cortex AI can read and mutate: tables, columns, primary keys, and read-only flags.",
|
|
173
|
+
mimeType: "application/json",
|
|
174
|
+
name: "database-schema",
|
|
175
|
+
title: "NextBlock database schema",
|
|
176
|
+
uri: "cortex://schema/database"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
description: "The built-in NextBlock block types available when composing page, post, and product layouts.",
|
|
180
|
+
mimeType: "application/json",
|
|
181
|
+
name: "block-types",
|
|
182
|
+
title: "NextBlock block types",
|
|
183
|
+
uri: "cortex://schema/blocks"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
description: "Data-defined custom block definitions registered in this workspace, keyed by the slug used as a block instance `block_type`.",
|
|
187
|
+
mimeType: "application/json",
|
|
188
|
+
name: "custom-blocks",
|
|
189
|
+
title: "NextBlock custom block definitions",
|
|
190
|
+
uri: "cortex://schema/custom-blocks"
|
|
191
|
+
}
|
|
192
|
+
];
|
|
193
|
+
async function B(e) {
|
|
194
|
+
const t = s(e.context);
|
|
195
|
+
if (e.uri === "cortex://schema/database") {
|
|
196
|
+
const o = await t.describe_database_schema?.execute?.({ includeReadOnly: !0 });
|
|
197
|
+
return {
|
|
198
|
+
mimeType: "application/json",
|
|
199
|
+
text: JSON.stringify(o ?? {}, null, 2),
|
|
200
|
+
uri: e.uri
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
if (e.uri === "cortex://schema/blocks")
|
|
204
|
+
return {
|
|
205
|
+
mimeType: "application/json",
|
|
206
|
+
text: JSON.stringify({ blockTypes: b }, null, 2),
|
|
207
|
+
uri: e.uri
|
|
208
|
+
};
|
|
209
|
+
if (e.uri === "cortex://schema/custom-blocks") {
|
|
210
|
+
const o = await t.list_custom_blocks?.execute?.({});
|
|
211
|
+
return {
|
|
212
|
+
mimeType: "application/json",
|
|
213
|
+
text: JSON.stringify(o ?? {}, null, 2),
|
|
214
|
+
uri: e.uri
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
const C = [
|
|
220
|
+
{
|
|
221
|
+
arguments: [
|
|
222
|
+
{ description: "What the page is for, and any brand or tone notes.", name: "brief", required: !0 },
|
|
223
|
+
{ description: 'Slug of the page or post to rewrite, e.g. "home".', name: "slug", required: !0 }
|
|
224
|
+
],
|
|
225
|
+
description: "Build or redesign a NextBlock page from a brief, following the section-based layout recipe, and stage it as a reviewable Live Draft.",
|
|
226
|
+
name: "build-page",
|
|
227
|
+
title: "Build a NextBlock page"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
arguments: [
|
|
231
|
+
{ description: "Source URL to draw structure and copy from.", name: "url", required: !0 },
|
|
232
|
+
{ description: "Slug of the page to write the result into.", name: "slug", required: !0 }
|
|
233
|
+
],
|
|
234
|
+
description: "Read an external page and rebuild an equivalent NextBlock page from it, reusing its imagery where available.",
|
|
235
|
+
name: "clone-from-url",
|
|
236
|
+
title: "Rebuild a page from a URL"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
arguments: [
|
|
240
|
+
{ description: 'Target language code, e.g. "fr".', name: "languageCode", required: !0 },
|
|
241
|
+
{ description: "Slug of the page or post to translate.", name: "slug", required: !0 }
|
|
242
|
+
],
|
|
243
|
+
description: "Translate an existing page or post into another language, preserving its layout and imagery.",
|
|
244
|
+
name: "translate-content",
|
|
245
|
+
title: "Translate a page or post"
|
|
246
|
+
}
|
|
247
|
+
], S = {
|
|
248
|
+
"build-page": (e) => [
|
|
249
|
+
`Build the NextBlock page with slug "${e.slug ?? "<slug>"}" from this brief:`,
|
|
250
|
+
"",
|
|
251
|
+
e.brief ?? "<brief>",
|
|
252
|
+
"",
|
|
253
|
+
"Process:",
|
|
254
|
+
"1. Call get_database_schema and read_current_cms_item (or read_database_records on `pages`) to ground yourself in what exists.",
|
|
255
|
+
'2. Compose the page from `section` blocks: one column entry per grid track, the first section a hero, alternating none / theme:"muted" / theme:"primary" backgrounds for rhythm. Use discrete heading blocks rather than <h2> inside text HTML.',
|
|
256
|
+
"3. Call search_stock_media for real photography; copy each photo's attribution fields onto the image block.",
|
|
257
|
+
"4. Write the result with generate_jsonb_layout. It stages a Live Draft — tell the user to preview and publish it."
|
|
258
|
+
].join(`
|
|
259
|
+
`),
|
|
260
|
+
"clone-from-url": (e) => [
|
|
261
|
+
`Rebuild the NextBlock page "${e.slug ?? "<slug>"}" based on ${e.url ?? "<url>"}.`,
|
|
262
|
+
"",
|
|
263
|
+
"Process:",
|
|
264
|
+
"1. Call fetch_url_content on the URL first. Use its headings, text, and mainImage — never invent an image URL.",
|
|
265
|
+
"2. Map the source structure onto NextBlock `section` blocks; do not copy its markup verbatim.",
|
|
266
|
+
"3. Write the result with generate_jsonb_layout so it lands as a reviewable Live Draft."
|
|
267
|
+
].join(`
|
|
268
|
+
`),
|
|
269
|
+
"translate-content": (e) => [
|
|
270
|
+
`Translate the page or post "${e.slug ?? "<slug>"}" into "${e.languageCode ?? "<languageCode>"}".`,
|
|
271
|
+
"",
|
|
272
|
+
"Use the translate_page tool: it copies layout, structure, and imagery automatically and links the copy to the original translation group. Supply only the text translations — every visible string, including headings, paragraph text, button labels, image alt text, and captions. Do not rebuild the layout and do not search for new imagery."
|
|
273
|
+
].join(`
|
|
274
|
+
`)
|
|
275
|
+
};
|
|
276
|
+
function P(e) {
|
|
277
|
+
const t = C.find((r) => r.name === e.name), o = S[e.name];
|
|
278
|
+
return !t || !o ? null : {
|
|
279
|
+
description: t.description,
|
|
280
|
+
messages: [
|
|
281
|
+
{ content: { text: o(e.args ?? {}), type: "text" }, role: "user" }
|
|
282
|
+
]
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
export {
|
|
286
|
+
C as CORTEX_MCP_PROMPTS,
|
|
287
|
+
A as CORTEX_MCP_RESOURCES,
|
|
288
|
+
u as CORTEX_MCP_TOOL_ALIASES,
|
|
289
|
+
i as CORTEX_MCP_TOOL_KINDS,
|
|
290
|
+
v as CortexMcpForbiddenToolError,
|
|
291
|
+
h as CortexMcpUnknownToolError,
|
|
292
|
+
j as assertCortexMcpToolCoverage,
|
|
293
|
+
O as buildCortexMcpToolDefinitions,
|
|
294
|
+
N as callCortexMcpTool,
|
|
295
|
+
d as cortexMcpScopesAllow,
|
|
296
|
+
P as getCortexMcpPrompt,
|
|
297
|
+
x as getCortexMcpToolKind,
|
|
298
|
+
B as readCortexMcpResource,
|
|
299
|
+
_ as resolveCortexMcpToolName
|
|
300
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextblock-cms/cortex",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.6",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@ai-sdk/openai-compatible": "^2.0.42",
|
|
30
|
-
"@nextblock-cms/db": "^0.14.
|
|
31
|
-
"@nextblock-cms/ecommerce": "npm:@nextblock-cms/ecom@^0.14.
|
|
32
|
-
"@nextblock-cms/utils": "^0.14.
|
|
30
|
+
"@nextblock-cms/db": "^0.14.6",
|
|
31
|
+
"@nextblock-cms/ecommerce": "npm:@nextblock-cms/ecom@^0.14.6",
|
|
32
|
+
"@nextblock-cms/utils": "^0.14.6",
|
|
33
33
|
"ai": "^6.0.170",
|
|
34
34
|
"zod": "^4.3.6"
|
|
35
35
|
},
|