@octane-xplat/mcp 0.15.0 → 0.16.1

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 (67) hide show
  1. package/README.md +9 -5
  2. package/dist/_virtual/_rolldown/runtime.js +27 -0
  3. package/dist/actions/bridge.js +1 -0
  4. package/dist/context.js +0 -0
  5. package/dist/contracts/actions.js +1 -0
  6. package/dist/contracts/boundaries.js +1 -0
  7. package/dist/contracts/capabilities.js +1 -0
  8. package/dist/contracts/code.js +1 -0
  9. package/dist/contracts/errors.js +8 -0
  10. package/dist/contracts/evidence.js +8 -0
  11. package/dist/contracts/identity.js +8 -0
  12. package/dist/contracts/index.js +1 -0
  13. package/dist/contracts/inspection.js +1 -0
  14. package/dist/contracts/policy.js +8 -0
  15. package/dist/contracts/sessions.js +1 -0
  16. package/dist/contracts/status.js +1 -0
  17. package/dist/discovery.js +8 -0
  18. package/dist/docs.js +63 -0
  19. package/dist/inspection/service.js +3 -0
  20. package/dist/inspection/tools.js +43 -0
  21. package/dist/runtime/logs.js +1 -0
  22. package/dist/runtime/process.js +1 -0
  23. package/dist/runtime/service.js +1 -0
  24. package/dist/runtime/targets.js +1 -0
  25. package/dist/runtime/tools.js +119 -0
  26. package/dist/server.js +324 -0
  27. package/dist/status.js +8 -0
  28. package/dist/xplat-mcp.js +68 -0
  29. package/package.json +18 -12
  30. package/src/context.ts +108 -0
  31. package/src/{docs.mjs → docs.ts} +31 -26
  32. package/src/inspection/{service.mjs → service.ts} +1 -1
  33. package/src/inspection/{tools.mjs → tools.ts} +13 -5
  34. package/src/runtime/{tools.mjs → tools.ts} +16 -6
  35. package/src/{server.mjs → server.ts} +48 -33
  36. package/src/{xplat-mcp.mjs → xplat-mcp.ts} +21 -10
  37. /package/src/actions/{bridge.mjs → bridge.ts} +0 -0
  38. /package/src/contracts/{actions.mjs → actions.ts} +0 -0
  39. /package/src/contracts/{boundaries.mjs → boundaries.ts} +0 -0
  40. /package/src/contracts/{capabilities.mjs → capabilities.ts} +0 -0
  41. /package/src/contracts/{code.mjs → code.ts} +0 -0
  42. /package/src/contracts/{errors.mjs → errors.ts} +0 -0
  43. /package/src/contracts/{evidence.mjs → evidence.ts} +0 -0
  44. /package/src/contracts/{identity.mjs → identity.ts} +0 -0
  45. /package/src/contracts/{index.mjs → index.ts} +0 -0
  46. /package/src/contracts/{inspection.mjs → inspection.ts} +0 -0
  47. /package/src/contracts/{policy.mjs → policy.ts} +0 -0
  48. /package/src/contracts/{sessions.mjs → sessions.ts} +0 -0
  49. /package/src/contracts/{status.mjs → status.ts} +0 -0
  50. /package/src/{discovery.mjs → discovery.ts} +0 -0
  51. /package/src/runtime/{logs.mjs → logs.ts} +0 -0
  52. /package/src/runtime/{process.mjs → process.ts} +0 -0
  53. /package/src/runtime/{service.mjs → service.ts} +0 -0
  54. /package/src/runtime/{targets.mjs → targets.ts} +0 -0
  55. /package/src/{status.mjs → status.ts} +0 -0
  56. /package/{src → types}/contracts/actions.d.ts +0 -0
  57. /package/{src → types}/contracts/boundaries.d.ts +0 -0
  58. /package/{src → types}/contracts/capabilities.d.ts +0 -0
  59. /package/{src → types}/contracts/code.d.ts +0 -0
  60. /package/{src → types}/contracts/errors.d.ts +0 -0
  61. /package/{src → types}/contracts/evidence.d.ts +0 -0
  62. /package/{src → types}/contracts/identity.d.ts +0 -0
  63. /package/{src → types}/contracts/index.d.ts +0 -0
  64. /package/{src → types}/contracts/inspection.d.ts +0 -0
  65. /package/{src → types}/contracts/policy.d.ts +0 -0
  66. /package/{src → types}/contracts/sessions.d.ts +0 -0
  67. /package/{src → types}/contracts/status.d.ts +0 -0
package/README.md CHANGED
@@ -38,7 +38,9 @@ A one-off run without a devDependency also works:
38
38
  pnpm dlx @octane-xplat/mcp --workspace /path/to/app-workspace
39
39
  ```
40
40
 
41
- For development inside this repository:
41
+ For development inside this repository — `start` runs the TypeScript source
42
+ directly (Node ≥22.18 strips types); `test` and `prepack` run `vite build` so
43
+ the checked and packed surface is the emitted `dist/`:
42
44
 
43
45
  ```sh
44
46
  pnpm --filter @octane-xplat/mcp start -- --workspace <path>
@@ -122,12 +124,14 @@ The service layer lives in `packages/cli/src/mcp/` — the `xplat` CLI projects
122
124
  the same contracts through its agent commands (`xplat catalog --json` is the
123
125
  entry point). `packages/mcp/src/` holds the stdio transport adapter: tool
124
126
  registration wraps the shared services, and the published `.d.ts` contract
125
- surface stays here.
127
+ surface stays here under `types/contracts/`. Sources are TypeScript; `pnpm
128
+ build` emits the runnable ESM to `dist/` (`pnpm test` builds first).
126
129
 
127
130
  ## Contract surface (`@octane-xplat/mcp/contracts/*`)
128
131
 
129
- Later work packages integrate against these modules; the `.d.ts` files are the
130
- documented surface and the `.mjs` files carry the runtime values and stores.
132
+ Later work packages integrate against these modules; the `.d.ts` files under
133
+ `types/contracts/` are the documented surface and the compiled `dist/` modules
134
+ carry the runtime values and stores (re-exported from `@octane-xplat/cli`).
131
135
 
132
136
  - `errors` — `ContractErrorCode` vocabulary (`invalid_selection`,
133
137
  `ambiguous_selection`, `permission_denied`, `unsupported_capability`,
@@ -178,7 +182,7 @@ on all six platforms. Adapters (`runtime/adapters/*`) own platform
178
182
  mechanics and always spawn the app's own toolchain — `pnpm exec vite`,
179
183
  `pnpm exec ns run …`, the app's installed `@octane-xplat/cli` dev entry, or
180
184
  its `dev` script — so a session behaves like the app's installed framework
181
- version. `service.mjs` owns the shared contract behavior: explicit
185
+ version. The shared `runtime/service` module owns the contract behavior: explicit
182
186
  app+target binding, `target_busy` contention, job dedupe/cooperative
183
187
  cancel, ownership-safe cleanup, bounded logs, and capability-matrix entries.
184
188
 
@@ -0,0 +1,27 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __exportAll = (all, no_symbols) => {
7
+ let target = {};
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true
11
+ });
12
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ return target;
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
17
+ key = keys[i];
18
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
19
+ get: ((k) => from[k]).bind(null, key),
20
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
21
+ });
22
+ }
23
+ return to;
24
+ };
25
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
26
+ //#endregion
27
+ export { __exportAll, __reExport };
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/actions/bridge";
File without changes
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/contracts/actions";
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/contracts/boundaries";
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/contracts/capabilities";
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/contracts/code";
@@ -0,0 +1,8 @@
1
+ import { __exportAll, __reExport } from "../_virtual/_rolldown/runtime.js";
2
+ export * from "@octane-xplat/cli/mcp/contracts/errors";
3
+ //#region src/contracts/errors.ts
4
+ var errors_exports = /* @__PURE__ */ __exportAll({});
5
+ import * as import__octane_xplat_cli_mcp_contracts_errors from "@octane-xplat/cli/mcp/contracts/errors";
6
+ __reExport(errors_exports, import__octane_xplat_cli_mcp_contracts_errors);
7
+ //#endregion
8
+ export { errors_exports };
@@ -0,0 +1,8 @@
1
+ import { __exportAll, __reExport } from "../_virtual/_rolldown/runtime.js";
2
+ export * from "@octane-xplat/cli/mcp/contracts/evidence";
3
+ //#region src/contracts/evidence.ts
4
+ var evidence_exports = /* @__PURE__ */ __exportAll({});
5
+ import * as import__octane_xplat_cli_mcp_contracts_evidence from "@octane-xplat/cli/mcp/contracts/evidence";
6
+ __reExport(evidence_exports, import__octane_xplat_cli_mcp_contracts_evidence);
7
+ //#endregion
8
+ export { evidence_exports };
@@ -0,0 +1,8 @@
1
+ import { __exportAll, __reExport } from "../_virtual/_rolldown/runtime.js";
2
+ export * from "@octane-xplat/cli/mcp/contracts/identity";
3
+ //#region src/contracts/identity.ts
4
+ var identity_exports = /* @__PURE__ */ __exportAll({});
5
+ import * as import__octane_xplat_cli_mcp_contracts_identity from "@octane-xplat/cli/mcp/contracts/identity";
6
+ __reExport(identity_exports, import__octane_xplat_cli_mcp_contracts_identity);
7
+ //#endregion
8
+ export { identity_exports };
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/contracts/index";
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/contracts/inspection";
@@ -0,0 +1,8 @@
1
+ import { __exportAll, __reExport } from "../_virtual/_rolldown/runtime.js";
2
+ export * from "@octane-xplat/cli/mcp/contracts/policy";
3
+ //#region src/contracts/policy.ts
4
+ var policy_exports = /* @__PURE__ */ __exportAll({});
5
+ import * as import__octane_xplat_cli_mcp_contracts_policy from "@octane-xplat/cli/mcp/contracts/policy";
6
+ __reExport(policy_exports, import__octane_xplat_cli_mcp_contracts_policy);
7
+ //#endregion
8
+ export { policy_exports };
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/contracts/sessions";
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/contracts/status";
@@ -0,0 +1,8 @@
1
+ import { __exportAll, __reExport } from "./_virtual/_rolldown/runtime.js";
2
+ export * from "@octane-xplat/cli/mcp/discovery";
3
+ //#region src/discovery.ts
4
+ var discovery_exports = /* @__PURE__ */ __exportAll({});
5
+ import * as import__octane_xplat_cli_mcp_discovery from "@octane-xplat/cli/mcp/discovery";
6
+ __reExport(discovery_exports, import__octane_xplat_cli_mcp_discovery);
7
+ //#endregion
8
+ export { discovery_exports };
package/dist/docs.js ADDED
@@ -0,0 +1,63 @@
1
+ import { errors_exports } from "./contracts/errors.js";
2
+ import { identity_exports } from "./contracts/identity.js";
3
+ import { status_exports } from "./status.js";
4
+ import { z } from "zod";
5
+ //#region src/docs.ts
6
+ function registerDocsTools(server, context, respond) {
7
+ const run = (method) => async (args) => {
8
+ const permission = context.policy.require("workspace");
9
+ if (!permission.granted) return respond({
10
+ ok: false,
11
+ error: permission.error
12
+ });
13
+ const selection = (0, status_exports.resolveSelection)(context);
14
+ if (selection.state !== "bound") return respond({
15
+ ok: false,
16
+ error: (0, errors_exports.contractError)(selection.state === "ambiguous" ? "ambiguous_selection" : "invalid_selection", "Bind an app with xplat_select_app before retrieving docs.")
17
+ });
18
+ try {
19
+ return respond({
20
+ ok: true,
21
+ data: await context.docs.serviceFor(selection.app)[method](args)
22
+ });
23
+ } catch (error) {
24
+ return respond({
25
+ ok: false,
26
+ error: (0, errors_exports.toContractError)(error)
27
+ });
28
+ }
29
+ };
30
+ server.registerTool("xplat_docs_search", {
31
+ description: "Search the selected app’s installed-version docs. Results include version/snapshot provenance, unavailable packages, conflicts, and separately labeled project guidance.",
32
+ inputSchema: {
33
+ query: z.string().trim().min(1).max(500),
34
+ package: z.string().optional(),
35
+ version: z.string().optional().describe("Explicit comparison version, visibly outside the installed binding."),
36
+ platform: z.enum(identity_exports.PLATFORMS).optional(),
37
+ corpus: z.enum([
38
+ "guide",
39
+ "recipe",
40
+ "design-note",
41
+ "implementation-note"
42
+ ]).optional().default("guide"),
43
+ limit: z.number().int().min(1).max(50).optional()
44
+ }
45
+ }, run("search"));
46
+ server.registerTool("xplat_docs_read", {
47
+ description: "Read a bounded documentation page from a search ref, or package and path, preserving its version binding.",
48
+ inputSchema: {
49
+ ref: z.string().optional(),
50
+ package: z.string().optional(),
51
+ path: z.string().optional(),
52
+ version: z.string().optional(),
53
+ offset: z.number().int().min(0).optional(),
54
+ limit: z.number().int().min(1).max(2e4).optional()
55
+ }
56
+ }, run("read"));
57
+ server.registerTool("xplat_guidance", {
58
+ description: "Retrieve tailored guidance for the selected app’s actual installed package versions.",
59
+ inputSchema: {}
60
+ }, run("guidance"));
61
+ }
62
+ //#endregion
63
+ export { registerDocsTools };
@@ -0,0 +1,3 @@
1
+ import { registerInspectionTools } from "./tools.js";
2
+ import { createInspectionService } from "@octane-xplat/cli/mcp/inspection/service";
3
+ export { createInspectionService, registerInspectionTools };
@@ -0,0 +1,43 @@
1
+ import { z } from "zod";
2
+ //#region src/inspection/tools.ts
3
+ function registerInspectionTools(server, context, respond) {
4
+ const control = z.object({
5
+ kind: z.enum(["id", "testID"]),
6
+ name: z.string().min(1).max(200)
7
+ });
8
+ const run = (method) => async (args) => {
9
+ const data = await context.inspection[method](args);
10
+ return data.error ? respond({
11
+ ok: false,
12
+ error: data.error
13
+ }) : respond({
14
+ ok: true,
15
+ data
16
+ });
17
+ };
18
+ server.registerTool("xplat_inspect", {
19
+ description: "Bounded main-document named DOM hosts in the owned Chromium session. Explicit id/testID selector; duplicates fail. Password/private values are redacted. Includes document/session/build identity and coverage.",
20
+ inputSchema: {
21
+ sessionId: z.string(),
22
+ control: control.optional(),
23
+ offset: z.number().int().min(0).optional(),
24
+ limit: z.number().int().min(1).max(100).optional()
25
+ }
26
+ }, run("inspect"));
27
+ server.registerTool("xplat_interact", {
28
+ description: "Send scoped input to one stable control from an inspected document. dom-event sends a CDP mouse click; os-input sends Space/Enter via the macOS event system to owned headed Chromium. Reserve desktop input for OS actions. Input delivery is not an app assertion.",
29
+ inputSchema: {
30
+ sessionId: z.string(),
31
+ documentId: z.string(),
32
+ control,
33
+ mechanism: z.enum(["dom-event", "os-input"]),
34
+ key: z.enum(["Space", "Enter"]).optional().default("Space")
35
+ }
36
+ }, run("interact"));
37
+ server.registerTool("xplat_screenshot", {
38
+ description: "Capture the owned Chromium viewport only with a current visual-capture grant. Returns a session-scoped artifact and provenance; capability discovery never grants approval.",
39
+ inputSchema: { sessionId: z.string() }
40
+ }, run("screenshot"));
41
+ }
42
+ //#endregion
43
+ export { registerInspectionTools };
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/runtime/logs";
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/runtime/process";
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/runtime/service";
@@ -0,0 +1 @@
1
+ export * from "@octane-xplat/cli/mcp/runtime/targets";
@@ -0,0 +1,119 @@
1
+ import { identity_exports } from "../contracts/identity.js";
2
+ import { z } from "zod";
3
+ //#region src/runtime/tools.ts
4
+ function registerRuntimeTools(server, context, respond) {
5
+ const runtime = context.runtime;
6
+ server.registerTool("xplat_targets", {
7
+ description: "Discover launchable targets for the bound app: simulators, emulators, devices and host targets with availability, missing-toolchain reasons, and session busy/ownership state.",
8
+ inputSchema: { platform: z.enum(identity_exports.PLATFORMS).optional().describe("Limit to one platform") }
9
+ }, async ({ platform }) => {
10
+ const result = await runtime.listTargets({ platform });
11
+ return result.error ? respond({
12
+ ok: false,
13
+ error: result.error
14
+ }) : respond({
15
+ ok: true,
16
+ data: result
17
+ });
18
+ });
19
+ server.registerTool("xplat_build", {
20
+ description: "Build the bound app for one platform as a background job (the same commands `xplat build` runs). Returns a job id — poll xplat_job_status and read output with xplat_logs. Repeating with the same requestKey returns the live job instead of duplicating it.",
21
+ inputSchema: {
22
+ platform: z.enum(identity_exports.PLATFORMS),
23
+ requestKey: z.string().optional().describe("Idempotence key for retries")
24
+ }
25
+ }, async ({ platform, requestKey }) => {
26
+ const result = await runtime.build({
27
+ platform,
28
+ requestKey
29
+ });
30
+ return result.error ? respond({
31
+ ok: false,
32
+ error: result.error
33
+ }) : respond({
34
+ ok: true,
35
+ data: result
36
+ });
37
+ });
38
+ server.registerTool("xplat_launch", {
39
+ description: "Start an owned development session: bind one app to one target and run the platform dev command as a job. The job completes when readiness is confirmed — a failed launch after a successful build reports accurately, and the session keeps the app alive until xplat_session_end.",
40
+ inputSchema: {
41
+ platform: z.enum(identity_exports.PLATFORMS),
42
+ targetId: z.string().optional().describe("Target from xplat_targets; required when several are available"),
43
+ requestKey: z.string().optional().describe("Idempotence key for retries"),
44
+ browserMode: z.enum(["headless", "headed"]).optional().describe("Web only. Headed mode enables scoped OS keyboard input on qualified hosts; reserve desktop input before using it.")
45
+ }
46
+ }, async ({ platform, targetId, requestKey, browserMode }) => {
47
+ const result = await runtime.launch({
48
+ platform,
49
+ targetId,
50
+ requestKey,
51
+ browserMode
52
+ });
53
+ return result.error ? respond({
54
+ ok: false,
55
+ error: result.error
56
+ }) : respond({
57
+ ok: true,
58
+ data: result
59
+ });
60
+ });
61
+ server.registerTool("xplat_attach", {
62
+ description: "Attach to a compatible development session that is already running — never restarts or terminates it. Reports candidates per platform; attach binds a preserved user-owned session.",
63
+ inputSchema: {
64
+ platform: z.enum(identity_exports.PLATFORMS),
65
+ targetId: z.string().optional().describe("Candidate target; required when several are attachable")
66
+ }
67
+ }, async ({ platform, targetId }) => {
68
+ const result = await runtime.attach({
69
+ platform,
70
+ targetId
71
+ });
72
+ return result.error ? respond({
73
+ ok: false,
74
+ error: result.error
75
+ }) : respond({
76
+ ok: true,
77
+ data: result
78
+ });
79
+ });
80
+ server.registerTool("xplat_logs", {
81
+ description: "Bounded, ordered log read for a session or build job. Cursor-paginated: pass the previous nextCursor to continue; truncated/dropped flags reveal gaps and reset marks a restarted capture. A stopped or disconnected session reports its capture as historical.",
82
+ inputSchema: {
83
+ sessionId: z.string().optional(),
84
+ jobId: z.string().optional(),
85
+ cursor: z.number().optional().describe("Continue after this record seq"),
86
+ limit: z.number().int().positive().max(5e3).optional(),
87
+ stream: z.enum([
88
+ "stdout",
89
+ "stderr",
90
+ "lifecycle"
91
+ ]).optional()
92
+ }
93
+ }, async ({ sessionId, jobId, cursor, limit, stream }) => {
94
+ if (!sessionId && !jobId) return respond({
95
+ ok: false,
96
+ error: {
97
+ code: "invalid_selection",
98
+ message: "Pass a sessionId or a jobId.",
99
+ recovery: { action: "Use xplat_sessions or a build/launch job id." }
100
+ }
101
+ });
102
+ const result = runtime.readLogs({
103
+ sessionId,
104
+ jobId,
105
+ cursor,
106
+ limit,
107
+ stream
108
+ });
109
+ return result.error ? respond({
110
+ ok: false,
111
+ error: result.error
112
+ }) : respond({
113
+ ok: true,
114
+ data: result
115
+ });
116
+ });
117
+ }
118
+ //#endregion
119
+ export { registerRuntimeTools };