@neopress/mcp 0.1.0 → 0.2.0
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/dist/bin.cjs +93 -2
- package/dist/http-bin.cjs +93 -2
- package/dist/index.js +93 -2
- package/package.json +2 -2
package/dist/bin.cjs
CHANGED
|
@@ -30619,6 +30619,29 @@ var AnalyticsEndpoint = class {
|
|
|
30619
30619
|
}
|
|
30620
30620
|
};
|
|
30621
30621
|
|
|
30622
|
+
// ../sdk/dist/endpoints/templates.js
|
|
30623
|
+
var TemplatesEndpoint = class {
|
|
30624
|
+
client;
|
|
30625
|
+
constructor(client) {
|
|
30626
|
+
this.client = client;
|
|
30627
|
+
}
|
|
30628
|
+
get basePath() {
|
|
30629
|
+
return `${this.client.siteBasePath}/template`;
|
|
30630
|
+
}
|
|
30631
|
+
async get() {
|
|
30632
|
+
const res = await this.client.get(this.basePath);
|
|
30633
|
+
return res.data;
|
|
30634
|
+
}
|
|
30635
|
+
async mark(data) {
|
|
30636
|
+
const res = await this.client.post(this.basePath, data);
|
|
30637
|
+
return res.data;
|
|
30638
|
+
}
|
|
30639
|
+
async delete() {
|
|
30640
|
+
const res = await this.client.delete(this.basePath);
|
|
30641
|
+
return res.data;
|
|
30642
|
+
}
|
|
30643
|
+
};
|
|
30644
|
+
|
|
30622
30645
|
// ../sdk/dist/client.js
|
|
30623
30646
|
var NeopressClient = class {
|
|
30624
30647
|
baseUrl;
|
|
@@ -30635,6 +30658,7 @@ var NeopressClient = class {
|
|
|
30635
30658
|
publish;
|
|
30636
30659
|
entryReferences;
|
|
30637
30660
|
analytics;
|
|
30661
|
+
templates;
|
|
30638
30662
|
constructor(options) {
|
|
30639
30663
|
this.baseUrl = (options.baseUrl || "https://app.neopress.ai").replace(/\/$/, "");
|
|
30640
30664
|
this.accessToken = options.accessToken || "";
|
|
@@ -30650,6 +30674,7 @@ var NeopressClient = class {
|
|
|
30650
30674
|
this.publish = new PublishEndpoint(this);
|
|
30651
30675
|
this.entryReferences = new EntryReferencesEndpoint(this);
|
|
30652
30676
|
this.analytics = new AnalyticsEndpoint(this);
|
|
30677
|
+
this.templates = new TemplatesEndpoint(this);
|
|
30653
30678
|
}
|
|
30654
30679
|
get siteBasePath() {
|
|
30655
30680
|
return `/api/v1/sites/${this.siteId}`;
|
|
@@ -30680,7 +30705,13 @@ var NeopressClient = class {
|
|
|
30680
30705
|
throw new NeopressApiError("CONNECTION_ERROR", `Cannot connect to ${this.baseUrl} \u2014 is the dev server running?`, 0);
|
|
30681
30706
|
}
|
|
30682
30707
|
clearTimeout(timeout);
|
|
30683
|
-
const
|
|
30708
|
+
const responseText = await response.text();
|
|
30709
|
+
let json2;
|
|
30710
|
+
try {
|
|
30711
|
+
json2 = responseText ? JSON.parse(responseText) : {};
|
|
30712
|
+
} catch {
|
|
30713
|
+
throw new NeopressApiError("NON_JSON_RESPONSE", `Expected JSON from ${method} ${url2} but received non-JSON response (${response.status} ${response.statusText})`, response.status, { body: responseText.slice(0, 500) });
|
|
30714
|
+
}
|
|
30684
30715
|
if (!response.ok) {
|
|
30685
30716
|
const err = json2?.error || {};
|
|
30686
30717
|
throw new NeopressApiError(err.code || "UNKNOWN", err.message || response.statusText, response.status, json2);
|
|
@@ -30871,6 +30902,16 @@ Use these rules before generating pages, collection schemas, entries, forms, or
|
|
|
30871
30902
|
- Generated page TSX is sandboxed. Do not import Supabase, create API clients, read env vars, use filesystem/process APIs, or assume arbitrary npm packages.
|
|
30872
30903
|
- Use allowed runtime packages only: React/Next basics, shadcn UI imports, lucide-react, date-fns, framer-motion, @neopress/content, @neopress/routing, @neopress/i18n, and @neopress/forms.
|
|
30873
30904
|
|
|
30905
|
+
## Templates
|
|
30906
|
+
|
|
30907
|
+
- Reusable templates are normal Neopress sites marked by a \`templates\` metadata row.
|
|
30908
|
+
- \`templates.id\` equals \`sites.id\`.
|
|
30909
|
+
- Build layout, pages, collections, entries, forms, assets, compile, publish, and verify before marking a finished template.
|
|
30910
|
+
- Use \`neopress_template_mark\` to create or update the metadata row with \`name\`, \`industry\`, required \`referenceUrl\`, optional \`description\`, and optional \`previewImgUrls\`.
|
|
30911
|
+
- \`referenceUrl\` is a single http(s) provenance URL. \`description\` is an optional summary of the template (max 150 characters).
|
|
30912
|
+
- Template metadata does not replace page TSX, CMS content, forms, or publish state.
|
|
30913
|
+
- Use \`neopress_template_delete\` only for explicit template-site hard deletion. It removes the metadata row and connected site.
|
|
30914
|
+
|
|
30874
30915
|
## Dynamic pages and queryConfig
|
|
30875
30916
|
|
|
30876
30917
|
- Dynamic pages require a collection, a page path like \`/blog/[slug]\`, a numeric \`collectionId\`, matching entries, entry publish, page compile, and site publish.
|
|
@@ -30904,6 +30945,7 @@ var SERVER_INSTRUCTIONS = `Use Neopress MCP tools to manage a selected Neopress
|
|
|
30904
30945
|
|
|
30905
30946
|
Before generating TSX or schema-backed pages, call neopress_get_runtime_contract or read neopress://runtime-contract.
|
|
30906
30947
|
Use numeric IDs returned by tools. Publish entries separately from site publish. Use read-only analytics tools before autopilot recommendations. Verify production URLs after production publish.
|
|
30948
|
+
For reusable templates, build and publish the real site resources first, then call neopress_template_mark with template metadata.
|
|
30907
30949
|
For reference-page copy, do the reference crawling, screenshots, DOM/CSS/SVG/background-image analysis, and TSX generation in the host agent; MCP only writes and verifies Neopress resources.`;
|
|
30908
30950
|
|
|
30909
30951
|
// src/result.ts
|
|
@@ -30950,6 +30992,10 @@ var optionalJsonSchema = external_exports.unknown().optional();
|
|
|
30950
30992
|
var requiredJsonSchema = external_exports.unknown().refine((value) => value !== void 0, "Required JSON value is missing.");
|
|
30951
30993
|
var analyticsParamSchema = external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()]);
|
|
30952
30994
|
var analyticsParamsSchema = external_exports.record(external_exports.string(), analyticsParamSchema).optional();
|
|
30995
|
+
var httpUrlSchema = external_exports.string().url().refine((value) => {
|
|
30996
|
+
const url2 = new URL(value);
|
|
30997
|
+
return url2.protocol === "http:" || url2.protocol === "https:";
|
|
30998
|
+
}, "Must be an http(s) URL.");
|
|
30953
30999
|
var analyticsDateShape = {
|
|
30954
31000
|
dateFrom: external_exports.string().optional(),
|
|
30955
31001
|
dateTo: external_exports.string().optional(),
|
|
@@ -30994,7 +31040,8 @@ var READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
|
30994
31040
|
"neopress_search_console_query",
|
|
30995
31041
|
"neopress_assets_list",
|
|
30996
31042
|
"neopress_asset_get",
|
|
30997
|
-
"neopress_publish_preview"
|
|
31043
|
+
"neopress_publish_preview",
|
|
31044
|
+
"neopress_template_get"
|
|
30998
31045
|
]);
|
|
30999
31046
|
var DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
31000
31047
|
"neopress_site_update",
|
|
@@ -31012,6 +31059,7 @@ var DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
31012
31059
|
"neopress_form_publish",
|
|
31013
31060
|
"neopress_form_delete",
|
|
31014
31061
|
"neopress_asset_delete",
|
|
31062
|
+
"neopress_template_mark",
|
|
31015
31063
|
"neopress_publish_site"
|
|
31016
31064
|
]);
|
|
31017
31065
|
var PUBLICATION_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -31186,6 +31234,49 @@ var toolDefinitions = [
|
|
|
31186
31234
|
});
|
|
31187
31235
|
}
|
|
31188
31236
|
},
|
|
31237
|
+
{
|
|
31238
|
+
name: "neopress_template_get",
|
|
31239
|
+
title: "Get Template Metadata",
|
|
31240
|
+
description: "Get template metadata for the active or specified site.",
|
|
31241
|
+
inputSchema: siteIdShape,
|
|
31242
|
+
handler: async (input, context, extra) => {
|
|
31243
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
31244
|
+
return client.templates.get();
|
|
31245
|
+
}
|
|
31246
|
+
},
|
|
31247
|
+
{
|
|
31248
|
+
name: "neopress_template_mark",
|
|
31249
|
+
title: "Mark Site As Template",
|
|
31250
|
+
description: "Create or update the template metadata row for a finished template site. The template id is the site id.",
|
|
31251
|
+
inputSchema: {
|
|
31252
|
+
...siteIdShape,
|
|
31253
|
+
name: external_exports.string(),
|
|
31254
|
+
description: external_exports.string().max(150).optional(),
|
|
31255
|
+
industry: external_exports.string(),
|
|
31256
|
+
referenceUrl: httpUrlSchema,
|
|
31257
|
+
previewImgUrls: external_exports.array(external_exports.string()).nullable().optional()
|
|
31258
|
+
},
|
|
31259
|
+
handler: async (input, context, extra) => {
|
|
31260
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
31261
|
+
return client.templates.mark({
|
|
31262
|
+
name: asString(input, "name"),
|
|
31263
|
+
description: asOptionalString(input, "description"),
|
|
31264
|
+
industry: asString(input, "industry"),
|
|
31265
|
+
referenceUrl: asString(input, "referenceUrl"),
|
|
31266
|
+
previewImgUrls: input.previewImgUrls
|
|
31267
|
+
});
|
|
31268
|
+
}
|
|
31269
|
+
},
|
|
31270
|
+
{
|
|
31271
|
+
name: "neopress_template_delete",
|
|
31272
|
+
title: "Delete Template Site",
|
|
31273
|
+
description: "Delete the template metadata row for a finished template site and hard-delete the linked site.",
|
|
31274
|
+
inputSchema: siteIdShape,
|
|
31275
|
+
handler: async (input, context, extra) => {
|
|
31276
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
31277
|
+
return client.templates.delete();
|
|
31278
|
+
}
|
|
31279
|
+
},
|
|
31189
31280
|
{
|
|
31190
31281
|
name: "neopress_layout_get",
|
|
31191
31282
|
title: "Get Layout",
|
package/dist/http-bin.cjs
CHANGED
|
@@ -31857,6 +31857,29 @@ var AnalyticsEndpoint = class {
|
|
|
31857
31857
|
}
|
|
31858
31858
|
};
|
|
31859
31859
|
|
|
31860
|
+
// ../sdk/dist/endpoints/templates.js
|
|
31861
|
+
var TemplatesEndpoint = class {
|
|
31862
|
+
client;
|
|
31863
|
+
constructor(client) {
|
|
31864
|
+
this.client = client;
|
|
31865
|
+
}
|
|
31866
|
+
get basePath() {
|
|
31867
|
+
return `${this.client.siteBasePath}/template`;
|
|
31868
|
+
}
|
|
31869
|
+
async get() {
|
|
31870
|
+
const res = await this.client.get(this.basePath);
|
|
31871
|
+
return res.data;
|
|
31872
|
+
}
|
|
31873
|
+
async mark(data) {
|
|
31874
|
+
const res = await this.client.post(this.basePath, data);
|
|
31875
|
+
return res.data;
|
|
31876
|
+
}
|
|
31877
|
+
async delete() {
|
|
31878
|
+
const res = await this.client.delete(this.basePath);
|
|
31879
|
+
return res.data;
|
|
31880
|
+
}
|
|
31881
|
+
};
|
|
31882
|
+
|
|
31860
31883
|
// ../sdk/dist/client.js
|
|
31861
31884
|
var NeopressClient = class {
|
|
31862
31885
|
baseUrl;
|
|
@@ -31873,6 +31896,7 @@ var NeopressClient = class {
|
|
|
31873
31896
|
publish;
|
|
31874
31897
|
entryReferences;
|
|
31875
31898
|
analytics;
|
|
31899
|
+
templates;
|
|
31876
31900
|
constructor(options) {
|
|
31877
31901
|
this.baseUrl = (options.baseUrl || "https://app.neopress.ai").replace(/\/$/, "");
|
|
31878
31902
|
this.accessToken = options.accessToken || "";
|
|
@@ -31888,6 +31912,7 @@ var NeopressClient = class {
|
|
|
31888
31912
|
this.publish = new PublishEndpoint(this);
|
|
31889
31913
|
this.entryReferences = new EntryReferencesEndpoint(this);
|
|
31890
31914
|
this.analytics = new AnalyticsEndpoint(this);
|
|
31915
|
+
this.templates = new TemplatesEndpoint(this);
|
|
31891
31916
|
}
|
|
31892
31917
|
get siteBasePath() {
|
|
31893
31918
|
return `/api/v1/sites/${this.siteId}`;
|
|
@@ -31918,7 +31943,13 @@ var NeopressClient = class {
|
|
|
31918
31943
|
throw new NeopressApiError("CONNECTION_ERROR", `Cannot connect to ${this.baseUrl} \u2014 is the dev server running?`, 0);
|
|
31919
31944
|
}
|
|
31920
31945
|
clearTimeout(timeout);
|
|
31921
|
-
const
|
|
31946
|
+
const responseText = await response.text();
|
|
31947
|
+
let json2;
|
|
31948
|
+
try {
|
|
31949
|
+
json2 = responseText ? JSON.parse(responseText) : {};
|
|
31950
|
+
} catch {
|
|
31951
|
+
throw new NeopressApiError("NON_JSON_RESPONSE", `Expected JSON from ${method} ${url2} but received non-JSON response (${response.status} ${response.statusText})`, response.status, { body: responseText.slice(0, 500) });
|
|
31952
|
+
}
|
|
31922
31953
|
if (!response.ok) {
|
|
31923
31954
|
const err = json2?.error || {};
|
|
31924
31955
|
throw new NeopressApiError(err.code || "UNKNOWN", err.message || response.statusText, response.status, json2);
|
|
@@ -32109,6 +32140,16 @@ Use these rules before generating pages, collection schemas, entries, forms, or
|
|
|
32109
32140
|
- Generated page TSX is sandboxed. Do not import Supabase, create API clients, read env vars, use filesystem/process APIs, or assume arbitrary npm packages.
|
|
32110
32141
|
- Use allowed runtime packages only: React/Next basics, shadcn UI imports, lucide-react, date-fns, framer-motion, @neopress/content, @neopress/routing, @neopress/i18n, and @neopress/forms.
|
|
32111
32142
|
|
|
32143
|
+
## Templates
|
|
32144
|
+
|
|
32145
|
+
- Reusable templates are normal Neopress sites marked by a \`templates\` metadata row.
|
|
32146
|
+
- \`templates.id\` equals \`sites.id\`.
|
|
32147
|
+
- Build layout, pages, collections, entries, forms, assets, compile, publish, and verify before marking a finished template.
|
|
32148
|
+
- Use \`neopress_template_mark\` to create or update the metadata row with \`name\`, \`industry\`, required \`referenceUrl\`, optional \`description\`, and optional \`previewImgUrls\`.
|
|
32149
|
+
- \`referenceUrl\` is a single http(s) provenance URL. \`description\` is an optional summary of the template (max 150 characters).
|
|
32150
|
+
- Template metadata does not replace page TSX, CMS content, forms, or publish state.
|
|
32151
|
+
- Use \`neopress_template_delete\` only for explicit template-site hard deletion. It removes the metadata row and connected site.
|
|
32152
|
+
|
|
32112
32153
|
## Dynamic pages and queryConfig
|
|
32113
32154
|
|
|
32114
32155
|
- Dynamic pages require a collection, a page path like \`/blog/[slug]\`, a numeric \`collectionId\`, matching entries, entry publish, page compile, and site publish.
|
|
@@ -32142,6 +32183,7 @@ var SERVER_INSTRUCTIONS = `Use Neopress MCP tools to manage a selected Neopress
|
|
|
32142
32183
|
|
|
32143
32184
|
Before generating TSX or schema-backed pages, call neopress_get_runtime_contract or read neopress://runtime-contract.
|
|
32144
32185
|
Use numeric IDs returned by tools. Publish entries separately from site publish. Use read-only analytics tools before autopilot recommendations. Verify production URLs after production publish.
|
|
32186
|
+
For reusable templates, build and publish the real site resources first, then call neopress_template_mark with template metadata.
|
|
32145
32187
|
For reference-page copy, do the reference crawling, screenshots, DOM/CSS/SVG/background-image analysis, and TSX generation in the host agent; MCP only writes and verifies Neopress resources.`;
|
|
32146
32188
|
|
|
32147
32189
|
// src/result.ts
|
|
@@ -32188,6 +32230,10 @@ var optionalJsonSchema = external_exports.unknown().optional();
|
|
|
32188
32230
|
var requiredJsonSchema = external_exports.unknown().refine((value) => value !== void 0, "Required JSON value is missing.");
|
|
32189
32231
|
var analyticsParamSchema = external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()]);
|
|
32190
32232
|
var analyticsParamsSchema = external_exports.record(external_exports.string(), analyticsParamSchema).optional();
|
|
32233
|
+
var httpUrlSchema = external_exports.string().url().refine((value) => {
|
|
32234
|
+
const url2 = new URL(value);
|
|
32235
|
+
return url2.protocol === "http:" || url2.protocol === "https:";
|
|
32236
|
+
}, "Must be an http(s) URL.");
|
|
32191
32237
|
var analyticsDateShape = {
|
|
32192
32238
|
dateFrom: external_exports.string().optional(),
|
|
32193
32239
|
dateTo: external_exports.string().optional(),
|
|
@@ -32232,7 +32278,8 @@ var READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
|
32232
32278
|
"neopress_search_console_query",
|
|
32233
32279
|
"neopress_assets_list",
|
|
32234
32280
|
"neopress_asset_get",
|
|
32235
|
-
"neopress_publish_preview"
|
|
32281
|
+
"neopress_publish_preview",
|
|
32282
|
+
"neopress_template_get"
|
|
32236
32283
|
]);
|
|
32237
32284
|
var DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
32238
32285
|
"neopress_site_update",
|
|
@@ -32250,6 +32297,7 @@ var DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
32250
32297
|
"neopress_form_publish",
|
|
32251
32298
|
"neopress_form_delete",
|
|
32252
32299
|
"neopress_asset_delete",
|
|
32300
|
+
"neopress_template_mark",
|
|
32253
32301
|
"neopress_publish_site"
|
|
32254
32302
|
]);
|
|
32255
32303
|
var PUBLICATION_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -32424,6 +32472,49 @@ var toolDefinitions = [
|
|
|
32424
32472
|
});
|
|
32425
32473
|
}
|
|
32426
32474
|
},
|
|
32475
|
+
{
|
|
32476
|
+
name: "neopress_template_get",
|
|
32477
|
+
title: "Get Template Metadata",
|
|
32478
|
+
description: "Get template metadata for the active or specified site.",
|
|
32479
|
+
inputSchema: siteIdShape,
|
|
32480
|
+
handler: async (input, context, extra) => {
|
|
32481
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
32482
|
+
return client.templates.get();
|
|
32483
|
+
}
|
|
32484
|
+
},
|
|
32485
|
+
{
|
|
32486
|
+
name: "neopress_template_mark",
|
|
32487
|
+
title: "Mark Site As Template",
|
|
32488
|
+
description: "Create or update the template metadata row for a finished template site. The template id is the site id.",
|
|
32489
|
+
inputSchema: {
|
|
32490
|
+
...siteIdShape,
|
|
32491
|
+
name: external_exports.string(),
|
|
32492
|
+
description: external_exports.string().max(150).optional(),
|
|
32493
|
+
industry: external_exports.string(),
|
|
32494
|
+
referenceUrl: httpUrlSchema,
|
|
32495
|
+
previewImgUrls: external_exports.array(external_exports.string()).nullable().optional()
|
|
32496
|
+
},
|
|
32497
|
+
handler: async (input, context, extra) => {
|
|
32498
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
32499
|
+
return client.templates.mark({
|
|
32500
|
+
name: asString(input, "name"),
|
|
32501
|
+
description: asOptionalString(input, "description"),
|
|
32502
|
+
industry: asString(input, "industry"),
|
|
32503
|
+
referenceUrl: asString(input, "referenceUrl"),
|
|
32504
|
+
previewImgUrls: input.previewImgUrls
|
|
32505
|
+
});
|
|
32506
|
+
}
|
|
32507
|
+
},
|
|
32508
|
+
{
|
|
32509
|
+
name: "neopress_template_delete",
|
|
32510
|
+
title: "Delete Template Site",
|
|
32511
|
+
description: "Delete the template metadata row for a finished template site and hard-delete the linked site.",
|
|
32512
|
+
inputSchema: siteIdShape,
|
|
32513
|
+
handler: async (input, context, extra) => {
|
|
32514
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
32515
|
+
return client.templates.delete();
|
|
32516
|
+
}
|
|
32517
|
+
},
|
|
32427
32518
|
{
|
|
32428
32519
|
name: "neopress_layout_get",
|
|
32429
32520
|
title: "Get Layout",
|
package/dist/index.js
CHANGED
|
@@ -30527,6 +30527,29 @@ var AnalyticsEndpoint = class {
|
|
|
30527
30527
|
}
|
|
30528
30528
|
};
|
|
30529
30529
|
|
|
30530
|
+
// ../sdk/dist/endpoints/templates.js
|
|
30531
|
+
var TemplatesEndpoint = class {
|
|
30532
|
+
client;
|
|
30533
|
+
constructor(client) {
|
|
30534
|
+
this.client = client;
|
|
30535
|
+
}
|
|
30536
|
+
get basePath() {
|
|
30537
|
+
return `${this.client.siteBasePath}/template`;
|
|
30538
|
+
}
|
|
30539
|
+
async get() {
|
|
30540
|
+
const res = await this.client.get(this.basePath);
|
|
30541
|
+
return res.data;
|
|
30542
|
+
}
|
|
30543
|
+
async mark(data) {
|
|
30544
|
+
const res = await this.client.post(this.basePath, data);
|
|
30545
|
+
return res.data;
|
|
30546
|
+
}
|
|
30547
|
+
async delete() {
|
|
30548
|
+
const res = await this.client.delete(this.basePath);
|
|
30549
|
+
return res.data;
|
|
30550
|
+
}
|
|
30551
|
+
};
|
|
30552
|
+
|
|
30530
30553
|
// ../sdk/dist/client.js
|
|
30531
30554
|
var NeopressClient = class {
|
|
30532
30555
|
baseUrl;
|
|
@@ -30543,6 +30566,7 @@ var NeopressClient = class {
|
|
|
30543
30566
|
publish;
|
|
30544
30567
|
entryReferences;
|
|
30545
30568
|
analytics;
|
|
30569
|
+
templates;
|
|
30546
30570
|
constructor(options) {
|
|
30547
30571
|
this.baseUrl = (options.baseUrl || "https://app.neopress.ai").replace(/\/$/, "");
|
|
30548
30572
|
this.accessToken = options.accessToken || "";
|
|
@@ -30558,6 +30582,7 @@ var NeopressClient = class {
|
|
|
30558
30582
|
this.publish = new PublishEndpoint(this);
|
|
30559
30583
|
this.entryReferences = new EntryReferencesEndpoint(this);
|
|
30560
30584
|
this.analytics = new AnalyticsEndpoint(this);
|
|
30585
|
+
this.templates = new TemplatesEndpoint(this);
|
|
30561
30586
|
}
|
|
30562
30587
|
get siteBasePath() {
|
|
30563
30588
|
return `/api/v1/sites/${this.siteId}`;
|
|
@@ -30588,7 +30613,13 @@ var NeopressClient = class {
|
|
|
30588
30613
|
throw new NeopressApiError("CONNECTION_ERROR", `Cannot connect to ${this.baseUrl} \u2014 is the dev server running?`, 0);
|
|
30589
30614
|
}
|
|
30590
30615
|
clearTimeout(timeout);
|
|
30591
|
-
const
|
|
30616
|
+
const responseText = await response.text();
|
|
30617
|
+
let json2;
|
|
30618
|
+
try {
|
|
30619
|
+
json2 = responseText ? JSON.parse(responseText) : {};
|
|
30620
|
+
} catch {
|
|
30621
|
+
throw new NeopressApiError("NON_JSON_RESPONSE", `Expected JSON from ${method} ${url2} but received non-JSON response (${response.status} ${response.statusText})`, response.status, { body: responseText.slice(0, 500) });
|
|
30622
|
+
}
|
|
30592
30623
|
if (!response.ok) {
|
|
30593
30624
|
const err = json2?.error || {};
|
|
30594
30625
|
throw new NeopressApiError(err.code || "UNKNOWN", err.message || response.statusText, response.status, json2);
|
|
@@ -30779,6 +30810,16 @@ Use these rules before generating pages, collection schemas, entries, forms, or
|
|
|
30779
30810
|
- Generated page TSX is sandboxed. Do not import Supabase, create API clients, read env vars, use filesystem/process APIs, or assume arbitrary npm packages.
|
|
30780
30811
|
- Use allowed runtime packages only: React/Next basics, shadcn UI imports, lucide-react, date-fns, framer-motion, @neopress/content, @neopress/routing, @neopress/i18n, and @neopress/forms.
|
|
30781
30812
|
|
|
30813
|
+
## Templates
|
|
30814
|
+
|
|
30815
|
+
- Reusable templates are normal Neopress sites marked by a \`templates\` metadata row.
|
|
30816
|
+
- \`templates.id\` equals \`sites.id\`.
|
|
30817
|
+
- Build layout, pages, collections, entries, forms, assets, compile, publish, and verify before marking a finished template.
|
|
30818
|
+
- Use \`neopress_template_mark\` to create or update the metadata row with \`name\`, \`industry\`, required \`referenceUrl\`, optional \`description\`, and optional \`previewImgUrls\`.
|
|
30819
|
+
- \`referenceUrl\` is a single http(s) provenance URL. \`description\` is an optional summary of the template (max 150 characters).
|
|
30820
|
+
- Template metadata does not replace page TSX, CMS content, forms, or publish state.
|
|
30821
|
+
- Use \`neopress_template_delete\` only for explicit template-site hard deletion. It removes the metadata row and connected site.
|
|
30822
|
+
|
|
30782
30823
|
## Dynamic pages and queryConfig
|
|
30783
30824
|
|
|
30784
30825
|
- Dynamic pages require a collection, a page path like \`/blog/[slug]\`, a numeric \`collectionId\`, matching entries, entry publish, page compile, and site publish.
|
|
@@ -30812,6 +30853,7 @@ var SERVER_INSTRUCTIONS = `Use Neopress MCP tools to manage a selected Neopress
|
|
|
30812
30853
|
|
|
30813
30854
|
Before generating TSX or schema-backed pages, call neopress_get_runtime_contract or read neopress://runtime-contract.
|
|
30814
30855
|
Use numeric IDs returned by tools. Publish entries separately from site publish. Use read-only analytics tools before autopilot recommendations. Verify production URLs after production publish.
|
|
30856
|
+
For reusable templates, build and publish the real site resources first, then call neopress_template_mark with template metadata.
|
|
30815
30857
|
For reference-page copy, do the reference crawling, screenshots, DOM/CSS/SVG/background-image analysis, and TSX generation in the host agent; MCP only writes and verifies Neopress resources.`;
|
|
30816
30858
|
|
|
30817
30859
|
// src/result.ts
|
|
@@ -30858,6 +30900,10 @@ var optionalJsonSchema = external_exports3.unknown().optional();
|
|
|
30858
30900
|
var requiredJsonSchema = external_exports3.unknown().refine((value) => value !== void 0, "Required JSON value is missing.");
|
|
30859
30901
|
var analyticsParamSchema = external_exports3.union([external_exports3.string(), external_exports3.number(), external_exports3.boolean()]);
|
|
30860
30902
|
var analyticsParamsSchema = external_exports3.record(external_exports3.string(), analyticsParamSchema).optional();
|
|
30903
|
+
var httpUrlSchema = external_exports3.string().url().refine((value) => {
|
|
30904
|
+
const url2 = new URL(value);
|
|
30905
|
+
return url2.protocol === "http:" || url2.protocol === "https:";
|
|
30906
|
+
}, "Must be an http(s) URL.");
|
|
30861
30907
|
var analyticsDateShape = {
|
|
30862
30908
|
dateFrom: external_exports3.string().optional(),
|
|
30863
30909
|
dateTo: external_exports3.string().optional(),
|
|
@@ -30902,7 +30948,8 @@ var READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
|
30902
30948
|
"neopress_search_console_query",
|
|
30903
30949
|
"neopress_assets_list",
|
|
30904
30950
|
"neopress_asset_get",
|
|
30905
|
-
"neopress_publish_preview"
|
|
30951
|
+
"neopress_publish_preview",
|
|
30952
|
+
"neopress_template_get"
|
|
30906
30953
|
]);
|
|
30907
30954
|
var DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
30908
30955
|
"neopress_site_update",
|
|
@@ -30920,6 +30967,7 @@ var DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
30920
30967
|
"neopress_form_publish",
|
|
30921
30968
|
"neopress_form_delete",
|
|
30922
30969
|
"neopress_asset_delete",
|
|
30970
|
+
"neopress_template_mark",
|
|
30923
30971
|
"neopress_publish_site"
|
|
30924
30972
|
]);
|
|
30925
30973
|
var PUBLICATION_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -31094,6 +31142,49 @@ var toolDefinitions = [
|
|
|
31094
31142
|
});
|
|
31095
31143
|
}
|
|
31096
31144
|
},
|
|
31145
|
+
{
|
|
31146
|
+
name: "neopress_template_get",
|
|
31147
|
+
title: "Get Template Metadata",
|
|
31148
|
+
description: "Get template metadata for the active or specified site.",
|
|
31149
|
+
inputSchema: siteIdShape,
|
|
31150
|
+
handler: async (input, context, extra) => {
|
|
31151
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
31152
|
+
return client.templates.get();
|
|
31153
|
+
}
|
|
31154
|
+
},
|
|
31155
|
+
{
|
|
31156
|
+
name: "neopress_template_mark",
|
|
31157
|
+
title: "Mark Site As Template",
|
|
31158
|
+
description: "Create or update the template metadata row for a finished template site. The template id is the site id.",
|
|
31159
|
+
inputSchema: {
|
|
31160
|
+
...siteIdShape,
|
|
31161
|
+
name: external_exports3.string(),
|
|
31162
|
+
description: external_exports3.string().max(150).optional(),
|
|
31163
|
+
industry: external_exports3.string(),
|
|
31164
|
+
referenceUrl: httpUrlSchema,
|
|
31165
|
+
previewImgUrls: external_exports3.array(external_exports3.string()).nullable().optional()
|
|
31166
|
+
},
|
|
31167
|
+
handler: async (input, context, extra) => {
|
|
31168
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
31169
|
+
return client.templates.mark({
|
|
31170
|
+
name: asString(input, "name"),
|
|
31171
|
+
description: asOptionalString(input, "description"),
|
|
31172
|
+
industry: asString(input, "industry"),
|
|
31173
|
+
referenceUrl: asString(input, "referenceUrl"),
|
|
31174
|
+
previewImgUrls: input.previewImgUrls
|
|
31175
|
+
});
|
|
31176
|
+
}
|
|
31177
|
+
},
|
|
31178
|
+
{
|
|
31179
|
+
name: "neopress_template_delete",
|
|
31180
|
+
title: "Delete Template Site",
|
|
31181
|
+
description: "Delete the template metadata row for a finished template site and hard-delete the linked site.",
|
|
31182
|
+
inputSchema: siteIdShape,
|
|
31183
|
+
handler: async (input, context, extra) => {
|
|
31184
|
+
const client = await context.createClient({ siteId: siteId(input) }, extra);
|
|
31185
|
+
return client.templates.delete();
|
|
31186
|
+
}
|
|
31187
|
+
},
|
|
31097
31188
|
{
|
|
31098
31189
|
name: "neopress_layout_get",
|
|
31099
31190
|
title: "Get Layout",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neopress/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Neopress MCP server for first-party AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"tsup": "^8.5.1",
|
|
34
34
|
"typescript": "^5.7.0",
|
|
35
35
|
"vitest": "^4.1.5",
|
|
36
|
-
"@neopress/sdk": "0.1
|
|
36
|
+
"@neopress/sdk": "0.3.1"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsup",
|