@martinloop/mcp 0.3.1 → 0.3.2

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Governed MCP server for AI coding agents over local stdio.
4
4
 
5
- `@martinloop/mcp@0.3.0` is the live public baseline today. `0.3.1` is the current in-repo release candidate for the next public cut.
5
+ `@martinloop/mcp@0.3.2` is the live public baseline today. `0.3.3` is the next planned public cut.
6
6
 
7
7
  This package stays local-first and stdio-first in the public OSS lane.
8
8
 
@@ -10,8 +10,9 @@ This package stays local-first and stdio-first in the public OSS lane.
10
10
 
11
11
  - `0.2.7` made the guided MCP workflow easier to adopt and harder to misuse.
12
12
  - `0.3.0` is the live adoption baseline that made host setup and onboarding clearer.
13
- - `0.3.1` is the review and handoff release candidate currently staged in-repo.
14
- - `0.3.2` remains the planned follow-on for opt-in execution controls.
13
+ - `0.3.1` is the live review and handoff release.
14
+ - `0.3.2` is the live engine-validation hotfix that fixes spend-limit requests for Gemini-backed runs.
15
+ - `0.3.3` is the planned follow-on for opt-in execution controls.
15
16
 
16
17
  ## What ships today
17
18
 
@@ -1 +1 @@
1
- export declare const MARTIN_MCP_PACKAGE_VERSION = "0.3.1";
1
+ export declare const MARTIN_MCP_PACKAGE_VERSION = "0.3.2";
@@ -1,3 +1,3 @@
1
1
  // Keep this aligned with packages/mcp/package.json during version bumps so the
2
2
  // runtime does not depend on package.json being present in every hosted bundle.
3
- export const MARTIN_MCP_PACKAGE_VERSION = "0.3.1";
3
+ export const MARTIN_MCP_PACKAGE_VERSION = "0.3.2";
@@ -156,7 +156,7 @@ function validateRunInput(args) {
156
156
  "workspaceId",
157
157
  "projectId"
158
158
  ]);
159
- const engine = optionalEnum(record.engine, "engine", ["claude", "codex"]);
159
+ const engine = optionalEnum(record.engine, "engine", ["claude", "codex", "gemini"]);
160
160
  return {
161
161
  objective: requireString(record.objective, "objective"),
162
162
  ...(record.workingDirectory !== undefined
@@ -246,7 +246,7 @@ function validateDoctorInput(args) {
246
246
  ...(record.runsDir !== undefined
247
247
  ? { runsDir: resolveSafeRunsRootPath(requireString(record.runsDir, "runsDir")) }
248
248
  : {}),
249
- ...optionalEnumAsObject(record.engine, "engine", ["claude", "codex"])
249
+ ...optionalEnumAsObject(record.engine, "engine", ["claude", "codex", "gemini"])
250
250
  };
251
251
  }
252
252
  function validatePreflightInput(args) {
package/dist/server.js CHANGED
@@ -739,7 +739,7 @@ export function createMartinMcpServer(serverInfo) {
739
739
  },
740
740
  engine: {
741
741
  type: "string",
742
- enum: ["claude", "codex"],
742
+ enum: ["claude", "codex", "gemini"],
743
743
  description: "Which agent CLI to use. Defaults to claude."
744
744
  },
745
745
  model: {
@@ -871,7 +871,7 @@ export function createMartinMcpServer(serverInfo) {
871
871
  },
872
872
  engine: {
873
873
  type: "string",
874
- enum: ["claude", "codex"],
874
+ enum: ["claude", "codex", "gemini"],
875
875
  description: "Optional engine to highlight in diagnostics."
876
876
  }
877
877
  }
@@ -934,7 +934,7 @@ export function createMartinMcpServer(serverInfo) {
934
934
  },
935
935
  engine: {
936
936
  type: "string",
937
- enum: ["claude", "codex"],
937
+ enum: ["claude", "codex", "gemini"],
938
938
  description: "Which agent CLI would be used. Defaults to claude."
939
939
  },
940
940
  model: {
@@ -1,6 +1,7 @@
1
1
  export type LoopStatus = "queued" | "running" | "verifying" | "completed" | "failed" | "exited";
2
2
  export type LoopLifecycleState = "created" | "running" | "verifying" | "completed" | "budget_exit" | "diminishing_returns" | "stuck_exit" | "human_escalation";
3
- export type FailureClass = "logic_error" | "hallucination" | "syntax_error" | "type_error" | "test_regression" | "scope_creep" | "no_progress" | "repo_grounding_failure" | "verification_failure" | "environment_mismatch" | "budget_pressure" | "safety_leash_blocked";
3
+ export declare const FAILURE_CLASSES: readonly ["logic_error", "hallucination", "syntax_error", "type_error", "test_regression", "scope_creep", "no_progress", "repo_grounding_failure", "verification_failure", "environment_mismatch", "budget_pressure", "safety_leash_blocked"];
4
+ export type FailureClass = (typeof FAILURE_CLASSES)[number];
4
5
  export type InterventionType = "compress_context" | "change_model" | "tighten_task" | "switch_adapter" | "run_verifier" | "escalate_human" | "stop_loop";
5
6
  export type LoopEventType = "run.started" | "attempt.started" | "attempt.completed" | "failure.classified" | "intervention.selected" | "verification.completed" | "budget.updated" | "run.completed";
6
7
  export interface LoopTask {
@@ -1,3 +1,17 @@
1
+ export const FAILURE_CLASSES = [
2
+ "logic_error",
3
+ "hallucination",
4
+ "syntax_error",
5
+ "type_error",
6
+ "test_regression",
7
+ "scope_creep",
8
+ "no_progress",
9
+ "repo_grounding_failure",
10
+ "verification_failure",
11
+ "environment_mismatch",
12
+ "budget_pressure",
13
+ "safety_leash_blocked",
14
+ ];
1
15
  export { MARTIN_ERROR_CATEGORIES } from "./operator.js";
2
16
  export const DEFAULT_BUDGET = {
3
17
  maxUsd: 25,
@@ -24,7 +24,12 @@ const BLOCKED_PATTERNS = [
24
24
  /\bshutil\.rmtree\s*\(/iu,
25
25
  /\bos\.(?:remove|rmdir|removedirs|unlink)\s*\(/iu,
26
26
  /\.(?:rm|rmdir|unlink)(?:Sync)?\s*\(/iu,
27
- /\brimraf\s*\(/iu
27
+ /\brimraf\s*\(/iu,
28
+ // Windows destructive deletion / formatting patterns
29
+ /\b(?:cmd(?:\.exe)?\s+\/c\s+)?del(?:\.exe)?\s+\/[^\n]*(?:\bs\b|\bq\b|\bf\b)/iu,
30
+ /\b(?:cmd(?:\.exe)?\s+\/c\s+)?rmdir(?:\.exe)?\s+\/[^\n]*\bs\b/iu,
31
+ /\bremove-item\b[^\n]*(?:-recurse|-r)\b[^\n]*(?:-force|-fo)\b/iu,
32
+ /\b(?:format-volume|diskpart)\b/iu
28
33
  ];
29
34
  /**
30
35
  * Detects `rm` invocations that combine recursive + force flags regardless of
@@ -17,9 +17,7 @@ export async function recordMcpWorkflowStep(input) {
17
17
  ...(input.engine ? { engine: input.engine } : {}),
18
18
  ...(input.verificationPlan ? { verificationPlanKey: hashVerificationPlan(input.verificationPlan) } : {}),
19
19
  ...(input.receiptScope ? { scopeKey: hashReceiptScope(input.receiptScope) } : {}),
20
- ...(input.allowedPaths || input.deniedPaths
21
- ? { pathScopeKey: hashPathScope(input.allowedPaths ?? [], input.deniedPaths ?? []) }
22
- : {}),
20
+ pathScopeKey: hashPathScope(input.allowedPaths ?? [], input.deniedPaths ?? []),
23
21
  ...(input.budget ? { budgetKey: hashBudget(input.budget) } : {})
24
22
  };
25
23
  await writeWorkflowState(input.runsRoot, state);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@martinloop/mcp",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
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.3.1",
10
+ "version": "0.3.2",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@martinloop/mcp",
15
- "version": "0.3.1",
15
+ "version": "0.3.2",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }