@martinloop/mcp 0.3.9 → 0.5.1

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.
Files changed (113) hide show
  1. package/README.md +82 -141
  2. package/dist/discovery-metadata.d.ts +1 -1
  3. package/dist/discovery-metadata.js +1 -1
  4. package/dist/resources.d.ts +1 -2
  5. package/dist/resources.js +62 -98
  6. package/dist/server-validation.d.ts +1 -1
  7. package/dist/server-validation.js +16 -11
  8. package/dist/server.d.ts +23 -0
  9. package/dist/server.js +192 -15
  10. package/dist/tools/doctor.js +5 -4
  11. package/dist/tools/get-status.d.ts +2 -0
  12. package/dist/tools/get-status.js +1 -0
  13. package/dist/tools/preflight.d.ts +2 -0
  14. package/dist/tools/preflight.js +43 -3
  15. package/dist/tools/run-dossier.d.ts +3 -1
  16. package/dist/tools/run-dossier.js +40 -2
  17. package/dist/tools/run-loop.d.ts +5 -3
  18. package/dist/tools/run-loop.js +15 -9
  19. package/dist/tools/tool-errors.js +1 -1
  20. package/dist/tools/tool-response.js +9 -2
  21. package/dist/tools/tool-support.d.ts +4 -2
  22. package/dist/tools/tool-support.js +6 -15
  23. package/dist/vendor/adapters/claude-cli.d.ts +2 -2
  24. package/dist/vendor/adapters/claude-cli.js +97 -69
  25. package/dist/vendor/adapters/cli-bridge.d.ts +9 -1
  26. package/dist/vendor/adapters/cli-bridge.js +54 -13
  27. package/dist/vendor/adapters/codex-launcher.d.ts +61 -1
  28. package/dist/vendor/adapters/codex-launcher.js +118 -19
  29. package/dist/vendor/adapters/index.d.ts +2 -4
  30. package/dist/vendor/adapters/index.js +2 -4
  31. package/dist/vendor/adapters/openai-compatible.d.ts +2 -3
  32. package/dist/vendor/adapters/openai-compatible.js +80 -15
  33. package/dist/vendor/adapters/verifier-only.js +9 -4
  34. package/dist/vendor/contracts/adapter-capabilities.d.ts +1 -1
  35. package/dist/vendor/contracts/context-handoff.d.ts +100 -0
  36. package/dist/vendor/contracts/context-handoff.js +11 -0
  37. package/dist/vendor/contracts/context-manifest.d.ts +195 -0
  38. package/dist/vendor/contracts/context-manifest.js +17 -0
  39. package/dist/vendor/contracts/context-shadow.d.ts +75 -0
  40. package/dist/vendor/contracts/context-shadow.js +8 -0
  41. package/dist/vendor/contracts/delivery.d.ts +47 -0
  42. package/dist/vendor/contracts/delivery.js +18 -0
  43. package/dist/vendor/contracts/exits.d.ts +126 -0
  44. package/dist/vendor/contracts/exits.js +32 -0
  45. package/dist/vendor/contracts/index.d.ts +55 -6
  46. package/dist/vendor/contracts/index.js +24 -0
  47. package/dist/vendor/contracts/mission.d.ts +102 -0
  48. package/dist/vendor/contracts/mission.js +64 -0
  49. package/dist/vendor/contracts/operator.d.ts +3 -1
  50. package/dist/vendor/contracts/operator.js +2 -1
  51. package/dist/vendor/contracts/verified-handoff.d.ts +106 -0
  52. package/dist/vendor/contracts/verified-handoff.js +40 -0
  53. package/dist/vendor/core/context-chain-gate.d.ts +89 -0
  54. package/dist/vendor/core/context-chain-gate.js +173 -0
  55. package/dist/vendor/core/context-compiler.d.ts +53 -0
  56. package/dist/vendor/core/context-compiler.js +261 -0
  57. package/dist/vendor/core/context-handoff.d.ts +42 -0
  58. package/dist/vendor/core/context-handoff.js +167 -0
  59. package/dist/vendor/core/context-shadow.d.ts +39 -0
  60. package/dist/vendor/core/context-shadow.js +200 -0
  61. package/dist/vendor/core/delivery/index.d.ts +6 -0
  62. package/dist/vendor/core/delivery/index.js +4 -0
  63. package/dist/vendor/core/delivery/message-client.d.ts +18 -0
  64. package/dist/vendor/core/delivery/message-client.js +38 -0
  65. package/dist/vendor/core/delivery/message-ledger.d.ts +35 -0
  66. package/dist/vendor/core/delivery/message-ledger.js +97 -0
  67. package/dist/vendor/core/delivery/message-schema.d.ts +16 -0
  68. package/dist/vendor/core/delivery/message-schema.js +111 -0
  69. package/dist/vendor/core/delivery/update-check.d.ts +19 -0
  70. package/dist/vendor/core/delivery/update-check.js +107 -0
  71. package/dist/vendor/core/exit-signal.d.ts +88 -0
  72. package/dist/vendor/core/exit-signal.js +339 -0
  73. package/dist/vendor/core/exits.d.ts +41 -0
  74. package/dist/vendor/core/exits.js +258 -0
  75. package/dist/vendor/core/grounding.d.ts +2 -1
  76. package/dist/vendor/core/grounding.js +40 -5
  77. package/dist/vendor/core/index.d.ts +47 -6
  78. package/dist/vendor/core/index.js +1102 -670
  79. package/dist/vendor/core/mission/aggregate.d.ts +27 -0
  80. package/dist/vendor/core/mission/aggregate.js +42 -0
  81. package/dist/vendor/core/mission/index.d.ts +2 -0
  82. package/dist/vendor/core/mission/index.js +1 -0
  83. package/dist/vendor/core/persistence/compiler.d.ts +8 -0
  84. package/dist/vendor/core/persistence/compiler.js +156 -0
  85. package/dist/vendor/core/persistence/context-handoff-store.d.ts +68 -0
  86. package/dist/vendor/core/persistence/context-handoff-store.js +112 -0
  87. package/dist/vendor/core/persistence/index.d.ts +4 -0
  88. package/dist/vendor/core/persistence/index.js +2 -0
  89. package/dist/vendor/core/persistence/ledger.d.ts +1 -1
  90. package/dist/vendor/core/persistence/mission-store.d.ts +56 -0
  91. package/dist/vendor/core/persistence/mission-store.js +281 -0
  92. package/dist/vendor/core/persistence/runs-reader.d.ts +2 -0
  93. package/dist/vendor/core/policy.d.ts +2 -0
  94. package/dist/vendor/core/policy.js +11 -8
  95. package/dist/vendor/core/red-blue/red-phase.d.ts +2 -1
  96. package/dist/vendor/core/red-blue/red-phase.js +3 -3
  97. package/dist/vendor/core/red-blue/risk-tiers.d.ts +2 -4
  98. package/dist/vendor/core/red-blue/risk-tiers.js +1 -3
  99. package/dist/vendor/core/rollback.js +15 -1
  100. package/dist/vendor/core/routing.d.ts +0 -42
  101. package/dist/vendor/core/routing.js +4 -154
  102. package/dist/vendor/core/savings.d.ts +13 -0
  103. package/dist/vendor/core/savings.js +22 -0
  104. package/dist/vendor/core/termination-store.d.ts +15 -0
  105. package/dist/vendor/core/termination-store.js +44 -0
  106. package/dist/vendor/core/verified-handoff.d.ts +72 -0
  107. package/dist/vendor/core/verified-handoff.js +238 -0
  108. package/package.json +4 -10
  109. package/server.json +3 -3
  110. package/dist/vendor/adapters/stub-agent-cli.d.ts +0 -8
  111. package/dist/vendor/adapters/stub-agent-cli.js +0 -40
  112. package/dist/vendor/adapters/stub-direct-provider.d.ts +0 -8
  113. package/dist/vendor/adapters/stub-direct-provider.js +0 -12
package/dist/resources.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
2
  import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
4
  import { buildMartinDiscoveryMetadata } from "./discovery-metadata.js";
5
5
  import { MARTIN_MCP_PACKAGE_VERSION } from "./package-version.js";
6
6
  import { inspectLoopTool } from "./tools/inspect-loop.js";
@@ -19,7 +19,6 @@ export const MARTIN_STATIC_RESOURCE_URIS = {
19
19
  triage: "martin://runs/triage",
20
20
  latestRun: "martin://runs/latest",
21
21
  latestSummary: "martin://runs/latest/summary",
22
- latestReceipt: "martin://runs/latest/receipt",
23
22
  latestProofCard: "martin://runs/latest/proof-card",
24
23
  latestBudgetStatus: "martin://runs/latest/budget-status",
25
24
  latestVerifierEvidence: "martin://runs/latest/verifier-evidence",
@@ -35,9 +34,19 @@ export const MARTIN_STATIC_RESOURCE_URIS = {
35
34
  operatingRulesGuide: "martin://guides/operating-rules",
36
35
  publishReadinessGuide: "martin://guides/publish-readiness",
37
36
  governanceStatus: "martin://agent/governance-status",
38
- memorySummary: "martin://agent/memory-summary",
39
- modeStatus: "martin://agent/mode-status"
37
+ modeStatus: "martin://agent/mode-status",
38
+ memorySummary: "martin://agent/memory-summary"
40
39
  };
40
+ function formatRecordedCost(usd, provenance) {
41
+ if (provenance === "unavailable")
42
+ return "unavailable";
43
+ if (provenance === "actual")
44
+ return `$${usd.toFixed(2)} provider-settled actual`;
45
+ if (provenance === "calculated") {
46
+ return `$${usd.toFixed(2)} calculated from observed usage`;
47
+ }
48
+ return `$${usd.toFixed(2)} estimated`;
49
+ }
41
50
  export const MARTIN_RESOURCE_TEMPLATES = [
42
51
  {
43
52
  name: "martin_run_record",
@@ -100,18 +109,11 @@ export const MARTIN_STATIC_RESOURCES = [
100
109
  description: "Compact latest-run summary for context-constrained agents.",
101
110
  mimeType: "application/json"
102
111
  },
103
- {
104
- uri: MARTIN_STATIC_RESOURCE_URIS.latestReceipt,
105
- name: "martin_latest_receipt",
106
- title: "Martin Latest Receipt",
107
- description: "Canonical structured receipt for the latest run; use this before optional proof-card views.",
108
- mimeType: "application/json"
109
- },
110
112
  {
111
113
  uri: MARTIN_STATIC_RESOURCE_URIS.latestProofCard,
112
114
  name: "martin_latest_proof_card",
113
115
  title: "Martin Latest Proof Card",
114
- description: "Optional Markdown proof view derived from the latest receipt.",
116
+ description: "Small Markdown receipt showing what happened, what Martin prevented, and the next safe action.",
115
117
  mimeType: "text/markdown"
116
118
  },
117
119
  {
@@ -212,19 +214,19 @@ export const MARTIN_STATIC_RESOURCES = [
212
214
  description: "Proactive governance status: whether work is governed, budget remaining, unreceipted runs, and recommended next action. Read this before starting agent work.",
213
215
  mimeType: "application/json"
214
216
  },
217
+ {
218
+ uri: MARTIN_STATIC_RESOURCE_URIS.modeStatus,
219
+ name: "martin_mode_status",
220
+ title: "Martin Mode Status",
221
+ description: "Current MartinLoop working mode, whether it is inherited or explicitly configured, and how to switch it.",
222
+ mimeType: "application/json"
223
+ },
215
224
  {
216
225
  uri: MARTIN_STATIC_RESOURCE_URIS.memorySummary,
217
226
  name: "martin_memory_summary",
218
227
  title: "Martin Memory Summary",
219
228
  description: "MartinLoop persistent memory: user preferences, consent signals, budget patterns, and behavioral observations aggregated over time. Read at session start to personalize recommendations.",
220
229
  mimeType: "application/json"
221
- },
222
- {
223
- uri: MARTIN_STATIC_RESOURCE_URIS.modeStatus,
224
- name: "martin_mode_status",
225
- title: "Martin Mode Status",
226
- description: "Current Martin working mode (auto, plan, or edits) and consent state. Read before starting agent work to confirm whether the user expects autonomous execution, plan approval, or per-edit review.",
227
- mimeType: "application/json"
228
230
  }
229
231
  ];
230
232
  export function listMartinResources() {
@@ -260,8 +262,6 @@ export async function readMartinResource(input) {
260
262
  return jsonResource(input.uri, withDiscoveryMetadata(await martinRunDossierTool({ latest: true, runsDir: context.runsRoot }), context.runsRoot));
261
263
  case MARTIN_STATIC_RESOURCE_URIS.latestSummary:
262
264
  return jsonResource(input.uri, withDiscoveryMetadata(await buildLatestSummaryResource(context.runsRoot), context.runsRoot));
263
- case MARTIN_STATIC_RESOURCE_URIS.latestReceipt:
264
- return jsonResource(input.uri, withDiscoveryMetadata(await buildLatestReceiptResource(context.runsRoot), context.runsRoot));
265
265
  case MARTIN_STATIC_RESOURCE_URIS.latestProofCard:
266
266
  return textResource(input.uri, "text/markdown", await buildLatestProofCardResource(context.runsRoot));
267
267
  case MARTIN_STATIC_RESOURCE_URIS.latestBudgetStatus:
@@ -284,7 +284,7 @@ export async function readMartinResource(input) {
284
284
  case MARTIN_STATIC_RESOURCE_URIS.governanceStatus:
285
285
  return jsonResource(input.uri, withDiscoveryMetadata(await buildGovernanceStatusResource(context.runsRoot, context.workingDirectory), context.runsRoot));
286
286
  case MARTIN_STATIC_RESOURCE_URIS.modeStatus:
287
- return jsonResource(input.uri, withDiscoveryMetadata(await buildModeStatusResource(), context.runsRoot));
287
+ return jsonResource(input.uri, withDiscoveryMetadata(await buildModeStatusResource(context.workingDirectory), context.runsRoot));
288
288
  case MARTIN_STATIC_RESOURCE_URIS.agentNextStep:
289
289
  return jsonResource(input.uri, withDiscoveryMetadata(await buildAgentNextStepResource(context.runsRoot), context.runsRoot));
290
290
  case MARTIN_STATIC_RESOURCE_URIS.mcpUsageGuide:
@@ -386,7 +386,7 @@ async function loadLatestRunForCompactResource(runsRoot) {
386
386
  empty: true,
387
387
  warnings: [
388
388
  "No Martin run records were found yet.",
389
- "Run `npx martin-loop demo`, then run `npx martin-loop run ... --proof --verify <command>` for a no-spend local proof pass."
389
+ "Run `npx martin-loop demo`, then use `--proof --verify <command>` for explicitly non-governed verification-only evidence."
390
390
  ]
391
391
  };
392
392
  }
@@ -414,6 +414,7 @@ async function buildLatestSummaryResource(runsRoot) {
414
414
  budget: loop.budget,
415
415
  cost: {
416
416
  actualUsd: loop.cost.actualUsd,
417
+ provenance: loop.cost.provenance ?? "unavailable",
417
418
  avoidedUsdEstimate: loop.cost.avoidedUsd ?? 0,
418
419
  tokensIn: loop.cost.tokensIn,
419
420
  tokensOut: loop.cost.tokensOut,
@@ -433,44 +434,6 @@ async function buildLatestSummaryResource(runsRoot) {
433
434
  warnings: [...latest.detail.warnings, ...verification.warnings]
434
435
  };
435
436
  }
436
- async function buildLatestReceiptResource(runsRoot) {
437
- const latest = await loadLatestRunForCompactResource(runsRoot);
438
- if (latest.empty || !latest.detail) {
439
- return compactEmptyState("latest-receipt", runsRoot, latest.warnings);
440
- }
441
- const ledgerEvents = await readLedgerEvents(latest.detail);
442
- const loop = latest.detail.loop;
443
- const verification = buildVerificationHistorySnapshot(loop, ledgerEvents);
444
- const preview = buildPersistedLoopPreview(loop);
445
- return {
446
- kind: "latest-receipt",
447
- loop: preview,
448
- task: {
449
- title: loop.task?.title,
450
- objective: loop.task?.objective,
451
- verificationPlan: loop.task?.verificationPlan ?? []
452
- },
453
- receiptIntegrity: latest.detail.loop.receiptIntegrity,
454
- verification: {
455
- status: verification.latestVerification?.passed === true
456
- ? "passed"
457
- : verification.latestVerification?.passed === false
458
- ? "failed"
459
- : "unavailable",
460
- summary: verification.latestVerification?.summary,
461
- latest: verification.latestVerification,
462
- count: verification.verificationCount
463
- },
464
- whatHappened: loop.attempts.at(-1)?.summary ?? verification.latestVerification?.summary ?? loop.task?.objective,
465
- whatMartinPrevented: describePrevention(loop),
466
- nextSafeAction: inferAgentNextStep(loop, verification),
467
- proofCard: {
468
- artifactGuaranteed: false,
469
- resource: MARTIN_STATIC_RESOURCE_URIS.latestProofCard
470
- },
471
- warnings: [...latest.detail.warnings, ...verification.warnings]
472
- };
473
- }
474
437
  async function buildLatestBudgetStatusResource(runsRoot) {
475
438
  const latest = await loadLatestRunForCompactResource(runsRoot);
476
439
  if (latest.empty || !latest.detail) {
@@ -487,6 +450,7 @@ async function buildLatestBudgetStatusResource(runsRoot) {
487
450
  budget: loop.budget,
488
451
  cost: {
489
452
  actualUsd: loop.cost.actualUsd,
453
+ provenance: loop.cost.provenance ?? "unavailable",
490
454
  avoidedUsdEstimate: loop.cost.avoidedUsd ?? 0,
491
455
  tokensIn: loop.cost.tokensIn,
492
456
  tokensOut: loop.cost.tokensOut,
@@ -601,7 +565,7 @@ async function buildLatestProofCardResource(runsRoot) {
601
565
  "",
602
566
  "What happened: Martin has not found a local run record in this runs root.",
603
567
  "What Martin prevented: unknown until a governed run executes.",
604
- "Next safe action: call `martin_doctor`, run `npx martin-loop demo`, then inspect `martin://runs/latest/receipt` or `martin://runs/latest/summary`.",
568
+ "Next safe action: call `martin_doctor`, run `npx martin-loop demo`, then inspect `martin://runs/latest/summary`.",
605
569
  "",
606
570
  "Estimate note: no cost or token savings are claimed without run evidence.",
607
571
  ""
@@ -623,7 +587,7 @@ async function buildLatestProofCardResource(runsRoot) {
623
587
  `Run: \`${loop.loopId}\``,
624
588
  `Status: ${loop.status} / ${loop.lifecycleState}`,
625
589
  `Attempts: ${loop.attempts.length}`,
626
- `Spend: $${loop.cost.actualUsd.toFixed(2)} actual, $${(loop.cost.avoidedUsd ?? 0).toFixed(2)} avoided estimate`,
590
+ `Spend: ${formatRecordedCost(loop.cost.actualUsd, loop.cost.provenance ?? "unavailable")}, $${(loop.cost.avoidedUsd ?? 0).toFixed(2)} avoided estimate`,
627
591
  `Tokens: ${loop.cost.tokensIn} in / ${loop.cost.tokensOut} out`,
628
592
  `Verifier: ${verifierStatus}`,
629
593
  "",
@@ -647,7 +611,7 @@ function compactEmptyState(kind, runsRoot, warnings) {
647
611
  status: "empty",
648
612
  runsRoot,
649
613
  summary: "No Martin run records are available yet.",
650
- nextStep: "Run `npx martin-loop doctor`, create the demo workspace with `npx martin-loop demo`, then run `npx martin-loop run ... --proof --verify <command>`.",
614
+ nextStep: "Run `npx martin-loop doctor`, create the demo workspace, then use `--proof --verify <command>` only for non-governed verification evidence.",
651
615
  warnings
652
616
  };
653
617
  }
@@ -708,6 +672,33 @@ async function buildGovernanceStatusResource(runsRoot, workingDirectory) {
708
672
  warning: governed ? undefined : "This session is NOT governed. Complete the required sequence before making changes."
709
673
  };
710
674
  }
675
+ async function buildModeStatusResource(workingDirectory) {
676
+ const configPath = join(homedir(), ".martin", "config.json");
677
+ let config = {};
678
+ try {
679
+ config = JSON.parse(await readFile(configPath, "utf8"));
680
+ }
681
+ catch {
682
+ // Fresh config means the implicit auto default is in effect.
683
+ }
684
+ const projectMode = config.projectOverrides?.[workingDirectory];
685
+ const defaultMode = config.defaultMode ?? "auto";
686
+ const effectiveMode = projectMode ?? defaultMode;
687
+ return {
688
+ kind: "mode-status",
689
+ effectiveMode,
690
+ defaultMode,
691
+ scope: projectMode ? "project" : config.defaultMode ? "global" : "implicit_default",
692
+ configured: Boolean(projectMode || config.defaultMode),
693
+ projectOverride: projectMode ?? null,
694
+ workingDirectory,
695
+ switchCommands: {
696
+ auto: "martin mode auto",
697
+ plan: "martin mode plan",
698
+ edits: "martin mode edits"
699
+ }
700
+ };
701
+ }
711
702
  function buildCurrentPoliciesResource(workingDirectory) {
712
703
  const signals = inspectRepoSignals(workingDirectory);
713
704
  const recommended = buildPolicyPackDefinition(undefined, signals);
@@ -751,14 +742,14 @@ function inferAgentNextStep(loop, verification) {
751
742
  return {
752
743
  action: "triage_before_retry",
753
744
  toolOrResource: "martin_triage_runs",
754
- instruction: "Call `martin_triage_runs` and inspect the latest receipt before spending another attempt."
745
+ instruction: "Call `martin_triage_runs` and inspect the proof card before spending another attempt."
755
746
  };
756
747
  }
757
748
  if (loop.status === "completed" && verification.latestVerification?.passed === true) {
758
749
  return {
759
750
  action: "prove_and_share",
760
- toolOrResource: MARTIN_STATIC_RESOURCE_URIS.latestReceipt,
761
- instruction: "Read the latest receipt and full dossier before sharing or promoting the result; generate a proof card only when a visual artifact is explicitly needed."
751
+ toolOrResource: MARTIN_STATIC_RESOURCE_URIS.latestProofCard,
752
+ instruction: "Read the proof card and full dossier before sharing or promoting the result."
762
753
  };
763
754
  }
764
755
  return {
@@ -783,14 +774,14 @@ Martin Loop exposes governed coding workflows over MCP. Use the server health an
783
774
  2. Use the \`martin_governed_coding_kickoff\` prompt to frame a governed coding request.
784
775
  3. Call \`martin_preflight\` before \`martin_run\` when the task or safety envelope is non-trivial.
785
776
  4. After execution, inspect \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\`, \`martin://runs/{loopId}\`, and \`martin://runs/{loopId}/verification\`.
786
- 5. For low-context agents, read \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`, or \`${MARTIN_STATIC_RESOURCE_URIS.latestReceipt}\` before asking for full JSON. Treat \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\` as an optional derived view.
777
+ 5. For low-context agents, read \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`, or \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\` before asking for full JSON.
787
778
  6. Read \`${MARTIN_STATIC_RESOURCE_URIS.triage}\` or call \`martin_triage_runs\` to prioritize which run needs attention first.
788
779
  7. Use \`martin_debug_failed_run\` when a loop exits failed, budget-bound, or escalated.
789
780
 
790
781
  ## Current Martin MCP Surface
791
782
 
792
783
  - Tools: \`martin_run\`, \`martin_inspect\`, \`martin_status\`, \`martin_doctor\`, \`martin_preflight\`, \`martin_list_runs\`, \`martin_triage_runs\`, \`martin_get_run\`, \`martin_get_attempt\`, \`martin_get_verification_results\`, \`martin_run_dossier\`
793
- - Static resources: \`${MARTIN_STATIC_RESOURCE_URIS.serverHealth}\`, \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\`, \`${MARTIN_STATIC_RESOURCE_URIS.triage}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestReceipt}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestBudgetStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestVerifierEvidence}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestRollbackEvidence}\`, \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`, \`${MARTIN_STATIC_RESOURCE_URIS.mcpUsageGuide}\`, \`${MARTIN_STATIC_RESOURCE_URIS.agentStartGuide}\`, \`${MARTIN_STATIC_RESOURCE_URIS.publishReadinessGuide}\`
784
+ - Static resources: \`${MARTIN_STATIC_RESOURCE_URIS.serverHealth}\`, \`${MARTIN_STATIC_RESOURCE_URIS.recentRuns}\`, \`${MARTIN_STATIC_RESOURCE_URIS.triage}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestBudgetStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestVerifierEvidence}\`, \`${MARTIN_STATIC_RESOURCE_URIS.latestRollbackEvidence}\`, \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`, \`${MARTIN_STATIC_RESOURCE_URIS.governanceStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.modeStatus}\`, \`${MARTIN_STATIC_RESOURCE_URIS.memorySummary}\`, \`${MARTIN_STATIC_RESOURCE_URIS.mcpUsageGuide}\`, \`${MARTIN_STATIC_RESOURCE_URIS.agentStartGuide}\`, \`${MARTIN_STATIC_RESOURCE_URIS.publishReadinessGuide}\`
794
785
  - Resource templates: \`martin://runs/{loopId}\`, \`martin://runs/{loopId}/attempts/{attemptIndex}\`, \`martin://runs/{loopId}/verification\`
795
786
  - Prompts: \`martin_start\`, \`martin_preflight\`, \`martin_triage\`, \`martin_resume\`, \`martin_prove\`, \`martin_release_check\`, \`martin_governed_coding_kickoff\`, \`martin_debug_failed_run\`, \`martin_publish_readiness_review\`, \`martin_triage_run_store\`
796
787
 
@@ -817,7 +808,7 @@ Use Martin Loop as the local governor before you spend agent tokens or retry a f
817
808
  2. If no runs exist, call \`martin_doctor\`, then \`martin_preflight\`.
818
809
  3. If a run exists, read \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\` before reading full run JSON.
819
810
  4. If the verifier failed, use prompt \`martin_debug_failed_run\` or \`martin_triage\`.
820
- 5. If you need a shareable receipt, read \`${MARTIN_STATIC_RESOURCE_URIS.latestReceipt}\` first. Generate or inspect \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\` only when a visual artifact is explicitly required.
811
+ 5. If you need a shareable receipt, read \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`.
821
812
 
822
813
  ## Install Profiles
823
814
 
@@ -855,8 +846,7 @@ Use this guide when an IDE or agent needs to know which Martin surface to call n
855
846
 
856
847
  - Need the smallest next action: \`${MARTIN_STATIC_RESOURCE_URIS.agentNextStep}\`
857
848
  - Need a quick receipt: \`${MARTIN_STATIC_RESOURCE_URIS.latestSummary}\`
858
- - Need the structured receipt source of truth: \`${MARTIN_STATIC_RESOURCE_URIS.latestReceipt}\`
859
- - Need an optional visual proof object: \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`
849
+ - Need a shareable proof object: \`${MARTIN_STATIC_RESOURCE_URIS.latestProofCard}\`
860
850
  - Need a full run review: \`martin_dossier\`
861
851
  - Need to decide whether to retry: \`martin_triage_runs\`
862
852
  - Need IDE setup guidance: \`${MARTIN_STATIC_RESOURCE_URIS.ideOnboardingGuide}\`
@@ -939,32 +929,6 @@ Use this guide when reviewing whether the public MCP package is ready to publish
939
929
  - If a discovery helper exists but is not yet wired into the server, report that as an integration gap instead of treating the capability as fully shipped.
940
930
  `;
941
931
  }
942
- async function buildModeStatusResource() {
943
- let currentMode = "auto";
944
- let modeConfigured = false;
945
- try {
946
- const config = JSON.parse(await readFile(join(homedir(), ".martin", "config.json"), "utf8"));
947
- if (config.defaultMode) {
948
- currentMode = config.defaultMode;
949
- modeConfigured = true;
950
- }
951
- }
952
- catch { /* fresh install — default to auto */ }
953
- return {
954
- kind: "mode-status",
955
- currentMode,
956
- modeConfigured,
957
- modes: {
958
- auto: "MartinLoop governs autonomously — estimate, preflight, run, receipt without per-step approval.",
959
- plan: "MartinLoop shows the proposed plan before executing. Agent waits for user approval.",
960
- edits: "MartinLoop shows each file change before writing. Maximum human control."
961
- },
962
- agentGuidance: modeConfigured
963
- ? `User has explicitly set mode to "${currentMode}". Respect this preference during the session.`
964
- : "Mode not explicitly configured. Defaulting to auto. Suggest running `martin mode auto|plan|edits` to set a preference.",
965
- changeCommand: "martin mode auto | plan | edits"
966
- };
967
- }
968
932
  function withDiscoveryMetadata(value, runsRoot) {
969
933
  return {
970
934
  metadata: {
@@ -1,4 +1,4 @@
1
- type ToolName = "martin_run" | "martin_inspect" | "martin_status" | "martin_doctor" | "martin_estimate" | "martin_plan" | "martin_preflight" | "martin_logs" | "martin_cancel" | "martin_pause" | "martin_continue" | "martin_list_runs" | "martin_triage_runs" | "martin_get_run" | "martin_get_attempt" | "martin_get_verification_results" | "martin_run_dossier" | "martin_dossier" | "martin_eval" | "martin_pr_summary" | "martin_create_pr" | "martin_review_pr";
1
+ type ToolName = "martin_run" | "martin_inspect" | "martin_status" | "martin_doctor" | "martin_plan" | "martin_preflight" | "martin_estimate" | "martin_logs" | "martin_cancel" | "martin_pause" | "martin_continue" | "martin_list_runs" | "martin_triage_runs" | "martin_get_run" | "martin_get_attempt" | "martin_get_verification_results" | "martin_run_dossier" | "martin_dossier" | "martin_eval" | "martin_pr_summary" | "martin_create_pr" | "martin_review_pr";
2
2
  export { sanitizeToolErrorMessage } from "./tools/tool-errors.js";
3
3
  export declare function validateToolInput(name: ToolName, args: unknown): unknown;
4
4
  export declare function resolveSafeRepoRoot(repoRoot?: string, workspaceRoot?: string): string;
@@ -14,12 +14,12 @@ export function validateToolInput(name, args) {
14
14
  return validateStatusInput(args);
15
15
  case "martin_doctor":
16
16
  return validateDoctorInput(args);
17
- case "martin_estimate":
18
- return validateEstimateInput(args);
19
17
  case "martin_plan":
20
18
  return validatePlanInput(args);
21
19
  case "martin_preflight":
22
20
  return validatePreflightInput(args);
21
+ case "martin_estimate":
22
+ return validateEstimateInput(args);
23
23
  case "martin_logs":
24
24
  return validateLogsInput(args);
25
25
  case "martin_cancel":
@@ -254,22 +254,27 @@ function validateDoctorInput(args) {
254
254
  ...optionalEnumAsObject(record.engine, "engine", MARTIN_ENGINE_VALUES)
255
255
  };
256
256
  }
257
+ function validatePreflightInput(args) {
258
+ return validateRunInput(args);
259
+ }
260
+ function validatePlanInput(args) {
261
+ return validateRunInput(args);
262
+ }
257
263
  function validateEstimateInput(args) {
258
264
  const record = requireObject(args);
259
- assertAllowedKeys(record, ["objective", "engine", "budgetUsd", "fileScope"]);
265
+ assertAllowedKeys(record, ["objective", "engine", "budgetUsd", "fileScope", "workingDirectory"]);
266
+ const engine = optionalEnum(record.engine, "engine", MARTIN_ENGINE_VALUES);
267
+ const fileScope = normalizeSafePathPatterns(record.fileScope, "fileScope");
260
268
  return {
261
269
  objective: requireString(record.objective, "objective"),
262
- ...optionalEnumAsObject(record.engine, "engine", MARTIN_ENGINE_VALUES),
270
+ ...(engine ? { engine } : {}),
263
271
  ...optionalPositiveNumber(record.budgetUsd, "budgetUsd"),
264
- ...optionalStringArrayAsObject(record.fileScope, "fileScope")
272
+ ...(fileScope ? { fileScope } : {}),
273
+ ...(record.workingDirectory !== undefined
274
+ ? { workingDirectory: resolveSafeRepoRoot(requireString(record.workingDirectory, "workingDirectory")) }
275
+ : {})
265
276
  };
266
277
  }
267
- function validatePreflightInput(args) {
268
- return validateRunInput(args);
269
- }
270
- function validatePlanInput(args) {
271
- return validateRunInput(args);
272
- }
273
278
  function validateLogsInput(args) {
274
279
  const record = requireObject(args);
275
280
  assertAllowedKeys(record, ["file", "loopId", "runsDir", "latest", "limit"]);
package/dist/server.d.ts CHANGED
@@ -16,6 +16,7 @@
16
16
  * Manual start:
17
17
  * node dist/server.js
18
18
  */
19
+ import { type Server as NodeHttpServer } from "node:http";
19
20
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
20
21
  export declare function createMartinMcpServer(serverInfo?: {
21
22
  name?: string;
@@ -88,4 +89,26 @@ export declare function connectMartinMcpStdioServer(): Promise<Server<{
88
89
  } | undefined;
89
90
  } | undefined;
90
91
  }>>;
92
+ export interface MartinMcpHttpServerOptions {
93
+ host?: string;
94
+ port?: number;
95
+ path?: string;
96
+ }
97
+ export interface MartinMcpHttpServerHandle {
98
+ server: NodeHttpServer;
99
+ host: string;
100
+ port: number;
101
+ path: string;
102
+ endpoint: string;
103
+ close: () => Promise<void>;
104
+ }
105
+ export declare function parseMartinMcpServerArgs(argv: string[]): {
106
+ transport: "stdio";
107
+ } | {
108
+ transport: "http";
109
+ host: string;
110
+ port: number;
111
+ path: string;
112
+ };
113
+ export declare function connectMartinMcpHttpServer(options?: MartinMcpHttpServerOptions): Promise<MartinMcpHttpServerHandle>;
91
114
  export declare function isDirectExecutionEntry(entryPath: string | undefined, moduleUrl?: string): boolean;