@martinloop/mcp 0.5.6 → 0.5.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/README.md +137 -175
- package/dist/arcade/resource.js +20 -20
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/resources.js +148 -160
- package/dist/server.js +192 -43
- package/dist/tools/execution-policy.js +1 -1
- package/dist/tools/get-status.d.ts +2 -4
- package/dist/tools/get-status.js +6 -3
- package/dist/tools/preflight.d.ts +1 -1
- package/dist/tools/run-loop.d.ts +1 -1
- package/dist/tools/run-loop.js +3 -1
- package/dist/tools/run-store.js +1 -1
- package/dist/tools/tool-support.d.ts +3 -2
- package/dist/tools/tool-support.js +9 -2
- package/dist/tools/workflow-governance.d.ts +1 -1
- package/dist/tools/workflow-governance.js +1 -1
- package/dist/vendor/adapters/openai-compatible.js +6 -6
- package/dist/vendor/adapters/verifier-only.js +1 -1
- package/dist/vendor/contracts/execution-policy.js +1 -1
- package/dist/vendor/contracts/exits.d.ts +1 -1
- package/dist/vendor/contracts/governance.d.ts +1 -1
- package/dist/vendor/contracts/index.d.ts +1 -1
- package/dist/vendor/contracts/index.js +1 -2
- package/dist/vendor/contracts/operator.d.ts +1 -1
- package/dist/vendor/contracts/operator.js +1 -2
- package/dist/vendor/core/compiler.d.ts +2 -2
- package/dist/vendor/core/compiler.js +3 -1
- package/dist/vendor/core/exits.js +9 -4
- package/dist/vendor/core/grounding.d.ts +1 -0
- package/dist/vendor/core/grounding.js +28 -1
- package/dist/vendor/core/index.d.ts +2 -2
- package/dist/vendor/core/index.js +3 -1
- package/dist/vendor/core/policy-compiler.js +17 -1
- package/dist/vendor/core/policy.d.ts +1 -1
- package/dist/vendor/core/policy.js +7 -5
- package/dist/vendor/presentation/motion.js +0 -4
- package/dist/workflow-state.js +1 -1
- package/package.json +90 -81
- package/server.json +21 -21
|
@@ -20,7 +20,7 @@ export interface CompilerAdapterRequest {
|
|
|
20
20
|
focus: string;
|
|
21
21
|
remainingBudgetUsd: number;
|
|
22
22
|
remainingIterations: number;
|
|
23
|
-
remainingTokens
|
|
23
|
+
remainingTokens?: number;
|
|
24
24
|
};
|
|
25
25
|
previousAttempts: LoopAttempt[];
|
|
26
26
|
}
|
|
@@ -41,7 +41,7 @@ export interface PromptPacket {
|
|
|
41
41
|
budgetEnvelope: {
|
|
42
42
|
remainingBudgetUsd: number;
|
|
43
43
|
remainingIterations: number;
|
|
44
|
-
remainingTokens
|
|
44
|
+
remainingTokens?: number;
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
@@ -41,7 +41,9 @@ export function compilePromptPacket(request) {
|
|
|
41
41
|
budgetEnvelope: {
|
|
42
42
|
remainingBudgetUsd: request.context.remainingBudgetUsd,
|
|
43
43
|
remainingIterations: request.context.remainingIterations,
|
|
44
|
-
|
|
44
|
+
...(request.context.remainingTokens !== undefined
|
|
45
|
+
? { remainingTokens: request.context.remainingTokens }
|
|
46
|
+
: {})
|
|
45
47
|
}
|
|
46
48
|
};
|
|
47
49
|
}
|
|
@@ -26,7 +26,10 @@ export function createDefaultExitPolicy(budget, overrides = {}) {
|
|
|
26
26
|
schemaVersion: "exit-policy/1",
|
|
27
27
|
goal: { verifierRequired: true, minimumScore: 1 },
|
|
28
28
|
turns: { max: budget.maxIterations },
|
|
29
|
-
budget: {
|
|
29
|
+
budget: {
|
|
30
|
+
maxUsd: budget.maxUsd,
|
|
31
|
+
...(budget.maxTokens !== undefined ? { maxTokens: budget.maxTokens } : {})
|
|
32
|
+
},
|
|
30
33
|
wallClock: { maxElapsedMs: 30 * 60 * 1000 },
|
|
31
34
|
progress: { windowSize: 3, unchangedStateLimit: 3 },
|
|
32
35
|
errors: { maxConsecutive: 3 },
|
|
@@ -49,7 +52,9 @@ export function createDefaultExitPolicy(budget, overrides = {}) {
|
|
|
49
52
|
export function validateExitPolicy(policy) {
|
|
50
53
|
assertFinitePositive("turns.max", policy.turns.max);
|
|
51
54
|
assertFinitePositive("budget.maxUsd", policy.budget.maxUsd);
|
|
52
|
-
|
|
55
|
+
if (policy.budget.maxTokens !== undefined) {
|
|
56
|
+
assertFinitePositive("budget.maxTokens", policy.budget.maxTokens);
|
|
57
|
+
}
|
|
53
58
|
assertFinitePositive("wallClock.maxElapsedMs", policy.wallClock.maxElapsedMs);
|
|
54
59
|
assertFinitePositive("progress.windowSize", policy.progress.windowSize);
|
|
55
60
|
assertFinitePositive("progress.unchangedStateLimit", policy.progress.unchangedStateLimit);
|
|
@@ -117,13 +122,13 @@ export function evaluateExitPolicy(policy, snapshot) {
|
|
|
117
122
|
}
|
|
118
123
|
// 5. Budget cap
|
|
119
124
|
const usdExceeded = snapshot.actualUsd >= policy.budget.maxUsd;
|
|
120
|
-
const tokensExceeded = snapshot.tokensUsed >= policy.budget.maxTokens;
|
|
125
|
+
const tokensExceeded = policy.budget.maxTokens !== undefined && snapshot.tokensUsed >= policy.budget.maxTokens;
|
|
121
126
|
if (usdExceeded || tokensExceeded) {
|
|
122
127
|
push("budget_cap", "Run token or dollar budget reached.", {
|
|
123
128
|
actualUsd: snapshot.actualUsd,
|
|
124
129
|
maxUsd: policy.budget.maxUsd,
|
|
125
130
|
tokensUsed: snapshot.tokensUsed,
|
|
126
|
-
maxTokens: policy.budget.maxTokens,
|
|
131
|
+
...(policy.budget.maxTokens !== undefined ? { maxTokens: policy.budget.maxTokens } : {}),
|
|
127
132
|
usdExceeded,
|
|
128
133
|
tokensExceeded
|
|
129
134
|
});
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
2
3
|
import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
4
|
import { homedir } from "node:os";
|
|
4
5
|
import { extname, join, relative } from "node:path";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
const execFileAsync = promisify(execFile);
|
|
5
8
|
const TEXT_EXTENSIONS = new Set([
|
|
6
9
|
".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
|
|
7
10
|
".json", ".md", ".yaml", ".yml", ".py", ".go",
|
|
@@ -42,21 +45,42 @@ export async function loadOrBuildRepoGroundingIndex(repoRoot) {
|
|
|
42
45
|
export async function buildRepoGroundingIndex(repoRoot, repositoryFingerprint) {
|
|
43
46
|
const files = [];
|
|
44
47
|
const discovered = await walk(repoRoot, repoRoot, files, { count: 0 });
|
|
48
|
+
const trackedPaths = await loadTrackedPaths(repoRoot);
|
|
45
49
|
return {
|
|
46
50
|
schemaVersion: "martin.grounding.v1",
|
|
47
51
|
repoRoot,
|
|
48
52
|
createdAt: new Date().toISOString(),
|
|
49
53
|
fileCount: discovered.count,
|
|
50
54
|
files,
|
|
55
|
+
...(trackedPaths.length > 0 ? { trackedPaths } : {}),
|
|
51
56
|
repositoryFingerprint: repositoryFingerprint ?? await computeRepositoryFingerprint(repoRoot)
|
|
52
57
|
};
|
|
53
58
|
}
|
|
54
59
|
async function computeRepositoryFingerprint(repoRoot) {
|
|
55
60
|
const entries = [];
|
|
56
61
|
await collectFingerprintEntries(repoRoot, repoRoot, entries, { count: 0 });
|
|
62
|
+
for (const trackedPath of await loadTrackedPaths(repoRoot)) {
|
|
63
|
+
entries.push(`tracked:${trackedPath}`);
|
|
64
|
+
}
|
|
57
65
|
entries.sort();
|
|
58
66
|
return createHash("sha256").update(entries.join("\n")).digest("hex");
|
|
59
67
|
}
|
|
68
|
+
async function loadTrackedPaths(repoRoot) {
|
|
69
|
+
try {
|
|
70
|
+
const { stdout } = await execFileAsync("git", ["-C", repoRoot, "ls-files", "-z"], {
|
|
71
|
+
encoding: "utf8",
|
|
72
|
+
windowsHide: true
|
|
73
|
+
});
|
|
74
|
+
return stdout
|
|
75
|
+
.split("\0")
|
|
76
|
+
.map((filePath) => filePath.trim().replace(/\\/g, "/"))
|
|
77
|
+
.filter(Boolean)
|
|
78
|
+
.sort();
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
60
84
|
async function collectFingerprintEntries(repoRoot, currentDir, entries, state) {
|
|
61
85
|
if (state.count >= MAX_FILES)
|
|
62
86
|
return;
|
|
@@ -193,7 +217,10 @@ function tokenize(input) {
|
|
|
193
217
|
export function scanPatchForGroundingViolations(diff, index, options = {}) {
|
|
194
218
|
const violations = [];
|
|
195
219
|
const resolvedFiles = [];
|
|
196
|
-
const indexedPaths = new Set(
|
|
220
|
+
const indexedPaths = new Set([
|
|
221
|
+
...index.files.map((file) => file.path),
|
|
222
|
+
...(index.trackedPaths ?? [])
|
|
223
|
+
]);
|
|
197
224
|
const indexedSymbols = new Set(index.files.flatMap((file) => file.symbols.map((symbol) => symbol.toLowerCase())));
|
|
198
225
|
const referencedFiles = new Set();
|
|
199
226
|
const addedFiles = new Set();
|
|
@@ -75,7 +75,7 @@ export interface MartinAdapterRequest {
|
|
|
75
75
|
focus: string;
|
|
76
76
|
remainingBudgetUsd: number;
|
|
77
77
|
remainingIterations: number;
|
|
78
|
-
remainingTokens
|
|
78
|
+
remainingTokens?: number;
|
|
79
79
|
};
|
|
80
80
|
previousAttempts: LoopAttempt[];
|
|
81
81
|
/** Abort signal propagated from the harness — adapters should honour it. */
|
|
@@ -165,7 +165,7 @@ export interface DistilledContext {
|
|
|
165
165
|
constraints: {
|
|
166
166
|
remainingBudgetUsd: number;
|
|
167
167
|
remainingIterations: number;
|
|
168
|
-
remainingTokens
|
|
168
|
+
remainingTokens?: number;
|
|
169
169
|
};
|
|
170
170
|
}
|
|
171
171
|
export interface AttemptPolicyDecision {
|
|
@@ -152,7 +152,9 @@ export function distillContext(loop, options = {}) {
|
|
|
152
152
|
constraints: {
|
|
153
153
|
remainingBudgetUsd: roundUsd(loop.budget.maxUsd - loop.cost.actualUsd),
|
|
154
154
|
remainingIterations: Math.max(loop.budget.maxIterations - loop.attempts.length, 0),
|
|
155
|
-
|
|
155
|
+
...(loop.budget.maxTokens !== undefined
|
|
156
|
+
? { remainingTokens: Math.max(loop.budget.maxTokens - loop.cost.tokensIn - loop.cost.tokensOut, 0) }
|
|
157
|
+
: {})
|
|
156
158
|
}
|
|
157
159
|
};
|
|
158
160
|
}
|
|
@@ -5,7 +5,7 @@ export function compileExecutionPolicy(input) {
|
|
|
5
5
|
maxUsd: resolveBudgetField("maxUsd", input, provenance),
|
|
6
6
|
softLimitUsd: resolveBudgetField("softLimitUsd", input, provenance),
|
|
7
7
|
maxIterations: resolveBudgetField("maxIterations", input, provenance),
|
|
8
|
-
|
|
8
|
+
...resolveOptionalTokenBudget(input, provenance)
|
|
9
9
|
};
|
|
10
10
|
if (budget.softLimitUsd >= budget.maxUsd) {
|
|
11
11
|
budget.softLimitUsd = Math.round(budget.maxUsd * 0.75 * 100) / 100;
|
|
@@ -103,6 +103,22 @@ export function compileExecutionPolicy(input) {
|
|
|
103
103
|
provenance
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
|
+
function resolveOptionalTokenBudget(input, provenance) {
|
|
107
|
+
if (input.request.budgetOverrides?.maxTokens && input.request.budget.maxTokens !== undefined) {
|
|
108
|
+
provenance.push({ field: "budget.maxTokens", source: "request", value: String(input.request.budget.maxTokens) });
|
|
109
|
+
return { maxTokens: input.request.budget.maxTokens };
|
|
110
|
+
}
|
|
111
|
+
const configValue = input.config?.budget?.maxTokens;
|
|
112
|
+
if (typeof configValue === "number" && Number.isFinite(configValue)) {
|
|
113
|
+
provenance.push({ field: "budget.maxTokens", source: "config", value: String(configValue) });
|
|
114
|
+
return { maxTokens: configValue };
|
|
115
|
+
}
|
|
116
|
+
if (input.defaults.budget.maxTokens !== undefined) {
|
|
117
|
+
provenance.push({ field: "budget.maxTokens", source: "default", value: String(input.defaults.budget.maxTokens) });
|
|
118
|
+
return { maxTokens: input.defaults.budget.maxTokens };
|
|
119
|
+
}
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
106
122
|
function resolveBudgetField(field, input, provenance) {
|
|
107
123
|
if (input.request.budgetOverrides?.[field]) {
|
|
108
124
|
const value = input.request.budget[field];
|
|
@@ -12,7 +12,7 @@ export interface CostGovernorState {
|
|
|
12
12
|
shouldStop: boolean;
|
|
13
13
|
remainingBudgetUsd: number;
|
|
14
14
|
remainingIterations: number;
|
|
15
|
-
remainingTokens
|
|
15
|
+
remainingTokens?: number;
|
|
16
16
|
recommendedIntervention?: InterventionType;
|
|
17
17
|
}
|
|
18
18
|
export interface ExitDecision {
|
|
@@ -165,16 +165,18 @@ export function classifyFailure(input) {
|
|
|
165
165
|
export function evaluateCostGovernor(input) {
|
|
166
166
|
const remainingBudgetUsd = roundUsd(input.budget.maxUsd - input.cost.actualUsd);
|
|
167
167
|
const remainingIterations = Math.max(input.budget.maxIterations - input.attemptsUsed, 0);
|
|
168
|
-
const remainingTokens =
|
|
168
|
+
const remainingTokens = input.budget.maxTokens === undefined
|
|
169
|
+
? undefined
|
|
170
|
+
: Math.max(input.budget.maxTokens - input.cost.tokensIn - input.cost.tokensOut, 0);
|
|
169
171
|
if (input.cost.actualUsd >= input.budget.maxUsd ||
|
|
170
172
|
input.attemptsUsed >= input.budget.maxIterations ||
|
|
171
|
-
remainingTokens <= 0) {
|
|
173
|
+
(remainingTokens !== undefined && remainingTokens <= 0)) {
|
|
172
174
|
return {
|
|
173
175
|
pressure: "hard_limit",
|
|
174
176
|
shouldStop: true,
|
|
175
177
|
remainingBudgetUsd,
|
|
176
178
|
remainingIterations,
|
|
177
|
-
remainingTokens,
|
|
179
|
+
...(remainingTokens !== undefined ? { remainingTokens } : {}),
|
|
178
180
|
recommendedIntervention: "stop_loop"
|
|
179
181
|
};
|
|
180
182
|
}
|
|
@@ -184,7 +186,7 @@ export function evaluateCostGovernor(input) {
|
|
|
184
186
|
shouldStop: false,
|
|
185
187
|
remainingBudgetUsd,
|
|
186
188
|
remainingIterations,
|
|
187
|
-
remainingTokens,
|
|
189
|
+
...(remainingTokens !== undefined ? { remainingTokens } : {}),
|
|
188
190
|
recommendedIntervention: "compress_context"
|
|
189
191
|
};
|
|
190
192
|
}
|
|
@@ -193,7 +195,7 @@ export function evaluateCostGovernor(input) {
|
|
|
193
195
|
shouldStop: false,
|
|
194
196
|
remainingBudgetUsd,
|
|
195
197
|
remainingIterations,
|
|
196
|
-
remainingTokens
|
|
198
|
+
...(remainingTokens !== undefined ? { remainingTokens } : {})
|
|
197
199
|
};
|
|
198
200
|
}
|
|
199
201
|
export function calculateCostPerOutcome(input) {
|
|
@@ -10,10 +10,6 @@ export function canAnimate(env = {}) {
|
|
|
10
10
|
if (mode !== "human") {
|
|
11
11
|
return false;
|
|
12
12
|
}
|
|
13
|
-
const noColor = env.noColor ?? Object.prototype.hasOwnProperty.call(process.env, "NO_COLOR");
|
|
14
|
-
if (noColor) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
13
|
const stdoutTty = env.stdoutIsTty ?? process.stdout.isTTY === true;
|
|
18
14
|
if (!stdoutTty) {
|
|
19
15
|
return false;
|
package/dist/workflow-state.js
CHANGED
|
@@ -145,7 +145,7 @@ function hashBudget(budget) {
|
|
|
145
145
|
maxUsd: Number(budget.maxUsd.toFixed(4)),
|
|
146
146
|
softLimitUsd: Number(budget.softLimitUsd.toFixed(4)),
|
|
147
147
|
maxIterations: budget.maxIterations,
|
|
148
|
-
maxTokens: budget.maxTokens
|
|
148
|
+
...(budget.maxTokens !== undefined ? { maxTokens: budget.maxTokens } : {})
|
|
149
149
|
};
|
|
150
150
|
return createHash("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
|
|
151
151
|
}
|
package/package.json
CHANGED
|
@@ -1,81 +1,90 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@martinloop/mcp",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"mcpName": "io.github.Keesan12/martin-loop",
|
|
5
|
-
"private": false,
|
|
6
|
-
"type": "module",
|
|
7
|
-
"description": "MCP server for AI coding agents
|
|
8
|
-
"license": "Apache-2.0",
|
|
9
|
-
"author": "MartinLoop contributors",
|
|
10
|
-
"homepage": "https://martinloop.com/",
|
|
11
|
-
"repository": {
|
|
12
|
-
"type": "git",
|
|
13
|
-
"url": "git+https://github.com/Keesan12/martin-loop.git",
|
|
14
|
-
"directory": "packages/mcp"
|
|
15
|
-
},
|
|
16
|
-
"bugs": {
|
|
17
|
-
"url": "https://github.com/Keesan12/martin-loop/issues"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"mcp",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"dist"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
},
|
|
76
|
-
"
|
|
77
|
-
"@
|
|
78
|
-
"@
|
|
79
|
-
"@
|
|
80
|
-
|
|
81
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@martinloop/mcp",
|
|
3
|
+
"version": "0.5.7",
|
|
4
|
+
"mcpName": "io.github.Keesan12/martin-loop",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"description": "MCP server for AI coding agents \u00e2\u20ac\u201d verifier gates, stop limits, and Verified Handoffs.",
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
|
+
"author": "MartinLoop contributors",
|
|
10
|
+
"homepage": "https://martinloop.com/",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/Keesan12/martin-loop.git",
|
|
14
|
+
"directory": "packages/mcp"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/Keesan12/martin-loop/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"mcp-server",
|
|
22
|
+
"model-context-protocol",
|
|
23
|
+
"coding-agent",
|
|
24
|
+
"coding-agents",
|
|
25
|
+
"ai-coding-agent",
|
|
26
|
+
"ai-coding-agents",
|
|
27
|
+
"autonomous-coding",
|
|
28
|
+
"claude-code",
|
|
29
|
+
"codex",
|
|
30
|
+
"gemini-cli",
|
|
31
|
+
"cursor",
|
|
32
|
+
"vscode",
|
|
33
|
+
"agent-runtime",
|
|
34
|
+
"agent-verification",
|
|
35
|
+
"developer-tools",
|
|
36
|
+
"software-engineering",
|
|
37
|
+
"martin-loop"
|
|
38
|
+
],
|
|
39
|
+
"bin": {
|
|
40
|
+
"mcp": "./dist/server.js",
|
|
41
|
+
"martin-loop-mcp": "./dist/server.js"
|
|
42
|
+
},
|
|
43
|
+
"exports": {
|
|
44
|
+
"./server.json": "./server.json",
|
|
45
|
+
"./package.json": "./package.json"
|
|
46
|
+
},
|
|
47
|
+
"files": [
|
|
48
|
+
"dist",
|
|
49
|
+
"README.md",
|
|
50
|
+
"server.json"
|
|
51
|
+
],
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=20.0.0"
|
|
54
|
+
},
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "node ./scripts/build-package.mjs",
|
|
60
|
+
"version:sync": "node ./scripts/version-sync.mjs",
|
|
61
|
+
"version:check": "node ./scripts/verify-version-consistency.mjs",
|
|
62
|
+
"prepack": "pnpm build",
|
|
63
|
+
"smoke:pack": "node ./scripts/smoke-package.mjs",
|
|
64
|
+
"smoke:published": "node ./scripts/smoke-published-package.mjs",
|
|
65
|
+
"smoke:published:pack": "node ./scripts/smoke-published-package.mjs --package-spec=pack",
|
|
66
|
+
"verify:release": "node --test ../../scripts/tests/publish-mcp-workflow.test.mjs ../../scripts/tests/mcp-publish-reliability.test.mjs ../../scripts/tests/mcp-release-docs.test.mjs",
|
|
67
|
+
"test:baseline": "node ./scripts/run-test-lane.mjs baseline",
|
|
68
|
+
"test": "vitest run --maxWorkers=1",
|
|
69
|
+
"lint": "tsc -p tsconfig.json --noEmit",
|
|
70
|
+
"start": "node dist/server.js",
|
|
71
|
+
"inspect:live": "node ./scripts/inspect-live.mjs",
|
|
72
|
+
"mcpb:build": "node ./mcpb/build-mcpb.mjs",
|
|
73
|
+
"mcpb:validate": "mcpb validate ./dist-mcpb/martinloop",
|
|
74
|
+
"mcpb:smoke": "node ./mcpb/smoke-mcpb.mjs"
|
|
75
|
+
},
|
|
76
|
+
"dependencies": {
|
|
77
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
78
|
+
"@open-policy-agent/opa-wasm": "^1.10.0",
|
|
79
|
+
"@opentelemetry/api-logs": "^0.214.0",
|
|
80
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.214.0",
|
|
81
|
+
"@opentelemetry/resources": "^2.6.1",
|
|
82
|
+
"@opentelemetry/sdk-logs": "^0.214.0",
|
|
83
|
+
"ts-morph": "^21.0.0"
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"@anthropic-ai/mcpb": "2.1.2",
|
|
87
|
+
"@martin/contracts": "workspace:*",
|
|
88
|
+
"@martin/presentation": "workspace:*"
|
|
89
|
+
}
|
|
90
|
+
}
|
package/server.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
-
"name": "io.github.Keesan12/martin-loop",
|
|
4
|
-
"title": "Martin Loop",
|
|
5
|
-
"description": "
|
|
6
|
-
"repository": {
|
|
7
|
-
"url": "https://github.com/Keesan12/martin-loop",
|
|
8
|
-
"source": "github"
|
|
9
|
-
},
|
|
10
|
-
"version": "0.5.
|
|
11
|
-
"packages": [
|
|
12
|
-
{
|
|
13
|
-
"registryType": "npm",
|
|
14
|
-
"identifier": "@martinloop/mcp",
|
|
15
|
-
"version": "0.5.
|
|
16
|
-
"transport": {
|
|
17
|
-
"type": "stdio"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.Keesan12/martin-loop",
|
|
4
|
+
"title": "Martin Loop",
|
|
5
|
+
"description": "One system around coding agents to run, verify, recover, and hand off software work.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"url": "https://github.com/Keesan12/martin-loop",
|
|
8
|
+
"source": "github"
|
|
9
|
+
},
|
|
10
|
+
"version": "0.5.7",
|
|
11
|
+
"packages": [
|
|
12
|
+
{
|
|
13
|
+
"registryType": "npm",
|
|
14
|
+
"identifier": "@martinloop/mcp",
|
|
15
|
+
"version": "0.5.7",
|
|
16
|
+
"transport": {
|
|
17
|
+
"type": "stdio"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|