@decantr/mcp-server 3.6.2 → 3.8.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 CHANGED
@@ -12,7 +12,7 @@ AI Frontend Governance for codebases touched by AI agents. Give Claude, Cursor,
12
12
 
13
13
  ![Decantr MCP demo](https://raw.githubusercontent.com/decantr-ai/decantr/main/packages/mcp-server/assets/decantr-demo.gif)
14
14
 
15
- - **Structured Contract context** -- gives your AI assistant patterns, layouts, component specs, typed graph context, Brownfield/Hybrid authority, local law, behavior obligations, and task-time context instead of letting it guess
15
+ - **Structured Contract context** -- gives your AI assistant patterns, layouts, component specs, shared Brownfield discovery metadata, typed graph context, Brownfield/Hybrid authority, local law, behavior obligations, and task-time context instead of letting it guess
16
16
  - **Evidence-backed repair loops** -- gives AI agents Project Health, component reuse drift, accepted behavior-obligation drift, accepted style bridge drift, stable diagnostic codes, typed repair IDs, graph-anchored 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
@@ -138,12 +138,12 @@ The server exposes a hard 8-tool MCP surface. Pass an `action` to select the rou
138
138
 
139
139
  | Tool | Description | Example Input |
140
140
  |------|-------------|---------------|
141
- | `decantr_project` | Read local project state and workspace health | `{ "action": "state", "project_path": "apps/web" }` |
141
+ | `decantr_project` | Read local project state, shared discovery summary, and workspace health | `{ "action": "state", "project_path": "apps/web" }` |
142
142
  | `decantr_contract` | Read Essence, validate, check drift, generate a skeleton, or read the Contract capsule | `{ "action": "validate", "path": "./decantr.essence.json" }` |
143
- | `decantr_context` | Read scaffold, section, page, task, and execution-pack context | `{ "action": "task", "project_path": "apps/web", "route": "/feed", "task": "improve recipe card loading" }` |
143
+ | `decantr_context` | Read scaffold, section, page, task, shared discovery summary, and execution-pack context | `{ "action": "task", "project_path": "apps/web", "route": "/feed", "task": "improve recipe card loading" }` |
144
144
  | `decantr_graph` | Read graph snapshots, query graph nodes/edges, or traverse graph relations | `{ "action": "query", "project_path": "apps/web", "file_path": "src/app/page.tsx", "include_impact": true }` |
145
- | `decantr_registry` | Search and resolve hosted registry content, benchmarks, and execution packs | `{ "action": "resolve_pattern", "id": "data-table", "preset": "product" }` |
146
- | `decantr_verify` | Run audit, critique, findings, v2 evidence bundles, or health-loop reads | `{ "action": "evidence_bundle", "project_path": "apps/web" }` |
145
+ | `decantr_registry` | Compatibility content-corpus tool for official vocabulary, benchmarks, and execution packs | `{ "action": "resolve_pattern", "id": "data-table", "preset": "product" }` |
146
+ | `decantr_verify` | Run audit, critique, findings, v2 evidence bundles with discovery metadata, or health-loop reads | `{ "action": "evidence_bundle", "project_path": "apps/web" }` |
147
147
  | `decantr_repair` | Return typed findings, repair plans, repair prompts, and v2 health-loop guidance | `{ "action": "health_loop", "project_path": "apps/web" }` |
148
148
  | `decantr_contract_write` | Explicit write surface for accepting drift, deferring drift to the drift log, or mutating Essence v4 | `{ "action": "update_essence", "operation": "add_feature", "payload": { "feature": "billing" } }` |
149
149
 
@@ -155,7 +155,7 @@ For Decantr 3 assistant prompt migration, see the MCP migration guide: https://d
155
155
 
156
156
  The MCP server reads Decantr files, including `.decantr/graph` typed graph artifacts, and selected project files from the active workspace. Write access is limited to the explicit `decantr_contract_write` tool with `accept_drift` and `update_essence` actions. `accept_drift` may defer a finding to `.decantr/drift-log.json` when the caller explicitly requests that resolution. Paths are contained to the active workspace root.
157
157
 
158
- Registry and pack-resolution tools may call the configured Decantr API. Source upload fallbacks for hosted critique/audit are disabled unless the tool call explicitly passes `allow_hosted_upload: true`. The MCP server does not emit Decantr telemetry. See [security permissions](https://decantr.ai/reference/security-permissions.md).
158
+ Content-corpus and pack-resolution tools may call the configured Decantr API. Source upload fallbacks for hosted critique/audit are retired; verification tools run local reads unless a future major version introduces a new upload contract. The MCP server does not emit Decantr telemetry. See [security permissions](https://decantr.ai/reference/security-permissions.md).
159
159
 
160
160
  ## Compatibility
161
161
 
@@ -167,11 +167,11 @@ Registry and pack-resolution tools may call the configured Decantr API. Source u
167
167
 
168
168
  ### 3.4 Tool Surface Migration
169
169
 
170
- Decantr 3.4 consolidated legacy MCP tool names into the eight action-based tools above. Decantr 3.6 keeps that surface, preserves v2 task/evidence/workspace-health/health-loop contracts, and adds compatible metadata only through the consolidated tools. For example, `decantr_get_project_state` becomes `decantr_project` with `{ "action": "state" }`, `decantr_get_graph_snapshot` becomes `decantr_graph` with `{ "action": "snapshot" }`, and the legacy write tools become `decantr_contract_write` with `{ "action": "accept_drift" }` or `{ "action": "update_essence" }`.
170
+ Decantr 3.4 consolidated legacy MCP tool names into the eight action-based tools above. Decantr 3.7 keeps that surface, preserves v2 task/evidence/workspace-health/health-loop contracts, and adds compatible discovery metadata only through the consolidated tools. For example, `decantr_get_project_state` becomes `decantr_project` with `{ "action": "state" }`, `decantr_get_graph_snapshot` becomes `decantr_graph` with `{ "action": "snapshot" }`, and the legacy write tools become `decantr_contract_write` with `{ "action": "accept_drift" }` or `{ "action": "update_essence" }`.
171
171
 
172
172
  ## How It Works
173
173
 
174
- An Essence spec (`decantr.essence.json`) captures your design intent -- archetype, theme, page structure, patterns, and guard rules -- in a single declarative file. The MCP server exposes this spec and the Decantr registry to your AI assistant, giving it concrete layout specs, component lists, and visual treatments instead of relying on the model's generic training data. The result is generated code that follows a coherent design system, and drift detection that catches deviations before they ship.
174
+ An Essence spec (`decantr.essence.json`) captures your design intent -- archetype, theme, page structure, patterns, and guard rules -- in a single declarative file. The MCP server exposes this spec and the official Decantr content corpus to your AI assistant, giving it concrete layout specs, component lists, and visual treatments instead of relying on the model's generic training data. The result is generated code that follows a coherent contract, and drift detection that catches deviations before they ship.
175
175
 
176
176
  ## Example Workflow
177
177
 
@@ -180,11 +180,11 @@ An Essence spec (`decantr.essence.json`) captures your design intent -- archetyp
180
180
  The AI assistant calls these tools behind the scenes:
181
181
 
182
182
  1. `decantr_contract` with `create_essence`, `validate`, or `check_drift` actions to generate and verify the contract
183
- 2. `decantr_registry` with `resolve_archetype`, `suggest_patterns`, `resolve_pattern`, or `compile_execution_packs` actions to fetch vocabulary and packs
183
+ 2. `decantr_registry` with `resolve_archetype`, `suggest_patterns`, `resolve_pattern`, or `compile_execution_packs` actions to fetch official content-corpus vocabulary and packs
184
184
  3. `decantr_context` with `execution_pack` or `task` actions to load the compact task contract before editing
185
185
  4. `decantr_project` with `state` to check Essence, packs, graph readiness, local law, diagnostics, and next useful action calls
186
186
  5. `decantr_contract` with `capsule` and `decantr_graph` with `snapshot`, `query`, or `traverse` to read typed graph context
187
- 6. `decantr_verify` with `critique`, `audit_project`, or `evidence_bundle` to produce local v2 evidence; hosted upload remains opt-in with `allow_hosted_upload: true`
187
+ 6. `decantr_verify` with `critique`, `audit_project`, or `evidence_bundle` to produce local v2 evidence
188
188
  7. `decantr_repair` with `findings`, `repair_plan`, `repair_prompt`, or `health_loop` to enter a scoped evidence-backed repair loop
189
189
 
190
190
  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.
package/dist/bin.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-XCTAGWHI.js";
2
+ import "./chunk-M45XVAPP.js";
@@ -8,7 +8,7 @@ import { execFileSync } from "child_process";
8
8
  import { createHash } from "crypto";
9
9
  import { existsSync, readdirSync, readFileSync } from "fs";
10
10
  import { readFile as readFile2 } from "fs/promises";
11
- import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "path";
11
+ import { dirname as dirname2, isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "path";
12
12
  import {
13
13
  buildGraphImpactContext,
14
14
  buildGraphRouteContext,
@@ -35,6 +35,7 @@ import {
35
35
  createEvidenceTier,
36
36
  createLoopReadiness,
37
37
  deriveVerificationDiagnostic,
38
+ discoverProject,
38
39
  KNOWN_VERIFICATION_DIAGNOSTICS,
39
40
  LOOP_READINESS_V2_SCHEMA_URL,
40
41
  PROJECT_HEALTH_REPORT_V2_SCHEMA_URL,
@@ -234,6 +235,65 @@ function displayProjectFile(projectRoot, path) {
234
235
  if (isAbsolute2(path)) return displayWorkspacePath(path);
235
236
  return displayWorkspacePath(join2(projectRoot, path));
236
237
  }
238
+ function mcpDiscoverySummary(projectRoot) {
239
+ const discovery = discoverProject(projectRoot);
240
+ return {
241
+ schema_version: "discovery.v1",
242
+ project_path: discovery.workspace.projectPath,
243
+ workspace_scope: discovery.workspace.scope,
244
+ project: {
245
+ framework: discovery.project.framework,
246
+ framework_version: discovery.project.frameworkVersion,
247
+ package_manager: discovery.project.packageManager,
248
+ primary_language: discovery.project.primaryLanguage,
249
+ has_typescript: discovery.project.hasTypeScript,
250
+ has_tailwind: discovery.project.hasTailwind,
251
+ has_decantr: discovery.project.hasDecantr,
252
+ package_name: discovery.project.packageName,
253
+ evidence: discovery.project.evidence
254
+ },
255
+ routes: {
256
+ strategy: discovery.routes.strategy,
257
+ route_signal_count: discovery.routes.routeSignalCount,
258
+ taskable_route_count: discovery.routes.taskableRouteCount,
259
+ confidence: discovery.routes.confidence,
260
+ taskable_routes: discovery.routes.taskableRoutes.slice(0, 20).map((route) => ({
261
+ path: route.path,
262
+ file: route.file,
263
+ source: route.source,
264
+ confidence: route.confidence
265
+ })),
266
+ signals: discovery.routes.routeSignals.slice(0, 20).map((signal) => ({
267
+ path: signal.path,
268
+ file: signal.file,
269
+ kind: signal.kind,
270
+ taskable: signal.taskable,
271
+ confidence: signal.confidence
272
+ }))
273
+ },
274
+ components: {
275
+ component_count: discovery.components.componentCount,
276
+ page_count: discovery.components.pageCount,
277
+ confidence: discovery.components.confidence,
278
+ directories: discovery.components.directories,
279
+ evidence: discovery.components.evidence,
280
+ limitations: discovery.components.limitations
281
+ },
282
+ styling: {
283
+ approach: discovery.styling.approach,
284
+ config_file: discovery.styling.configFile,
285
+ css_variable_count: discovery.styling.cssVariableCount,
286
+ color_token_count: discovery.styling.colorTokenCount,
287
+ dark_mode: discovery.styling.darkMode,
288
+ theme_signals: discovery.styling.themeSignals
289
+ },
290
+ assistant: {
291
+ rule_files: discovery.assistant.ruleFiles
292
+ },
293
+ confidence: discovery.confidence,
294
+ limitations: discovery.limitations
295
+ };
296
+ }
237
297
  function graphAvailableRoutes(snapshot) {
238
298
  return snapshot.nodes.filter((node) => node.type === "Route").map((node) => graphPayloadString(node.payload, "path") ?? node.id.replace(/^rt:/, "")).sort();
239
299
  }
@@ -950,111 +1010,6 @@ async function getHostedExecutionPackManifestPayload(args) {
950
1010
  typeof args.namespace === "string" ? { namespace: args.namespace } : void 0
951
1011
  );
952
1012
  }
953
- async function getHostedFileCritiquePayload(args) {
954
- const client = getAPIClient();
955
- const filePath = args.file_path;
956
- const resolvedFilePath = resolveWorkspacePath(filePath);
957
- const snapshotFilePath = relative2(process.cwd(), resolvedFilePath).replace(/\\/g, "/") || basename2(resolvedFilePath);
958
- const code = await readFile2(resolvedFilePath, "utf-8");
959
- const { essence } = await readEssenceFile(args.path);
960
- const treatmentsPath = typeof args.treatments_path === "string" ? resolveWorkspacePath(args.treatments_path) : join2(process.cwd(), "src", "styles", "treatments.css");
961
- const treatmentsCss = existsSync(treatmentsPath) ? readFileSync(treatmentsPath, "utf-8") : void 0;
962
- return client.critiqueFile(
963
- {
964
- essence,
965
- filePath: snapshotFilePath,
966
- code,
967
- treatmentsCss
968
- },
969
- typeof args.namespace === "string" ? { namespace: args.namespace } : void 0
970
- );
971
- }
972
- function extractHostedAssetPaths(indexHtml) {
973
- const assetPaths = /* @__PURE__ */ new Set();
974
- for (const match of indexHtml.matchAll(/<(?:script|link)[^>]+(?:src|href)="([^"]+)"/g)) {
975
- const assetPath = match[1];
976
- const assetsIndex = assetPath.indexOf("/assets/");
977
- if (assetsIndex === -1) continue;
978
- assetPaths.add(assetPath.slice(assetsIndex));
979
- }
980
- return [...assetPaths];
981
- }
982
- async function captureHostedDistSnapshot(projectRoot, distPathArg) {
983
- const distRoot = distPathArg ? resolveWorkspacePath(distPathArg, projectRoot) : join2(projectRoot, "dist");
984
- const indexPath = join2(distRoot, "index.html");
985
- if (!existsSync(indexPath)) {
986
- return void 0;
987
- }
988
- const indexHtml = readFileSync(indexPath, "utf-8");
989
- const assets = {};
990
- for (const assetPath of extractHostedAssetPaths(indexHtml)) {
991
- const snapshotAssetPath = assetPath.replace(/^[/\\]+/, "");
992
- const assetFilePath = resolveWorkspacePath(snapshotAssetPath, distRoot);
993
- if (existsSync(assetFilePath)) {
994
- assets[snapshotAssetPath] = readFileSync(assetFilePath, "utf-8");
995
- }
996
- }
997
- return {
998
- indexHtml,
999
- assets
1000
- };
1001
- }
1002
- function isHostedSourceSnapshotFile(path) {
1003
- if (/\.d\.ts$/i.test(path)) return false;
1004
- return /\.(?:[cm]?[jt]sx?)$/i.test(path);
1005
- }
1006
- async function captureHostedSourceSnapshot(projectRoot, sourcesPathArg) {
1007
- if (!sourcesPathArg) {
1008
- return void 0;
1009
- }
1010
- const sourcesRoot = resolveWorkspacePath(sourcesPathArg, projectRoot);
1011
- if (!existsSync(sourcesRoot)) {
1012
- return void 0;
1013
- }
1014
- const files = {};
1015
- const ignoredDirNames = /* @__PURE__ */ new Set([
1016
- "node_modules",
1017
- ".git",
1018
- ".decantr",
1019
- "dist",
1020
- "build",
1021
- "coverage"
1022
- ]);
1023
- const rootPrefix = basename2(sourcesRoot);
1024
- const walk = (absoluteDir, relativeDir) => {
1025
- for (const entry of readdirSync(absoluteDir, { withFileTypes: true })) {
1026
- if (ignoredDirNames.has(entry.name)) continue;
1027
- const absolutePath = join2(absoluteDir, entry.name);
1028
- const relativePath = join2(relativeDir, entry.name).replace(/\\/g, "/");
1029
- if (entry.isDirectory()) {
1030
- walk(absolutePath, relativePath);
1031
- continue;
1032
- }
1033
- if (!entry.isFile()) continue;
1034
- if (!isHostedSourceSnapshotFile(relativePath)) continue;
1035
- files[relativePath] = readFileSync(absolutePath, "utf-8");
1036
- }
1037
- };
1038
- walk(sourcesRoot, rootPrefix);
1039
- return Object.keys(files).length > 0 ? { files } : void 0;
1040
- }
1041
- async function getHostedProjectAuditPayload(args) {
1042
- const client = getAPIClient();
1043
- const { essence } = await readEssenceFile(args.path);
1044
- const dist = await captureHostedDistSnapshot(process.cwd(), args.dist_path);
1045
- const sources = await captureHostedSourceSnapshot(
1046
- process.cwd(),
1047
- args.sources_path
1048
- );
1049
- return client.auditProject(
1050
- {
1051
- essence,
1052
- dist,
1053
- sources
1054
- },
1055
- typeof args.namespace === "string" ? { namespace: args.namespace } : void 0
1056
- );
1057
- }
1058
1013
  async function loadHostedExecutionPackBundleFallback(args) {
1059
1014
  try {
1060
1015
  return {
@@ -1094,38 +1049,9 @@ async function loadHostedSelectedExecutionPackFallback(args) {
1094
1049
  };
1095
1050
  }
1096
1051
  }
1097
- async function loadHostedFileCritiqueFallback(args) {
1098
- try {
1099
- return {
1100
- report: await getHostedFileCritiquePayload(args),
1101
- error: null
1102
- };
1103
- } catch (error) {
1104
- return {
1105
- report: null,
1106
- error: error.message
1107
- };
1108
- }
1109
- }
1110
- async function loadHostedProjectAuditFallback(args) {
1111
- try {
1112
- return {
1113
- report: await getHostedProjectAuditPayload(args),
1114
- error: null
1115
- };
1116
- } catch (error) {
1117
- return {
1118
- report: null,
1119
- error: error.message
1120
- };
1121
- }
1122
- }
1123
1052
  function hasExecutionPackPayload(payload) {
1124
1053
  return payload.markdown !== null || payload.json !== null;
1125
1054
  }
1126
- function allowsHostedUpload(args) {
1127
- return args.allow_hosted_upload === true;
1128
- }
1129
1055
  function toHostedExecutionPackPayload(pack) {
1130
1056
  return {
1131
1057
  markdown: pack && typeof pack.renderedMarkdown === "string" ? pack.renderedMarkdown : null,
@@ -1285,7 +1211,7 @@ function mcpCommandsForFinding(source) {
1285
1211
  case "pack":
1286
1212
  return [
1287
1213
  "decantr refresh",
1288
- "decantr registry get-pack review --write-context",
1214
+ "decantr content get-pack review --write-context",
1289
1215
  "decantr health"
1290
1216
  ];
1291
1217
  case "runtime":
@@ -1974,7 +1900,7 @@ var TOOLS = [
1974
1900
  consolidatedTool(
1975
1901
  "decantr_registry",
1976
1902
  "Decantr Registry",
1977
- "Search and resolve hosted registry content, benchmark metadata, and execution packs.",
1903
+ "Compatibility tool for searching the official Decantr content corpus, benchmark metadata, and execution packs.",
1978
1904
  READ_ONLY_NETWORK
1979
1905
  ),
1980
1906
  consolidatedTool(
@@ -2292,7 +2218,7 @@ async function handleLegacyTool(name, args) {
2292
2218
  if (args.components_used && Array.isArray(args.components_used) && args.page_id && typeof args.page_id === "string") {
2293
2219
  const pages = listEssencePages(essence);
2294
2220
  const page = pages.find((p) => p.id === args.page_id);
2295
- if (page && page.layout) {
2221
+ if (page?.layout) {
2296
2222
  const expectedPatterns = /* @__PURE__ */ new Set();
2297
2223
  for (const item of page.layout) {
2298
2224
  if (typeof item === "string") {
@@ -2621,6 +2547,7 @@ async function handleLegacyTool(name, args) {
2621
2547
  return {
2622
2548
  source: "local_workspace",
2623
2549
  project_root: displayWorkspacePath(projectRoot),
2550
+ discovery: mcpDiscoverySummary(projectRoot),
2624
2551
  essence: essence ? {
2625
2552
  present: true,
2626
2553
  version: typeof essence.version === "string" ? essence.version : null,
@@ -3222,7 +3149,7 @@ async function handleLegacyTool(name, args) {
3222
3149
  const hosted = await loadHostedExecutionPackBundleFallback(args);
3223
3150
  if (!hosted.bundle) {
3224
3151
  return {
3225
- error: "Scaffold context not found. Run `decantr refresh` or `decantr registry compile-packs --write-context` to materialize scaffold context and execution packs.",
3152
+ error: "Scaffold context not found. Run `decantr refresh` or `decantr content compile-packs --write-context` to materialize scaffold context and execution packs.",
3226
3153
  hosted_fallback_error: hosted.error ?? hostedScaffold.error ?? hostedReview.error
3227
3154
  };
3228
3155
  }
@@ -3353,7 +3280,7 @@ async function handleLegacyTool(name, args) {
3353
3280
  context: derivedContext,
3354
3281
  execution_pack_source: executionPackSource,
3355
3282
  execution_pack: executionPack,
3356
- note: executionPackSource === "hosted_fallback" ? "Section context file not found. Using hosted compiled execution pack fallback as the readable section context." : `Section context file not found. Run \`decantr refresh\` or \`decantr registry get-pack section ${sectionId} --write-context\` to generate it.`,
3283
+ note: executionPackSource === "hosted_fallback" ? "Section context file not found. Using hosted compiled execution pack fallback as the readable section context." : `Section context file not found. Run \`decantr refresh\` or \`decantr content get-pack section ${sectionId} --write-context\` to generate it.`,
3357
3284
  hosted_fallback_error: executionPackSource ? void 0 : hostedFallbackError
3358
3285
  };
3359
3286
  }
@@ -3406,7 +3333,7 @@ async function handleLegacyTool(name, args) {
3406
3333
  const hosted = await loadHostedPageSelection();
3407
3334
  if (!hosted) {
3408
3335
  return {
3409
- error: "Execution pack manifest not found. Run `decantr refresh` or `decantr registry get-pack manifest --write-context` to generate compiled packs.",
3336
+ error: "Execution pack manifest not found. Run `decantr refresh` or `decantr content get-pack manifest --write-context` to generate compiled packs.",
3410
3337
  hosted_fallback_error: hostedFallbackError
3411
3338
  };
3412
3339
  }
@@ -3651,6 +3578,7 @@ async function handleLegacyTool(name, args) {
3651
3578
  verifyCommand
3652
3579
  };
3653
3580
  return {
3581
+ discovery: mcpDiscoverySummary(projectRoot),
3654
3582
  route: resolvedRoute,
3655
3583
  page_id: pageId,
3656
3584
  section_id: section.id,
@@ -3755,7 +3683,7 @@ async function handleLegacyTool(name, args) {
3755
3683
  hostedFallbackError = hosted.error;
3756
3684
  if (!hosted.bundle) {
3757
3685
  return {
3758
- error: "Execution pack manifest not found. Run `decantr refresh` or `decantr registry get-pack manifest --write-context` to generate compiled packs.",
3686
+ error: "Execution pack manifest not found. Run `decantr refresh` or `decantr content get-pack manifest --write-context` to generate compiled packs.",
3759
3687
  hosted_fallback_error: hosted.error
3760
3688
  };
3761
3689
  }
@@ -3775,7 +3703,7 @@ async function handleLegacyTool(name, args) {
3775
3703
  hostedFallbackError = hosted.error;
3776
3704
  if (!hosted.selected) {
3777
3705
  return {
3778
- error: "Execution pack manifest not found. Run `decantr refresh` or `decantr registry get-pack manifest --write-context` to generate compiled packs.",
3706
+ error: "Execution pack manifest not found. Run `decantr refresh` or `decantr content get-pack manifest --write-context` to generate compiled packs.",
3779
3707
  hosted_fallback_error: hosted.error
3780
3708
  };
3781
3709
  }
@@ -3930,12 +3858,6 @@ async function handleLegacyTool(name, args) {
3930
3858
  if (existsSync(localReviewPackPath)) {
3931
3859
  return critiqueFile(args.file_path, process.cwd());
3932
3860
  }
3933
- if (allowsHostedUpload(args)) {
3934
- const hosted = await loadHostedFileCritiqueFallback(args);
3935
- if (hosted.report) {
3936
- return hosted.report;
3937
- }
3938
- }
3939
3861
  return critiqueFile(args.file_path, process.cwd());
3940
3862
  }
3941
3863
  case "decantr_audit_project": {
@@ -3965,12 +3887,6 @@ async function handleLegacyTool(name, args) {
3965
3887
  if (hasReviewPack && hasPackManifest) {
3966
3888
  return auditProject(projectRoot);
3967
3889
  }
3968
- if (allowsHostedUpload(args)) {
3969
- const hosted = await loadHostedProjectAuditFallback(args);
3970
- if (hosted.report) {
3971
- return hosted.report;
3972
- }
3973
- }
3974
3890
  return auditProject(projectRoot);
3975
3891
  }
3976
3892
  case "decantr_get_findings": {
@@ -4072,7 +3988,10 @@ async function handleLegacyTool(name, args) {
4072
3988
  try {
4073
3989
  const projectRoot = resolveMcpProjectRoot(args.project_path);
4074
3990
  const state = await getMcpHealthState(projectRoot);
4075
- return state.evidence;
3991
+ return {
3992
+ ...state.evidence,
3993
+ discovery: mcpDiscoverySummary(projectRoot)
3994
+ };
4076
3995
  } catch (error) {
4077
3996
  return { error: error.message };
4078
3997
  }
@@ -4111,6 +4030,7 @@ async function handleLegacyTool(name, args) {
4111
4030
  }
4112
4031
  return {
4113
4032
  project: state.evidence.project,
4033
+ discovery: mcpDiscoverySummary(projectRoot),
4114
4034
  health: state.evidence.health,
4115
4035
  finding: {
4116
4036
  id: finding.id,
@@ -4329,7 +4249,7 @@ function describeUpdate(operation, payload) {
4329
4249
  }
4330
4250
 
4331
4251
  // src/index.ts
4332
- var VERSION = "3.6.2";
4252
+ var VERSION = "3.8.0";
4333
4253
  var server = new Server({ name: "decantr", version: VERSION }, { capabilities: { tools: {} } });
4334
4254
  server.setRequestHandler(ListToolsRequestSchema, async () => {
4335
4255
  return { tools: TOOLS };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import "./chunk-XCTAGWHI.js";
1
+ import "./chunk-M45XVAPP.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decantr/mcp-server",
3
- "version": "3.6.2",
3
+ "version": "3.8.0",
4
4
  "mcpName": "io.github.decantr-ai/mcp-server",
5
5
  "description": "MCP server for Decantr — exposes Contract context, typed graph artifacts, and verification evidence to AI coding assistants",
6
6
  "keywords": [
@@ -41,7 +41,8 @@
41
41
  "main": "dist/index.js",
42
42
  "types": "dist/index.d.ts",
43
43
  "files": [
44
- "dist"
44
+ "dist",
45
+ "server.json"
45
46
  ],
46
47
  "engines": {
47
48
  "node": ">=20.19.0"
@@ -51,10 +52,10 @@
51
52
  },
52
53
  "dependencies": {
53
54
  "@modelcontextprotocol/sdk": "^1.29.0",
54
- "@decantr/core": "3.6.0",
55
- "@decantr/verifier": "3.6.1",
56
- "@decantr/essence-spec": "3.4.0",
57
- "@decantr/registry": "3.4.0"
55
+ "@decantr/core": "3.8.0",
56
+ "@decantr/verifier": "3.8.0",
57
+ "@decantr/essence-spec": "3.8.0",
58
+ "@decantr/registry": "3.8.0"
58
59
  },
59
60
  "scripts": {
60
61
  "build": "tsup",
package/server.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.decantr-ai/mcp-server",
4
+ "description": "AI Frontend Governance for codebases touched by AI agents. Serves Contract context, typed graph artifacts, drift evidence, and repair prompts.",
5
+ "repository": {
6
+ "url": "https://github.com/decantr-ai/decantr",
7
+ "source": "github"
8
+ },
9
+ "version": "3.8.0",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "identifier": "@decantr/mcp-server",
14
+ "version": "3.8.0",
15
+ "transport": {
16
+ "type": "stdio"
17
+ }
18
+ }
19
+ ]
20
+ }