@decantr/mcp-server 2.1.0 → 2.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 +10 -8
- package/dist/bin.js +1 -1
- package/dist/{chunk-FEXPLJKB.js → chunk-SVLMT45O.js} +248 -70
- package/dist/index.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Design intelligence for AI-generated UI. Make Claude, Cursor, and Windsurf gener
|
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
|
|
15
|
-
- **Structured design context** -- gives your AI assistant patterns, layouts,
|
|
15
|
+
- **Structured design context** -- gives your AI assistant patterns, layouts, component specs, and Brownfield task-time context instead of letting it guess
|
|
16
16
|
- **Evidence-backed repair loops** -- gives AI agents Project Health, Evidence Bundles, workspace health, and scoped repair prompts without uploading source
|
|
17
17
|
- **Drift detection** -- catches when generated code deviates from your design intent
|
|
18
18
|
- **Zero config** -- run with `npx`, no API keys or accounts required
|
|
@@ -133,9 +133,10 @@ The server exposes Decantr registry, context, benchmark, and verification tools.
|
|
|
133
133
|
| `decantr_resolve_pattern` | Get full pattern details: layout spec, components, presets, code examples | `{ "id": "data-table", "preset": "product" }` |
|
|
134
134
|
| `decantr_resolve_archetype` | Get archetype details: default pages, layouts, features, suggested theme | `{ "id": "saas-dashboard" }` |
|
|
135
135
|
| `decantr_resolve_blueprint` | Get a full app composition with page structure and personality traits | `{ "id": "ecommerce" }` |
|
|
136
|
-
| `decantr_suggest_patterns` | Given a page description, get ranked pattern suggestions | `{ "description": "
|
|
136
|
+
| `decantr_suggest_patterns` | Given a page description plus optional route/source excerpt, get ranked pattern suggestions | `{ "description": "recipe feed with avatars and infinite scroll", "route": "/feed" }` |
|
|
137
137
|
| `decantr_check_drift` | Check if generated code violates the design intent in the Essence spec | `{ "page_id": "overview", "components_used": ["Card", "LineChart"], "theme_used": "auradecantism" }` |
|
|
138
138
|
| `decantr_get_execution_pack` | Read compiled scaffold, section, page, review, or mutation execution packs, with hosted fallback when local context is missing | `{ "pack_type": "page", "id": "overview", "format": "json" }` |
|
|
139
|
+
| `decantr_prepare_task_context` | Resolve compact route/task context before editing a Brownfield or Essence route | `{ "route": "/feed", "task": "improve recipe card loading" }` |
|
|
139
140
|
| `decantr_compile_execution_packs` | Compile a hosted execution-pack bundle from a local or inline essence document | `{ "path": "./decantr.essence.json", "namespace": "@official" }` |
|
|
140
141
|
| `decantr_audit_project` | Run the schema-backed Decantr project audit against essence and compiled packs, with hosted fallback when local pack artifacts are missing | `{ "namespace": "@official" }` |
|
|
141
142
|
| `decantr_critique` | Critique a file against the compiled review contract, with hosted fallback when local review packs are missing | `{ "file_path": "./src/pages/Overview.tsx", "namespace": "@official" }` |
|
|
@@ -170,12 +171,13 @@ The AI assistant calls these tools behind the scenes:
|
|
|
170
171
|
3. `decantr_suggest_patterns` -- recommends `kpi-grid`, `chart-grid`, `data-table`, and `form-sections` for the described pages
|
|
171
172
|
4. `decantr_resolve_pattern` -- fetches layout specs and component lists for each pattern
|
|
172
173
|
5. `decantr_get_execution_pack` -- loads the compiled scaffold/page/review packs as the task contract, falling back to hosted compilation when local pack artifacts are missing
|
|
173
|
-
6. `
|
|
174
|
-
7. `
|
|
175
|
-
8. `
|
|
176
|
-
9. `
|
|
177
|
-
10. `
|
|
178
|
-
11. `
|
|
174
|
+
6. `decantr_prepare_task_context` -- resolves route-local Brownfield context, visual evidence, and theme inventory before editing an existing app
|
|
175
|
+
7. `decantr_compile_execution_packs` -- compiles the hosted pack bundle when the task needs a fresh remote contract from the essence document
|
|
176
|
+
8. `decantr_check_drift` -- validates the generated code against the Essence spec before presenting it
|
|
177
|
+
9. `decantr_critique` -- critiques a specific file, falling back to the hosted verifier when the local review pack is missing
|
|
178
|
+
10. `decantr_audit_project` -- runs the stronger project-level audit once the implementation is in place
|
|
179
|
+
11. `decantr_get_evidence_bundle` -- returns the local evidence bundle for the AI repair loop
|
|
180
|
+
12. `decantr_get_repair_prompt` -- gives the assistant exact finding evidence, constraints to preserve, and commands to rerun
|
|
179
181
|
|
|
180
182
|
The AI now generates code with the right layout structure, correct components, and consistent styling, then gets a scoped evidence-backed repair loop instead of a generic guess.
|
|
181
183
|
|
package/dist/bin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./chunk-
|
|
2
|
+
import "./chunk-SVLMT45O.js";
|
|
@@ -8,7 +8,12 @@ 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
10
|
import { evaluateGuard, isV4 as isV42, validateEssence } from "@decantr/essence-spec";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
isContentIntelligenceSource,
|
|
13
|
+
patternToDiscoveryCandidate,
|
|
14
|
+
rankPatternCandidates,
|
|
15
|
+
resolvePatternPreset
|
|
16
|
+
} from "@decantr/registry";
|
|
12
17
|
|
|
13
18
|
// src/helpers.ts
|
|
14
19
|
import { realpathSync } from "fs";
|
|
@@ -124,6 +129,47 @@ async function writeDriftLog(entries, projectRoot) {
|
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
// src/tools.ts
|
|
132
|
+
function readJsonIfExists(path) {
|
|
133
|
+
if (!existsSync(path)) return null;
|
|
134
|
+
try {
|
|
135
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
136
|
+
} catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function extractPatternIdsFromLayoutItem(item, ids) {
|
|
141
|
+
if (typeof item === "string") {
|
|
142
|
+
ids.add(item);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (!item || typeof item !== "object") return;
|
|
146
|
+
const record = item;
|
|
147
|
+
if (typeof record.pattern === "string") ids.add(record.pattern);
|
|
148
|
+
if (Array.isArray(record.cols)) {
|
|
149
|
+
for (const col of record.cols) extractPatternIdsFromLayoutItem(col, ids);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function extractPagePatternIds(page) {
|
|
153
|
+
if (!page) return [];
|
|
154
|
+
const ids = /* @__PURE__ */ new Set();
|
|
155
|
+
for (const item of page.layout ?? []) extractPatternIdsFromLayoutItem(item, ids);
|
|
156
|
+
return [...ids].sort();
|
|
157
|
+
}
|
|
158
|
+
function summarizePackJson(pack) {
|
|
159
|
+
if (!pack || typeof pack !== "object") {
|
|
160
|
+
return { directives: [], patterns: [], visualTarget: null, sharedComponents: [] };
|
|
161
|
+
}
|
|
162
|
+
const record = pack;
|
|
163
|
+
const data = record.data && typeof record.data === "object" ? record.data : record;
|
|
164
|
+
const patterns = Array.isArray(data.patterns) ? data.patterns : [];
|
|
165
|
+
const directives = Array.isArray(data.directives) ? data.directives : [];
|
|
166
|
+
const sharedComponents = Array.isArray(data.sharedComponents) ? data.sharedComponents : Array.isArray(data.shared_components) ? data.shared_components : [];
|
|
167
|
+
const visualTarget = typeof data.visualTarget === "string" ? data.visualTarget : typeof data.visual_target === "string" ? data.visual_target : null;
|
|
168
|
+
return { directives, patterns, visualTarget, sharedComponents };
|
|
169
|
+
}
|
|
170
|
+
function routeSlug(route) {
|
|
171
|
+
return route.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "root";
|
|
172
|
+
}
|
|
127
173
|
async function getShowcaseBenchmarkPayload(view) {
|
|
128
174
|
const client = getPublicAPIClient();
|
|
129
175
|
if (view === "manifest") {
|
|
@@ -490,7 +536,10 @@ function mcpStatusFromCounts(counts) {
|
|
|
490
536
|
return "healthy";
|
|
491
537
|
}
|
|
492
538
|
function mcpScoreFromCounts(counts) {
|
|
493
|
-
return Math.max(
|
|
539
|
+
return Math.max(
|
|
540
|
+
0,
|
|
541
|
+
Math.min(100, 100 - counts.errorCount * 15 - counts.warnCount * 5 - counts.infoCount)
|
|
542
|
+
);
|
|
494
543
|
}
|
|
495
544
|
function mcpCommandsForFinding(source) {
|
|
496
545
|
switch (source) {
|
|
@@ -507,7 +556,11 @@ function mcpCommandsForFinding(source) {
|
|
|
507
556
|
case "interaction":
|
|
508
557
|
return ["decantr check --strict", "decantr health"];
|
|
509
558
|
case "pack":
|
|
510
|
-
return [
|
|
559
|
+
return [
|
|
560
|
+
"decantr refresh",
|
|
561
|
+
"decantr registry get-pack review --write-context",
|
|
562
|
+
"decantr health"
|
|
563
|
+
];
|
|
511
564
|
case "runtime":
|
|
512
565
|
return ["npm run build", "decantr health"];
|
|
513
566
|
default:
|
|
@@ -908,6 +961,14 @@ var TOOLS = [
|
|
|
908
961
|
description: {
|
|
909
962
|
type: "string",
|
|
910
963
|
description: 'Description of the page or section (e.g. "dashboard with metrics and charts", "settings form with toggles")'
|
|
964
|
+
},
|
|
965
|
+
route: {
|
|
966
|
+
type: "string",
|
|
967
|
+
description: 'Optional route context, for example "/feed" or "/settings".'
|
|
968
|
+
},
|
|
969
|
+
source_code: {
|
|
970
|
+
type: "string",
|
|
971
|
+
description: "Optional local source excerpt to rank against actual code evidence."
|
|
911
972
|
}
|
|
912
973
|
},
|
|
913
974
|
required: ["description"]
|
|
@@ -1105,7 +1166,31 @@ var TOOLS = [
|
|
|
1105
1166
|
},
|
|
1106
1167
|
annotations: READ_ONLY
|
|
1107
1168
|
},
|
|
1108
|
-
// 16.
|
|
1169
|
+
// 16. decantr_prepare_task_context — local read
|
|
1170
|
+
{
|
|
1171
|
+
name: "decantr_prepare_task_context",
|
|
1172
|
+
title: "Prepare Task Context",
|
|
1173
|
+
description: "Resolve compact Brownfield/Essence task-time context for a route or page before editing. Returns route, section, page pack, directives, patterns, shared components, visual target, health evidence, and local screenshot references when available.",
|
|
1174
|
+
inputSchema: {
|
|
1175
|
+
type: "object",
|
|
1176
|
+
properties: {
|
|
1177
|
+
route: {
|
|
1178
|
+
type: "string",
|
|
1179
|
+
description: 'Route being edited, for example "/feed". Preferred when known.'
|
|
1180
|
+
},
|
|
1181
|
+
page_id: {
|
|
1182
|
+
type: "string",
|
|
1183
|
+
description: "Page ID when route is unknown."
|
|
1184
|
+
},
|
|
1185
|
+
task: {
|
|
1186
|
+
type: "string",
|
|
1187
|
+
description: "Short task description used to rank relevant patterns and context."
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
},
|
|
1191
|
+
annotations: READ_ONLY
|
|
1192
|
+
},
|
|
1193
|
+
// 17. decantr_get_execution_pack — local read
|
|
1109
1194
|
{
|
|
1110
1195
|
name: "decantr_get_execution_pack",
|
|
1111
1196
|
title: "Get Execution Pack",
|
|
@@ -1506,78 +1591,59 @@ async function handleTool(name, args) {
|
|
|
1506
1591
|
case "decantr_suggest_patterns": {
|
|
1507
1592
|
const err = validateStringArg(args, "description");
|
|
1508
1593
|
if (err) return { error: err };
|
|
1509
|
-
const desc = args.description
|
|
1594
|
+
const desc = args.description;
|
|
1595
|
+
const route = typeof args.route === "string" ? args.route : void 0;
|
|
1596
|
+
const sourceCode = typeof args.source_code === "string" ? args.source_code : void 0;
|
|
1510
1597
|
try {
|
|
1511
1598
|
const patternsResponse = await apiClient.listContent("patterns", {
|
|
1512
1599
|
namespace: "@official",
|
|
1513
|
-
limit:
|
|
1600
|
+
limit: 250
|
|
1514
1601
|
});
|
|
1515
|
-
const
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
if (desc.includes("landing") && ["hero", "cta-section", "card-grid"].includes(slug))
|
|
1535
|
-
score += 20;
|
|
1536
|
-
if (desc.includes("hero") && slug === "hero") score += 20;
|
|
1537
|
-
if (desc.includes("ecommerce") && ["card-grid", "filter-bar", "detail-header"].includes(slug))
|
|
1538
|
-
score += 15;
|
|
1539
|
-
if (desc.includes("product") && slug === "card-grid") score += 15;
|
|
1540
|
-
if (desc.includes("feed") && slug === "activity-feed") score += 15;
|
|
1541
|
-
if (desc.includes("filter") && slug === "filter-bar") score += 15;
|
|
1542
|
-
if (desc.includes("search") && slug === "filter-bar") score += 10;
|
|
1543
|
-
if (score > 0) {
|
|
1544
|
-
prelimScores.push({ slug, score, name: name2, description });
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
prelimScores.sort((a, b) => b.score - a.score);
|
|
1548
|
-
const top10 = prelimScores.slice(0, 10);
|
|
1549
|
-
const suggestions = [];
|
|
1550
|
-
for (const candidate of top10) {
|
|
1551
|
-
let fullPattern = null;
|
|
1552
|
-
try {
|
|
1553
|
-
const fetched = await apiClient.getPattern("@official", candidate.slug);
|
|
1554
|
-
fullPattern = fetched;
|
|
1555
|
-
} catch {
|
|
1556
|
-
}
|
|
1557
|
-
let score = candidate.score;
|
|
1558
|
-
if (fullPattern) {
|
|
1559
|
-
const fullSearchable = [...fullPattern.components || [], ...fullPattern.tags || []].join(" ").toLowerCase();
|
|
1560
|
-
const words = desc.split(/\s+/);
|
|
1561
|
-
for (const word of words) {
|
|
1562
|
-
if (word.length < 3) continue;
|
|
1563
|
-
if (fullSearchable.includes(word)) score += 10;
|
|
1602
|
+
const preliminary = rankPatternCandidates(
|
|
1603
|
+
{ query: desc, route, code: sourceCode, limit: 12 },
|
|
1604
|
+
patternsResponse.items.map(
|
|
1605
|
+
(item) => patternToDiscoveryCandidate({
|
|
1606
|
+
id: item.slug || item.name || "pattern",
|
|
1607
|
+
slug: item.slug,
|
|
1608
|
+
name: item.name,
|
|
1609
|
+
description: item.description
|
|
1610
|
+
})
|
|
1611
|
+
)
|
|
1612
|
+
);
|
|
1613
|
+
const fullCandidates = await Promise.all(
|
|
1614
|
+
preliminary.map(async (match) => {
|
|
1615
|
+
const slug = match.candidate.slug || match.candidate.id;
|
|
1616
|
+
try {
|
|
1617
|
+
const fetched = await apiClient.getPattern("@official", slug);
|
|
1618
|
+
return patternToDiscoveryCandidate(fetched, { slug, source: "hosted" });
|
|
1619
|
+
} catch {
|
|
1620
|
+
return match.candidate;
|
|
1564
1621
|
}
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1622
|
+
})
|
|
1623
|
+
);
|
|
1624
|
+
const suggestions = rankPatternCandidates(
|
|
1625
|
+
{ query: desc, route, code: sourceCode, limit: 5 },
|
|
1626
|
+
fullCandidates
|
|
1627
|
+
).map((match) => {
|
|
1628
|
+
const pattern = match.candidate.pattern;
|
|
1629
|
+
const preset = pattern?.presets ? Object.values(pattern.presets)[0] : null;
|
|
1630
|
+
return {
|
|
1631
|
+
id: match.candidate.slug || match.candidate.id,
|
|
1632
|
+
score: match.score,
|
|
1633
|
+
name: match.candidate.name || match.candidate.slug || match.candidate.id,
|
|
1634
|
+
description: match.candidate.description || "",
|
|
1635
|
+
components: match.candidate.components || [],
|
|
1636
|
+
interactions: match.candidate.interactions || [],
|
|
1637
|
+
layout: preset?.layout ? preset.layout.layout : "unknown",
|
|
1638
|
+
reasons: match.reasons,
|
|
1639
|
+
matched_terms: match.matchedTerms
|
|
1640
|
+
};
|
|
1641
|
+
});
|
|
1577
1642
|
return {
|
|
1578
1643
|
query: args.description,
|
|
1579
|
-
|
|
1580
|
-
|
|
1644
|
+
route,
|
|
1645
|
+
suggestions,
|
|
1646
|
+
total: preliminary.length
|
|
1581
1647
|
};
|
|
1582
1648
|
} catch (e) {
|
|
1583
1649
|
return { error: `Could not fetch patterns: ${e.message}` };
|
|
@@ -2251,6 +2317,118 @@ async function handleTool(name, args) {
|
|
|
2251
2317
|
hosted_fallback_error: hostedFallbackError ?? void 0
|
|
2252
2318
|
};
|
|
2253
2319
|
}
|
|
2320
|
+
case "decantr_prepare_task_context": {
|
|
2321
|
+
const routeArg = typeof args.route === "string" ? args.route : void 0;
|
|
2322
|
+
const pageArg = typeof args.page_id === "string" ? args.page_id : void 0;
|
|
2323
|
+
const task = typeof args.task === "string" ? args.task : "";
|
|
2324
|
+
if (!routeArg && !pageArg) {
|
|
2325
|
+
return { error: "Provide route or page_id." };
|
|
2326
|
+
}
|
|
2327
|
+
let essence;
|
|
2328
|
+
try {
|
|
2329
|
+
const result = await readEssenceFile();
|
|
2330
|
+
essence = result.essence;
|
|
2331
|
+
} catch {
|
|
2332
|
+
return { error: "No valid essence file found. Run decantr init first." };
|
|
2333
|
+
}
|
|
2334
|
+
if (!isV42(essence)) {
|
|
2335
|
+
return {
|
|
2336
|
+
error: "Task context requires Essence v4.0.0. Run `decantr migrate --to v4` first."
|
|
2337
|
+
};
|
|
2338
|
+
}
|
|
2339
|
+
const routeEntry = routeArg ? essence.blueprint.routes?.[routeArg] : null;
|
|
2340
|
+
const sectionId = routeEntry?.section;
|
|
2341
|
+
const pageId = pageArg || routeEntry?.page;
|
|
2342
|
+
const section = sectionId ? essence.blueprint.sections.find((entry) => entry.id === sectionId) : essence.blueprint.sections.find(
|
|
2343
|
+
(entry) => entry.pages.some((page2) => page2.id === pageId)
|
|
2344
|
+
);
|
|
2345
|
+
const page = section?.pages.find((entry) => entry.id === pageId) ?? null;
|
|
2346
|
+
if (!section || !page || !pageId) {
|
|
2347
|
+
return {
|
|
2348
|
+
error: "Could not resolve route/page to an Essence section page.",
|
|
2349
|
+
available_routes: Object.keys(essence.blueprint.routes ?? {}).sort(),
|
|
2350
|
+
available_pages: essence.blueprint.sections.flatMap(
|
|
2351
|
+
(entry) => entry.pages.map((pageEntry) => ({ section_id: entry.id, page_id: pageEntry.id }))
|
|
2352
|
+
)
|
|
2353
|
+
};
|
|
2354
|
+
}
|
|
2355
|
+
const contextDir = join2(process.cwd(), ".decantr", "context");
|
|
2356
|
+
const manifest = readJsonIfExists(join2(contextDir, "pack-manifest.json"));
|
|
2357
|
+
const pageManifest = manifest?.pages.find((entry) => entry.id === pageId) ?? null;
|
|
2358
|
+
const sectionManifest = manifest?.sections.find((entry) => entry.id === section.id) ?? null;
|
|
2359
|
+
const pagePackJson = pageManifest ? readJsonIfExists(join2(contextDir, pageManifest.json)) : null;
|
|
2360
|
+
const sectionPackJson = sectionManifest ? readJsonIfExists(join2(contextDir, sectionManifest.json)) : null;
|
|
2361
|
+
const pagePackMarkdown = pageManifest && existsSync(join2(contextDir, pageManifest.markdown)) ? readFileSync(join2(contextDir, pageManifest.markdown), "utf-8") : null;
|
|
2362
|
+
const sectionContextPath = join2(contextDir, `section-${section.id}.md`);
|
|
2363
|
+
const sectionContext = existsSync(sectionContextPath) ? readFileSync(sectionContextPath, "utf-8") : null;
|
|
2364
|
+
const pagePackSummary = summarizePackJson(pagePackJson);
|
|
2365
|
+
const sectionPackSummary = summarizePackJson(sectionPackJson);
|
|
2366
|
+
const visualManifest = readJsonIfExists(join2(process.cwd(), ".decantr", "evidence", "visual-manifest.json"));
|
|
2367
|
+
const visualRoute = visualManifest?.routes?.find((entry) => entry.route === routeArg) ?? visualManifest?.routes?.find(
|
|
2368
|
+
(entry) => entry.screenshot?.includes(routeSlug(routeArg ?? pageId))
|
|
2369
|
+
) ?? null;
|
|
2370
|
+
const health = readJsonIfExists(join2(process.cwd(), ".decantr", "health-baseline-diff.json"));
|
|
2371
|
+
const themeInventory = readJsonIfExists(
|
|
2372
|
+
join2(process.cwd(), ".decantr", "theme-inventory.json")
|
|
2373
|
+
);
|
|
2374
|
+
const patternIds = extractPagePatternIds(page);
|
|
2375
|
+
const ranked = rankPatternCandidates(
|
|
2376
|
+
{
|
|
2377
|
+
query: [task, routeArg, page.description, ...patternIds].filter(Boolean).join(" "),
|
|
2378
|
+
limit: 5
|
|
2379
|
+
},
|
|
2380
|
+
patternIds.map((id) => patternToDiscoveryCandidate({ id, name: id, description: id }))
|
|
2381
|
+
);
|
|
2382
|
+
return {
|
|
2383
|
+
route: routeArg ?? null,
|
|
2384
|
+
page_id: pageId,
|
|
2385
|
+
section_id: section.id,
|
|
2386
|
+
section_role: section.role,
|
|
2387
|
+
shell: section.shell,
|
|
2388
|
+
task,
|
|
2389
|
+
visual_target: pagePackSummary.visualTarget ?? sectionPackSummary.visualTarget ?? essence.dna.personality?.join(". ") ?? null,
|
|
2390
|
+
directives: pagePackSummary.directives,
|
|
2391
|
+
patterns: pagePackSummary.patterns.length > 0 ? pagePackSummary.patterns : patternIds,
|
|
2392
|
+
ranked_patterns: ranked.map((match) => ({
|
|
2393
|
+
id: match.candidate.slug || match.candidate.id,
|
|
2394
|
+
score: match.score,
|
|
2395
|
+
reasons: match.reasons
|
|
2396
|
+
})),
|
|
2397
|
+
shared_components: pagePackSummary.sharedComponents,
|
|
2398
|
+
section_context: sectionContext,
|
|
2399
|
+
page_pack_excerpt: pagePackMarkdown ? pagePackMarkdown.slice(0, 12e3) : null,
|
|
2400
|
+
health_evidence: health ? {
|
|
2401
|
+
baseline_path: health.baselinePath,
|
|
2402
|
+
saved_at: health.savedAt,
|
|
2403
|
+
status_changed: health.statusChanged,
|
|
2404
|
+
score_delta: health.scoreDelta,
|
|
2405
|
+
added_findings: health.addedFindings?.slice(0, 8) ?? [],
|
|
2406
|
+
resolved_findings: health.resolvedFindings?.slice(0, 8) ?? [],
|
|
2407
|
+
changed_routes: health.changedRoutes ?? [],
|
|
2408
|
+
changed_screenshots: health.changedScreenshots ?? [],
|
|
2409
|
+
contract_drift: health.contractDrift ?? []
|
|
2410
|
+
} : null,
|
|
2411
|
+
visual_evidence: visualRoute ? {
|
|
2412
|
+
screenshot: visualRoute.screenshot ?? null,
|
|
2413
|
+
screenshot_hash: visualRoute.screenshotHash ?? null,
|
|
2414
|
+
status: visualRoute.status ?? null,
|
|
2415
|
+
error: visualRoute.error ?? null
|
|
2416
|
+
} : null,
|
|
2417
|
+
theme_inventory: themeInventory ? {
|
|
2418
|
+
modes: themeInventory.modes,
|
|
2419
|
+
variants: themeInventory.variants,
|
|
2420
|
+
path: ".decantr/theme-inventory.json"
|
|
2421
|
+
} : null,
|
|
2422
|
+
local_files: {
|
|
2423
|
+
page_pack: pageManifest?.markdown ?? null,
|
|
2424
|
+
section_pack: sectionManifest?.markdown ?? null,
|
|
2425
|
+
section_context: existsSync(sectionContextPath) ? `.decantr/context/section-${section.id}.md` : null,
|
|
2426
|
+
visual_manifest: existsSync(
|
|
2427
|
+
join2(process.cwd(), ".decantr", "evidence", "visual-manifest.json")
|
|
2428
|
+
) ? ".decantr/evidence/visual-manifest.json" : null
|
|
2429
|
+
}
|
|
2430
|
+
};
|
|
2431
|
+
}
|
|
2254
2432
|
case "decantr_get_execution_pack": {
|
|
2255
2433
|
const contextDir = join2(process.cwd(), ".decantr", "context");
|
|
2256
2434
|
const manifestPath = join2(contextDir, "pack-manifest.json");
|
|
@@ -2747,7 +2925,7 @@ function describeUpdate(operation, payload) {
|
|
|
2747
2925
|
}
|
|
2748
2926
|
|
|
2749
2927
|
// src/index.ts
|
|
2750
|
-
var VERSION = "2.
|
|
2928
|
+
var VERSION = "2.2.0";
|
|
2751
2929
|
var server = new Server({ name: "decantr", version: VERSION }, { capabilities: { tools: {} } });
|
|
2752
2930
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
2753
2931
|
return { tools: TOOLS };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-SVLMT45O.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decantr/mcp-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.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": [
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
52
52
|
"@decantr/essence-spec": "2.0.1",
|
|
53
|
-
"@decantr/verifier": "2.
|
|
54
|
-
"@decantr/registry": "2.
|
|
53
|
+
"@decantr/verifier": "2.2.0",
|
|
54
|
+
"@decantr/registry": "2.2.0"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "tsup",
|