@decantr/mcp-server 1.0.5 → 2.0.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/LICENSE +21 -0
- package/README.md +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-A4ZCCVQR.js → chunk-MUNBODQK.js} +116 -79
- package/dist/index.js +1 -1
- package/package.json +8 -9
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Decantr AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -144,7 +144,7 @@ For the broader product surface and support policy, see the root Decantr docs an
|
|
|
144
144
|
|
|
145
145
|
## Compatibility
|
|
146
146
|
|
|
147
|
-
`@decantr/mcp-server` is stable in the `
|
|
147
|
+
`@decantr/mcp-server` is stable in the `2.x` line for the documented MCP tool surface.
|
|
148
148
|
|
|
149
149
|
- new tools may be added in compatible releases
|
|
150
150
|
- existing documented tool names and envelopes should not break without a major version
|
package/dist/bin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-MUNBODQK.js";
|
|
@@ -7,14 +7,14 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprot
|
|
|
7
7
|
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
8
8
|
import { readFile as readFile2 } from "fs/promises";
|
|
9
9
|
import { basename as basename2, dirname as dirname2, join as join2, relative as relative2 } from "path";
|
|
10
|
-
import { evaluateGuard,
|
|
10
|
+
import { evaluateGuard, isV4 as isV42, validateEssence } from "@decantr/essence-spec";
|
|
11
11
|
import { isContentIntelligenceSource, resolvePatternPreset } from "@decantr/registry";
|
|
12
12
|
|
|
13
13
|
// src/helpers.ts
|
|
14
14
|
import { realpathSync } from "fs";
|
|
15
15
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
16
16
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "path";
|
|
17
|
-
import {
|
|
17
|
+
import { isV4 } from "@decantr/essence-spec";
|
|
18
18
|
import { RegistryAPIClient } from "@decantr/registry";
|
|
19
19
|
var MAX_INPUT_LENGTH = 1e3;
|
|
20
20
|
function validateStringArg(args, field) {
|
|
@@ -95,8 +95,13 @@ async function writeEssenceFile(essencePath, essence) {
|
|
|
95
95
|
}
|
|
96
96
|
async function mutateEssenceFile(essencePath, mutate) {
|
|
97
97
|
const { essence, path } = await readEssenceFile(essencePath);
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
if (!isV4(essence)) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
"Active Decantr V2 workflows require Essence v4.0.0. Run `decantr migrate --to v4` for older essence files."
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const v4 = structuredClone(essence);
|
|
104
|
+
const updated = mutate(v4);
|
|
100
105
|
await writeEssenceFile(path, updated);
|
|
101
106
|
return { essence: updated, path };
|
|
102
107
|
}
|
|
@@ -469,7 +474,7 @@ var TOOLS = [
|
|
|
469
474
|
{
|
|
470
475
|
name: "decantr_read_essence",
|
|
471
476
|
title: "Read Essence",
|
|
472
|
-
description: "Read and return the current decantr.essence.json file from the working directory.
|
|
477
|
+
description: "Read and return the current Essence v4 decantr.essence.json file from the working directory. Optionally filter by layer (dna, blueprint, or full).",
|
|
473
478
|
inputSchema: {
|
|
474
479
|
type: "object",
|
|
475
480
|
properties: {
|
|
@@ -480,7 +485,7 @@ var TOOLS = [
|
|
|
480
485
|
layer: {
|
|
481
486
|
type: "string",
|
|
482
487
|
enum: ["dna", "blueprint", "full"],
|
|
483
|
-
description: "For
|
|
488
|
+
description: "For Essence v4 files: return only the specified layer. Defaults to full."
|
|
484
489
|
}
|
|
485
490
|
}
|
|
486
491
|
},
|
|
@@ -490,7 +495,7 @@ var TOOLS = [
|
|
|
490
495
|
{
|
|
491
496
|
name: "decantr_validate",
|
|
492
497
|
title: "Validate Essence",
|
|
493
|
-
description: "Validate
|
|
498
|
+
description: "Validate an Essence v4 decantr.essence.json file against the schema and guard rules, reporting DNA vs Blueprint violations separately.",
|
|
494
499
|
inputSchema: {
|
|
495
500
|
type: "object",
|
|
496
501
|
properties: {
|
|
@@ -593,7 +598,7 @@ var TOOLS = [
|
|
|
593
598
|
{
|
|
594
599
|
name: "decantr_check_drift",
|
|
595
600
|
title: "Check Drift",
|
|
596
|
-
description: "Check if code changes violate the design intent captured in the Essence spec.
|
|
601
|
+
description: "Check if code changes violate the design intent captured in the Essence v4 spec. Returns separate dna_violations and blueprint_drift with autoFixable flags.",
|
|
597
602
|
inputSchema: {
|
|
598
603
|
type: "object",
|
|
599
604
|
properties: {
|
|
@@ -619,7 +624,7 @@ var TOOLS = [
|
|
|
619
624
|
{
|
|
620
625
|
name: "decantr_create_essence",
|
|
621
626
|
title: "Create Essence",
|
|
622
|
-
description: "Generate a valid
|
|
627
|
+
description: "Generate a valid Essence v4 skeleton from a project description. Returns a sectioned decantr.essence.json template based on the closest matching archetype and blueprint.",
|
|
623
628
|
inputSchema: {
|
|
624
629
|
type: "object",
|
|
625
630
|
properties: {
|
|
@@ -680,7 +685,7 @@ var TOOLS = [
|
|
|
680
685
|
{
|
|
681
686
|
name: "decantr_update_essence",
|
|
682
687
|
title: "Update Essence",
|
|
683
|
-
description: "Mutate
|
|
688
|
+
description: "Mutate an Essence v4 file: add/remove/update pages, update DNA or blueprint fields, add/remove features. Older projects must run `decantr migrate --to v4` first.",
|
|
684
689
|
inputSchema: {
|
|
685
690
|
type: "object",
|
|
686
691
|
properties: {
|
|
@@ -946,7 +951,12 @@ async function handleTool(name, args) {
|
|
|
946
951
|
const raw = await readFile2(essencePath, "utf-8");
|
|
947
952
|
const essence = JSON.parse(raw);
|
|
948
953
|
const layer = args.layer;
|
|
949
|
-
if (
|
|
954
|
+
if (!isV42(essence)) {
|
|
955
|
+
return {
|
|
956
|
+
error: "Active Decantr V2 workflows require Essence v4.0.0. Run `decantr migrate --to v4` for older essence files."
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
if (layer) {
|
|
950
960
|
if (layer === "dna") return essence.dna;
|
|
951
961
|
if (layer === "blueprint") return essence.blueprint;
|
|
952
962
|
}
|
|
@@ -975,13 +985,13 @@ async function handleTool(name, args) {
|
|
|
975
985
|
} catch {
|
|
976
986
|
}
|
|
977
987
|
}
|
|
978
|
-
if (result.valid && typeof essence === "object" && essence !== null &&
|
|
988
|
+
if (result.valid && typeof essence === "object" && essence !== null && isV42(essence)) {
|
|
979
989
|
const dnaViolations = guardViolations.filter((v) => v.layer === "dna");
|
|
980
990
|
const blueprintViolations = guardViolations.filter((v) => v.layer === "blueprint");
|
|
981
991
|
const otherViolations = guardViolations.filter((v) => !v.layer);
|
|
982
992
|
return {
|
|
983
993
|
...result,
|
|
984
|
-
format: "
|
|
994
|
+
format: "v4",
|
|
985
995
|
dna_violations: dnaViolations,
|
|
986
996
|
blueprint_violations: blueprintViolations,
|
|
987
997
|
guardViolations: otherViolations
|
|
@@ -1189,51 +1199,43 @@ async function handleTool(name, args) {
|
|
|
1189
1199
|
if (!validation.valid) {
|
|
1190
1200
|
return { drifted: true, reason: "invalid_essence", errors: validation.errors };
|
|
1191
1201
|
}
|
|
1202
|
+
if (!isV42(essence)) {
|
|
1203
|
+
return {
|
|
1204
|
+
drifted: true,
|
|
1205
|
+
reason: "legacy_essence",
|
|
1206
|
+
errors: [
|
|
1207
|
+
"Active Decantr V2 workflows require Essence v4.0.0. Run `decantr migrate --to v4` for older essence files."
|
|
1208
|
+
]
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1192
1211
|
const violations = [];
|
|
1193
1212
|
if (args.theme_used && typeof args.theme_used === "string") {
|
|
1194
|
-
|
|
1195
|
-
if (isV32(essence)) {
|
|
1196
|
-
expectedThemeId = essence.dna.theme.id;
|
|
1197
|
-
} else {
|
|
1198
|
-
const expectedTheme = essence.theme;
|
|
1199
|
-
expectedThemeId = expectedTheme?.id ?? expectedTheme?.style;
|
|
1200
|
-
}
|
|
1213
|
+
const expectedThemeId = essence.dna.theme.id;
|
|
1201
1214
|
if (expectedThemeId && args.theme_used !== expectedThemeId) {
|
|
1202
1215
|
violations.push({
|
|
1203
1216
|
rule: "theme-match",
|
|
1204
1217
|
severity: "critical",
|
|
1205
1218
|
message: `Theme drift: code uses "${args.theme_used}" but Essence specifies "${expectedThemeId}". Do not switch themes.`,
|
|
1206
|
-
|
|
1219
|
+
layer: "dna",
|
|
1220
|
+
autoFixable: false
|
|
1207
1221
|
});
|
|
1208
1222
|
}
|
|
1209
1223
|
}
|
|
1210
1224
|
if (args.page_id && typeof args.page_id === "string") {
|
|
1211
|
-
|
|
1212
|
-
if (isV32(essence)) {
|
|
1213
|
-
pages = essence.blueprint.pages;
|
|
1214
|
-
} else {
|
|
1215
|
-
pages = essence.structure || [];
|
|
1216
|
-
}
|
|
1225
|
+
const pages = listEssencePages(essence);
|
|
1217
1226
|
if (!pages.find((p) => p.id === args.page_id)) {
|
|
1218
1227
|
violations.push({
|
|
1219
1228
|
rule: "page-exists",
|
|
1220
1229
|
severity: "critical",
|
|
1221
1230
|
message: `Page "${args.page_id}" not found in Essence structure. Add it to the Essence before generating code for it.`,
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
autoFix: { type: "add_page", patch: { id: args.page_id } }
|
|
1226
|
-
} : {}
|
|
1231
|
+
layer: "blueprint",
|
|
1232
|
+
autoFixable: true,
|
|
1233
|
+
autoFix: { type: "add_page", patch: { id: args.page_id } }
|
|
1227
1234
|
});
|
|
1228
1235
|
}
|
|
1229
1236
|
}
|
|
1230
1237
|
if (args.components_used && Array.isArray(args.components_used) && args.page_id && typeof args.page_id === "string") {
|
|
1231
|
-
|
|
1232
|
-
if (isV32(essence)) {
|
|
1233
|
-
pages = essence.blueprint.pages;
|
|
1234
|
-
} else {
|
|
1235
|
-
pages = essence.structure || [];
|
|
1236
|
-
}
|
|
1238
|
+
const pages = listEssencePages(essence);
|
|
1237
1239
|
const page = pages.find((p) => p.id === args.page_id);
|
|
1238
1240
|
if (page && page.layout) {
|
|
1239
1241
|
const expectedPatterns = /* @__PURE__ */ new Set();
|
|
@@ -1265,7 +1267,8 @@ async function handleTool(name, args) {
|
|
|
1265
1267
|
rule: "component-pattern-match",
|
|
1266
1268
|
severity: "warning",
|
|
1267
1269
|
message: `Components [${unmatchedComponents.join(", ")}] do not match any pattern in page "${args.page_id}" layout. Expected patterns: [${[...expectedPatterns].join(", ")}].`,
|
|
1268
|
-
|
|
1270
|
+
layer: "blueprint",
|
|
1271
|
+
autoFixable: false
|
|
1269
1272
|
});
|
|
1270
1273
|
}
|
|
1271
1274
|
}
|
|
@@ -1286,21 +1289,11 @@ async function handleTool(name, args) {
|
|
|
1286
1289
|
}
|
|
1287
1290
|
} catch {
|
|
1288
1291
|
}
|
|
1289
|
-
if (isV32(essence)) {
|
|
1290
|
-
const dnaViolations = violations.filter((v) => v.layer === "dna");
|
|
1291
|
-
const blueprintDrift = violations.filter((v) => v.layer === "blueprint");
|
|
1292
|
-
const other = violations.filter((v) => !v.layer);
|
|
1293
|
-
return {
|
|
1294
|
-
drifted: violations.length > 0,
|
|
1295
|
-
dna_violations: dnaViolations,
|
|
1296
|
-
blueprint_drift: blueprintDrift,
|
|
1297
|
-
other_violations: other,
|
|
1298
|
-
checkedAgainst: essencePath
|
|
1299
|
-
};
|
|
1300
|
-
}
|
|
1301
1292
|
return {
|
|
1302
1293
|
drifted: violations.length > 0,
|
|
1303
|
-
violations,
|
|
1294
|
+
dna_violations: violations.filter((v) => v.layer === "dna"),
|
|
1295
|
+
blueprint_drift: violations.filter((v) => v.layer === "blueprint"),
|
|
1296
|
+
other_violations: violations.filter((v) => !v.layer),
|
|
1304
1297
|
checkedAgainst: essencePath
|
|
1305
1298
|
};
|
|
1306
1299
|
}
|
|
@@ -1348,8 +1341,17 @@ async function handleTool(name, args) {
|
|
|
1348
1341
|
}
|
|
1349
1342
|
const rawPages = pages || [{ id: "home", shell: "full-bleed", default_layout: ["hero"] }];
|
|
1350
1343
|
const defaultShell = rawPages[0]?.shell || "sidebar-main";
|
|
1344
|
+
const sectionPages = rawPages.map((p, index) => ({
|
|
1345
|
+
id: p.id,
|
|
1346
|
+
route: p.id === "home" || index === 0 ? "/" : `/${p.id}`,
|
|
1347
|
+
...p.shell !== defaultShell ? { shell_override: p.shell } : {},
|
|
1348
|
+
layout: p.default_layout || []
|
|
1349
|
+
}));
|
|
1350
|
+
const routes = Object.fromEntries(
|
|
1351
|
+
sectionPages.map((page) => [page.route, { section: bestMatch, page: page.id }])
|
|
1352
|
+
);
|
|
1351
1353
|
const essence = {
|
|
1352
|
-
version: "
|
|
1354
|
+
version: "4.0.0",
|
|
1353
1355
|
dna: {
|
|
1354
1356
|
theme: {
|
|
1355
1357
|
id: "auradecantism",
|
|
@@ -1394,12 +1396,18 @@ async function handleTool(name, args) {
|
|
|
1394
1396
|
},
|
|
1395
1397
|
blueprint: {
|
|
1396
1398
|
shell: defaultShell,
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1399
|
+
sections: [
|
|
1400
|
+
{
|
|
1401
|
+
id: bestMatch,
|
|
1402
|
+
role: "primary",
|
|
1403
|
+
shell: defaultShell,
|
|
1404
|
+
features,
|
|
1405
|
+
description: `${bestMatch} primary section`,
|
|
1406
|
+
pages: sectionPages
|
|
1407
|
+
}
|
|
1408
|
+
],
|
|
1409
|
+
features,
|
|
1410
|
+
routes
|
|
1403
1411
|
},
|
|
1404
1412
|
meta: {
|
|
1405
1413
|
archetype: bestMatch,
|
|
@@ -1411,7 +1419,7 @@ async function handleTool(name, args) {
|
|
|
1411
1419
|
return {
|
|
1412
1420
|
essence,
|
|
1413
1421
|
archetype: bestMatch,
|
|
1414
|
-
format: "
|
|
1422
|
+
format: "v4",
|
|
1415
1423
|
instructions: `Save this as decantr.essence.json in your project root. Review the dna (design tokens), blueprint (pages/features), and meta (project config) sections and adjust to match your needs. The guard rules will validate your code against this spec.`,
|
|
1416
1424
|
_generated: {
|
|
1417
1425
|
matched_archetype: bestMatch,
|
|
@@ -1477,11 +1485,11 @@ async function handleTool(name, args) {
|
|
|
1477
1485
|
};
|
|
1478
1486
|
}
|
|
1479
1487
|
try {
|
|
1480
|
-
const { essence, path } = await mutateEssenceFile(args.path, (
|
|
1488
|
+
const { essence, path } = await mutateEssenceFile(args.path, (v4) => {
|
|
1481
1489
|
for (const v of violations) {
|
|
1482
|
-
applyDriftAcceptance(
|
|
1490
|
+
applyDriftAcceptance(v4, v, resolution, args.scope);
|
|
1483
1491
|
}
|
|
1484
|
-
return
|
|
1492
|
+
return v4;
|
|
1485
1493
|
});
|
|
1486
1494
|
return {
|
|
1487
1495
|
status: resolution === "accept_scoped" ? "accepted_scoped" : "accepted",
|
|
@@ -1517,8 +1525,8 @@ async function handleTool(name, args) {
|
|
|
1517
1525
|
};
|
|
1518
1526
|
}
|
|
1519
1527
|
try {
|
|
1520
|
-
const { essence, path } = await mutateEssenceFile(args.path, (
|
|
1521
|
-
return applyEssenceUpdate(
|
|
1528
|
+
const { essence, path } = await mutateEssenceFile(args.path, (v4) => {
|
|
1529
|
+
return applyEssenceUpdate(v4, operation, payload);
|
|
1522
1530
|
});
|
|
1523
1531
|
return {
|
|
1524
1532
|
status: "updated",
|
|
@@ -1647,8 +1655,10 @@ async function handleTool(name, args) {
|
|
|
1647
1655
|
} catch {
|
|
1648
1656
|
return { error: "No valid essence file found. Run decantr init first." };
|
|
1649
1657
|
}
|
|
1650
|
-
if (!
|
|
1651
|
-
return {
|
|
1658
|
+
if (!isV42(essence)) {
|
|
1659
|
+
return {
|
|
1660
|
+
error: "Section context requires Essence v4.0.0. Run `decantr migrate --to v4` first."
|
|
1661
|
+
};
|
|
1652
1662
|
}
|
|
1653
1663
|
const sections = essence.blueprint.sections || [];
|
|
1654
1664
|
const section = sections.find((s) => s.id === sectionId);
|
|
@@ -2096,6 +2106,28 @@ async function handleTool(name, args) {
|
|
|
2096
2106
|
return { error: `Unknown tool: ${name}` };
|
|
2097
2107
|
}
|
|
2098
2108
|
}
|
|
2109
|
+
function listEssencePages(essence) {
|
|
2110
|
+
return essence.blueprint.sections.flatMap(
|
|
2111
|
+
(section) => section.pages.map((page) => ({ ...page, sectionId: section.id }))
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
function getMutablePage(essence, id, sectionId) {
|
|
2115
|
+
for (const section of essence.blueprint.sections) {
|
|
2116
|
+
if (sectionId && section.id !== sectionId) continue;
|
|
2117
|
+
const index = section.pages.findIndex((page) => page.id === id);
|
|
2118
|
+
if (index !== -1) {
|
|
2119
|
+
return { page: section.pages[index], section, index };
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
return null;
|
|
2123
|
+
}
|
|
2124
|
+
function getDefaultSection(essence) {
|
|
2125
|
+
const section = essence.blueprint.sections.find((s) => s.role === "primary") ?? essence.blueprint.sections[0];
|
|
2126
|
+
if (!section) {
|
|
2127
|
+
throw new Error("Essence v4 requires at least one blueprint section.");
|
|
2128
|
+
}
|
|
2129
|
+
return section;
|
|
2130
|
+
}
|
|
2099
2131
|
function applyDriftAcceptance(essence, violation, resolution, scope) {
|
|
2100
2132
|
switch (violation.rule) {
|
|
2101
2133
|
case "theme-match":
|
|
@@ -2109,9 +2141,10 @@ function applyDriftAcceptance(essence, violation, resolution, scope) {
|
|
|
2109
2141
|
case "page-exists":
|
|
2110
2142
|
case "structure": {
|
|
2111
2143
|
if (violation.page_id) {
|
|
2112
|
-
const
|
|
2144
|
+
const section = getDefaultSection(essence);
|
|
2145
|
+
const existing = getMutablePage(essence, violation.page_id);
|
|
2113
2146
|
if (!existing) {
|
|
2114
|
-
|
|
2147
|
+
section.pages.push({
|
|
2115
2148
|
id: violation.page_id,
|
|
2116
2149
|
layout: []
|
|
2117
2150
|
});
|
|
@@ -2134,11 +2167,15 @@ function applyEssenceUpdate(essence, operation, payload) {
|
|
|
2134
2167
|
case "add_page": {
|
|
2135
2168
|
const id = payload.id;
|
|
2136
2169
|
if (!id) throw new Error('Payload must include "id" for add_page.');
|
|
2137
|
-
const
|
|
2170
|
+
const sectionId = payload.section_id;
|
|
2171
|
+
const section = sectionId ? essence.blueprint.sections.find((candidate) => candidate.id === sectionId) : getDefaultSection(essence);
|
|
2172
|
+
if (!section) throw new Error(`Section "${sectionId}" not found.`);
|
|
2173
|
+
const existing = getMutablePage(essence, id, section.id);
|
|
2138
2174
|
if (existing) throw new Error(`Page "${id}" already exists.`);
|
|
2139
|
-
|
|
2175
|
+
section.pages.push({
|
|
2140
2176
|
id,
|
|
2141
2177
|
layout: payload.layout || [],
|
|
2178
|
+
...payload.route ? { route: payload.route } : {},
|
|
2142
2179
|
...payload.shell_override ? { shell_override: payload.shell_override } : {},
|
|
2143
2180
|
...payload.surface ? { surface: payload.surface } : {}
|
|
2144
2181
|
});
|
|
@@ -2147,9 +2184,9 @@ function applyEssenceUpdate(essence, operation, payload) {
|
|
|
2147
2184
|
case "remove_page": {
|
|
2148
2185
|
const id = payload.id;
|
|
2149
2186
|
if (!id) throw new Error('Payload must include "id" for remove_page.');
|
|
2150
|
-
const
|
|
2151
|
-
if (
|
|
2152
|
-
|
|
2187
|
+
const match = getMutablePage(essence, id, payload.section_id);
|
|
2188
|
+
if (!match) throw new Error(`Page "${id}" not found.`);
|
|
2189
|
+
match.section.pages.splice(match.index, 1);
|
|
2153
2190
|
break;
|
|
2154
2191
|
}
|
|
2155
2192
|
case "update_page_layout": {
|
|
@@ -2158,9 +2195,9 @@ function applyEssenceUpdate(essence, operation, payload) {
|
|
|
2158
2195
|
if (!id) throw new Error('Payload must include "id" for update_page_layout.');
|
|
2159
2196
|
if (!layout || !Array.isArray(layout))
|
|
2160
2197
|
throw new Error('Payload must include "layout" array for update_page_layout.');
|
|
2161
|
-
const
|
|
2162
|
-
if (!
|
|
2163
|
-
page.layout = layout;
|
|
2198
|
+
const match = getMutablePage(essence, id, payload.section_id);
|
|
2199
|
+
if (!match) throw new Error(`Page "${id}" not found.`);
|
|
2200
|
+
match.page.layout = layout;
|
|
2164
2201
|
break;
|
|
2165
2202
|
}
|
|
2166
2203
|
case "update_dna": {
|
|
@@ -2178,7 +2215,7 @@ function applyEssenceUpdate(essence, operation, payload) {
|
|
|
2178
2215
|
}
|
|
2179
2216
|
case "update_blueprint": {
|
|
2180
2217
|
for (const [key, value] of Object.entries(payload)) {
|
|
2181
|
-
if (key === "pages") continue;
|
|
2218
|
+
if (key === "pages" || key === "sections") continue;
|
|
2182
2219
|
essence.blueprint[key] = value;
|
|
2183
2220
|
}
|
|
2184
2221
|
break;
|
|
@@ -2224,7 +2261,7 @@ function describeUpdate(operation, payload) {
|
|
|
2224
2261
|
}
|
|
2225
2262
|
|
|
2226
2263
|
// src/index.ts
|
|
2227
|
-
var VERSION = "
|
|
2264
|
+
var VERSION = "2.0.0";
|
|
2228
2265
|
var server = new Server({ name: "decantr", version: VERSION }, { capabilities: { tools: {} } });
|
|
2229
2266
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
2230
2267
|
return { tools: TOOLS };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-MUNBODQK.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decantr/mcp-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"mcpName": "io.github.decantr-ai/mcp-server",
|
|
5
5
|
"description": "MCP server for Decantr — exposes design intelligence, packs, and verification to AI coding assistants",
|
|
6
6
|
"keywords": [
|
|
@@ -44,17 +44,16 @@
|
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
49
|
+
"@decantr/registry": "2.0.0",
|
|
50
|
+
"@decantr/verifier": "2.0.0",
|
|
51
|
+
"@decantr/essence-spec": "2.0.1"
|
|
52
|
+
},
|
|
47
53
|
"scripts": {
|
|
48
54
|
"build": "tsup",
|
|
49
55
|
"test": "vitest run",
|
|
50
56
|
"test:watch": "vitest",
|
|
51
|
-
"prepublishOnly": "pnpm build",
|
|
52
57
|
"preversion": "pnpm build && pnpm test"
|
|
53
|
-
},
|
|
54
|
-
"dependencies": {
|
|
55
|
-
"@decantr/essence-spec": "workspace:*",
|
|
56
|
-
"@decantr/registry": "workspace:*",
|
|
57
|
-
"@decantr/verifier": "workspace:*",
|
|
58
|
-
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
59
58
|
}
|
|
60
|
-
}
|
|
59
|
+
}
|