@timelesscms-com/mcp-server 0.4.0 → 0.6.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/tools/bulk.js +1 -1
- package/dist/tools/deploy.js +1 -1
- package/dist/tools/pages.js +9 -1
- package/dist/tools/settings.js +13 -5
- package/package.json +1 -1
package/dist/tools/bulk.js
CHANGED
|
@@ -6,7 +6,7 @@ function v(version) {
|
|
|
6
6
|
export const bulkTools = [
|
|
7
7
|
{
|
|
8
8
|
name: 'bulk_replace_text',
|
|
9
|
-
description: 'Replace a literal substring or regex across pages in one call. ALWAYS run with dry_run=true first and show the sample_diffs to the user before running the real call. Writes go through the normal pipeline (SEO transforms + revision snapshots).',
|
|
9
|
+
description: 'Replace a literal substring or regex across pages in one call. ALWAYS run with dry_run=true first and show the sample_diffs to the user before running the real call. Writes go through the normal pipeline (SEO transforms + revision snapshots). Response shape: { dry_run, updated, total_matches, pages_with_matches, sample_diffs_shown, additional_pages_with_matches, sample_diffs[], skipped (deprecated) }.',
|
|
10
10
|
inputSchema: {
|
|
11
11
|
pattern: z.string().min(1).describe('Literal substring (default) or JS regex source if regex=true.'),
|
|
12
12
|
replacement: z.string(),
|
package/dist/tools/deploy.js
CHANGED
|
@@ -27,7 +27,7 @@ export const deployTools = [
|
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
name: 'get_deploy_status',
|
|
30
|
-
description:
|
|
30
|
+
description: "Status of a single deploy job. Returns { job, queued_for_seconds, queue_timeout_seconds }. job.status is one of queued | running | succeeded | failed. Polling cadence: ~5s for queued/running. A job stuck in 'queued' for longer than queue_timeout_seconds (default 300s) auto-flips to failed with phase='queue_timeout' — so a single poll past that timestamp returns the terminal state and you can stop polling.",
|
|
31
31
|
inputSchema: { job_id: z.string() },
|
|
32
32
|
handler: withErrorBoundary(async (args, { client, siteId }) => {
|
|
33
33
|
const res = await client.get(siteId, `deploys/${encodeURIComponent(args.job_id)}`);
|
package/dist/tools/pages.js
CHANGED
|
@@ -151,9 +151,17 @@ export const pageTools = [
|
|
|
151
151
|
// 2. Build the new page body. Title + slug from args, everything else
|
|
152
152
|
// copied — except the new page always starts as a draft so cloning
|
|
153
153
|
// a published page doesn't accidentally publish a half-edited copy.
|
|
154
|
+
// Critical: preserve the source's content_mode exactly. Without
|
|
155
|
+
// this, create_page falls back to its blocks-default and seeds a
|
|
156
|
+
// fresh heading+prose tree, leaving the clone with TWO content
|
|
157
|
+
// sources (the copied html_content AND a default blocks[]). Bug
|
|
158
|
+
// surfaced in MCP-FEEDBACK-2.md from the Sundsvallsflytt demo build.
|
|
159
|
+
const srcMode = src.content_mode ?? 'html';
|
|
154
160
|
const body = {
|
|
155
161
|
title: args.title,
|
|
156
|
-
|
|
162
|
+
content_mode: srcMode,
|
|
163
|
+
html_content: srcMode === 'html' ? src.html_content : '',
|
|
164
|
+
blocks: srcMode === 'blocks' ? (src.blocks ?? []) : undefined,
|
|
157
165
|
seo_title: src.seo_title,
|
|
158
166
|
seo_description: src.seo_description,
|
|
159
167
|
og_image: src.og_image,
|
package/dist/tools/settings.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
// Settings tools. scripts_head, scripts_body_end, and custom_css
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Settings tools. scripts_head, scripts_body_end, and custom_css ARE
|
|
2
|
+
// writable via the public API (as of mcp-server 0.4.x) — the v1 route
|
|
3
|
+
// accepts them and they round-trip through read_site_settings. Same
|
|
4
|
+
// trust model as user-authored block-type JS: a bearer-token caller
|
|
5
|
+
// takes responsibility for what they ship. The portal chat AI still
|
|
6
|
+
// doesn't expose these fields, so conversation-driven assistants can't
|
|
7
|
+
// smuggle scripts in.
|
|
4
8
|
import { z } from 'zod';
|
|
5
9
|
import { ok, withErrorBoundary } from './helpers.js';
|
|
6
10
|
export const settingsTools = [
|
|
7
11
|
{
|
|
8
12
|
name: 'read_site_settings',
|
|
9
|
-
description:
|
|
13
|
+
description: "Read every site setting: name, tagline, logo, favicon, colors, fonts, contact info, social links, default SEO suffix, language, robots_txt, plus the scriptable surfaces scripts_head, scripts_body_end, and custom_css.",
|
|
10
14
|
handler: withErrorBoundary(async (_args, { client, siteId }) => {
|
|
11
15
|
const res = await client.get(siteId, 'settings');
|
|
12
16
|
return ok(res);
|
|
@@ -14,7 +18,7 @@ export const settingsTools = [
|
|
|
14
18
|
},
|
|
15
19
|
{
|
|
16
20
|
name: 'update_site_settings',
|
|
17
|
-
description: 'Patch site settings. Only the fields you pass change. Nested objects (colors, fonts, contact, social) are shallow-merged.
|
|
21
|
+
description: 'Patch site settings. Only the fields you pass change. Nested objects (colors, fonts, contact, social) are shallow-merged. scripts_head / scripts_body_end / custom_css ARE writable here — useful for a global stylesheet across all pages. Whatever you ship in those fields runs verbatim on the rendered site, so treat them as code, not data.',
|
|
18
22
|
inputSchema: {
|
|
19
23
|
site_name: z.string().optional(),
|
|
20
24
|
tagline: z.string().optional(),
|
|
@@ -23,6 +27,10 @@ export const settingsTools = [
|
|
|
23
27
|
default_seo_suffix: z.string().optional(),
|
|
24
28
|
language: z.string().optional().describe('BCP-47 tag (e.g. "en", "sv", "en-GB"). Drives <html lang> on the rendered site.'),
|
|
25
29
|
robots_txt: z.string().optional(),
|
|
30
|
+
// Scriptable surfaces. Trusted because the caller has an API key.
|
|
31
|
+
scripts_head: z.string().optional().describe('Raw HTML injected into <head> on every page. Use for analytics, fonts, third-party CSS links.'),
|
|
32
|
+
scripts_body_end: z.string().optional().describe('Raw HTML injected just before </body> on every page. Use for chat widgets, deferred analytics.'),
|
|
33
|
+
custom_css: z.string().optional().describe('Global CSS shipped in <style> at the end of <head>. Lets you define site-wide design tokens (CSS variables, @media queries, :hover states) without inlining on every element.'),
|
|
26
34
|
colors: z.record(z.string()).optional(),
|
|
27
35
|
fonts: z.record(z.unknown()).optional(),
|
|
28
36
|
contact: z
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timelesscms-com/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Model Context Protocol server for the TimelessCMS public API. Use with Claude Code or any MCP-compatible client to manage a TimelessCMS site.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|