@minicor/mcp-server 3.3.4 → 3.4.0

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
@@ -19,20 +19,25 @@ Build, deploy, and debug VM-based browser and desktop automations from **Cursor*
19
19
  }
20
20
  ```
21
21
 
22
- **Claude Code:**
22
+ **Claude Code** — no global install needed (npx always runs the latest):
23
23
 
24
24
  ```bash
25
- npm install -g @minicor/mcp-server
26
- claude mcp add minicor -- minicor-mcp
25
+ claude mcp add minicor -- npx -y @minicor/mcp-server
27
26
  ```
28
27
 
29
28
  ### 2. Authenticate
30
29
 
31
30
  ```bash
32
- npx @minicor/mcp-server
31
+ npx -y -p @minicor/mcp-server minicor-mcp-setup
33
32
  ```
34
33
 
35
- Opens a browser to sign in. Tokens stored at `~/.minicor/tokens.json` with auto-refresh. For headless: `npx @minicor/mcp-server-setup --cli`.
34
+ Opens a browser to sign in. Tokens are stored at `~/.minicor/tokens.json` with auto-refresh. For headless / SSH:
35
+
36
+ ```bash
37
+ npx -y -p @minicor/mcp-server minicor-mcp-setup --cli
38
+ ```
39
+
40
+ > The package ships multiple commands. Always use `npx -p @minicor/mcp-server <command>` to run a specific one (`minicor-mcp-setup`, `minicor-bootstrap`, …). Running `npx @minicor/mcp-server` alone only starts the MCP server and ignores trailing arguments.
36
41
 
37
42
  ### 3. Bootstrap Workspace (optional)
38
43
 
@@ -40,22 +45,44 @@ After cloning a workspace, generate harness-specific config files:
40
45
 
41
46
  ```bash
42
47
  # For Claude Code — creates CLAUDE.md + .claude/settings.local.json
43
- npx @minicor/mcp-server minicor-bootstrap claude-code --dir ./my-workspace
48
+ npx -y -p @minicor/mcp-server minicor-bootstrap claude-code --dir ./my-workspace
44
49
 
45
50
  # For Cursor — creates .cursor/rules/workspace.mdc
46
- npx @minicor/mcp-server minicor-bootstrap cursor --dir ./my-workspace
51
+ npx -y -p @minicor/mcp-server minicor-bootstrap cursor --dir ./my-workspace
47
52
 
48
53
  # All harnesses at once
49
- npx @minicor/mcp-server minicor-bootstrap all --dir ./my-workspace
54
+ npx -y -p @minicor/mcp-server minicor-bootstrap all --dir ./my-workspace
50
55
  ```
51
56
 
52
57
  ### 4. Update
53
58
 
54
59
  `npx` users: restart your editor (auto-fetches latest). Global: `npm update -g @minicor/mcp-server`.
55
60
 
56
- ## Code Mode
61
+ ## Code Mode (experimental, opt-in)
62
+
63
+ By default the server exposes every Minicor operation as its own MCP tool. As an **experimental** alternative, you can enable a code-mode surface: a single `codemode` tool that runs JavaScript and provides Minicor methods as async functions on the `minicor` global.
64
+
65
+ Enable it by setting the environment variable before launching the server:
66
+
67
+ ```bash
68
+ EXPERIMENTAL_USE_CODE_MODE=1 minicor-mcp
69
+ ```
57
70
 
58
- Authenticated servers now default to a code-mode MCP surface. Instead of exposing every Minicor operation as a separate MCP tool, the server exposes one `codemode` tool that runs JavaScript and provides Minicor methods as async functions on the `minicor` global:
71
+ In Cursor, add it to the server's `env` block in `~/.cursor/mcp.json`:
72
+
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "minicor": {
77
+ "command": "npx",
78
+ "args": ["-y", "@minicor/mcp-server"],
79
+ "env": { "EXPERIMENTAL_USE_CODE_MODE": "1" }
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ Once enabled:
59
86
 
60
87
  ```javascript
61
88
  const workspaces = await minicor.list_workspaces({});
@@ -73,21 +100,17 @@ Inside `codemode`:
73
100
  - `await codemode.describe("minicor.tool_name")` returns TypeScript-style parameter docs.
74
101
  - `await codemode.list()` lists all available methods.
75
102
 
76
- If you need the legacy one-tool-per-operation surface, set either environment variable before launching the server:
77
-
78
- ```bash
79
- MINICOR_MCP_LEGACY_TOOLS=1 minicor-mcp
80
- # or
81
- MINICOR_MCP_CODE_MODE=0 minicor-mcp
82
- ```
103
+ Unset `EXPERIMENTAL_USE_CODE_MODE` to return to the default one-tool-per-operation surface.
83
104
 
84
105
  ## Session Lifecycle
85
106
 
86
- The MCP server sends **instructions** to every client on connect, telling agents to start a session first when in a workspace clone. In code mode, call `session_start` through the `codemode` tool:
107
+ The MCP server sends **instructions** to every client on connect, telling agents to start a session first when in a workspace clone. Call the `session_start` tool with the workspace directory:
87
108
 
88
- ```javascript
89
- return await minicor.session_start({ directory: "/path/to/workspace" });
90
109
  ```
110
+ session_start({ directory: "/path/to/workspace" })
111
+ ```
112
+
113
+ (With experimental code mode enabled, run the same call as `await minicor.session_start({ ... })` through the `codemode` tool.)
91
114
 
92
115
  This works across all harnesses, including Claude Code, Cursor, and Bedrock.
93
116
 
@@ -195,9 +218,75 @@ After a successful build:
195
218
  - Skills are stored per-workspace and available to future builds
196
219
  - Customer-specific quirks become reusable knowledge
197
220
 
221
+ ## Jobs (RPA orchestration)
222
+
223
+ A **Job** is a middleware route whose behavior is a structured `definition` (a step graph) instead of freeform handler code. Jobs sit **above** workflows: a job step either calls an entire Minicor workflow (`kind: "workflow"`, by `workflowId`) or runs a code block (`kind: "code"`). The job never touches a workflow's internal steps — a workflow is an opaque callable with an input and an output. A job is the **macro zoom** (what ran, status, replays); a workflow → step is the **microscope**. This is the layer that turns one or more workflows into a versioned, testable, observable API endpoint.
224
+
225
+ ### The job tools
226
+
227
+ | Tool | What it does |
228
+ | --- | --- |
229
+ | `list_middlewares` | List the routers (middlewares) in a workspace — jobs attach to one of these. |
230
+ | `register_middleware` | Create a router jobs attach to. `autoConfigure` (default true) populates the router's `workspaceApiKey` from the workspace's first key; or pass `workspaceApiKey` explicitly. |
231
+ | `register_job` | Create a job — a route backed by a structured `definition` (step graph). |
232
+ | `update_job` | Update a job's `definition`, path, method, or description (snapshots a new route version). |
233
+ | `get_job` | Get a job (route) incl. its `definition`; omit `routeId` to list all routes on the router. |
234
+ | `run_job` | Run a job once with an input, poll to completion, return the full `JobExecution` (per-step Minicor deep-links). |
235
+ | `add_test_case` | Attach a test case to a job: named `input` + assertions `[{ name, expr }]` (the green-gate). |
236
+ | `run_tests` | Run a job's test suite (or a subset), poll to completion, return the report (`green`, totals, per-case). |
237
+ | `get_test_report` | Fetch a test run report by id (totals + per-case results, each linking to its job execution). |
238
+ | `list_workspace_api_keys` | List a workspace's API keys (id, apiKey, name) — to find a key for the two tools below. |
239
+ | `set_middleware_api_key` | Set a router's `workspaceApiKey` after the fact, then re-read to confirm it stuck. |
240
+
241
+ ### The recommended build loop — test-driven → job → workflow
242
+
243
+ You work **backwards from the job's test cases**. The job's test suite is the macro green-gate; individual workflows are the micro RPA underneath.
244
+
245
+ ```
246
+ 1. CONTRACT FIRST — define the JOB's input/output and its test cases (the macro green-gate)
247
+ via register_job + add_test_case. Cases start RED.
248
+ 2. BUILD WORKFLOWS — build/curate the Minicor workflow(s) each step will call (the micro RPA).
249
+ 3. WIRE THE STEPS — wire workflows as `kind: "workflow"` steps with `input` mappings,
250
+ plus `when` / `forEach` / `cache` / `onError` as needed.
251
+ 4. RUN TESTS — run_tests until green: true. (run_job to inspect a single execution.)
252
+ ```
253
+
254
+ A job step supports `saveAs`, `when` (conditional skip), `forEach` (fan-out), `onError` (`abort`/`skip`/`continue`/`{goto}` — `goto` currently treated as abort), `retry`, and `cache` (a login/smart-launch gate). Use `resource.lockKey` to serialize execution per desktop/VM. To migrate an existing NestJS customer middleware onto this layer, use the `nestjs-middleware-to-job` prompt or skill.
255
+
256
+ ### ctx / job-shape primer
257
+
258
+ The `definition` you pass to `register_job` (see `register_job`'s `definition` param for the full schema):
259
+
260
+ ```ts
261
+ {
262
+ region: "us" | "ca", // region awareness — also auto-detected from workspace
263
+ resource?: { configStoreId?, lockKey? }, // configStoreId = which VM/desktop; lockKey serializes runs
264
+ inputSchema: JSONSchema,
265
+ outputSchema: JSONSchema,
266
+ steps: [ { id, name, kind, saveAs?, when?, forEach?, onError?, retry?, cache?,
267
+ // kind:"workflow" → workflowId + input (object with {{ctx.x}} OR a (ctx)=>({...}) code block)
268
+ // kind:"code" → code: "(ctx) => ..."
269
+ } ],
270
+ output?: "(ctx) => response", // builds the job's response from the final ctx
271
+ }
272
+ ```
273
+
274
+ **`ctx` is the data through-line** between steps — each step's `saveAs` key is what the next step reads:
275
+
276
+ - `ctx` starts as `{ input: <the job input> }`.
277
+ - Each step's result is stored at `ctx.<saveAs>` (when `saveAs` is set), so later steps / `when` / `forEach` / `output` can read it.
278
+ - Inside a `forEach` step, the current item is `ctx.item` (results are collected into an array under `saveAs`).
279
+ - The top-level `output` block `(ctx) => ...` builds the job's response from the accumulated `ctx`.
280
+
281
+ Assertions (`add_test_case`) are TS booleans over `{ input, output, ctx, steps }`, e.g. `output.status === "COMPLETED"`. The full model + runner semantics live in the **middleware-service** repo's `README.md` ("## Jobs") and `middlewares/JOBS-DESIGN.md`.
282
+
283
+ ### Region & API key
284
+
285
+ Jobs are **region-aware** (`us` / `ca`) — pass `region` or let it be auto-detected from the workspace. Running a job requires the router's `workspaceApiKey` to be set so a job's workflow steps can call the Laminar API: it's populated by `register_middleware`'s `autoConfigure` (default), or set later with `set_middleware_api_key` (find a key via `list_workspace_api_keys`). `register_middleware` / `set_middleware_api_key` report `workspaceApiKeyConfigured` so you can confirm it stuck.
286
+
198
287
  ## Skills System
199
288
 
200
- Skills are reusable RPA patterns that accumulate as you build automations. The MCP ships with 6 bundled general skills:
289
+ Skills are reusable RPA patterns that accumulate as you build automations. The MCP ships with bundled general skills, including:
201
290
 
202
291
 
203
292
  | Skill | Purpose |
@@ -208,6 +297,7 @@ Skills are reusable RPA patterns that accumulate as you build automations. The M
208
297
  | `data-extraction-strategies` | Priority-ordered methods for reading data from screen |
209
298
  | `data-passing-between-steps` | JS-layer interpolation, config variables, step outputs |
210
299
  | `state-verification` | LLM-based UI verification for production workflows |
300
+ | `nestjs-middleware-to-job` | Map a NestJS middleware controller onto the Jobs layer (step graph + test cases) |
211
301
 
212
302
 
213
303
  ### Using Skills
@@ -300,6 +390,26 @@ For manual setup, use `get_lds_setup_guide` for step-by-step instructions.
300
390
  | `preview_flow_changes` / `compare_flow_versions` | Diff code before deploying |
301
391
 
302
392
 
393
+ ### Jobs & Test Cases
394
+
395
+
396
+ | Tool | What it does |
397
+ | --------------------- | -------------------------------------------------------------------------------------------- |
398
+ | `list_middlewares` | List the routers (middlewares) in a workspace — jobs attach to one of these |
399
+ | `register_middleware` | Create a router (middleware) jobs attach to; `autoConfigure` populates its workspace API key |
400
+ | `register_job` | Create a job — a middleware route backed by a structured `definition` (step graph) |
401
+ | `update_job` | Update a job's `definition`, path, method, or description (snapshots a new route version) |
402
+ | `get_job` | Get a job (route) incl. its `definition`; omit `routeId` to list all routes on the router |
403
+ | `run_job` | Run a job once with an input, poll to completion, return the full `JobExecution` |
404
+ | `add_test_case` | Attach a test case to a job: named `input` + assertions `[{ name, expr }]` (the green-gate) |
405
+ | `run_tests` | Run a job's test suite, poll to completion, return the report (`green`, totals, per-case) |
406
+ | `get_test_report` | Fetch a test run report by id (totals + per-case results, each linking to its job execution) |
407
+ | `list_workspace_api_keys` | List a workspace's API keys (id, apiKey, name) — find one for the two tools below |
408
+ | `set_middleware_api_key` | Set a router's `workspaceApiKey` (then re-reads to confirm it stuck) |
409
+
410
+
411
+ See the **Jobs (RPA orchestration)** section above for the build loop and job/ctx shape. `batch_test_rpa` can also persist each passing input as a real job test case — set `persistAsTestCases` with `routeId` + `middlewareId` + `workspaceId`.
412
+
303
413
  ### 2FA / OTP
304
414
 
305
415
 
@@ -410,6 +520,7 @@ Agents are autonomous runners that execute tasks on VMs using MCP tools. After b
410
520
  | `minicor-workflow-guide` | Full workflow specification: step types, data access, keywords, libraries |
411
521
  | `2fa-workflow-guide` | Handling 2FA in workflows: provisioning channels, TOTP secrets, auto-resolving OTP codes |
412
522
  | `workspace-session-guide` | Returns AGENTS.md rules and session state for any workspace clone |
523
+ | `nestjs-middleware-to-job` | Convert an existing NestJS customer middleware endpoint into a Job (structured step graph) with test cases as the green-gate |
413
524
 
414
525
 
415
526
  The `build-rpa-workflow` prompt accepts a `mode` parameter:
@@ -421,14 +532,26 @@ The `build-rpa-workflow` prompt accepts a `mode` parameter:
421
532
  ## Environment Variables
422
533
 
423
534
 
424
- | Variable | Purpose | Default |
425
- | -------------------- | ---------------------- | ------------------ |
426
- | `VM_MANAGER_API_URL` | VM Manager service URL | Cloud Run instance |
535
+ Jobs/middleware base resolution (precedence: **proxy > direct > default**):
536
+
537
+ | Variable | Purpose | Default |
538
+ | --------------------------------- | ------------------------------------------------------------------- | ---------------------- |
539
+ | `VM_MANAGER_API_URL` | VM Manager service URL | Cloud Run instance |
540
+ | `MIDDLEWARE_SERVICE_PROXY_BASE` | Frontend origin fronting the middleware proxy, all regions | unset |
541
+ | `MIDDLEWARE_SERVICE_PROXY_BASE_US`| Frontend proxy origin for US (overrides the generic one) | unset |
542
+ | `MIDDLEWARE_SERVICE_PROXY_BASE_CA`| Frontend proxy origin for CA (overrides the generic one) | unset |
543
+ | `MIDDLEWARE_SERVICE_PROXY_PREFIX` | Proxy path prefix | `/api/middleware` |
544
+ | `MIDDLEWARE_SERVICE_URL` | Direct middleware-service base, all regions (dev/local) | unset |
545
+ | `MIDDLEWARE_SERVICE_URL_US` | Direct middleware-service base for US (overrides the generic one) | unset |
546
+ | `MIDDLEWARE_SERVICE_URL_CA` | Direct middleware-service base for CA (overrides the generic one) | unset |
547
+ | `EXPERIMENTAL_USE_CODE_MODE` | Expose the experimental single `codemode` tool surface | unset (standard tools) |
548
+
549
+ When none are set, Jobs calls the region's public middleware-service Cloud Run directly. To route through the frontend (once it deploys an `/api/middleware/[...path]` proxy), set `MIDDLEWARE_SERVICE_PROXY_BASE` (or the per-region variants).
427
550
 
428
551
 
429
552
  ## Auth
430
553
 
431
- - **Sign in**: `minicor-mcp-setup` (browser) or `minicor-mcp-setup --cli`
554
+ - **Sign in**: `npx -y -p @minicor/mcp-server minicor-mcp-setup` (browser) or append `--cli` for headless
432
555
  - **Token storage**: `~/.minicor/tokens.json`
433
556
  - **Auto-refresh**: tokens refresh before expiry
434
557
  - **Regions**: US (default) or Canada
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=middleware-service-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-service-client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/middleware-service-client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,293 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { MiddlewareServiceClient } from "../middleware-service-client.js";
3
+ /**
4
+ * The client only parses the body as JSON when the response carries an
5
+ * `application/json` content-type, so tests must set it explicitly (this also
6
+ * documents the contract the frontend proxy must satisfy).
7
+ */
8
+ function jsonResponse(body, status = 200) {
9
+ return new Response(JSON.stringify(body), {
10
+ status,
11
+ headers: { "Content-Type": "application/json" },
12
+ });
13
+ }
14
+ describe("MiddlewareServiceClient", () => {
15
+ const originalFetch = globalThis.fetch;
16
+ const apiBase = "https://api.minicor.com";
17
+ const token = "user-bearer-xyz";
18
+ const ws = 257;
19
+ const mw = "mw-1";
20
+ const route = "route-1";
21
+ // Default (deployed): the region's public middleware-service Cloud Run, hit
22
+ // directly at `${base}/api/workspaces/...`. (us by default for api.minicor.com.)
23
+ const US_DIRECT = "https://middleware-service-489511347341.northamerica-northeast1.run.app";
24
+ const middlewaresBase = `${US_DIRECT}/api/workspaces/257/middlewares`;
25
+ const routesBase = `${middlewaresBase}/mw-1/routes`;
26
+ const ENV_KEYS = [
27
+ "MIDDLEWARE_SERVICE_URL",
28
+ "MIDDLEWARE_SERVICE_URL_US",
29
+ "MIDDLEWARE_SERVICE_URL_CA",
30
+ "MIDDLEWARE_SERVICE_PROXY_BASE",
31
+ "MIDDLEWARE_SERVICE_PROXY_BASE_US",
32
+ "MIDDLEWARE_SERVICE_PROXY_BASE_CA",
33
+ "MIDDLEWARE_SERVICE_PROXY_PREFIX",
34
+ ];
35
+ const savedEnv = {};
36
+ let client;
37
+ beforeEach(() => {
38
+ for (const k of ENV_KEYS) {
39
+ savedEnv[k] = process.env[k];
40
+ delete process.env[k];
41
+ }
42
+ globalThis.fetch = vi.fn();
43
+ client = new MiddlewareServiceClient(apiBase, token);
44
+ });
45
+ afterEach(() => {
46
+ for (const k of ENV_KEYS) {
47
+ if (savedEnv[k] === undefined)
48
+ delete process.env[k];
49
+ else
50
+ process.env[k] = savedEnv[k];
51
+ }
52
+ globalThis.fetch = originalFetch;
53
+ vi.restoreAllMocks();
54
+ });
55
+ function lastCall() {
56
+ const { calls } = vi.mocked(globalThis.fetch).mock;
57
+ return calls[calls.length - 1];
58
+ }
59
+ function lastUrl() {
60
+ return lastCall()[0];
61
+ }
62
+ function lastInit() {
63
+ return lastCall()[1];
64
+ }
65
+ function lastBody() {
66
+ return JSON.parse(lastInit().body);
67
+ }
68
+ it("defaults to the US Cloud Run (direct /api/workspaces) with the bearer token", async () => {
69
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ id: "exec-1" }));
70
+ await client.getExecution(ws, mw, route, "exec-1");
71
+ expect(lastUrl()).toBe(`${routesBase}/route-1/executions/exec-1`);
72
+ expect(lastInit().method).toBe("GET");
73
+ expect(lastInit().headers.Authorization).toBe(`Bearer ${token}`);
74
+ });
75
+ it("defaults to the CA Cloud Run for a CA api base", async () => {
76
+ const ca = new MiddlewareServiceClient("https://ca.api.minicor.com", token);
77
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([]));
78
+ await ca.listRoutes(ws, mw);
79
+ expect(lastUrl()).toBe("https://middleware-service-ca-ernfuwetfa-nn.a.run.app/api/workspaces/257/middlewares/mw-1/routes");
80
+ });
81
+ it("routes through the frontend proxy when MIDDLEWARE_SERVICE_PROXY_BASE is set (/api/ stripped)", async () => {
82
+ process.env.MIDDLEWARE_SERVICE_PROXY_BASE = "https://app.minicor.com";
83
+ const proxied = new MiddlewareServiceClient(apiBase, token);
84
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([]));
85
+ await proxied.listRoutes(ws, mw);
86
+ expect(lastUrl()).toBe("https://app.minicor.com/api/middleware/workspaces/257/middlewares/mw-1/routes");
87
+ expect(lastInit().headers.Authorization).toBe(`Bearer ${token}`);
88
+ });
89
+ it("uses a region-specific proxy base for CA, overriding the generic one", async () => {
90
+ process.env.MIDDLEWARE_SERVICE_PROXY_BASE = "https://app.laminar.run";
91
+ process.env.MIDDLEWARE_SERVICE_PROXY_BASE_CA = "https://ca.app.laminar.run";
92
+ const ca = new MiddlewareServiceClient("https://ca.api.laminar.run", token);
93
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([]));
94
+ await ca.listRoutes(ws, mw);
95
+ expect(lastUrl()).toBe("https://ca.app.laminar.run/api/middleware/workspaces/257/middlewares/mw-1/routes");
96
+ });
97
+ it("falls back to the generic proxy base for US when no US-specific one is set", async () => {
98
+ process.env.MIDDLEWARE_SERVICE_PROXY_BASE = "https://app.laminar.run";
99
+ process.env.MIDDLEWARE_SERVICE_PROXY_BASE_CA = "https://ca.app.laminar.run";
100
+ const us = new MiddlewareServiceClient("https://api.laminar.run", token);
101
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([]));
102
+ await us.listRoutes(ws, mw);
103
+ expect(lastUrl()).toBe("https://app.laminar.run/api/middleware/workspaces/257/middlewares/mw-1/routes");
104
+ });
105
+ it("honors a custom MIDDLEWARE_SERVICE_PROXY_PREFIX", async () => {
106
+ process.env.MIDDLEWARE_SERVICE_PROXY_BASE = "https://app.minicor.com";
107
+ process.env.MIDDLEWARE_SERVICE_PROXY_PREFIX = "api/mw-proxy";
108
+ const proxied = new MiddlewareServiceClient(apiBase, token);
109
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([]));
110
+ await proxied.listRoutes(ws, mw);
111
+ expect(lastUrl()).toBe("https://app.minicor.com/api/mw-proxy/workspaces/257/middlewares/mw-1/routes");
112
+ });
113
+ it("proxy base takes precedence over a direct override", async () => {
114
+ process.env.MIDDLEWARE_SERVICE_PROXY_BASE = "https://app.minicor.com";
115
+ process.env.MIDDLEWARE_SERVICE_URL = "https://mw.dev.example.com";
116
+ const proxied = new MiddlewareServiceClient(apiBase, token);
117
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([]));
118
+ await proxied.listRoutes(ws, mw);
119
+ expect(lastUrl()).toBe("https://app.minicor.com/api/middleware/workspaces/257/middlewares/mw-1/routes");
120
+ });
121
+ it("hits a direct base (no proxy) when MIDDLEWARE_SERVICE_URL is set", async () => {
122
+ process.env.MIDDLEWARE_SERVICE_URL = "https://mw.dev.example.com";
123
+ const direct = new MiddlewareServiceClient(apiBase, token);
124
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([]));
125
+ await direct.listRoutes(ws, mw);
126
+ expect(lastUrl()).toBe("https://mw.dev.example.com/api/workspaces/257/middlewares/mw-1/routes");
127
+ });
128
+ it("MIDDLEWARE_SERVICE_URL_CA overrides only the CA region", async () => {
129
+ process.env.MIDDLEWARE_SERVICE_URL_CA = "https://mw-ca.example.com";
130
+ const ca = new MiddlewareServiceClient("https://ca.api.minicor.com", token);
131
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([]));
132
+ await ca.listRoutes(ws, mw);
133
+ expect(lastUrl()).toBe("https://mw-ca.example.com/api/workspaces/257/middlewares/mw-1/routes");
134
+ });
135
+ it("listMiddlewares GETs the workspace middlewares", async () => {
136
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([{ id: "mw-1" }, { id: "mw-2" }]));
137
+ const mws = await client.listMiddlewares(ws);
138
+ expect(lastUrl()).toBe(middlewaresBase);
139
+ expect(lastInit().method).toBe("GET");
140
+ expect(mws.map((m) => m.id)).toEqual(["mw-1", "mw-2"]);
141
+ });
142
+ it("createMiddleware POSTs name/slug/description", async () => {
143
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ id: "mw-9", name: "AMS", slug: "ams" }));
144
+ await client.createMiddleware(ws, { name: "AMS", slug: "ams", description: "d" });
145
+ expect(lastUrl()).toBe(middlewaresBase);
146
+ expect(lastInit().method).toBe("POST");
147
+ expect(lastBody()).toEqual({ name: "AMS", slug: "ams", description: "d" });
148
+ });
149
+ it("autoConfigureMiddleware POSTs to the auto-configure endpoint", async () => {
150
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({}));
151
+ await client.autoConfigureMiddleware(ws, "mw-9");
152
+ expect(lastUrl()).toBe(`${middlewaresBase}/mw-9/auto-configure`);
153
+ expect(lastInit().method).toBe("POST");
154
+ });
155
+ it("createJob defaults method to POST and sends the definition", async () => {
156
+ const definition = {
157
+ region: "us",
158
+ inputSchema: {},
159
+ outputSchema: {},
160
+ steps: [],
161
+ };
162
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ id: route, path: "/coi" }));
163
+ await client.createJob(ws, mw, { path: "/coi", definition });
164
+ expect(lastUrl()).toBe(routesBase);
165
+ expect(lastInit().method).toBe("POST");
166
+ expect(lastBody()).toEqual({ method: "POST", path: "/coi", definition });
167
+ });
168
+ it("createJob keeps an explicit method", async () => {
169
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ id: route }));
170
+ await client.createJob(ws, mw, {
171
+ path: "/x",
172
+ method: "GET",
173
+ definition: {},
174
+ });
175
+ expect(lastBody().method).toBe("GET");
176
+ });
177
+ it("updateJob PUTs only the provided fields to the route id", async () => {
178
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ id: route }));
179
+ await client.updateJob(ws, mw, route, { description: "new desc" });
180
+ expect(lastUrl()).toBe(`${routesBase}/route-1`);
181
+ expect(lastInit().method).toBe("PUT");
182
+ expect(lastBody()).toEqual({ description: "new desc" });
183
+ });
184
+ it("listRoutes handles a bare array", async () => {
185
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([{ id: "a" }, { id: "b" }]));
186
+ const routes = await client.listRoutes(ws, mw);
187
+ expect(routes.map((r) => r.id)).toEqual(["a", "b"]);
188
+ });
189
+ it("listRoutes handles a { routes } envelope", async () => {
190
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ routes: [{ id: "a" }] }));
191
+ const routes = await client.listRoutes(ws, mw);
192
+ expect(routes.map((r) => r.id)).toEqual(["a"]);
193
+ });
194
+ it("getJob filters the route list by id, returning undefined when absent", async () => {
195
+ vi.mocked(globalThis.fetch).mockResolvedValueOnce(jsonResponse([{ id: "a" }, { id: "route-1" }]));
196
+ expect((await client.getJob(ws, mw, "route-1"))?.id).toBe("route-1");
197
+ vi.mocked(globalThis.fetch).mockResolvedValueOnce(jsonResponse([{ id: "a" }]));
198
+ expect(await client.getJob(ws, mw, "route-1")).toBeUndefined();
199
+ });
200
+ it("runJob posts input + trigger to /run and returns the execution id", async () => {
201
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ jobExecutionId: "je-1" }));
202
+ const res = await client.runJob(ws, mw, route, { a: 1 }, "test");
203
+ expect(res.jobExecutionId).toBe("je-1");
204
+ expect(lastUrl()).toBe(`${routesBase}/route-1/run`);
205
+ expect(lastBody()).toEqual({ input: { a: 1 }, trigger: "test" });
206
+ });
207
+ it("runJob defaults the trigger to mcp", async () => {
208
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ jobExecutionId: "je-2" }));
209
+ await client.runJob(ws, mw, route, {});
210
+ expect(lastBody().trigger).toBe("mcp");
211
+ });
212
+ it("addTestCase posts the case to /test-cases", async () => {
213
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ id: "tc-1" }));
214
+ await client.addTestCase(ws, mw, route, {
215
+ name: "happy path",
216
+ input: { x: 1 },
217
+ assertions: [{ name: "ok", expr: "output != null" }],
218
+ });
219
+ expect(lastUrl()).toBe(`${routesBase}/route-1/test-cases`);
220
+ expect(lastInit().method).toBe("POST");
221
+ expect(lastBody().name).toBe("happy path");
222
+ });
223
+ it("startTestRun sends testCaseIds when provided and {} otherwise", async () => {
224
+ vi.mocked(globalThis.fetch).mockImplementation(async () => jsonResponse({ testRunId: "tr-1" }));
225
+ await client.startTestRun(ws, mw, route, ["tc1", "tc2"]);
226
+ expect(lastUrl()).toBe(`${routesBase}/route-1/test-runs`);
227
+ expect(lastBody()).toEqual({ testCaseIds: ["tc1", "tc2"] });
228
+ await client.startTestRun(ws, mw, route);
229
+ expect(lastBody()).toEqual({});
230
+ });
231
+ it("throws on a non-ok response with the method, path and body", async () => {
232
+ vi.mocked(globalThis.fetch).mockResolvedValue(new Response("nope", { status: 403 }));
233
+ await expect(client.getExecution(ws, mw, route, "e")).rejects.toThrow(/Middleware service GET .*failed \(403\): nope/);
234
+ });
235
+ describe("pollExecution", () => {
236
+ it("polls until a terminal state and returns it", async () => {
237
+ vi.mocked(globalThis.fetch)
238
+ .mockResolvedValueOnce(jsonResponse({ id: "e", status: "queued" }))
239
+ .mockResolvedValueOnce(jsonResponse({ id: "e", status: "running" }))
240
+ .mockResolvedValueOnce(jsonResponse({ id: "e", status: "succeeded" }));
241
+ const exec = await client.pollExecution(ws, mw, route, "e", {
242
+ intervalMs: 1,
243
+ timeoutMs: 1000,
244
+ });
245
+ expect(exec.status).toBe("succeeded");
246
+ expect(globalThis.fetch).toHaveBeenCalledTimes(3);
247
+ });
248
+ it("treats partial/failed as terminal", async () => {
249
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse({ id: "e", status: "partial" }));
250
+ const exec = await client.pollExecution(ws, mw, route, "e", {
251
+ intervalMs: 1,
252
+ timeoutMs: 1000,
253
+ });
254
+ expect(exec.status).toBe("partial");
255
+ expect(globalThis.fetch).toHaveBeenCalledTimes(1);
256
+ });
257
+ it("throws on timeout while still running", async () => {
258
+ vi.mocked(globalThis.fetch).mockImplementation(async () => jsonResponse({ id: "e", status: "running" }));
259
+ await expect(client.pollExecution(ws, mw, route, "e", {
260
+ intervalMs: 1,
261
+ timeoutMs: 15,
262
+ })).rejects.toThrow(/Timed out polling job execution e .*last status: running/);
263
+ });
264
+ });
265
+ describe("pollTestRun", () => {
266
+ it("polls until the run leaves running and returns the report", async () => {
267
+ vi.mocked(globalThis.fetch)
268
+ .mockResolvedValueOnce(jsonResponse({ testRun: { id: "tr", status: "running" }, results: [] }))
269
+ .mockResolvedValueOnce(jsonResponse({
270
+ testRun: {
271
+ id: "tr",
272
+ status: "passed",
273
+ totals: { total: 1, passed: 1, failed: 0, errored: 0 },
274
+ },
275
+ results: [{ id: "r1", testRunId: "tr", testCaseId: "tc", passed: true }],
276
+ }));
277
+ const report = await client.pollTestRun(ws, mw, route, "tr", {
278
+ intervalMs: 1,
279
+ timeoutMs: 1000,
280
+ });
281
+ expect(report.testRun.status).toBe("passed");
282
+ expect(report.results).toHaveLength(1);
283
+ });
284
+ it("throws on timeout while still running", async () => {
285
+ vi.mocked(globalThis.fetch).mockImplementation(async () => jsonResponse({ testRun: { id: "tr", status: "running" }, results: [] }));
286
+ await expect(client.pollTestRun(ws, mw, route, "tr", {
287
+ intervalMs: 1,
288
+ timeoutMs: 15,
289
+ })).rejects.toThrow(/Timed out polling test run tr/);
290
+ });
291
+ });
292
+ });
293
+ //# sourceMappingURL=middleware-service-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-service-client.test.js","sourceRoot":"","sources":["../../src/__tests__/middleware-service-client.test.ts"],"names":[],"mappings":"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"}
package/dist/codemode.js CHANGED
@@ -694,19 +694,20 @@ export class CodeModeToolRegistry {
694
694
  }
695
695
  }
696
696
  export function shouldUseCodeMode() {
697
- const explicit = process.env.MINICOR_MCP_CODE_MODE;
698
- if (explicit != null) {
699
- return !["0", "false", "off", "no"].includes(explicit.toLowerCase());
700
- }
701
- return !["1", "true", "on", "yes"].includes((process.env.MINICOR_MCP_LEGACY_TOOLS ?? "").toLowerCase());
697
+ // Code mode is experimental and OFF by default. Opt in with
698
+ // EXPERIMENTAL_USE_CODE_MODE=1 (legacy aliases kept for back-compat).
699
+ const flag = process.env.EXPERIMENTAL_USE_CODE_MODE ??
700
+ process.env.MINICOR_MCP_CODE_MODE ??
701
+ "";
702
+ return ["1", "true", "on", "yes"].includes(flag.toLowerCase());
702
703
  }
703
704
  export function buildCodeModeInstructions(baseInstructions) {
704
705
  return `${baseInstructions}
705
706
 
706
- CODE MODE:
707
- This MCP exposes Minicor capabilities through a code-mode surface by default. Use the \`codemode\` tool to run JavaScript that calls Minicor methods as \`await minicor.tool_name({ ... })\`.
707
+ CODE MODE (EXPERIMENTAL):
708
+ This MCP is running with the experimental code-mode surface enabled. Use the \`codemode\` tool to run JavaScript that calls Minicor methods as \`await minicor.tool_name({ ... })\`.
708
709
 
709
- If the server starts unauthenticated and only exposes \`setup_account\`, call \`setup_account\` directly, authenticate, and restart the MCP server. Code mode is enabled for authenticated sessions.
710
+ If the server starts unauthenticated and only exposes \`setup_account\`, call \`setup_account\` directly, authenticate, and restart the MCP server.
710
711
 
711
712
  Discovery inside code mode:
712
713
  - \`await codemode.search("workflow")\` finds relevant Minicor methods.
@@ -715,7 +716,7 @@ Discovery inside code mode:
715
716
 
716
717
  If the current directory contains a minicor.json file, your first MCP action should be a \`codemode\` call whose code invokes \`await minicor.session_start({ directory: "<current directory>" })\`. Before ending work, invoke \`await minicor.session_end(...)\` through code mode.
717
718
 
718
- Set MINICOR_MCP_LEGACY_TOOLS=1 or MINICOR_MCP_CODE_MODE=0 to expose the legacy one-tool-per-operation MCP surface.`;
719
+ Code mode is opt-in: unset EXPERIMENTAL_USE_CODE_MODE to return to the default one-tool-per-operation MCP surface.`;
719
720
  }
720
721
  export function asMcpServer(registry) {
721
722
  return registry;