@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.
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/server.js +14 -41
- package/dist/tools/tool-support.js +10 -1
- package/dist/vendor/adapters/codex-host.js +12 -3
- package/dist/vendor/core/index.d.ts +2 -0
- package/dist/vendor/core/index.js +9 -1
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MARTIN_MCP_PACKAGE_VERSION = "0.6.
|
|
1
|
+
export declare const MARTIN_MCP_PACKAGE_VERSION = "0.6.7";
|
package/dist/package-version.js
CHANGED
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({
|
|
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
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.
|
|
10
|
+
"version": "0.6.7",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@martinloop/mcp",
|
|
15
|
-
"version": "0.6.
|
|
15
|
+
"version": "0.6.7",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|