@martinloop/mcp 0.6.5 → 0.6.7

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.
@@ -1 +1 @@
1
- export declare const MARTIN_MCP_PACKAGE_VERSION = "0.6.5";
1
+ export declare const MARTIN_MCP_PACKAGE_VERSION = "0.6.7";
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by build — do not edit by hand.
2
2
  // Source of truth: packages/mcp/package.json#version
3
- export const MARTIN_MCP_PACKAGE_VERSION = "0.6.5";
3
+ export const MARTIN_MCP_PACKAGE_VERSION = "0.6.7";
package/dist/server.js CHANGED
@@ -999,13 +999,7 @@ export function createMartinMcpServer(serverInfo) {
999
999
  const: true,
1000
1000
  description: "When true, loads the most recently updated loop record. Mutually exclusive with loopJson, file, and loopId."
1001
1001
  }
1002
- },
1003
- oneOf: [
1004
- { required: ["loopJson"] },
1005
- { required: ["file"] },
1006
- { required: ["loopId"] },
1007
- { required: ["latest"] }
1008
- ]
1002
+ }
1009
1003
  },
1010
1004
  outputSchema: statusOutputSchema
1011
1005
  },
@@ -1182,8 +1176,7 @@ export function createMartinMcpServer(serverInfo) {
1182
1176
  runsDir: { type: "string", description: "Override the default run-store root directory. Optional; defaults to the MartinLoop runs directory." },
1183
1177
  latest: { const: true, description: "When true, loads the most recently updated run in the run store. Mutually exclusive with file and loopId." },
1184
1178
  limit: { type: "integer", minimum: 1, description: "Maximum number of log entries to return, sorted by timestamp descending. Defaults to 20." }
1185
- },
1186
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1179
+ }
1187
1180
  },
1188
1181
  outputSchema: logsOutputSchema
1189
1182
  },
@@ -1204,8 +1197,7 @@ export function createMartinMcpServer(serverInfo) {
1204
1197
  latest: { const: true, description: "When true, targets the latest canonical run. Mutually exclusive with file and loopId." },
1205
1198
  reason: { type: "string", description: "Optional non-empty reason recorded in the pause receipt." },
1206
1199
  requestedBy: { type: "string", description: "Optional human or runtime identity label recorded for audit context." }
1207
- },
1208
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1200
+ }
1209
1201
  },
1210
1202
  outputSchema: controlOutputSchema
1211
1203
  },
@@ -1226,8 +1218,7 @@ export function createMartinMcpServer(serverInfo) {
1226
1218
  latest: { const: true, description: "When true, targets the latest canonical run. Mutually exclusive with file and loopId." },
1227
1219
  reason: { type: "string", description: "Optional non-empty reason recorded in the cancellation receipt." },
1228
1220
  requestedBy: { type: "string", description: "Optional human or runtime identity label recorded for audit context." }
1229
- },
1230
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1221
+ }
1231
1222
  },
1232
1223
  outputSchema: controlOutputSchema
1233
1224
  },
@@ -1248,8 +1239,7 @@ export function createMartinMcpServer(serverInfo) {
1248
1239
  latest: { const: true },
1249
1240
  reason: { type: "string" },
1250
1241
  requestedBy: { type: "string" }
1251
- },
1252
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1242
+ }
1253
1243
  },
1254
1244
  outputSchema: controlOutputSchema
1255
1245
  },
@@ -1339,12 +1329,7 @@ export function createMartinMcpServer(serverInfo) {
1339
1329
  const: true,
1340
1330
  description: "When true, loads the most recently updated loop record in the run store."
1341
1331
  }
1342
- },
1343
- oneOf: [
1344
- { required: ["file"] },
1345
- { required: ["loopId"] },
1346
- { required: ["latest"] }
1347
- ]
1332
+ }
1348
1333
  },
1349
1334
  outputSchema: getRunOutputSchema
1350
1335
  },
@@ -1370,8 +1355,7 @@ export function createMartinMcpServer(serverInfo) {
1370
1355
  minimum: 1,
1371
1356
  description: "Attempt index to inspect. Defaults to the latest attempt."
1372
1357
  }
1373
- },
1374
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }]
1358
+ }
1375
1359
  },
1376
1360
  outputSchema: getAttemptOutputSchema
1377
1361
  },
@@ -1398,8 +1382,7 @@ export function createMartinMcpServer(serverInfo) {
1398
1382
  },
1399
1383
  loopId: { type: "string", description: "MartinLoop run identifier from the run store. Mutually exclusive with file." },
1400
1384
  runsDir: { type: "string", description: "Override the default run-store root directory. Optional." }
1401
- },
1402
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }]
1385
+ }
1403
1386
  },
1404
1387
  outputSchema: verificationResultsOutputSchema
1405
1388
  },
@@ -1424,12 +1407,7 @@ export function createMartinMcpServer(serverInfo) {
1424
1407
  const: true,
1425
1408
  description: "When true, loads the most recently updated loop record. Mutually exclusive with file and loopId."
1426
1409
  }
1427
- },
1428
- oneOf: [
1429
- { required: ["file"] },
1430
- { required: ["loopId"] },
1431
- { required: ["latest"] }
1432
- ]
1410
+ }
1433
1411
  },
1434
1412
  outputSchema: dossierOutputSchema
1435
1413
  },
@@ -1449,8 +1427,7 @@ export function createMartinMcpServer(serverInfo) {
1449
1427
  runsDir: { type: "string", description: "Optional run-store root override used to resolve loopId or latest." },
1450
1428
  latest: { const: true, description: "When true, loads the latest run. Mutually exclusive with file and loopId." },
1451
1429
  format: { type: "string", enum: ["json", "md", "github-pr"], description: "Output format. Defaults to json." }
1452
- },
1453
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1430
+ }
1454
1431
  },
1455
1432
  outputSchema: dossierOutputSchema
1456
1433
  },
@@ -1476,8 +1453,7 @@ export function createMartinMcpServer(serverInfo) {
1476
1453
  loopId: { type: "string", description: "MartinLoop run identifier from the run store. Mutually exclusive with file and latest." },
1477
1454
  runsDir: { type: "string", description: "Override the default run-store root directory. Optional." },
1478
1455
  latest: { const: true, description: "When true, evaluates the most recently updated run in the run store. Mutually exclusive with file and loopId." }
1479
- },
1480
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1456
+ }
1481
1457
  },
1482
1458
  outputSchema: evalOutputSchema
1483
1459
  },
@@ -1504,8 +1480,7 @@ export function createMartinMcpServer(serverInfo) {
1504
1480
  runsDir: { type: "string", description: "Override the default run-store root directory. Optional." },
1505
1481
  latest: { const: true, description: "When true, generates the summary for the most recently updated run. Mutually exclusive with file and loopId." },
1506
1482
  format: { type: "string", enum: ["json", "md", "github-pr"], description: "Dossier rendering format. Defaults to github-pr for PR body generation. Use md for plain Markdown or json for structured output." }
1507
- },
1508
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1483
+ }
1509
1484
  },
1510
1485
  outputSchema: prSummaryOutputSchema
1511
1486
  },
@@ -1528,8 +1503,7 @@ export function createMartinMcpServer(serverInfo) {
1528
1503
  title: { type: "string" },
1529
1504
  base: { type: "string" },
1530
1505
  execute: { type: "boolean" }
1531
- },
1532
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1506
+ }
1533
1507
  },
1534
1508
  outputSchema: prSummaryOutputSchema
1535
1509
  },
@@ -1557,8 +1531,7 @@ export function createMartinMcpServer(serverInfo) {
1557
1531
  latest: { const: true, description: "When true, reviews against the most recently updated run. Mutually exclusive with file and loopId." },
1558
1532
  format: { type: "string", enum: ["json", "md", "github-pr"], description: "Dossier format used when generating the reference body for comparison. Defaults to github-pr." },
1559
1533
  prBody: { type: "string", description: "The PR body text to review. If omitted, the auto-generated dossier body is evaluated instead." }
1560
- },
1561
- oneOf: [{ required: ["file"] }, { required: ["loopId"] }, { required: ["latest"] }]
1534
+ }
1562
1535
  },
1563
1536
  outputSchema: prReviewOutputSchema
1564
1537
  },
@@ -80,6 +80,10 @@ function discoverCommonInstallDirectories(command) {
80
80
  const localAppData = process.env.LOCALAPPDATA;
81
81
  if (localAppData)
82
82
  dirs.push(join(localAppData, "OpenAI", "Codex", "bin"));
83
+ // Claude Code's native Windows installer uses %USERPROFILE%\.local\bin.
84
+ const userProfile = process.env.USERPROFILE ?? process.env.HOMEPATH;
85
+ if (userProfile)
86
+ dirs.push(join(userProfile, ".local", "bin"));
83
87
  if (home)
84
88
  dirs.push(join(home, "scoop", "shims"));
85
89
  }
@@ -112,8 +116,13 @@ function isOnPathDirectly(_command, resolvedPath) {
112
116
  return pathEntries.some((entry) => entry.toLowerCase() === resolvedDir.toLowerCase());
113
117
  }
114
118
  function suggestInstallCommand(command) {
119
+ if (command === "claude") {
120
+ const installCmd = process.platform === "win32"
121
+ ? "irm https://claude.ai/install.ps1 | iex"
122
+ : "curl -fsSL https://claude.ai/install.sh | bash";
123
+ return `Install with: ${installCmd}`;
124
+ }
115
125
  const npmInstalls = {
116
- claude: "npm install -g @anthropic-ai/claude-code",
117
126
  codex: "npm install -g @openai/codex",
118
127
  gemini: "npm install -g @google/gemini-cli"
119
128
  };
@@ -135,7 +135,7 @@ export function resolveCliCommandAvailability(command, options = {}) {
135
135
  command,
136
136
  available: false,
137
137
  locator: discovery.locator,
138
- detail: `${command} is not installed. ${suggestInstall(command)}`
138
+ detail: `${command} is not installed. ${suggestInstall(command, platform)}`
139
139
  };
140
140
  }
141
141
  function discoverCommandOffPath(command, platform, env) {
@@ -146,6 +146,10 @@ function discoverCommandOffPath(command, platform, env) {
146
146
  directories.push(join(env.APPDATA, "npm"));
147
147
  if (env.LOCALAPPDATA)
148
148
  directories.push(join(env.LOCALAPPDATA, "OpenAI", "Codex", "bin"));
149
+ // Claude Code's native Windows installer uses %USERPROFILE%\.local\bin.
150
+ const userProfile = env.USERPROFILE ?? env.HOMEPATH;
151
+ if (userProfile)
152
+ directories.push(join(userProfile, ".local", "bin"));
149
153
  if (home)
150
154
  directories.push(join(home, "scoop", "shims"));
151
155
  }
@@ -169,9 +173,14 @@ function discoverCommandOffPath(command, platform, env) {
169
173
  }
170
174
  return undefined;
171
175
  }
172
- function suggestInstall(command) {
176
+ function suggestInstall(command, platform = process.platform) {
177
+ if (command === "claude") {
178
+ const installCmd = platform === "win32"
179
+ ? "irm https://claude.ai/install.ps1 | iex"
180
+ : "curl -fsSL https://claude.ai/install.sh | bash";
181
+ return `Install with: ${installCmd}`;
182
+ }
173
183
  const installs = {
174
- claude: "Install with: npm install -g @anthropic-ai/claude-code",
175
184
  codex: "Install with: npm install -g @openai/codex",
176
185
  gemini: "Install with: npm install -g @google/gemini-cli"
177
186
  };
@@ -190,6 +190,8 @@ export interface RunMartinInput {
190
190
  teamId?: string;
191
191
  task: LoopTask;
192
192
  budget: LoopBudget;
193
+ /** Comparable ungoverned spend for this task. Stored with provenance for RoTS-Cost. */
194
+ savingsBaseline?: NonNullable<LoopRecord["cost"]["savingsBaseline"]>;
193
195
  metadata?: Record<string, string>;
194
196
  adapter: MartinAdapter;
195
197
  now?: () => string;
@@ -168,6 +168,7 @@ export async function runMartin(input) {
168
168
  projectId: input.projectId,
169
169
  task: { ...input.task, agentExecutionIntent, providerExecutionTimeoutMs },
170
170
  budget: input.budget,
171
+ ...(input.savingsBaseline ? { cost: { savingsBaseline: input.savingsBaseline } } : {}),
171
172
  ...(input.receiptScope
172
173
  ? { receiptScope: { ...input.receiptScope, agentExecutionIntent, providerExecutionTimeoutMs } }
173
174
  : {}),
@@ -849,6 +850,9 @@ export async function runMartin(input) {
849
850
  provenance: mergeCostProvenance(loop.cost.provenance, getUsageProvenance(result.usage)),
850
851
  ...(result.usage.providerSettlement
851
852
  ? { providerSettlement: result.usage.providerSettlement }
853
+ : {}),
854
+ ...(loop.cost.savingsBaseline
855
+ ? { savingsBaseline: loop.cost.savingsBaseline }
852
856
  : {})
853
857
  },
854
858
  updatedAt: attemptCompletedAt
@@ -1476,7 +1480,11 @@ function finalizeLoop(loop, decision, timestamp, idFactory, routingEconomicsInpu
1476
1480
  const routingEconomics = routingEconomicsInput
1477
1481
  ? buildRoutingEconomics(finalized, routingEconomicsInput, decision)
1478
1482
  : undefined;
1479
- const avoidedUsd = calculateLoopAvoidedUsd({ loop: finalized, decision });
1483
+ const avoidedUsd = calculateLoopAvoidedUsd({
1484
+ loop: finalized,
1485
+ decision,
1486
+ uncontrolledBaselineUsd: finalized.cost.savingsBaseline?.usd
1487
+ });
1480
1488
  return {
1481
1489
  ...finalized,
1482
1490
  status: decision.status,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@martinloop/mcp",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
4
4
  "mcpName": "io.github.Keesan12/martin-loop",
5
5
  "private": false,
6
6
  "type": "module",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/Keesan12/martin-loop",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.6.5",
10
+ "version": "0.6.7",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@martinloop/mcp",
15
- "version": "0.6.5",
15
+ "version": "0.6.7",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }