@wootsup/yt-builder-mcp 1.1.7 → 1.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/README.md +7 -7
- package/bin/yt-builder-mcp.js +55 -40
- package/dist/auth.d.ts +18 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +18 -0
- package/dist/auth.js.map +1 -1
- package/dist/cli/invocation-decision.d.ts +57 -0
- package/dist/cli/invocation-decision.d.ts.map +1 -0
- package/dist/cli/invocation-decision.js +86 -0
- package/dist/cli/invocation-decision.js.map +1 -0
- package/dist/client.d.ts +28 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +40 -1
- package/dist/client.js.map +1 -1
- package/dist/clients/claude-code.d.ts.map +1 -1
- package/dist/clients/claude-code.js +3 -1
- package/dist/clients/claude-code.js.map +1 -1
- package/dist/clients/claude-desktop.d.ts.map +1 -1
- package/dist/clients/claude-desktop.js +3 -1
- package/dist/clients/claude-desktop.js.map +1 -1
- package/dist/clients/cline.d.ts.map +1 -1
- package/dist/clients/cline.js +3 -1
- package/dist/clients/cline.js.map +1 -1
- package/dist/clients/codex-cli.d.ts +1 -1
- package/dist/clients/codex-cli.d.ts.map +1 -1
- package/dist/clients/codex-cli.js +98 -0
- package/dist/clients/codex-cli.js.map +1 -1
- package/dist/clients/continue.d.ts.map +1 -1
- package/dist/clients/continue.js +70 -1
- package/dist/clients/continue.js.map +1 -1
- package/dist/clients/cursor.d.ts.map +1 -1
- package/dist/clients/cursor.js +3 -1
- package/dist/clients/cursor.js.map +1 -1
- package/dist/clients/gemini-cli.d.ts.map +1 -1
- package/dist/clients/gemini-cli.js +3 -1
- package/dist/clients/gemini-cli.js.map +1 -1
- package/dist/clients/index.d.ts +104 -0
- package/dist/clients/index.d.ts.map +1 -1
- package/dist/clients/index.js +141 -0
- package/dist/clients/index.js.map +1 -1
- package/dist/clients/roo-code.d.ts.map +1 -1
- package/dist/clients/roo-code.js +3 -1
- package/dist/clients/roo-code.js.map +1 -1
- package/dist/clients/zed.d.ts.map +1 -1
- package/dist/clients/zed.js +3 -1
- package/dist/clients/zed.js.map +1 -1
- package/dist/gateway/essentials.d.ts +4 -4
- package/dist/gateway/essentials.d.ts.map +1 -1
- package/dist/gateway/essentials.js +19 -5
- package/dist/gateway/essentials.js.map +1 -1
- package/dist/gateway/test-support.d.ts +3 -3
- package/dist/gateway/test-support.js +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/install-skill.js +1 -1
- package/dist/server.d.ts +3 -3
- package/dist/server.js +3 -3
- package/dist/setup-cli.d.ts +41 -0
- package/dist/setup-cli.d.ts.map +1 -1
- package/dist/setup-cli.js +163 -1
- package/dist/setup-cli.js.map +1 -1
- package/dist/setup-prompts.d.ts +23 -0
- package/dist/setup-prompts.d.ts.map +1 -1
- package/dist/setup-prompts.js +76 -1
- package/dist/setup-prompts.js.map +1 -1
- package/dist/sites/bootstrap.d.ts +41 -0
- package/dist/sites/bootstrap.d.ts.map +1 -0
- package/dist/sites/bootstrap.js +58 -0
- package/dist/sites/bootstrap.js.map +1 -0
- package/dist/sites/client-pool.d.ts +33 -0
- package/dist/sites/client-pool.d.ts.map +1 -1
- package/dist/sites/client-pool.js +51 -1
- package/dist/sites/client-pool.js.map +1 -1
- package/dist/sites/tools/index.d.ts.map +1 -1
- package/dist/sites/tools/index.js +9 -1
- package/dist/sites/tools/index.js.map +1 -1
- package/dist/sites/tools/use-site.d.ts +47 -0
- package/dist/sites/tools/use-site.d.ts.map +1 -0
- package/dist/sites/tools/use-site.js +183 -0
- package/dist/sites/tools/use-site.js.map +1 -0
- package/dist/tools/elements/builders.d.ts.map +1 -1
- package/dist/tools/elements/builders.js +16 -7
- package/dist/tools/elements/builders.js.map +1 -1
- package/dist/tools/elements/handlers-write.d.ts +1 -1
- package/dist/tools/elements/handlers-write.d.ts.map +1 -1
- package/dist/tools/elements/handlers-write.js +202 -9
- package/dist/tools/elements/handlers-write.js.map +1 -1
- package/dist/tools/elements/handlers.d.ts.map +1 -1
- package/dist/tools/elements/handlers.js +3 -3
- package/dist/tools/elements/handlers.js.map +1 -1
- package/dist/tools/format/elements-format.d.ts.map +1 -1
- package/dist/tools/format/elements-format.js +10 -11
- package/dist/tools/format/elements-format.js.map +1 -1
- package/dist/tools/format/inspection-format.d.ts +11 -0
- package/dist/tools/format/inspection-format.d.ts.map +1 -1
- package/dist/tools/format/inspection-format.js +77 -21
- package/dist/tools/format/inspection-format.js.map +1 -1
- package/dist/tools/inspection.d.ts.map +1 -1
- package/dist/tools/inspection.js +194 -1
- package/dist/tools/inspection.js.map +1 -1
- package/dist/tools/multi-items/builders.d.ts.map +1 -1
- package/dist/tools/multi-items/builders.js +7 -1
- package/dist/tools/multi-items/builders.js.map +1 -1
- package/dist/tools/multi-items/clean-implode-handler.d.ts.map +1 -1
- package/dist/tools/multi-items/clean-implode-handler.js +2 -2
- package/dist/tools/multi-items/clean-implode-handler.js.map +1 -1
- package/dist/tools/multi-items/format/inspection-format.d.ts +41 -0
- package/dist/tools/multi-items/format/inspection-format.d.ts.map +1 -0
- package/dist/tools/multi-items/format/inspection-format.js +64 -0
- package/dist/tools/multi-items/format/inspection-format.js.map +1 -0
- package/dist/tools/multi-items/inspect-handler.d.ts +37 -2
- package/dist/tools/multi-items/inspect-handler.d.ts.map +1 -1
- package/dist/tools/multi-items/inspect-handler.js +93 -10
- package/dist/tools/multi-items/inspect-handler.js.map +1 -1
- package/dist/tools/multi-items/inspection-cache.d.ts +85 -0
- package/dist/tools/multi-items/inspection-cache.d.ts.map +1 -0
- package/dist/tools/multi-items/inspection-cache.js +126 -0
- package/dist/tools/multi-items/inspection-cache.js.map +1 -0
- package/dist/tools/pages/builders.d.ts +31 -2
- package/dist/tools/pages/builders.d.ts.map +1 -1
- package/dist/tools/pages/builders.js +102 -9
- package/dist/tools/pages/builders.js.map +1 -1
- package/dist/tools/pages/handlers-read.d.ts +1 -1
- package/dist/tools/pages/handlers-read.d.ts.map +1 -1
- package/dist/tools/pages/handlers-read.js +78 -21
- package/dist/tools/pages/handlers-read.js.map +1 -1
- package/dist/tools/pages/handlers-write.d.ts +48 -6
- package/dist/tools/pages/handlers-write.d.ts.map +1 -1
- package/dist/tools/pages/handlers-write.js +83 -8
- package/dist/tools/pages/handlers-write.js.map +1 -1
- package/dist/tools/pages/schemas.d.ts +112 -0
- package/dist/tools/pages/schemas.d.ts.map +1 -1
- package/dist/tools/pages/schemas.js +150 -0
- package/dist/tools/pages/schemas.js.map +1 -1
- package/dist/tools/shared-schemas.d.ts.map +1 -1
- package/dist/tools/shared-schemas.js +15 -2
- package/dist/tools/shared-schemas.js.map +1 -1
- package/dist/tools/sources/handlers-bind.d.ts.map +1 -1
- package/dist/tools/sources/handlers-bind.js +56 -4
- package/dist/tools/sources/handlers-bind.js.map +1 -1
- package/dist/tools/sources/handlers.d.ts.map +1 -1
- package/dist/tools/sources/handlers.js +2 -2
- package/dist/tools/sources/handlers.js.map +1 -1
- package/dist/uninstall-skill.d.ts +52 -0
- package/dist/uninstall-skill.d.ts.map +1 -0
- package/dist/uninstall-skill.js +146 -0
- package/dist/uninstall-skill.js.map +1 -0
- package/dist/uninstall.d.ts +73 -0
- package/dist/uninstall.d.ts.map +1 -0
- package/dist/uninstall.js +82 -0
- package/dist/uninstall.js.map +1 -0
- package/icon.png +0 -0
- package/manifest.json +10 -10
- package/package.json +4 -2
- package/skills/yt-builder-mcp/SKILL.md +30 -26
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `uninstall-skill` — the inverse of {@link installSkill}.
|
|
3
|
+
*
|
|
4
|
+
* Removes the bundled skill directory from the user's agent-skill folder
|
|
5
|
+
* (`~/.claude/skills/yt-builder-mcp/`, plus the legacy
|
|
6
|
+
* `~/.claude/skills/yootheme-builder/`) and strips the marker block this
|
|
7
|
+
* package appended to `~/AGENTS.md`.
|
|
8
|
+
*
|
|
9
|
+
* Idempotent + non-destructive to the user's own content: only OUR
|
|
10
|
+
* `## YT Builder MCP` marker section is removed from AGENTS.md; every
|
|
11
|
+
* other line the user wrote is preserved verbatim.
|
|
12
|
+
*
|
|
13
|
+
* @license MIT
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, readFileSync, rmSync, writeFileSync, } from 'node:fs';
|
|
16
|
+
import { homedir } from 'node:os';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { MARKER_LINE } from './install-skill.js';
|
|
19
|
+
/** Skill folder names this package has ever installed (canonical first). */
|
|
20
|
+
const SKILL_DIR_NAMES = ['yt-builder-mcp', 'yootheme-builder'];
|
|
21
|
+
function resolveSkillsDir(opts) {
|
|
22
|
+
return opts.targetSkillsDir ?? join(homedir(), '.claude', 'skills');
|
|
23
|
+
}
|
|
24
|
+
function resolveAgentsFile(opts) {
|
|
25
|
+
return opts.targetAgentsFile ?? join(homedir(), 'AGENTS.md');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* True when a skill folder OR an AGENTS.md marker is present — used by
|
|
29
|
+
* the uninstall CLI to decide whether to surface the "remove skill"
|
|
30
|
+
* checkbox at all.
|
|
31
|
+
*/
|
|
32
|
+
export function isSkillInstalled(opts = {}) {
|
|
33
|
+
const skillsDir = resolveSkillsDir(opts);
|
|
34
|
+
for (const name of SKILL_DIR_NAMES) {
|
|
35
|
+
if (existsSync(join(skillsDir, name)))
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
const agentsFile = resolveAgentsFile(opts);
|
|
39
|
+
if (existsSync(agentsFile)) {
|
|
40
|
+
try {
|
|
41
|
+
if (readFileSync(agentsFile, 'utf-8').includes(MARKER_LINE))
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// unreadable → treat as not-installed
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Strip our `## YT Builder MCP` marker section from an AGENTS.md body.
|
|
52
|
+
*
|
|
53
|
+
* The block installSkill writes is:
|
|
54
|
+
*
|
|
55
|
+
* \n\n## YT Builder MCP\n\n<MARKER_LINE>\n<a few prose lines>\n
|
|
56
|
+
*
|
|
57
|
+
* It is always appended at EOF. We locate the `## YT Builder MCP`
|
|
58
|
+
* heading whose following lines contain {@link MARKER_LINE}, then remove
|
|
59
|
+
* from that heading (collapsing the blank lines that preceded it) up to
|
|
60
|
+
* the next top-level/section heading (`# ` or `## `) or EOF. Returns the
|
|
61
|
+
* cleaned body, or `null` when no marker block was found (no-op).
|
|
62
|
+
*/
|
|
63
|
+
export function stripMarkerBlock(body) {
|
|
64
|
+
if (!body.includes(MARKER_LINE))
|
|
65
|
+
return null;
|
|
66
|
+
const lines = body.split('\n');
|
|
67
|
+
// Find the `## YT Builder MCP` heading that owns the marker line.
|
|
68
|
+
let headingIdx = -1;
|
|
69
|
+
for (let i = 0; i < lines.length; i++) {
|
|
70
|
+
if (lines[i].trim() === '## YT Builder MCP') {
|
|
71
|
+
// Confirm the marker line appears before the next heading.
|
|
72
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
73
|
+
const t = lines[j];
|
|
74
|
+
if (/^#{1,2}\s/.test(t))
|
|
75
|
+
break;
|
|
76
|
+
if (t.includes(MARKER_LINE)) {
|
|
77
|
+
headingIdx = i;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (headingIdx !== -1)
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
// Fallback: marker present but no recognised heading (hand-edited).
|
|
86
|
+
// Remove just the marker line + its immediate prose paragraph.
|
|
87
|
+
if (headingIdx === -1) {
|
|
88
|
+
const filtered = lines.filter((l) => !l.includes(MARKER_LINE));
|
|
89
|
+
const cleaned = filtered.join('\n');
|
|
90
|
+
return cleaned === body ? null : cleaned;
|
|
91
|
+
}
|
|
92
|
+
// Walk to the end of the block: next `# `/`## ` heading or EOF.
|
|
93
|
+
let endIdx = lines.length;
|
|
94
|
+
for (let j = headingIdx + 1; j < lines.length; j++) {
|
|
95
|
+
if (/^#{1,2}\s/.test(lines[j])) {
|
|
96
|
+
endIdx = j;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Collapse trailing blank lines that immediately preceded the heading
|
|
101
|
+
// so we don't leave a widening gap.
|
|
102
|
+
let startIdx = headingIdx;
|
|
103
|
+
while (startIdx > 0 && lines[startIdx - 1].trim() === '') {
|
|
104
|
+
startIdx--;
|
|
105
|
+
}
|
|
106
|
+
const kept = [...lines.slice(0, startIdx), ...lines.slice(endIdx)];
|
|
107
|
+
let cleaned = kept.join('\n');
|
|
108
|
+
// Normalise trailing whitespace: collapse 3+ newlines, ensure single
|
|
109
|
+
// trailing newline when there is content.
|
|
110
|
+
cleaned = cleaned.replace(/\n{3,}/g, '\n\n').replace(/\n*$/, '');
|
|
111
|
+
if (cleaned !== '')
|
|
112
|
+
cleaned += '\n';
|
|
113
|
+
return cleaned;
|
|
114
|
+
}
|
|
115
|
+
export async function uninstallSkill(options = {}) {
|
|
116
|
+
const skillsDir = resolveSkillsDir(options);
|
|
117
|
+
const agentsFile = resolveAgentsFile(options);
|
|
118
|
+
const skillTargetDir = join(skillsDir, SKILL_DIR_NAMES[0]);
|
|
119
|
+
// 1. Remove skill directories (canonical + legacy).
|
|
120
|
+
let skillRemoved = false;
|
|
121
|
+
for (const name of SKILL_DIR_NAMES) {
|
|
122
|
+
const dir = join(skillsDir, name);
|
|
123
|
+
if (existsSync(dir)) {
|
|
124
|
+
rmSync(dir, { recursive: true, force: true });
|
|
125
|
+
skillRemoved = true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// 2. Strip the marker block from AGENTS.md.
|
|
129
|
+
let markerRemoved = false;
|
|
130
|
+
if (existsSync(agentsFile)) {
|
|
131
|
+
let body = '';
|
|
132
|
+
try {
|
|
133
|
+
body = readFileSync(agentsFile, 'utf-8');
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
body = '';
|
|
137
|
+
}
|
|
138
|
+
const cleaned = stripMarkerBlock(body);
|
|
139
|
+
if (cleaned !== null) {
|
|
140
|
+
writeFileSync(agentsFile, cleaned, 'utf-8');
|
|
141
|
+
markerRemoved = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return { skillRemoved, skillTargetDir, markerRemoved, agentsFile };
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=uninstall-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstall-skill.js","sourceRoot":"","sources":["../src/uninstall-skill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uninstall orchestration core — the inverse of the setup wizard.
|
|
3
|
+
*
|
|
4
|
+
* `setup` writes the yt-builder-mcp MCP server entry into one or more AI
|
|
5
|
+
* clients' config files (and optionally installs a skill). `uninstall`
|
|
6
|
+
* reverses that: it detects which clients currently carry our entry,
|
|
7
|
+
* removes the chosen ones, and optionally removes the installed skill.
|
|
8
|
+
*
|
|
9
|
+
* This module is the pure, testable core: detection + removal across the
|
|
10
|
+
* client registry, with every side effect injected via {@link
|
|
11
|
+
* UninstallDeps} so unit tests touch no real disk. The interactive clack
|
|
12
|
+
* checklist + the CLI flag-parsing live in `setup-cli.ts` and call into
|
|
13
|
+
* `detectInstalledClients` / `runUninstall` here.
|
|
14
|
+
*
|
|
15
|
+
* @license MIT
|
|
16
|
+
*/
|
|
17
|
+
import { type ClientWriter } from './clients/index.js';
|
|
18
|
+
import { isSkillInstalled as defaultIsSkillInstalled, uninstallSkill as defaultUninstallSkill, type UninstallSkillResult } from './uninstall-skill.js';
|
|
19
|
+
/** A client that currently carries a yt-builder-mcp server entry. */
|
|
20
|
+
export interface InstalledClient {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly label: string;
|
|
23
|
+
readonly configPath: string;
|
|
24
|
+
/** The server keys/names found (e.g. `['yt-builder-mcp']`). */
|
|
25
|
+
readonly matchedKeys: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Probe every client in `clients` and return those whose config carries
|
|
29
|
+
* our server entry. Detection is parallel — the probes are independent
|
|
30
|
+
* file reads.
|
|
31
|
+
*/
|
|
32
|
+
export declare function detectInstalledClients(clients?: readonly ClientWriter[]): Promise<InstalledClient[]>;
|
|
33
|
+
/** What the caller asked to uninstall. */
|
|
34
|
+
export interface UninstallSelection {
|
|
35
|
+
/** Client ids to remove our entry from. */
|
|
36
|
+
readonly clientIds: readonly string[];
|
|
37
|
+
/** Also remove the installed skill (+ AGENTS.md marker)? */
|
|
38
|
+
readonly removeSkill: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Per-client outcome of a removal. */
|
|
41
|
+
export interface ClientUninstallResult {
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly label: string;
|
|
44
|
+
readonly configPath: string;
|
|
45
|
+
/** True when an entry was actually removed (false on no-op or error). */
|
|
46
|
+
readonly removed: boolean;
|
|
47
|
+
/** The keys removed (empty on no-op / error). */
|
|
48
|
+
readonly removedKeys: readonly string[];
|
|
49
|
+
/** Populated when removal threw. */
|
|
50
|
+
readonly error?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface UninstallResult {
|
|
53
|
+
readonly clientResults: readonly ClientUninstallResult[];
|
|
54
|
+
/** Present only when `removeSkill` was requested. */
|
|
55
|
+
readonly skillResult?: UninstallSkillResult;
|
|
56
|
+
}
|
|
57
|
+
/** Injectable side effects so tests run without touching disk. */
|
|
58
|
+
export interface UninstallDeps {
|
|
59
|
+
/** Registry to resolve `clientIds` against. */
|
|
60
|
+
readonly clients: readonly ClientWriter[];
|
|
61
|
+
readonly uninstallSkill: typeof defaultUninstallSkill;
|
|
62
|
+
readonly isSkillInstalled: typeof defaultIsSkillInstalled;
|
|
63
|
+
}
|
|
64
|
+
export declare const DEFAULT_UNINSTALL_DEPS: UninstallDeps;
|
|
65
|
+
/**
|
|
66
|
+
* Execute an uninstall. Removes our server entry from each selected,
|
|
67
|
+
* KNOWN client id (unknown ids are silently skipped) and — when
|
|
68
|
+
* `removeSkill` is set — removes the installed skill. Each client removal
|
|
69
|
+
* is isolated: a failure on one is captured into its result and does not
|
|
70
|
+
* abort the others (so a partial uninstall still cleans what it can).
|
|
71
|
+
*/
|
|
72
|
+
export declare function runUninstall(selection: UninstallSelection, deps?: UninstallDeps): Promise<UninstallResult>;
|
|
73
|
+
//# sourceMappingURL=uninstall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../src/uninstall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACH,gBAAgB,IAAI,uBAAuB,EAC3C,cAAc,IAAI,qBAAqB,EACvC,KAAK,oBAAoB,EAC5B,MAAM,sBAAsB,CAAC;AAE9B,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CACxC,OAAO,GAAE,SAAS,YAAY,EAAgB,GAC/C,OAAO,CAAC,eAAe,EAAE,CAAC,CAY5B;AAED,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IAC/B,2CAA2C;IAC3C,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CACjC;AAED,uCAAuC;AACvC,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,oCAAoC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,aAAa,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACzD,qDAAqD;IACrD,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC/C;AAED,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC1B,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAC1C,QAAQ,CAAC,cAAc,EAAE,OAAO,qBAAqB,CAAC;IACtD,QAAQ,CAAC,gBAAgB,EAAE,OAAO,uBAAuB,CAAC;CAC7D;AAED,eAAO,MAAM,sBAAsB,EAAE,aAIpC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,YAAY,CAC9B,SAAS,EAAE,kBAAkB,EAC7B,IAAI,GAAE,aAAsC,GAC7C,OAAO,CAAC,eAAe,CAAC,CAmC1B"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uninstall orchestration core — the inverse of the setup wizard.
|
|
3
|
+
*
|
|
4
|
+
* `setup` writes the yt-builder-mcp MCP server entry into one or more AI
|
|
5
|
+
* clients' config files (and optionally installs a skill). `uninstall`
|
|
6
|
+
* reverses that: it detects which clients currently carry our entry,
|
|
7
|
+
* removes the chosen ones, and optionally removes the installed skill.
|
|
8
|
+
*
|
|
9
|
+
* This module is the pure, testable core: detection + removal across the
|
|
10
|
+
* client registry, with every side effect injected via {@link
|
|
11
|
+
* UninstallDeps} so unit tests touch no real disk. The interactive clack
|
|
12
|
+
* checklist + the CLI flag-parsing live in `setup-cli.ts` and call into
|
|
13
|
+
* `detectInstalledClients` / `runUninstall` here.
|
|
14
|
+
*
|
|
15
|
+
* @license MIT
|
|
16
|
+
*/
|
|
17
|
+
import { ALL_CLIENTS } from './clients/index.js';
|
|
18
|
+
import { isSkillInstalled as defaultIsSkillInstalled, uninstallSkill as defaultUninstallSkill, } from './uninstall-skill.js';
|
|
19
|
+
/**
|
|
20
|
+
* Probe every client in `clients` and return those whose config carries
|
|
21
|
+
* our server entry. Detection is parallel — the probes are independent
|
|
22
|
+
* file reads.
|
|
23
|
+
*/
|
|
24
|
+
export async function detectInstalledClients(clients = ALL_CLIENTS) {
|
|
25
|
+
const detections = await Promise.all(clients.map(async (c) => ({ client: c, det: await c.detect() })));
|
|
26
|
+
return detections
|
|
27
|
+
.filter((d) => d.det.present)
|
|
28
|
+
.map((d) => ({
|
|
29
|
+
id: d.client.id,
|
|
30
|
+
label: d.client.label,
|
|
31
|
+
configPath: d.det.configPath,
|
|
32
|
+
matchedKeys: d.det.matchedKeys,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
export const DEFAULT_UNINSTALL_DEPS = {
|
|
36
|
+
clients: ALL_CLIENTS,
|
|
37
|
+
uninstallSkill: defaultUninstallSkill,
|
|
38
|
+
isSkillInstalled: defaultIsSkillInstalled,
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Execute an uninstall. Removes our server entry from each selected,
|
|
42
|
+
* KNOWN client id (unknown ids are silently skipped) and — when
|
|
43
|
+
* `removeSkill` is set — removes the installed skill. Each client removal
|
|
44
|
+
* is isolated: a failure on one is captured into its result and does not
|
|
45
|
+
* abort the others (so a partial uninstall still cleans what it can).
|
|
46
|
+
*/
|
|
47
|
+
export async function runUninstall(selection, deps = DEFAULT_UNINSTALL_DEPS) {
|
|
48
|
+
const byId = new Map(deps.clients.map((c) => [c.id, c]));
|
|
49
|
+
const clientResults = [];
|
|
50
|
+
for (const id of selection.clientIds) {
|
|
51
|
+
const client = byId.get(id);
|
|
52
|
+
if (client === undefined)
|
|
53
|
+
continue; // unknown id — skip
|
|
54
|
+
try {
|
|
55
|
+
const res = await client.remove();
|
|
56
|
+
clientResults.push({
|
|
57
|
+
id: client.id,
|
|
58
|
+
label: client.label,
|
|
59
|
+
configPath: res.configPath,
|
|
60
|
+
removed: res.removed,
|
|
61
|
+
removedKeys: res.removedKeys,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
const error = e instanceof Error ? e.message : String(e);
|
|
66
|
+
clientResults.push({
|
|
67
|
+
id: client.id,
|
|
68
|
+
label: client.label,
|
|
69
|
+
configPath: client.configPath(),
|
|
70
|
+
removed: false,
|
|
71
|
+
removedKeys: [],
|
|
72
|
+
error,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
let skillResult;
|
|
77
|
+
if (selection.removeSkill) {
|
|
78
|
+
skillResult = await deps.uninstallSkill();
|
|
79
|
+
}
|
|
80
|
+
return { clientResults, ...(skillResult !== undefined ? { skillResult } : {}) };
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=uninstall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../src/uninstall.ts"],"names":[],"mappings":"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"}
|
package/icon.png
CHANGED
|
Binary file
|
package/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"dxt_version": "0.1",
|
|
3
3
|
"name": "@wootsup/yt-builder-mcp",
|
|
4
4
|
"display_name": "YT Builder MCP for YOOtheme Pro (unofficial)",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.2.0",
|
|
6
6
|
"description": "Drive your YOOtheme Pro Page Builder programmatically from Claude, Cursor, Codex, Gemini and 5 other MCP-capable AI assistants — read layouts, edit settings, add elements, bind dynamic sources. Works on WordPress and Joomla 5/6. Built for YOOtheme Pro 4.0+. Independent third-party project, not affiliated with YOOtheme GmbH.",
|
|
7
7
|
"long_description": "YT Builder MCP gives AI assistants a typed, scoped, and idempotent surface for your YOOtheme Pro Page Builder, on either WordPress or Joomla 5/6. Tools cover page discovery, layout inspection, element CRUD, source binding, and diagnostics. Bearer auth, optimistic locking via ETag, scope hierarchy (read < write < admin), and structured-error responses keep the agent safe and the workflow correct on first try. Independent third-party project — YOOtheme® is a registered trademark of YOOtheme GmbH (yootheme.com); YT Builder MCP is built by WootsUp (getimo productions) and is not affiliated with, endorsed by, or sponsored by YOOtheme.",
|
|
8
8
|
"icon": "icon.png",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"${__dirname}/dist/index.js"
|
|
40
40
|
],
|
|
41
41
|
"env": {
|
|
42
|
-
"YTB_MCP_SITES_FILE": "${user_config.YTB_MCP_SITES_FILE}",
|
|
43
42
|
"YTB_MCP_SITE_URL": "${user_config.YTB_MCP_SITE_URL}",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
43
|
+
"YTB_MCP_BEARER_TOKEN": "${user_config.YTB_MCP_BEARER_TOKEN}",
|
|
44
|
+
"YTB_MCP_PROFILE": "${user_config.YTB_MCP_PROFILE}",
|
|
45
|
+
"YTB_MCP_SITES_FILE": "${user_config.YTB_MCP_SITES_FILE}"
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
},
|
|
@@ -60,17 +60,17 @@
|
|
|
60
60
|
"required": false,
|
|
61
61
|
"sensitive": true
|
|
62
62
|
},
|
|
63
|
-
"
|
|
63
|
+
"YTB_MCP_PROFILE": {
|
|
64
64
|
"type": "string",
|
|
65
|
-
"title": "
|
|
66
|
-
"description": "
|
|
65
|
+
"title": "Profile name (Optional for Single Site Configuration)",
|
|
66
|
+
"description": "Optional label for this site profile. Defaults to 'default'. With a Sites file, it selects which configured site is active; switch any time via yootheme_builder_use_site.",
|
|
67
67
|
"required": false,
|
|
68
|
-
"default": "
|
|
68
|
+
"default": "default"
|
|
69
69
|
},
|
|
70
70
|
"YTB_MCP_SITES_FILE": {
|
|
71
71
|
"type": "string",
|
|
72
|
-
"title": "Sites file (
|
|
73
|
-
"description": "Only for managing several sites from one install (agencies). Path to a sites.json, e.g. /Users/you/.config/yt-builder-mcp/sites.json. Create and fill it with: npx -y @wootsup/yt-builder-mcp add-site (do not hand-edit). When set, the
|
|
72
|
+
"title": "Sites file (for Multi-Site Configurations)",
|
|
73
|
+
"description": "Only for managing several sites from one install (agencies). Path to a sites.json, e.g. /Users/you/.config/yt-builder-mcp/sites.json. Create and fill it with: npx -y @wootsup/yt-builder-mcp add-site (do not hand-edit). When set, the single-site YTB_MCP_SITE_URL + token fields above are ignored. Most people leave this empty.",
|
|
74
74
|
"required": false
|
|
75
75
|
}
|
|
76
76
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wootsup/yt-builder-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "YT Builder MCP — drive your page builder from Claude, Cursor, Codex, Gemini and 5 other MCP-capable AI assistants. Built for YOOtheme Pro 4.0+. Independent third-party project, not affiliated with YOOtheme GmbH.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
"node": ">=18.17.0"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
|
+
"prepublishOnly": "node -e \"if (process.env.RELEASE_PHP_PUBLISH !== '1') { console.error('Manual npm publish is no longer supported. Use: php scripts/release.php release yt-builder-mcp <bump> followed by php scripts/release.php push-tag yt-builder-mcp <version>, which triggers the GitHub Actions publish workflow (.github/workflows/yt-builder-mcp-publish.yml). Set RELEASE_PHP_PUBLISH=1 only if you know you are running from that workflow.'); process.exit(1); }\"",
|
|
51
52
|
"build": "tsc",
|
|
52
|
-
"prepublishOnly": "npm run build",
|
|
53
53
|
"dev": "tsc --watch",
|
|
54
54
|
"test": "vitest run",
|
|
55
55
|
"test:watch": "vitest",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"test:grep-gate": "vitest run tests/auth/secrets-grep-gate.test.ts",
|
|
58
58
|
"typecheck": "tsc --noEmit",
|
|
59
59
|
"lint": "eslint src --max-warnings=0",
|
|
60
|
+
"bump": "node ./scripts/bump-version.mjs",
|
|
60
61
|
"setup": "node ./bin/yt-builder-mcp.js setup",
|
|
61
62
|
"install-skill": "node ./bin/yt-builder-mcp.js install-skill",
|
|
62
63
|
"build:dxt": "node ./scripts/build-dxt.js",
|
|
@@ -76,6 +77,7 @@
|
|
|
76
77
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
77
78
|
"@typescript-eslint/parser": "^8.0.0",
|
|
78
79
|
"@vitest/coverage-v8": "^1.4.0",
|
|
80
|
+
"esbuild": "^0.21.5",
|
|
79
81
|
"eslint": "^9.0.0",
|
|
80
82
|
"typescript": "^5.4.0",
|
|
81
83
|
"typescript-eslint": "^8.0.0",
|
|
@@ -12,9 +12,9 @@ description: Drive the YOOtheme Pro Page Builder on WordPress or Joomla 5/6. Dis
|
|
|
12
12
|
> WordPress and Joomla 5/6.
|
|
13
13
|
|
|
14
14
|
This skill helps AI assistants drive the YOOtheme Pro Page Builder through the
|
|
15
|
-
`@wootsup/yt-builder-mcp` server. The server exposes
|
|
16
|
-
callable tools.
|
|
17
|
-
(
|
|
15
|
+
`@wootsup/yt-builder-mcp` server. The server exposes 30 typed, scoped, idempotent
|
|
16
|
+
callable tools. 23 of them advertised as first-class entries in `tools/list`
|
|
17
|
+
(20 essential L1 forwards + 2 direct L3 entries + 1 gateway), and 7 advanced
|
|
18
18
|
tools reachable through the single `yootheme_builder_advanced` gateway. This
|
|
19
19
|
3-lane split keeps `tools/list` well below the ~40-tool Cursor cap while every
|
|
20
20
|
catalogued tool stays fully reachable.
|
|
@@ -48,7 +48,7 @@ Some clients (notably Claude Desktop with the `.dxt` bundle) expose **two**
|
|
|
48
48
|
entries when the user types "YT Builder MCP" into the picker:
|
|
49
49
|
|
|
50
50
|
- **`YT Builder MCP for YOOtheme Pro (unofficial)`**: the MCP **server**.
|
|
51
|
-
Provides the
|
|
51
|
+
Provides the 23 first-class tools (20 essential, 2 direct, 1 gateway).
|
|
52
52
|
The `yootheme_builder_advanced` gateway routes 7 additional tools.
|
|
53
53
|
- **`Von YT Builder MCP for YOOtheme Pro`**: the bundled **skill** (this
|
|
54
54
|
document). Gives the agent the workflow knowledge needed to drive those
|
|
@@ -74,21 +74,22 @@ The server exposes:
|
|
|
74
74
|
- **2 direct top-level tools**, always callable, always in `tools/list`:
|
|
75
75
|
`yootheme_builder_health` and `yootheme_builder_diagnose`. These are
|
|
76
76
|
the "the gateway itself might be broken" escape hatch.
|
|
77
|
-
- **
|
|
78
|
-
(pages_list, get_etag, element_list / add /
|
|
79
|
-
clone / delete, page_get_layout,
|
|
80
|
-
|
|
81
|
-
sites_list, sites_test
|
|
82
|
-
see them
|
|
77
|
+
- **20 essential forwarded tools**: common reads + the most-used writes
|
|
78
|
+
(pages_list, pages_create, pages_delete, get_etag, element_list / add /
|
|
79
|
+
update_settings / get / move / clone / delete, page_get_layout,
|
|
80
|
+
sources_list, element_types_list, element_type_get_schema,
|
|
81
|
+
template_summary, inspect_multi_items_binding, sites_list, sites_test,
|
|
82
|
+
use_site). Always advertised in `tools/list` so AI clients see them
|
|
83
|
+
first-class.
|
|
83
84
|
- **7 advanced captured tools**: everything else (page_save, page_publish,
|
|
84
85
|
page_get_schema, element_get_binding, element_bind_source,
|
|
85
86
|
element_unbind_source, clean_implode_directives). Reachable through one
|
|
86
87
|
gateway tool: `yootheme_builder_advanced({ tool: "<name>", input: { ... } })`.
|
|
87
88
|
- **1 gateway tool**: `yootheme_builder_advanced`.
|
|
88
89
|
|
|
89
|
-
`tools/list` therefore advertises
|
|
90
|
-
essentials + 2 L3 direct + 1 gateway. The total callable surface is
|
|
91
|
-
(
|
|
90
|
+
`tools/list` therefore advertises 23 names (20 + 2 + 1). That's 20 L1
|
|
91
|
+
essentials + 2 L3 direct + 1 gateway. The total callable surface is 30
|
|
92
|
+
(23 advertised + 7 advanced reachable through the gateway). If the AI
|
|
92
93
|
client reports "tool not found", you are almost certainly calling an
|
|
93
94
|
advanced tool by its raw name. Wrap it in
|
|
94
95
|
`yootheme_builder_advanced({ tool, input })` instead.
|
|
@@ -137,7 +138,7 @@ Do not loop on auth errors.
|
|
|
137
138
|
> REST endpoints for per-article custom layouts, but they are NOT exposed
|
|
138
139
|
> via MCP tools in v1.x. To use that surface, call the REST endpoints
|
|
139
140
|
> directly with the Bearer key. MCP tool coverage for L2 articles is
|
|
140
|
-
> planned for
|
|
141
|
+
> planned for a future release.
|
|
141
142
|
|
|
142
143
|
---
|
|
143
144
|
|
|
@@ -650,7 +651,7 @@ yootheme_builder_diagnose({})
|
|
|
650
651
|
// Response shape:
|
|
651
652
|
// {
|
|
652
653
|
// plugin_reachable: true,
|
|
653
|
-
// plugin_version: "1.
|
|
654
|
+
// plugin_version: "1.2.0",
|
|
654
655
|
// yootheme_loaded: true,
|
|
655
656
|
// yootheme_version: "5.0.22",
|
|
656
657
|
// endpoint_count: 16,
|
|
@@ -821,35 +822,38 @@ Joomla administrator access." Don't fabricate tool calls.
|
|
|
821
822
|
|
|
822
823
|
<!-- TOOL-CATALOG:BEGIN -->
|
|
823
824
|
|
|
824
|
-
**
|
|
825
|
+
**29 catalogued tools** plus the `yootheme_builder_advanced` gateway = **30 reachable via `tools/list`** (20 L1 + 2 L3 + 1 gateway = 23 advertised; the gateway routes to 7 additional advanced tools, bringing the total to 30 callable). Generated by `scripts/extract-tools.mjs` from the compiled `buildAllTools()` registry. Do not hand-edit this section; re-run `npm run build && node scripts/extract-tools.mjs` after changing tool definitions.
|
|
825
826
|
|
|
826
827
|
| Tool | Kind | Input keys | Description |
|
|
827
828
|
| --- | --- | --- | --- |
|
|
828
|
-
| `yootheme_builder_clean_implode_directives` |
|
|
829
|
+
| `yootheme_builder_clean_implode_directives` | destructive | `confirm`, `element_path`, `etag`, `site_id`, `template_id` | Strips `props.source.props.*.implode` directives from an element binding. Returns audit log + new ETag. Idempotent at the server (cleaned_count: 0 when nothing to remove) but classed as destructive because the affected binding cannot be restored without re-mapping. Always ask the user to confirm first, then call again with `confirm: true`. Requires ETag. Operates on the default site unless site_id is provided. |
|
|
829
830
|
| `yootheme_builder_diagnose` | read+idempotent | `site_id` | Full diagnostic: /health + authenticated /etag probe. Returns site_url, home_url, plugin reachability, Bearer validity in one call. First call when you need to know where the site lives. For per-template URLs see pages_list. Operates on the default site unless site_id is provided. |
|
|
830
831
|
| `yootheme_builder_element_add` | mutating | `children`, `element_type`, `etag`, `parent_path`, `props`, `site_id`, `template_id` | Add a new element to a template. Provide `parent_path` (or "" for root), `element_type` (e.g. "headline", "text", "grid"), and optional `props` / `children`. Returns the new element's JSON-Pointer path. Requires ETag. Operates on the default site unless site_id is provided. |
|
|
831
832
|
| `yootheme_builder_element_bind_source` | idempotent | `bindingLevel`, `element_path`, `etag`, `field_mappings`, `site_id`, `source_id`, `source_name`, `template_id` | Binds a Builder source to an element (sets `props.source`). Use bindingLevel "item" on Multi-Items containers (grid/slideshow/switcher/…) to bind on the first *_item child instead of the container itself. Requires ETag. Operates on the default site unless site_id is provided. |
|
|
832
833
|
| `yootheme_builder_element_clone` | mutating | `element_path`, `etag`, `site_id`, `template_id` | Clone an element as a sibling (same parent, immediately after the source). Returns the new element's path. Requires ETag. Operates on the default site unless site_id is provided. |
|
|
833
|
-
| `yootheme_builder_element_delete` | destructive | `confirm`, `element_path`, `etag`, `site_id`, `template_id` | PERMANENTLY delete an element
|
|
834
|
+
| `yootheme_builder_element_delete` | destructive | `confirm`, `element_path`, `etag`, `site_id`, `template_id` | PERMANENTLY delete an element + children. Cannot be undone. Pass `confirm: true` (boolean) AND a fresh ETag. If `preview:true` returns despite confirm, check `details.received_confirm` — strings/numbers accepted, but boolean is canonical. Operates on the default site unless site_id is provided. |
|
|
834
835
|
| `yootheme_builder_element_get` | read+idempotent | `element_path`, `site_id`, `template_id` | Get the full element object at a specific JSON-Pointer path, including props and children. Use yootheme_builder_element_list to discover paths. Operates on the default site unless site_id is provided. |
|
|
835
|
-
| `yootheme_builder_element_get_binding` | read+idempotent | `element_path`, `site_id`, `template_id` | Read the source binding attached to an element
|
|
836
|
+
| `yootheme_builder_element_get_binding` | read+idempotent | `element_path`, `site_id`, `template_id` | Read the source binding attached to an element — the bound source name, the field-mappings (which source field feeds which element prop) and the query arguments/directives. Returns the empty object if the element is not bound. Operates on the default site unless site_id is provided. |
|
|
836
837
|
| `yootheme_builder_element_list` | read+idempotent | `cursor`, `depth`, `fields`, `limit`, `root_path`, `site_id`, `template_id` | List elements in a template as a flat array with JSON-Pointer paths + types. Scope with `root_path`/`depth` for a subtree, paginate with `limit`/`cursor` for large templates. `fields[]` narrows each row. Operates on the default site unless site_id is provided. |
|
|
837
838
|
| `yootheme_builder_element_move` | idempotent | `element_path`, `etag`, `site_id`, `template_id`, `to_index`, `to_parent_path` | Move an element to a new parent + index in the tree. Useful for reordering or reparenting (e.g. moving a card from one grid column to another). Requires ETag. Operates on the default site unless site_id is provided. |
|
|
838
|
-
| `yootheme_builder_element_type_get_schema` | read+idempotent | `element_type`, `site_id`, `type_name` | **Call before every `element_add` / `_update_settings
|
|
839
|
+
| `yootheme_builder_element_type_get_schema` | read+idempotent | `element_type`, `site_id`, `type_name` | **Call before every `element_add` / `_update_settings`** — unknown prop keys are silently dropped server-side, so guessing fails quietly. Returns `{name,type,label?}` field descriptors. Use `element_type`; `type_name` is DEPRECATED. Operates on the default site unless site_id is provided. |
|
|
839
840
|
| `yootheme_builder_element_types_list` | read+idempotent | `fields`, `site_id` | List element types registered on this site (built-ins + YOOessentials/uEssentials extras). Names feed `element_type` of element_add. Pass `fields[]` to narrow each row. Operates on the default site unless site_id is provided. |
|
|
840
|
-
| `yootheme_builder_element_unbind_source` | destructive | `confirm`, `element_path`, `etag`, `site_id`, `template_id` | Remove the source binding from an element. Clears `props.source`. Destructive in the sense that it may break dynamic-content rendering
|
|
841
|
-
| `yootheme_builder_element_update_settings` | idempotent | `element_path`, `etag`, `merge`, `props`, `site_id`, `template_id` | Update `props` on an element. Default replaces all props; pass `merge:true` for server-side deep-merge (only request keys overwritten, others survive
|
|
841
|
+
| `yootheme_builder_element_unbind_source` | destructive | `confirm`, `element_path`, `etag`, `site_id`, `template_id` | Remove the source binding from an element. Clears `props.source`. Destructive in the sense that it may break dynamic-content rendering — always ask the user to confirm. Requires ETag. Operates on the default site unless site_id is provided. |
|
|
842
|
+
| `yootheme_builder_element_update_settings` | idempotent | `element_path`, `etag`, `merge`, `props`, `site_id`, `template_id` | Update `props` on an element. Default replaces all props; pass `merge:true` for server-side deep-merge (only request keys overwritten, others survive — avoids read-modify-write races). Requires ETag. Operates on the default site unless site_id is provided. |
|
|
842
843
|
| `yootheme_builder_get_etag` | read+idempotent | `site_id` | Get the current ETag (state revision) for the YOOtheme builder. Returns sha256+revision string used for optimistic locking on writes. Pass the returned value back as `etag` on any write tool (page_save, page_publish, element_add, element_update_settings, element_clone, element_move, element_delete). The server returns HTTP 412 if the ETag has changed since you read it. Keywords: get etag, current etag, state revision, optimistic lock, version stamp. Operates on the default site unless site_id is provided. |
|
|
843
844
|
| `yootheme_builder_health` | read+idempotent | `site_id` | Check plugin installed/reachable. Returns plugin version, YT Pro version, REST endpoints. Authenticated payload adds site_url + home_url for deep-linking. See yootheme_builder_diagnose for Bearer-validity + connectivity summary. Operates on the default site unless site_id is provided. |
|
|
844
845
|
| `yootheme_builder_inspect_multi_items_binding` | read+idempotent | `element_path`, `site_id`, `template_id` | Reports Multi-Items binding state: container/item pair (grid↔grid_item, slideshow↔slideshow_item, …), current binding level (none\|container\|item), and a recommended_fix when the binding sits on the container instead of the child. Operates on the default site unless site_id is provided. |
|
|
845
846
|
| `yootheme_builder_page_get_layout` | read+idempotent | `fields`, `flat`, `site_id`, `template_id` | Get full layout tree for one template. Default nested `{layout, etag}`. Set `flat:true` for depth-first array `{elements:[...], etag}`; combine with `fields[]` to project per-element. Operates on the default site unless site_id is provided. |
|
|
846
|
-
| `yootheme_builder_page_get_schema` | read+idempotent | `site_id`, `template_id` | Get the flat schema for a template
|
|
847
|
-
| `yootheme_builder_page_publish` | idempotent | `etag`, `site_id`, `template_id` | Publish a template
|
|
848
|
-
| `yootheme_builder_page_save` | idempotent | `etag`, `site_id`, `template_id` | Re-run save-transforms
|
|
847
|
+
| `yootheme_builder_page_get_schema` | read+idempotent | `site_id`, `template_id` | Get the flat schema for a template — a list of nodes with their JSON-Pointer paths and element types. Best entry-point for navigation: lighter than page_get_layout, sufficient to locate elements before editing. Operates on the default site unless site_id is provided. |
|
|
848
|
+
| `yootheme_builder_page_publish` | idempotent | `etag`, `site_id`, `template_id` | Publish a template — persist state, flush YT + WP caches, snapshot the published-state ETag. ETag optional — when provided, 412 on conflict; when omitted, last-write-wins. Recommended for collaborative edits. Operates on the default site unless site_id is provided. |
|
|
849
|
+
| `yootheme_builder_page_save` | idempotent | `etag`, `site_id`, `template_id` | Re-run save-transforms + flush caches. Does NOT accept a layout — land edits via element_add/update/bind/delete first. No-op if byte-identical. New pages: pages_create. Publish: page_publish. ETag optional. Operates on the default site unless site_id is provided. |
|
|
850
|
+
| `yootheme_builder_pages_create` | idempotent | `dry_run`, `layout`, `site_id`, `slug`, `status`, `title` | Create a new WordPress page with a YOOtheme per-page layout. Required: title. Optional: slug (defaults to sanitize_title(title)), status (default: draft), layout (JSON, default: {type:"layout",children:[]}). Supports dry-run mode (dry_run:true) to preflight all hardening layers without persisting. Returns page_id, slug (post-collision-resolved), template_id, etag, warnings. Operates on the default site unless site_id is provided. |
|
|
851
|
+
| `yootheme_builder_pages_delete` | idempotent | `confirm`, `force`, `post_id`, `site_id` | Delete a WordPress page (with associated YOOtheme per-page layout). Requires confirm:true (gate against accidental deletion). Default behavior: wp_trash_post (recoverable via wp-admin). With force:true: permanent wp_delete_post(force=true). Refuses non-page post types with 403 (Layer 9 defense). Returns deleted:true, page_id, force_deleted, bumped etag. Operates on the default site unless site_id is provided. |
|
|
849
852
|
| `yootheme_builder_pages_list` | read+idempotent | `fields`, `site_id` | List all pages, templates, and layouts in the YOOtheme Pro builder. Returns template_id, label, type, element count, and frontend_url per row. CALL THIS FIRST to discover available template IDs before any tool that needs a template_id (page_get_layout, element_list, page_get_schema, etc.). Keywords: list pages, list templates, list layouts, discover template_id, index, available templates, what pages exist. Pass `fields:["id","label"]` to slim. Returns ALL pages in one call (no pagination, typically <50 templates per site). Operates on the default site unless site_id is provided. |
|
|
850
853
|
| `yootheme_builder_sites_list` | read+idempotent | `site_id` | List all sites configured in this multi-site MCP installation. Returns site_id + URL + platform (wordpress\|joomla) + default flag per row. CALL THIS FIRST when working with a fresh MCP connection to discover available site_ids before targeting one with any other tool. Read-only, no REST calls. Keywords: list sites, list connections, list installations, discover site_id, available sites, configured sites, what sites exist, multi-site index. (site_id is accepted for schema-uniformity but ignored by this tool.) |
|
|
851
854
|
| `yootheme_builder_sites_test` | read+idempotent | `site_id` | Verify connectivity to ONE site: probes /health (no auth) + /etag (auth) in parallel; returns plugin_reachable + bearer_valid. `site_id` is REQUIRED. Use sites_list to find IDs. |
|
|
852
855
|
| `yootheme_builder_sources_list` | read+idempotent | `fields`, `site_id` | List all data sources, feeds, and dynamic content sources available in the YOOtheme Pro builder. Returns name + label + origin (apimapper / wordpress / joomla / essentials) per source. CALL THIS BEFORE binding any element to a data source. Pick a source name from the list and pass it to `element_bind_source`. Keywords: list sources, list data sources, list feeds, list bindings, dynamic content, available data, what sources exist. Pass `fields[]` to narrow each row. Operates on the default site unless site_id is provided. |
|
|
853
|
-
| `yootheme_builder_template_summary` | read+idempotent | `site_id`, `template_id` | Token-efficient template overview: element counts by type, binding count, max nesting depth, and named landmark sections
|
|
856
|
+
| `yootheme_builder_template_summary` | read+idempotent | `site_id`, `template_id` | Token-efficient template overview: element counts by type, binding count, max nesting depth, and named landmark sections — computed server-side in one call. Use this to grasp a large template before pulling element_list or page_get_layout. Operates on the default site unless site_id is provided. |
|
|
857
|
+
| `yootheme_builder_use_site` | idempotent | `probe`, `site_id` | Switch the ACTIVE site for this multi-site session. After this call, every tool that omits `site_id` targets the site you picked here (until you switch again or restart). Runs a /health + /etag probe by default; pass `probe: false` to switch offline. A degraded site is a soft warning (the switch still happens). `site_id` is REQUIRED. Keywords: switch site, change site, set active site, select installation, use profile, activate site, target site. Use yootheme_builder_sites_list first to find IDs. |
|
|
854
858
|
|
|
855
859
|
<!-- TOOL-CATALOG:END -->
|