@martinloop/mcp 0.5.5 → 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.
Files changed (57) hide show
  1. package/README.md +14 -52
  2. package/dist/arcade/capabilities.d.ts +36 -0
  3. package/dist/arcade/capabilities.js +37 -0
  4. package/dist/arcade/resource.d.ts +31 -0
  5. package/dist/arcade/resource.js +52 -0
  6. package/dist/arcade/status.d.ts +23 -0
  7. package/dist/arcade/status.js +25 -0
  8. package/dist/package-version.d.ts +1 -1
  9. package/dist/package-version.js +3 -3
  10. package/dist/resources.js +1 -13
  11. package/dist/server.js +241 -75
  12. package/dist/tools/execution-policy.js +1 -1
  13. package/dist/tools/get-status.d.ts +2 -4
  14. package/dist/tools/get-status.js +6 -3
  15. package/dist/tools/preflight.d.ts +1 -1
  16. package/dist/tools/run-loop.d.ts +2 -3
  17. package/dist/tools/run-loop.js +4 -3
  18. package/dist/tools/run-store.js +1 -1
  19. package/dist/tools/tool-support.d.ts +3 -2
  20. package/dist/tools/tool-support.js +9 -2
  21. package/dist/tools/workflow-governance.d.ts +1 -1
  22. package/dist/tools/workflow-governance.js +1 -1
  23. package/dist/vendor/adapters/claude-cli.js +2 -1
  24. package/dist/vendor/adapters/cli-bridge.js +7 -1
  25. package/dist/vendor/adapters/index.d.ts +1 -0
  26. package/dist/vendor/adapters/index.js +1 -0
  27. package/dist/vendor/adapters/openai-compatible.js +6 -3
  28. package/dist/vendor/adapters/stub-agent-cli.d.ts +9 -0
  29. package/dist/vendor/adapters/stub-agent-cli.js +43 -0
  30. package/dist/vendor/adapters/stub-direct-provider.d.ts +8 -0
  31. package/dist/vendor/adapters/stub-direct-provider.js +16 -0
  32. package/dist/vendor/adapters/verifier-only.js +1 -1
  33. package/dist/vendor/contracts/execution-policy.js +1 -1
  34. package/dist/vendor/contracts/exits.d.ts +1 -1
  35. package/dist/vendor/contracts/governance.d.ts +1 -1
  36. package/dist/vendor/contracts/index.d.ts +1 -1
  37. package/dist/vendor/contracts/index.js +1 -2
  38. package/dist/vendor/contracts/operator.d.ts +1 -1
  39. package/dist/vendor/contracts/operator.js +1 -2
  40. package/dist/vendor/core/compiler.d.ts +2 -2
  41. package/dist/vendor/core/compiler.js +3 -1
  42. package/dist/vendor/core/exits.js +9 -4
  43. package/dist/vendor/core/grounding.d.ts +1 -0
  44. package/dist/vendor/core/grounding.js +28 -1
  45. package/dist/vendor/core/index.d.ts +2 -2
  46. package/dist/vendor/core/index.js +11 -64
  47. package/dist/vendor/core/policy-compiler.js +17 -1
  48. package/dist/vendor/core/policy.d.ts +2 -1
  49. package/dist/vendor/core/policy.js +15 -5
  50. package/dist/vendor/core/rollback.d.ts +3 -0
  51. package/dist/vendor/core/rollback.js +33 -20
  52. package/dist/vendor/core/verified-handoff.js +25 -6
  53. package/dist/vendor/presentation/motion.js +0 -4
  54. package/dist/vendor/presentation/verified-handoff.js +10 -13
  55. package/dist/workflow-state.js +1 -1
  56. package/package.json +20 -11
  57. package/server.json +3 -3
@@ -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
- maxTokens: resolveBudgetField("maxTokens", input, provenance)
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: number;
15
+ remainingTokens?: number;
16
16
  recommendedIntervention?: InterventionType;
17
17
  }
18
18
  export interface ExitDecision {
@@ -97,6 +97,7 @@ export declare function inferExit(input: {
97
97
  lastFailure?: FailureAssessment;
98
98
  costState: CostGovernorState;
99
99
  canSwitchAdapter?: boolean;
100
+ verificationRequired?: boolean;
100
101
  }): ExitDecision;
101
102
  export interface BudgetPreflightInput {
102
103
  promptCharCount: number;
@@ -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 = Math.max(input.budget.maxTokens - input.cost.tokensIn - input.cost.tokensOut, 0);
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) {
@@ -210,6 +212,14 @@ export function calculateCostPerOutcome(input) {
210
212
  };
211
213
  }
212
214
  export function inferExit(input) {
215
+ if (input.lastResult.status === "completed" && input.verificationRequired === false) {
216
+ return {
217
+ shouldExit: true,
218
+ lifecycleState: "completed",
219
+ status: "completed",
220
+ reason: "Execution-only work completed without verifier evidence; outcome is not VERIFIED."
221
+ };
222
+ }
213
223
  if (input.lastResult.status === "completed" && input.lastResult.verification.passed) {
214
224
  return {
215
225
  shouldExit: true,
@@ -1,4 +1,7 @@
1
1
  import type { PatchDecision, RollbackBoundaryArtifact, RollbackOutcomeArtifact } from "../contracts/index.js";
2
+ export declare class RollbackStateUnavailableError extends Error {
3
+ constructor(message: string);
4
+ }
2
5
  export declare function listAttemptChangedFilesSinceBoundary(input: {
3
6
  repoRoot?: string;
4
7
  boundary?: RollbackBoundaryArtifact;
@@ -1,7 +1,12 @@
1
1
  import { spawnSync } from "node:child_process";
2
- import { readFileSync } from "node:fs";
3
2
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
4
3
  import { dirname, relative, resolve } from "node:path";
4
+ export class RollbackStateUnavailableError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "RollbackStateUnavailableError";
8
+ }
9
+ }
5
10
  export function listAttemptChangedFilesSinceBoundary(input) {
6
11
  if (!input.repoRoot) {
7
12
  return [];
@@ -12,24 +17,11 @@ export function listAttemptChangedFilesSinceBoundary(input) {
12
17
  }
13
18
  const baselineTracked = new Set(input.boundary.trackedDirtyFiles);
14
19
  const baselineUntracked = new Set(input.boundary.untrackedFiles);
15
- const baselineContentChanges = input.boundary.snapshots
16
- .filter((snapshot) => snapshot.existed && repoFileDiffersFromSnapshot(input.repoRoot, snapshot))
17
- .map((snapshot) => snapshot.path);
18
20
  return uniqueSorted([
19
21
  ...repoState.trackedDirtyFiles.filter((filePath) => !baselineTracked.has(filePath)),
20
- ...repoState.untrackedFiles.filter((filePath) => !baselineUntracked.has(filePath)),
21
- ...baselineContentChanges
22
+ ...repoState.untrackedFiles.filter((filePath) => !baselineUntracked.has(filePath))
22
23
  ]);
23
24
  }
24
- function repoFileDiffersFromSnapshot(repoRoot, snapshot) {
25
- try {
26
- const current = readFileSync(resolveRepoPath(repoRoot, snapshot.path));
27
- return current.toString("base64") !== snapshot.contentBase64;
28
- }
29
- catch {
30
- return true;
31
- }
32
- }
33
25
  export async function captureRollbackBoundary(input) {
34
26
  if (!input.repoRoot) {
35
27
  return undefined;
@@ -147,6 +139,7 @@ function readRepoState(repoRoot) {
147
139
  };
148
140
  }
149
141
  function readGitLines(repoRoot, args) {
142
+ let lastFailure = "unknown Git failure";
150
143
  for (let attempt = 0; attempt < 2; attempt++) {
151
144
  const result = spawnSync("git", args, {
152
145
  cwd: repoRoot,
@@ -158,13 +151,14 @@ function readGitLines(repoRoot, args) {
158
151
  .map((line) => normalizeRepoPath(line))
159
152
  .filter(Boolean));
160
153
  }
154
+ lastFailure = gitFailureMessage(result);
161
155
  // Retry once after a short delay — handles git lock-file contention
162
156
  // that occurs when another process holds .git/index.lock.
163
157
  if (attempt === 0 && result.status !== 0) {
164
- spawnSync("sleep", ["0.5"], { encoding: "utf8" });
158
+ delaySynchronously(500);
165
159
  }
166
160
  }
167
- return [];
161
+ throw new RollbackStateUnavailableError(`Git rollback state unavailable for ${args.join(" ")}: ${lastFailure}`);
168
162
  }
169
163
  function readGitScalar(repoRoot, args) {
170
164
  const result = spawnSync("git", args, {
@@ -172,7 +166,7 @@ function readGitScalar(repoRoot, args) {
172
166
  encoding: "utf8"
173
167
  });
174
168
  if (result.status !== 0 || typeof result.stdout !== "string") {
175
- return undefined;
169
+ throw new RollbackStateUnavailableError(`Git rollback state unavailable for ${args.join(" ")}: ${gitFailureMessage(result)}`);
176
170
  }
177
171
  const value = result.stdout.trim();
178
172
  return value.length > 0 ? value : undefined;
@@ -188,7 +182,10 @@ async function readRollbackSnapshot(repoRoot, filePath) {
188
182
  contentBase64: contents.toString("base64")
189
183
  };
190
184
  }
191
- catch {
185
+ catch (error) {
186
+ if (!isFileNotFoundError(error)) {
187
+ throw new RollbackStateUnavailableError(`Rollback snapshot unavailable for ${normalizeRepoPath(filePath)}: ${toErrorMessage(error)}`);
188
+ }
192
189
  return {
193
190
  path: normalizeRepoPath(filePath),
194
191
  existed: false,
@@ -214,7 +211,7 @@ function restoreTrackedFileFromHead(repoRoot, filePath) {
214
211
  return;
215
212
  }
216
213
  // Retry once after a short delay (git lock-file contention)
217
- spawnSync("sleep", ["0.5"], { encoding: "utf8" });
214
+ delaySynchronously(500);
218
215
  const retry = spawnSync("git", ["restore", "--staged", "--worktree", "--source=HEAD", "--", filePath], { cwd: repoRoot, encoding: "utf8" });
219
216
  if (retry.status === 0) {
220
217
  return;
@@ -264,3 +261,19 @@ function emptyRepoState() {
264
261
  function toErrorMessage(error) {
265
262
  return error instanceof Error ? error.message : String(error);
266
263
  }
264
+ function gitFailureMessage(result) {
265
+ if (result.error) {
266
+ return result.error.message;
267
+ }
268
+ if (typeof result.stderr === "string" && result.stderr.trim().length > 0) {
269
+ return result.stderr.trim();
270
+ }
271
+ return `git exited with status ${String(result.status)}`;
272
+ }
273
+ function isFileNotFoundError(error) {
274
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
275
+ }
276
+ function delaySynchronously(milliseconds) {
277
+ const signal = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
278
+ Atomics.wait(signal, 0, 0, milliseconds);
279
+ }
@@ -33,6 +33,9 @@ export function verifierActuallyPassed(evidence, expected) {
33
33
  if (!evidence?.passed || !evidence.binding || !evidence.steps) {
34
34
  return false;
35
35
  }
36
+ if (expected.commands.length === 0) {
37
+ return false;
38
+ }
36
39
  if (evidence.binding.runId !== expected.runId ||
37
40
  evidence.binding.workspaceId !== expected.workspaceId ||
38
41
  evidence.binding.cwd !== expected.cwd ||
@@ -93,7 +96,6 @@ export function deriveVerifiedHandoffExecutionBoundary(loop) {
93
96
  const persistedMode = isExecutionMode(loop.metadata["executionMode"])
94
97
  ? loop.metadata["executionMode"]
95
98
  : undefined;
96
- const groundingEvidenceAvailable = loop.metadata["groundingEvidenceStatus"] !== "unavailable";
97
99
  const executionMode = hasSimulatedAdapter
98
100
  ? "simulated"
99
101
  : hasVerifierOnlyAdapter
@@ -101,7 +103,7 @@ export function deriveVerifiedHandoffExecutionBoundary(loop) {
101
103
  : persistedMode ?? (adapterIds.length > 0 ? "governed" : "simulated");
102
104
  return {
103
105
  executionMode,
104
- governanceClaimEligible: executionMode === "governed" && adapterIds.length > 0 && groundingEvidenceAvailable,
106
+ governanceClaimEligible: executionMode === "governed" && adapterIds.length > 0,
105
107
  };
106
108
  }
107
109
  function toEvidenceStatus(status) {
@@ -157,17 +159,34 @@ export function buildVerifiedHandoff(input) {
157
159
  "Test integrity was not evaluated for this run.",
158
160
  };
159
161
  const executionBoundary = deriveVerifiedHandoffExecutionBoundary(input.loop);
162
+ const verifierStepsActuallyPassed = input.verification.steps.length > 0 &&
163
+ input.verification.steps.every((step) => step.launched === true &&
164
+ step.completed === true &&
165
+ step.crashed === false &&
166
+ step.timedOut !== true &&
167
+ step.exitCode === 0);
168
+ const effectiveVerificationStatus = input.verification.status === "passed" && !verifierStepsActuallyPassed
169
+ ? input.verification.steps.length === 0
170
+ ? "not_run"
171
+ : "contradicted"
172
+ : input.verification.status;
173
+ const verificationWarnings = [
174
+ ...input.verification.warnings,
175
+ ...(effectiveVerificationStatus !== input.verification.status
176
+ ? ["A VERIFIED claim requires at least one launched, completed, exit-zero verifier step."]
177
+ : []),
178
+ ];
160
179
  const outcome = resolveVerifiedHandoffOutcome({
161
180
  lifecycleState: input.loop.lifecycleState,
162
181
  executionStatus: input.executionStatus,
163
- verificationStatus: input.verification.status,
182
+ verificationStatus: effectiveVerificationStatus,
164
183
  receiptIntegrity: input.receiptIntegrity.state,
165
184
  scopeStatus: scope.status,
166
185
  testIntegrityStatus: testIntegrity.status,
167
186
  mutationRequired: input.mutationRequired ?? input.loop.task.mutationMode === "edit",
168
187
  changedFileCount: scope.changedFiles.length,
169
188
  definitionOfDonePreSatisfied: input.definitionOfDonePreSatisfied,
170
- evidenceContradicted: input.evidenceContradicted ?? input.verification.status === "contradicted",
189
+ evidenceContradicted: input.evidenceContradicted ?? effectiveVerificationStatus === "contradicted",
171
190
  governanceClaimEligible: executionBoundary.governanceClaimEligible,
172
191
  unresolvedWorkCount: unresolvedWork.length,
173
192
  });
@@ -196,10 +215,10 @@ export function buildVerifiedHandoff(input) {
196
215
  lifecycleState: input.loop.lifecycleState,
197
216
  },
198
217
  verification: {
199
- status: toEvidenceStatus(input.verification.status),
218
+ status: toEvidenceStatus(effectiveVerificationStatus),
200
219
  summary: input.verification.summary,
201
220
  checks: input.verification.steps.map(toCheck),
202
- warnings: input.verification.warnings,
221
+ warnings: verificationWarnings,
203
222
  },
204
223
  requirements: input.requirements ?? [],
205
224
  scope,
@@ -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;
@@ -22,19 +22,6 @@ function evidenceTone(status) {
22
22
  function humanize(value) {
23
23
  return value.replaceAll("_", " ").toLowerCase();
24
24
  }
25
- function formatCost(usd, provenance) {
26
- if (provenance === "unavailable") {
27
- return "unavailable";
28
- }
29
- const amount = "$" + usd.toFixed(2);
30
- if (provenance === "actual") {
31
- return amount + " provider-settled actual";
32
- }
33
- if (provenance === "calculated") {
34
- return amount + " calculated from observed usage";
35
- }
36
- return amount + " estimated";
37
- }
38
25
  function checkSymbol(status) {
39
26
  if (status === "PASSED") {
40
27
  return "✓";
@@ -44,6 +31,16 @@ function checkSymbol(status) {
44
31
  }
45
32
  return "•";
46
33
  }
34
+ function formatCost(usd, provenance) {
35
+ if (provenance === "unavailable")
36
+ return "unavailable";
37
+ const amount = "$" + usd.toFixed(2);
38
+ if (provenance === "actual")
39
+ return amount + " provider-settled actual";
40
+ if (provenance === "calculated")
41
+ return amount + " calculated from observed usage";
42
+ return amount + " estimated";
43
+ }
47
44
  /**
48
45
  * Single source of truth for the trust-authority outcome calculation.
49
46
  * Both terminal and Markdown renderers call this — never duplicate.
@@ -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,10 +1,10 @@
1
1
  {
2
2
  "name": "@martinloop/mcp",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "mcpName": "io.github.Keesan12/martin-loop",
5
5
  "private": false,
6
6
  "type": "module",
7
- "description": "MCP server for AI coding agents — verifier gates, stop limits, and Verified Handoffs.",
7
+ "description": "MCP server for AI coding agents \u00e2\u20ac\u201d verifier gates, stop limits, and Verified Handoffs.",
8
8
  "license": "Apache-2.0",
9
9
  "author": "MartinLoop contributors",
10
10
  "homepage": "https://martinloop.com/",
@@ -18,16 +18,23 @@
18
18
  },
19
19
  "keywords": [
20
20
  "mcp",
21
+ "mcp-server",
21
22
  "model-context-protocol",
22
- "martin-loop",
23
- "ai-agent",
24
- "claude",
23
+ "coding-agent",
24
+ "coding-agents",
25
+ "ai-coding-agent",
26
+ "ai-coding-agents",
27
+ "autonomous-coding",
28
+ "claude-code",
25
29
  "codex",
26
- "martin_doctor",
27
- "martin_triage_runs",
28
- "martin_run_dossier",
29
- "mcp-resources",
30
- "mcp-prompts"
30
+ "gemini-cli",
31
+ "cursor",
32
+ "vscode",
33
+ "agent-runtime",
34
+ "agent-verification",
35
+ "developer-tools",
36
+ "software-engineering",
37
+ "martin-loop"
31
38
  ],
32
39
  "bin": {
33
40
  "mcp": "./dist/server.js",
@@ -50,6 +57,8 @@
50
57
  },
51
58
  "scripts": {
52
59
  "build": "node ./scripts/build-package.mjs",
60
+ "version:sync": "node ./scripts/version-sync.mjs",
61
+ "version:check": "node ./scripts/verify-version-consistency.mjs",
53
62
  "prepack": "pnpm build",
54
63
  "smoke:pack": "node ./scripts/smoke-package.mjs",
55
64
  "smoke:published": "node ./scripts/smoke-published-package.mjs",
@@ -78,4 +87,4 @@
78
87
  "@martin/contracts": "workspace:*",
79
88
  "@martin/presentation": "workspace:*"
80
89
  }
81
- }
90
+ }
package/server.json CHANGED
@@ -2,17 +2,17 @@
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.Keesan12/martin-loop",
4
4
  "title": "Martin Loop",
5
- "description": "MCP server for AI coding agents — verifier gates, stop limits, and Verified Handoffs.",
5
+ "description": "One system around coding agents to run, verify, recover, and hand off software work.",
6
6
  "repository": {
7
7
  "url": "https://github.com/Keesan12/martin-loop",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.5.5",
10
+ "version": "0.5.7",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@martinloop/mcp",
15
- "version": "0.5.5",
15
+ "version": "0.5.7",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }