@minicor/mcp-server 3.2.0 → 3.2.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 +69 -24
- package/dist/__tests__/laminar-client.test.d.ts +2 -0
- package/dist/__tests__/laminar-client.test.d.ts.map +1 -0
- package/dist/__tests__/laminar-client.test.js +70 -0
- package/dist/__tests__/laminar-client.test.js.map +1 -0
- package/dist/__tests__/token-provider.test.d.ts +2 -0
- package/dist/__tests__/token-provider.test.d.ts.map +1 -0
- package/dist/__tests__/token-provider.test.js +82 -0
- package/dist/__tests__/token-provider.test.js.map +1 -0
- package/dist/bootstrap.d.ts +12 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +244 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/config.d.ts +6 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -10
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +64 -10
- package/dist/index.js.map +1 -1
- package/dist/laminar-client.d.ts +3 -1
- package/dist/laminar-client.d.ts.map +1 -1
- package/dist/laminar-client.js +18 -5
- package/dist/laminar-client.js.map +1 -1
- package/dist/lib.d.ts +10 -7
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +64 -10
- package/dist/lib.js.map +1 -1
- package/dist/prompts/workspace-session.d.ts +3 -0
- package/dist/prompts/workspace-session.d.ts.map +1 -0
- package/dist/prompts/workspace-session.js +58 -0
- package/dist/prompts/workspace-session.js.map +1 -0
- package/dist/state.d.ts +22 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +12 -0
- package/dist/state.js.map +1 -1
- package/dist/token-provider.d.ts +16 -0
- package/dist/token-provider.d.ts.map +1 -0
- package/dist/token-provider.js +44 -0
- package/dist/token-provider.js.map +1 -0
- package/dist/tools/session.d.ts +8 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +392 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/sync-tools.d.ts.map +1 -1
- package/dist/tools/sync-tools.js +37 -8
- package/dist/tools/sync-tools.js.map +1 -1
- package/dist/tools/vm.d.ts.map +1 -1
- package/dist/tools/vm.js +17 -9
- package/dist/tools/vm.js.map +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -34,10 +34,46 @@ npx @minicor/mcp-server-setup
|
|
|
34
34
|
|
|
35
35
|
Opens a browser to sign in. Tokens stored at `~/.minicor/tokens.json` with auto-refresh. For headless: `npx @minicor/mcp-server-setup --cli`.
|
|
36
36
|
|
|
37
|
-
### 3.
|
|
37
|
+
### 3. Bootstrap Workspace (optional)
|
|
38
|
+
|
|
39
|
+
After cloning a workspace, generate harness-specific config files:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# For Claude Code — creates CLAUDE.md + .claude/settings.local.json
|
|
43
|
+
npx @minicor/mcp-server minicor-bootstrap claude-code --dir ./my-workspace
|
|
44
|
+
|
|
45
|
+
# For Cursor — creates .cursor/rules/workspace.mdc
|
|
46
|
+
npx @minicor/mcp-server minicor-bootstrap cursor --dir ./my-workspace
|
|
47
|
+
|
|
48
|
+
# All harnesses at once
|
|
49
|
+
npx @minicor/mcp-server minicor-bootstrap all --dir ./my-workspace
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 4. Update
|
|
38
53
|
|
|
39
54
|
`npx` users: restart your editor (auto-fetches latest). Global: `npm update -g @minicor/mcp-server`.
|
|
40
55
|
|
|
56
|
+
## Session Lifecycle
|
|
57
|
+
|
|
58
|
+
The MCP server sends **instructions** to every client on connect, telling agents to call `session_start` first when in a workspace clone. This works across all harnesses — Claude Code, Cursor, Bedrock, etc.
|
|
59
|
+
|
|
60
|
+
### Session Tools
|
|
61
|
+
|
|
62
|
+
| Tool | What it does |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `session_start` | Load workspace context (AGENTS.md, VMs, skills, issues, prior session). Call FIRST in a workspace clone. |
|
|
65
|
+
| `session_checkpoint` | Save progress mid-session. Writes `.minicor/session.json` + syncs `[Workspace:Session]` issue. |
|
|
66
|
+
| `session_end` | Persist final state, sync to platform, optionally update context.md. Call before ending work. |
|
|
67
|
+
| `set_workspaces_root` | Set default root directory for cloning workspaces (saved to `~/.minicor/config.json`). |
|
|
68
|
+
|
|
69
|
+
### Auto-Save on Disconnect
|
|
70
|
+
|
|
71
|
+
If the agent crashes or the user closes the IDE, the server auto-checkpoints with `status: "interrupted"` so no session state is lost. The next agent resumes from that checkpoint.
|
|
72
|
+
|
|
73
|
+
### Multi-Agent Handoff
|
|
74
|
+
|
|
75
|
+
Sessions are synced to `[Workspace:Session]` issues on the platform, so agents on other machines (or scheduled Bedrock agents) can resume where the last agent left off.
|
|
76
|
+
|
|
41
77
|
## The RPA Lifecycle
|
|
42
78
|
|
|
43
79
|
This is the complete flow from zero to production automation. The agent handles each phase using MCP tools and skills.
|
|
@@ -310,24 +346,36 @@ Agents are autonomous runners that execute tasks on VMs using MCP tools. After b
|
|
|
310
346
|
### Workspace Sync
|
|
311
347
|
|
|
312
348
|
|
|
313
|
-
| Tool | What it does
|
|
314
|
-
| --------------------------------- |
|
|
315
|
-
| `clone_workspace` | Full workspace clone: workflows + skills + issues + metadata
|
|
316
|
-
| `init_project` | Scaffold a git-ready project from a workspace (workflows only)
|
|
317
|
-
| `pull_workflow` / `push_workflow` | Sync individual workflows
|
|
318
|
-
| `pull_all` / `push_changed` | Bulk sync
|
|
319
|
-
| `sync_status` | Diff local vs deployed
|
|
349
|
+
| Tool | What it does |
|
|
350
|
+
| --------------------------------- | ------------------------------------------------------------------------------ |
|
|
351
|
+
| `clone_workspace` | Full workspace clone: workflows + skills + issues + metadata. Defaults to configured workspaces root if outputDir omitted. |
|
|
352
|
+
| `init_project` | Scaffold a git-ready project from a workspace (workflows only) |
|
|
353
|
+
| `pull_workflow` / `push_workflow` | Sync individual workflows |
|
|
354
|
+
| `pull_all` / `push_changed` | Bulk sync |
|
|
355
|
+
| `sync_status` | Diff local vs deployed |
|
|
356
|
+
| `set_workspaces_root` | Set default root directory for cloning workspaces (`~/.minicor/config.json`) |
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
### Session Lifecycle
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
| Tool | What it does |
|
|
363
|
+
| --------------------- | --------------------------------------------------------------------------------------------- |
|
|
364
|
+
| `session_start` | Load full workspace context + begin session tracking. Call FIRST in a workspace clone. |
|
|
365
|
+
| `session_checkpoint` | Save progress: writes `.minicor/session.json` + syncs `[Workspace:Session]` issue. |
|
|
366
|
+
| `session_end` | End session: persist final state, sync to platform, optionally update context.md. |
|
|
320
367
|
|
|
321
368
|
|
|
322
369
|
## Prompts
|
|
323
370
|
|
|
324
371
|
|
|
325
|
-
| Prompt
|
|
326
|
-
|
|
|
327
|
-
| `build-rpa-workflow`
|
|
328
|
-
| `debug-workflow-execution`
|
|
329
|
-
| `minicor-workflow-guide`
|
|
330
|
-
| `2fa-workflow-guide`
|
|
372
|
+
| Prompt | What it does |
|
|
373
|
+
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
374
|
+
| `build-rpa-workflow` | Guided automation building with POC/production mode. Loads skills, iterative build loop, per-step Minicor testing, optional hardening. |
|
|
375
|
+
| `debug-workflow-execution` | Analyze a failed execution with VM-aware debugging and replay |
|
|
376
|
+
| `minicor-workflow-guide` | Full workflow specification: step types, data access, keywords, libraries |
|
|
377
|
+
| `2fa-workflow-guide` | Handling 2FA in workflows: provisioning channels, TOTP secrets, auto-resolving OTP codes |
|
|
378
|
+
| `workspace-session-guide` | Returns AGENTS.md rules and session state for any workspace clone |
|
|
331
379
|
|
|
332
380
|
|
|
333
381
|
The `build-rpa-workflow` prompt accepts a `mode` parameter:
|
|
@@ -363,27 +411,24 @@ npm test
|
|
|
363
411
|
|
|
364
412
|
```
|
|
365
413
|
src/
|
|
366
|
-
index.ts — CLI MCP entry (stdio transport, token management)
|
|
414
|
+
index.ts — CLI MCP entry (stdio transport, token management, disconnect hooks)
|
|
367
415
|
lib.ts — Embeddable server factory (in-process, no side effects)
|
|
416
|
+
bootstrap.ts — CLI to generate harness configs (CLAUDE.md, .cursor/rules, etc.)
|
|
417
|
+
config.ts — User config (~/.minicor/config.json) — workspacesRoot, etc.
|
|
418
|
+
state.ts — Shared mutable state (VM connections, active session tracking)
|
|
368
419
|
skills.ts — Skill loader, parser, index builder
|
|
369
|
-
skills-service-client.ts — HTTP client for skills service
|
|
370
|
-
seed-skills.ts — CLI to seed skills service from bundled files
|
|
371
420
|
tools/
|
|
421
|
+
session.ts — session_start, session_checkpoint, session_end, auto-checkpoint
|
|
372
422
|
skills.ts — list_skills, get_skill, save_skill, generate_skill
|
|
423
|
+
sync-tools.ts — clone_workspace, init_project, pull/push, set_workspaces_root
|
|
373
424
|
vm.ts, vm-rpa.ts — VM and RPA tools
|
|
374
425
|
core.ts — Workflows, flows, executions
|
|
375
|
-
sync-tools.ts — clone_workspace, init_project, pull/push
|
|
376
426
|
...
|
|
377
427
|
prompts/
|
|
428
|
+
workspace-session.ts — Workspace session guide prompt
|
|
378
429
|
build-rpa.ts — Guided RPA building (POC/production modes)
|
|
379
430
|
...
|
|
380
431
|
skills/
|
|
381
432
|
general/ — Bundled skill files (shipped with npm package)
|
|
382
|
-
rpa-testing-workflow.md
|
|
383
|
-
cdp-browser-automation.md
|
|
384
|
-
desktop-uiautomation.md
|
|
385
|
-
data-extraction-strategies.md
|
|
386
|
-
data-passing-between-steps.md
|
|
387
|
-
state-verification.md
|
|
388
433
|
```
|
|
389
434
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"laminar-client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/laminar-client.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { LaminarClient } from "../laminar-client.js";
|
|
3
|
+
import { TokenProvider } from "../token-provider.js";
|
|
4
|
+
let fetchMock;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
fetchMock = vi.fn();
|
|
7
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
8
|
+
});
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
vi.restoreAllMocks();
|
|
11
|
+
});
|
|
12
|
+
function jsonResponse(status, body) {
|
|
13
|
+
return new Response(JSON.stringify(body), {
|
|
14
|
+
status,
|
|
15
|
+
headers: { "Content-Type": "application/json" },
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
describe("LaminarClient 401 retry", () => {
|
|
19
|
+
it("retries once on 401 when tokenProvider is available", async () => {
|
|
20
|
+
const refreshFn = vi.fn().mockResolvedValue({
|
|
21
|
+
token: "tok-new",
|
|
22
|
+
expiresAt: Date.now() + 3600_000,
|
|
23
|
+
});
|
|
24
|
+
const provider = new TokenProvider("tok-old", Date.now() - 1000, refreshFn);
|
|
25
|
+
const client = new LaminarClient({ type: "bearer", token: "tok-old" }, "https://api.test.com", provider);
|
|
26
|
+
fetchMock
|
|
27
|
+
.mockResolvedValueOnce(new Response("Unauthorized", { status: 401 }))
|
|
28
|
+
.mockResolvedValueOnce(jsonResponse(200, { id: 1 }));
|
|
29
|
+
const result = await client.getMe();
|
|
30
|
+
expect(result).toEqual({ id: 1 });
|
|
31
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
32
|
+
expect(refreshFn).toHaveBeenCalledOnce();
|
|
33
|
+
});
|
|
34
|
+
it("throws on 401 without tokenProvider (existing behavior)", async () => {
|
|
35
|
+
const client = new LaminarClient({ type: "bearer", token: "tok-old" }, "https://api.test.com");
|
|
36
|
+
fetchMock.mockResolvedValueOnce(new Response("Unauthorized", { status: 401 }));
|
|
37
|
+
await expect(client.getMe()).rejects.toThrow("failed (401)");
|
|
38
|
+
expect(fetchMock).toHaveBeenCalledOnce();
|
|
39
|
+
});
|
|
40
|
+
it("throws if retry also returns 401", async () => {
|
|
41
|
+
const refreshFn = vi.fn().mockResolvedValue({
|
|
42
|
+
token: "tok-still-bad",
|
|
43
|
+
expiresAt: Date.now() + 3600_000,
|
|
44
|
+
});
|
|
45
|
+
const provider = new TokenProvider("tok-old", Date.now() - 1000, refreshFn);
|
|
46
|
+
const client = new LaminarClient({ type: "bearer", token: "tok-old" }, "https://api.test.com", provider);
|
|
47
|
+
fetchMock
|
|
48
|
+
.mockResolvedValueOnce(new Response("Unauthorized", { status: 401 }))
|
|
49
|
+
.mockResolvedValueOnce(new Response("Unauthorized", { status: 401 }));
|
|
50
|
+
await expect(client.getMe()).rejects.toThrow("failed (401)");
|
|
51
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
52
|
+
});
|
|
53
|
+
it("uses refreshed token in the retry request header", async () => {
|
|
54
|
+
const refreshFn = vi.fn().mockResolvedValue({
|
|
55
|
+
token: "tok-fresh",
|
|
56
|
+
expiresAt: Date.now() + 3600_000,
|
|
57
|
+
});
|
|
58
|
+
const provider = new TokenProvider("tok-stale", Date.now() - 1000, refreshFn);
|
|
59
|
+
const client = new LaminarClient({ type: "bearer", token: "ignored" }, "https://api.test.com", provider);
|
|
60
|
+
fetchMock
|
|
61
|
+
.mockResolvedValueOnce(new Response("Unauthorized", { status: 401 }))
|
|
62
|
+
.mockResolvedValueOnce(jsonResponse(200, { ok: true }));
|
|
63
|
+
await client.listWorkspaces();
|
|
64
|
+
const firstCall = fetchMock.mock.calls[0][1].headers;
|
|
65
|
+
expect(firstCall["Authorization"]).toBe("Bearer tok-stale");
|
|
66
|
+
const retryCall = fetchMock.mock.calls[1][1].headers;
|
|
67
|
+
expect(retryCall["Authorization"]).toBe("Bearer tok-fresh");
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=laminar-client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"laminar-client.test.js","sourceRoot":"","sources":["../../src/__tests__/laminar-client.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-provider.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/token-provider.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { TokenProvider } from "../token-provider.js";
|
|
3
|
+
describe("TokenProvider", () => {
|
|
4
|
+
it("returns the initial token", () => {
|
|
5
|
+
const provider = new TokenProvider("tok-1", Date.now() + 60_000);
|
|
6
|
+
expect(provider.getToken()).toBe("tok-1");
|
|
7
|
+
});
|
|
8
|
+
it("refreshes the token and updates state", async () => {
|
|
9
|
+
const refreshFn = vi.fn().mockResolvedValue({
|
|
10
|
+
token: "tok-2",
|
|
11
|
+
expiresAt: Date.now() + 3600_000,
|
|
12
|
+
});
|
|
13
|
+
const provider = new TokenProvider("tok-1", Date.now() - 1000, refreshFn);
|
|
14
|
+
const newToken = await provider.refreshToken();
|
|
15
|
+
expect(newToken).toBe("tok-2");
|
|
16
|
+
expect(provider.getToken()).toBe("tok-2");
|
|
17
|
+
expect(refreshFn).toHaveBeenCalledOnce();
|
|
18
|
+
});
|
|
19
|
+
it("fires onTokenRefreshed callback", async () => {
|
|
20
|
+
const refreshFn = vi.fn().mockResolvedValue({
|
|
21
|
+
token: "tok-2",
|
|
22
|
+
expiresAt: Date.now() + 3600_000,
|
|
23
|
+
});
|
|
24
|
+
const provider = new TokenProvider("tok-1", Date.now() - 1000, refreshFn);
|
|
25
|
+
const hook = vi.fn();
|
|
26
|
+
provider.onTokenRefreshed = hook;
|
|
27
|
+
await provider.refreshToken();
|
|
28
|
+
expect(hook).toHaveBeenCalledWith("tok-2");
|
|
29
|
+
});
|
|
30
|
+
it("deduplicates concurrent refresh calls (mutex)", async () => {
|
|
31
|
+
let resolveRefresh;
|
|
32
|
+
const refreshFn = vi.fn().mockImplementation(() => new Promise((r) => { resolveRefresh = r; }));
|
|
33
|
+
const provider = new TokenProvider("tok-1", Date.now() - 1000, refreshFn);
|
|
34
|
+
const p1 = provider.refreshToken();
|
|
35
|
+
const p2 = provider.refreshToken();
|
|
36
|
+
resolveRefresh({ token: "tok-2", expiresAt: Date.now() + 3600_000 });
|
|
37
|
+
const [r1, r2] = await Promise.all([p1, p2]);
|
|
38
|
+
expect(r1).toBe("tok-2");
|
|
39
|
+
expect(r2).toBe("tok-2");
|
|
40
|
+
expect(refreshFn).toHaveBeenCalledOnce();
|
|
41
|
+
});
|
|
42
|
+
it("throws when refresh returns null", async () => {
|
|
43
|
+
const refreshFn = vi.fn().mockResolvedValue(null);
|
|
44
|
+
const provider = new TokenProvider("tok-1", Date.now() - 1000, refreshFn);
|
|
45
|
+
await expect(provider.refreshToken()).rejects.toThrow("Token refresh returned null");
|
|
46
|
+
expect(provider.getToken()).toBe("tok-1");
|
|
47
|
+
});
|
|
48
|
+
it("throws when no refresh function is configured", async () => {
|
|
49
|
+
const provider = new TokenProvider("tok-1", Date.now() - 1000);
|
|
50
|
+
await expect(provider.refreshToken()).rejects.toThrow("No refresh function configured");
|
|
51
|
+
});
|
|
52
|
+
it("allows a new refresh after a previous one completes", async () => {
|
|
53
|
+
let callCount = 0;
|
|
54
|
+
const refreshFn = vi.fn().mockImplementation(async () => {
|
|
55
|
+
callCount++;
|
|
56
|
+
return { token: `tok-${callCount + 1}`, expiresAt: Date.now() + 3600_000 };
|
|
57
|
+
});
|
|
58
|
+
const provider = new TokenProvider("tok-1", Date.now() - 1000, refreshFn);
|
|
59
|
+
await provider.refreshToken();
|
|
60
|
+
expect(provider.getToken()).toBe("tok-2");
|
|
61
|
+
await provider.refreshToken();
|
|
62
|
+
expect(provider.getToken()).toBe("tok-3");
|
|
63
|
+
expect(refreshFn).toHaveBeenCalledTimes(2);
|
|
64
|
+
});
|
|
65
|
+
it("succeeds even if onTokenRefreshed callback throws", async () => {
|
|
66
|
+
const refreshFn = vi.fn().mockResolvedValue({
|
|
67
|
+
token: "tok-2",
|
|
68
|
+
expiresAt: Date.now() + 3600_000,
|
|
69
|
+
});
|
|
70
|
+
const provider = new TokenProvider("tok-1", Date.now() - 1000, refreshFn);
|
|
71
|
+
provider.onTokenRefreshed = () => { throw new Error("disk write failed"); };
|
|
72
|
+
const result = await provider.refreshToken();
|
|
73
|
+
expect(result).toBe("tok-2");
|
|
74
|
+
expect(provider.getToken()).toBe("tok-2");
|
|
75
|
+
});
|
|
76
|
+
it("isExpiringSoon returns true when token is about to expire", () => {
|
|
77
|
+
const provider = new TokenProvider("tok-1", Date.now() + 60_000);
|
|
78
|
+
expect(provider.isExpiringSoon(120_000)).toBe(true);
|
|
79
|
+
expect(provider.isExpiringSoon(30_000)).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=token-provider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-provider.test.js","sourceRoot":"","sources":["../../src/__tests__/token-provider.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Bootstrap CLI — generates harness-specific config files for a Minicor workspace clone.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* minicor-bootstrap claude-code [--dir <workspace-dir>]
|
|
7
|
+
* minicor-bootstrap cursor [--dir <workspace-dir>]
|
|
8
|
+
* minicor-bootstrap generic [--dir <workspace-dir>]
|
|
9
|
+
* minicor-bootstrap all [--dir <workspace-dir>]
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Bootstrap CLI — generates harness-specific config files for a Minicor workspace clone.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* minicor-bootstrap claude-code [--dir <workspace-dir>]
|
|
7
|
+
* minicor-bootstrap cursor [--dir <workspace-dir>]
|
|
8
|
+
* minicor-bootstrap generic [--dir <workspace-dir>]
|
|
9
|
+
* minicor-bootstrap all [--dir <workspace-dir>]
|
|
10
|
+
*/
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
function resolveDir(args) {
|
|
14
|
+
const idx = args.indexOf("--dir");
|
|
15
|
+
if (idx !== -1 && args[idx + 1]) {
|
|
16
|
+
return path.resolve(args[idx + 1]);
|
|
17
|
+
}
|
|
18
|
+
return process.cwd();
|
|
19
|
+
}
|
|
20
|
+
function loadWorkspaceInfo(dir) {
|
|
21
|
+
const manifestPath = path.join(dir, "minicor.json");
|
|
22
|
+
if (!fs.existsSync(manifestPath)) {
|
|
23
|
+
console.error(`Error: ${dir} is not a Minicor workspace clone (no minicor.json found).`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
27
|
+
let name = "Minicor Workspace";
|
|
28
|
+
let region;
|
|
29
|
+
const wsPath = path.join(dir, ".minicor", "workspace.json");
|
|
30
|
+
if (fs.existsSync(wsPath)) {
|
|
31
|
+
const ws = JSON.parse(fs.readFileSync(wsPath, "utf-8"));
|
|
32
|
+
name = ws.name || name;
|
|
33
|
+
region = ws.region;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
dir,
|
|
37
|
+
name,
|
|
38
|
+
workspaceId: manifest.workspace ?? 0,
|
|
39
|
+
region,
|
|
40
|
+
hasAgentsMd: fs.existsSync(path.join(dir, "AGENTS.md")),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function bootstrapClaudeCode(info) {
|
|
44
|
+
const claudeMd = `# ${info.name} — Minicor Workspace
|
|
45
|
+
|
|
46
|
+
This workspace is a Minicor workspace clone (workspace **${info.workspaceId}**).
|
|
47
|
+
|
|
48
|
+
## CRITICAL: First Action
|
|
49
|
+
|
|
50
|
+
Call \`session_start(directory: "${info.dir}")\` as your FIRST action in every session.
|
|
51
|
+
It returns the workspace rules (AGENTS.md), prior session state for resuming, and all
|
|
52
|
+
context you need. Follow the phase loop it describes.
|
|
53
|
+
|
|
54
|
+
## Session Management
|
|
55
|
+
|
|
56
|
+
- **Resume**: If session_start returns a prior session, resume from where the last agent left off.
|
|
57
|
+
Do NOT start over.
|
|
58
|
+
- **Checkpoint**: Call \`session_checkpoint\` between phases or after significant progress.
|
|
59
|
+
- **End**: Call \`session_end\` before ending your work. Other agents depend on this to resume.
|
|
60
|
+
|
|
61
|
+
## Key Rules
|
|
62
|
+
|
|
63
|
+
- Use \`create_rpa_flow\` for RPA steps, never \`create_flow\`
|
|
64
|
+
- Follow the \`rpa-testing-workflow\` skill for testing
|
|
65
|
+
- Fix failures through the executor, NOT \`vm_execute_script\`
|
|
66
|
+
- Update \`.minicor/context.md\` when you learn something new
|
|
67
|
+
- Create/update \`[Workspace:Session]\` and \`[Workspace:Context]\` issues
|
|
68
|
+
`;
|
|
69
|
+
const claudeMdPath = path.join(info.dir, "CLAUDE.md");
|
|
70
|
+
fs.writeFileSync(claudeMdPath, claudeMd, "utf-8");
|
|
71
|
+
console.log(` Created ${claudeMdPath}`);
|
|
72
|
+
const claudeDir = path.join(info.dir, ".claude");
|
|
73
|
+
if (!fs.existsSync(claudeDir))
|
|
74
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
75
|
+
const settingsPath = path.join(claudeDir, "settings.local.json");
|
|
76
|
+
let settings = {};
|
|
77
|
+
if (fs.existsSync(settingsPath)) {
|
|
78
|
+
try {
|
|
79
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
settings = {};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (!settings.permissions)
|
|
86
|
+
settings.permissions = {};
|
|
87
|
+
if (!settings.permissions.allow)
|
|
88
|
+
settings.permissions.allow = [];
|
|
89
|
+
const requiredPerms = [
|
|
90
|
+
"mcp__minicor__session_start",
|
|
91
|
+
"mcp__minicor__session_checkpoint",
|
|
92
|
+
"mcp__minicor__session_end",
|
|
93
|
+
"mcp__minicor__get_workspace_context",
|
|
94
|
+
"mcp__minicor__list_workspaces",
|
|
95
|
+
"mcp__minicor__list_workflows",
|
|
96
|
+
"mcp__minicor__get_workflow",
|
|
97
|
+
"mcp__minicor__get_workflow_overview",
|
|
98
|
+
"mcp__minicor__list_executions",
|
|
99
|
+
"mcp__minicor__get_execution",
|
|
100
|
+
"mcp__minicor__get_execution_status",
|
|
101
|
+
"mcp__minicor__get_execution_result",
|
|
102
|
+
"mcp__minicor__execute_workflow",
|
|
103
|
+
"mcp__minicor__execute_workflow_async",
|
|
104
|
+
"mcp__minicor__create_rpa_flow",
|
|
105
|
+
"mcp__minicor__debug_rpa_step",
|
|
106
|
+
"mcp__minicor__vm_connect",
|
|
107
|
+
"mcp__minicor__vm_disconnect",
|
|
108
|
+
"mcp__minicor__vm_status",
|
|
109
|
+
"mcp__minicor__vm_screenshot",
|
|
110
|
+
"mcp__minicor__vm_execute_script",
|
|
111
|
+
"mcp__minicor__vm_inspect_ui",
|
|
112
|
+
"mcp__minicor__vm_list",
|
|
113
|
+
"mcp__minicor__list_issues",
|
|
114
|
+
"mcp__minicor__get_issue",
|
|
115
|
+
"mcp__minicor__create_issue",
|
|
116
|
+
"mcp__minicor__update_issue",
|
|
117
|
+
"mcp__minicor__list_skills",
|
|
118
|
+
"mcp__minicor__get_skill",
|
|
119
|
+
"mcp__minicor__save_skill",
|
|
120
|
+
"mcp__minicor__generate_skill",
|
|
121
|
+
"mcp__minicor__push_changed",
|
|
122
|
+
"mcp__minicor__pull_all",
|
|
123
|
+
"mcp__minicor__sync_status",
|
|
124
|
+
"mcp__minicor__create_agent",
|
|
125
|
+
"mcp__minicor__list_agents",
|
|
126
|
+
"mcp__minicor__test_workflow_step",
|
|
127
|
+
"mcp__minicor__diagnose_execution",
|
|
128
|
+
];
|
|
129
|
+
const existing = new Set(settings.permissions.allow);
|
|
130
|
+
for (const perm of requiredPerms) {
|
|
131
|
+
if (!existing.has(perm)) {
|
|
132
|
+
settings.permissions.allow.push(perm);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
136
|
+
console.log(` Updated ${settingsPath}`);
|
|
137
|
+
}
|
|
138
|
+
function bootstrapCursor(info) {
|
|
139
|
+
const cursorDir = path.join(info.dir, ".cursor", "rules");
|
|
140
|
+
if (!fs.existsSync(cursorDir))
|
|
141
|
+
fs.mkdirSync(cursorDir, { recursive: true });
|
|
142
|
+
const mdc = `---
|
|
143
|
+
description: Minicor workspace clone
|
|
144
|
+
alwaysApply: true
|
|
145
|
+
---
|
|
146
|
+
You are in a Minicor workspace clone (${info.name}). Call \`session_start(directory: "${info.dir}")\` as your FIRST action. It returns AGENTS.md, workspace metadata, VMs, skills, session state, and any prior context. If there is an active session, resume from where the last agent left off. Before ending your session, call \`session_end()\` to persist progress and sync it to a [Workspace:Session] issue.
|
|
147
|
+
`;
|
|
148
|
+
const mdcPath = path.join(cursorDir, "workspace.mdc");
|
|
149
|
+
fs.writeFileSync(mdcPath, mdc, "utf-8");
|
|
150
|
+
console.log(` Created ${mdcPath}`);
|
|
151
|
+
}
|
|
152
|
+
function bootstrapGeneric(info) {
|
|
153
|
+
const minicorDir = path.join(info.dir, ".minicor");
|
|
154
|
+
if (!fs.existsSync(minicorDir))
|
|
155
|
+
fs.mkdirSync(minicorDir, { recursive: true });
|
|
156
|
+
const prompt = `# ${info.name} — System Prompt
|
|
157
|
+
|
|
158
|
+
You are working in a Minicor workspace clone (workspace ${info.workspaceId}).
|
|
159
|
+
|
|
160
|
+
## Required First Action
|
|
161
|
+
|
|
162
|
+
Call \`session_start(directory: "${info.dir}")\` as your FIRST action.
|
|
163
|
+
It returns:
|
|
164
|
+
- AGENTS.md with the full agent phase loop
|
|
165
|
+
- Workspace metadata (VMs, agents, skills)
|
|
166
|
+
- Prior session state for resuming
|
|
167
|
+
- Context from previous agent runs
|
|
168
|
+
|
|
169
|
+
## Session Lifecycle
|
|
170
|
+
|
|
171
|
+
1. **Start**: \`session_start\` — loads context and begins tracking
|
|
172
|
+
2. **Checkpoint**: \`session_checkpoint\` — saves progress between phases
|
|
173
|
+
3. **End**: \`session_end\` — persists final state, syncs to platform
|
|
174
|
+
|
|
175
|
+
## Key Rules
|
|
176
|
+
|
|
177
|
+
- Follow the phase loop from AGENTS.md: gather-context → orient → scope → build → test → harden → learn
|
|
178
|
+
- If a prior session exists, resume from where it left off
|
|
179
|
+
- Use \`create_rpa_flow\` for RPA steps (never \`create_flow\`)
|
|
180
|
+
- Always call \`session_end\` before finishing
|
|
181
|
+
`;
|
|
182
|
+
const promptPath = path.join(minicorDir, "system-prompt.md");
|
|
183
|
+
fs.writeFileSync(promptPath, prompt, "utf-8");
|
|
184
|
+
console.log(` Created ${promptPath}`);
|
|
185
|
+
}
|
|
186
|
+
function showHelp() {
|
|
187
|
+
console.log(`
|
|
188
|
+
minicor-bootstrap — Generate harness-specific config for a Minicor workspace clone
|
|
189
|
+
|
|
190
|
+
Usage:
|
|
191
|
+
minicor-bootstrap <target> [--dir <workspace-dir>]
|
|
192
|
+
|
|
193
|
+
Targets:
|
|
194
|
+
claude-code Generate CLAUDE.md + .claude/settings.local.json
|
|
195
|
+
cursor Generate .cursor/rules/workspace.mdc
|
|
196
|
+
generic Generate .minicor/system-prompt.md
|
|
197
|
+
all Generate all of the above
|
|
198
|
+
|
|
199
|
+
Options:
|
|
200
|
+
--dir <path> Workspace directory (default: current directory)
|
|
201
|
+
|
|
202
|
+
Examples:
|
|
203
|
+
minicor-bootstrap all
|
|
204
|
+
minicor-bootstrap claude-code --dir /path/to/workspace
|
|
205
|
+
minicor-bootstrap cursor --dir ./my-workspace
|
|
206
|
+
`);
|
|
207
|
+
}
|
|
208
|
+
async function main() {
|
|
209
|
+
const args = process.argv.slice(2);
|
|
210
|
+
const target = args[0];
|
|
211
|
+
if (!target || target === "help" || target === "--help") {
|
|
212
|
+
showHelp();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const dir = resolveDir(args);
|
|
216
|
+
const info = loadWorkspaceInfo(dir);
|
|
217
|
+
console.log(`Bootstrapping "${info.name}" (workspace ${info.workspaceId}) at ${dir}\n`);
|
|
218
|
+
switch (target) {
|
|
219
|
+
case "claude-code":
|
|
220
|
+
bootstrapClaudeCode(info);
|
|
221
|
+
break;
|
|
222
|
+
case "cursor":
|
|
223
|
+
bootstrapCursor(info);
|
|
224
|
+
break;
|
|
225
|
+
case "generic":
|
|
226
|
+
bootstrapGeneric(info);
|
|
227
|
+
break;
|
|
228
|
+
case "all":
|
|
229
|
+
bootstrapClaudeCode(info);
|
|
230
|
+
bootstrapCursor(info);
|
|
231
|
+
bootstrapGeneric(info);
|
|
232
|
+
break;
|
|
233
|
+
default:
|
|
234
|
+
console.error(`Unknown target: ${target}`);
|
|
235
|
+
showHelp();
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
console.log("\nDone. Re-run after updating AGENTS.md to regenerate configs.");
|
|
239
|
+
}
|
|
240
|
+
main().catch((err) => {
|
|
241
|
+
console.error(`Error: ${err.message}`);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
});
|
|
244
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Configuration helpers for Minicor MCP.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Stores user preferences in ~/.minicor/config.json:
|
|
5
|
+
* - workspacesRoot: default directory for cloning workspaces
|
|
6
6
|
*/
|
|
7
7
|
export interface ServiceConfig {
|
|
8
|
+
/** Default root directory for cloning workspaces (e.g. ~/laminar/customers) */
|
|
9
|
+
workspacesRoot?: string;
|
|
8
10
|
}
|
|
9
11
|
export declare function loadServiceConfig(): ServiceConfig;
|
|
10
|
-
export declare function saveServiceConfig(update: ServiceConfig): void;
|
|
12
|
+
export declare function saveServiceConfig(update: Partial<ServiceConfig>): void;
|
|
13
|
+
export declare function getWorkspacesRoot(): string | undefined;
|
|
11
14
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,aAAa;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,aAAa;IAC5B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,iBAAiB,IAAI,aAAa,CAQjD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,QAU/D;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAGtD"}
|