@octane-xplat/mcp 0.1.0 → 0.16.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/LICENSE +21 -0
- package/README.md +342 -1
- package/dist/_virtual/_rolldown/runtime.js +27 -0
- package/dist/actions/bridge.js +1 -0
- package/dist/context.js +0 -0
- package/dist/contracts/actions.js +1 -0
- package/dist/contracts/boundaries.js +1 -0
- package/dist/contracts/capabilities.js +1 -0
- package/dist/contracts/code.js +1 -0
- package/dist/contracts/errors.js +8 -0
- package/dist/contracts/evidence.js +8 -0
- package/dist/contracts/identity.js +8 -0
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/inspection.js +1 -0
- package/dist/contracts/policy.js +8 -0
- package/dist/contracts/sessions.js +1 -0
- package/dist/contracts/status.js +1 -0
- package/dist/discovery.js +8 -0
- package/dist/docs.js +63 -0
- package/dist/inspection/service.js +3 -0
- package/dist/inspection/tools.js +43 -0
- package/dist/runtime/logs.js +1 -0
- package/dist/runtime/process.js +1 -0
- package/dist/runtime/service.js +1 -0
- package/dist/runtime/targets.js +1 -0
- package/dist/runtime/tools.js +119 -0
- package/dist/server.js +324 -0
- package/dist/status.js +8 -0
- package/dist/xplat-mcp.js +68 -0
- package/package.json +43 -4
- package/src/actions/bridge.ts +2 -0
- package/src/context.ts +108 -0
- package/src/contracts/actions.ts +3 -0
- package/src/contracts/boundaries.ts +3 -0
- package/src/contracts/capabilities.ts +3 -0
- package/src/contracts/code.ts +3 -0
- package/src/contracts/errors.ts +3 -0
- package/src/contracts/evidence.ts +3 -0
- package/src/contracts/identity.ts +3 -0
- package/src/contracts/index.ts +3 -0
- package/src/contracts/inspection.ts +3 -0
- package/src/contracts/policy.ts +3 -0
- package/src/contracts/sessions.ts +3 -0
- package/src/contracts/status.ts +3 -0
- package/src/discovery.ts +2 -0
- package/src/docs.ts +89 -0
- package/src/inspection/service.ts +5 -0
- package/src/inspection/tools.ts +61 -0
- package/src/runtime/logs.ts +2 -0
- package/src/runtime/process.ts +2 -0
- package/src/runtime/service.ts +2 -0
- package/src/runtime/targets.ts +2 -0
- package/src/runtime/tools.ts +136 -0
- package/src/server.ts +580 -0
- package/src/status.ts +2 -0
- package/src/xplat-mcp.ts +96 -0
- package/types/contracts/actions.d.ts +209 -0
- package/types/contracts/boundaries.d.ts +6 -0
- package/types/contracts/capabilities.d.ts +106 -0
- package/types/contracts/code.d.ts +134 -0
- package/types/contracts/errors.d.ts +75 -0
- package/types/contracts/evidence.d.ts +115 -0
- package/types/contracts/identity.d.ts +127 -0
- package/types/contracts/index.d.ts +11 -0
- package/types/contracts/inspection.d.ts +45 -0
- package/types/contracts/policy.d.ts +86 -0
- package/types/contracts/sessions.d.ts +160 -0
- package/types/contracts/status.d.ts +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alec Larson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,344 @@
|
|
|
1
1
|
# @octane-xplat/mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MCP server for agents working on Octane Xplat consumer apps. One entry point
|
|
4
|
+
gives the agent detected project identity, framework versions, guidance,
|
|
5
|
+
capability discovery, and the shared permission / session / evidence contracts
|
|
6
|
+
that every later subsystem (docs, code search, runtime, inspection,
|
|
7
|
+
development actions) plugs into.
|
|
8
|
+
|
|
9
|
+
Published as a normal lockstep package on npm. The qualified surface today is
|
|
10
|
+
the Chromium consumer lane (status/docs/code/build/launch/inspection/
|
|
11
|
+
interaction/development actions); native-platform inspection and input
|
|
12
|
+
adapters report honest `unavailable` results until they are qualified — see
|
|
13
|
+
[Remaining acceptance](#remaining-acceptance).
|
|
14
|
+
|
|
15
|
+
## Install and run
|
|
16
|
+
|
|
17
|
+
Add the server to a consumer app and point the agent's MCP client at the
|
|
18
|
+
installed `xplat-mcp` bin:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
pnpm add -D @octane-xplat/mcp
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"octane-xplat": {
|
|
28
|
+
"command": "xplat-mcp",
|
|
29
|
+
"args": ["--workspace", "/path/to/app-workspace"]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
A one-off run without a devDependency also works:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
pnpm dlx @octane-xplat/mcp --workspace /path/to/app-workspace
|
|
39
|
+
```
|
|
40
|
+
|
|
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/`:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
pnpm --filter @octane-xplat/mcp start -- --workspace <path>
|
|
47
|
+
pnpm --filter @octane-xplat/mcp test
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Transport is stdio; stdout is protocol-clean (diagnostics go to stderr).
|
|
51
|
+
Options: `--workspace` / `XPLAT_MCP_WORKSPACE` (default cwd), `--app` /
|
|
52
|
+
`XPLAT_MCP_APP` (pre-select an app id), `--permissions` /
|
|
53
|
+
`XPLAT_MCP_PERMISSIONS` (comma-separated scope grants), `--evidence-dir` /
|
|
54
|
+
`XPLAT_MCP_EVIDENCE_DIR`.
|
|
55
|
+
|
|
56
|
+
## Tools
|
|
57
|
+
|
|
58
|
+
| Tool | Purpose |
|
|
59
|
+
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
60
|
+
| `xplat_project_status` | Detected apps, selection state, framework version binding, guidance sources, docs/code-index status, declared platforms, runtime prerequisites, capability summary, permissions, boundaries, next steps. |
|
|
61
|
+
| `xplat_select_app` | Explicitly bind an app by id/path/name. Ambiguous or unknown selections fail with the candidate list — the server never picks silently. |
|
|
62
|
+
| `xplat_capability_matrix` | Per-platform capability entries: build, launch, logs, inspection, screenshot, interaction, and the rest are separate rows with status, detail, and alternatives. |
|
|
63
|
+
| `xplat_permissions` | Grant states per scope plus the action-time check result and recovery path. |
|
|
64
|
+
| `xplat_sessions` | Bound sessions: owned vs attached user-owned, state, build identity. |
|
|
65
|
+
| `xplat_targets` | Launchable targets per platform (simulators, devices, host targets) with availability, missing-toolchain reasons, and busy/ownership state. |
|
|
66
|
+
| `xplat_build` | Build the bound app for one platform as a job — same commands `xplat build` runs. `requestKey` dedupes retries. |
|
|
67
|
+
| `xplat_launch` | Owned dev session on one target as a job; completes at confirmed readiness, session owns the processes until `xplat_session_end`. |
|
|
68
|
+
| `xplat_attach` | Bind a compatible already-running dev session (user-owned, preserved). |
|
|
69
|
+
| `xplat_logs` | Bounded ordered logs for a session or build job: cursor, limit, stream filter, truncation/reset indicators, `historical` flag for dead sessions. |
|
|
70
|
+
| `xplat_dev_actions` | The bound app's live development-action registry: instance identity, revision, declarations (contracts, effects, availability). Empty vs disconnected vs no-bridge are distinct states. |
|
|
71
|
+
| `xplat_dev_action_invoke` | Invoke an action against an exact app instance + registry revision. Pre-validates input, availability, grants and queue bounds; returns a job (`requestKey` dedupes retries). |
|
|
72
|
+
| `xplat_dev_action_status` | Invocation status/result — same job data restricted to dev-action jobs, with instance/request identity. |
|
|
73
|
+
| `xplat_job_status` / `xplat_job_cancel` | Bounded job status and cooperative cancellation. |
|
|
74
|
+
| `xplat_session_end` | Ownership-safe cleanup: owned sessions release resources; attached sessions are preserved (our log taps still stop). |
|
|
75
|
+
| `xplat_evidence` | `list` / `retain` / `delete` evidence; retain takes an optional ISO expiration. |
|
|
76
|
+
| `xplat_code_search` | Exact identifier/token search over current source (`mode: 'exact'`), optional local semantic index (`mode: 'semantic'`), or both (`'auto'`). Corpus filters: `app`, `framework`; platform and package filters. |
|
|
77
|
+
| `xplat_code_read` | Bounded read of current source by search ref (`xplat-code://…`) or explicit corpus + path; results carry freshness markers and continuation offsets. |
|
|
78
|
+
| `xplat_docs_search` / `xplat_docs_read` | Installed-version docs search and bounded page reads, with snapshot/version provenance and unavailable/conflict results. |
|
|
79
|
+
| `xplat_guidance` | Tailored guidance for the selected app's installed packages. |
|
|
80
|
+
|
|
81
|
+
## Retrieve the app's documentation
|
|
82
|
+
|
|
83
|
+
Select your app first. Search defaults to maintained guides for its actual
|
|
84
|
+
installed versions; design notes and recipes require an explicit corpus.
|
|
85
|
+
The provider validates release tags and preserves cached snapshot commits.
|
|
86
|
+
Missing matching docs return an installed-source fallback instead of latest docs.
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"name": "xplat_docs_search",
|
|
91
|
+
"arguments": { "query": "testID", "package": "@octane-xplat/ui", "platform": "web" }
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Read a result using its `ref`. A ref from an older installation remains tied
|
|
96
|
+
to that version and is labeled outside the installed binding after an upgrade.
|
|
97
|
+
`xplat_project_status` reports provider readiness; each search reports actual
|
|
98
|
+
snapshot availability, so readiness alone is not a successful retrieval.
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"name": "xplat_docs_read",
|
|
103
|
+
"arguments": {
|
|
104
|
+
"package": "@octane-xplat/ui",
|
|
105
|
+
"path": "docs/verify/test-identifiers.md",
|
|
106
|
+
"limit": 2000
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Code search reads the bound application's source plus its installed
|
|
112
|
+
`@octane-xplat/*` package sources — corpora stay labeled and distinguishable.
|
|
113
|
+
The semantic index is local TF-IDF (`local-tfidf`): it builds in the
|
|
114
|
+
background, reports `preparing` / `ready` / `stale` / `unavailable`, and stale
|
|
115
|
+
hits are revalidated against current file content before serving. Nothing
|
|
116
|
+
leaves the machine; there is no remote embedding path. Secrets, private
|
|
117
|
+
configuration, generated output, and paths outside the bound scope are
|
|
118
|
+
excluded and unreadable.
|
|
119
|
+
|
|
120
|
+
Every result is `{ ok: true, data } | { ok: false, error }` where `error` is a
|
|
121
|
+
`ContractError` from the shared vocabulary.
|
|
122
|
+
|
|
123
|
+
The service layer lives in `packages/cli/src/mcp/` — the `xplat` CLI projects
|
|
124
|
+
the same contracts through its agent commands (`xplat catalog --json` is the
|
|
125
|
+
entry point). `packages/mcp/src/` holds the stdio transport adapter: tool
|
|
126
|
+
registration wraps the shared services, and the published `.d.ts` contract
|
|
127
|
+
surface stays here under `types/contracts/`. Sources are TypeScript; `pnpm
|
|
128
|
+
build` emits the runnable ESM to `dist/` (`pnpm test` builds first).
|
|
129
|
+
|
|
130
|
+
## Contract surface (`@octane-xplat/mcp/contracts/*`)
|
|
131
|
+
|
|
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`).
|
|
135
|
+
|
|
136
|
+
- `errors` — `ContractErrorCode` vocabulary (`invalid_selection`,
|
|
137
|
+
`ambiguous_selection`, `permission_denied`, `unsupported_capability`,
|
|
138
|
+
`prerequisite_missing`, `target_busy`, `stale_identity`,
|
|
139
|
+
`disconnected_runtime`, `execution_failure`, `not_found`, `cancelled`,
|
|
140
|
+
`timeout`, `unavailable`) with `recovery` (smallest corrective action) and
|
|
141
|
+
`retryable` semantics.
|
|
142
|
+
- `identity` — `Platform`, `AppRef`, `FrameworkBinding` (installed / workspace /
|
|
143
|
+
lockfile / provisional version sources), `GuidanceStatus`,
|
|
144
|
+
`RuntimePrerequisite`, `AppSelection` (`bound` / `ambiguous` / `none`).
|
|
145
|
+
- `capabilities` — `CapabilityId`, `CapabilityStatus`, `CapabilityEntry`,
|
|
146
|
+
`PlatformCapabilityMatrix`, and the `CapabilityProvider` / registry seam
|
|
147
|
+
adapters use to report real support.
|
|
148
|
+
- `policy` — `PermissionScope` grants (`workspace`, `runtime-actions`,
|
|
149
|
+
`visual-capture`, `evidence-retain`, `external-effects`), `PolicyStore` with
|
|
150
|
+
task-authorization baseline, action-time checks, expiry, revocation, and an
|
|
151
|
+
elicitation channel for explicit developer grants. `visual-capture` is never
|
|
152
|
+
baseline-granted.
|
|
153
|
+
- `sessions` — `SessionBinding` (`owned` / `attached`, `starting` / `ready` /
|
|
154
|
+
`disconnected` / `stopped`), `Job` (`queued` → `running` → terminal, with
|
|
155
|
+
`cancelling` / `cancelled`), request-key deduplication, and ownership-safe
|
|
156
|
+
`end` / `shutdown`.
|
|
157
|
+
- `evidence` — `EvidenceRecord` with provenance (app, platform, target,
|
|
158
|
+
session, build identity, time, interaction mechanism), session-scoped
|
|
159
|
+
default retention, `retain` with expiration, ownership-safe deletion, and
|
|
160
|
+
`TRANSCRIPT_LIMITATION_NOTE`. `isOsInputEvidence` is the guard that keeps
|
|
161
|
+
handler-dispatch results from being labeled OS-input verification.
|
|
162
|
+
- `status` — `ProjectStatusReport`, the shape `xplat_project_status` returns.
|
|
163
|
+
- `code` — the `CodeProvider` seam the context's `code` slot consumes, plus
|
|
164
|
+
`CodeHit` / `CodeSearchResult` / provenance and freshness shapes.
|
|
165
|
+
- `boundaries` — `PRODUCT_BOUNDARIES`, the advertised out-of-scope list.
|
|
166
|
+
- `actions` — the app-declared development-action wire contract (package G):
|
|
167
|
+
`DevActionDeclaration` (stable id, title, description, runtime-validatable
|
|
168
|
+
input/result field contracts, disclosed effects, availability, execution
|
|
169
|
+
policy), `DevActionRegistryAnnouncement` (instance identity + revision +
|
|
170
|
+
declarations), invocation request/outcome types, and the field-subset
|
|
171
|
+
validators both sides share. The app announces its registry through a
|
|
172
|
+
dev-bridge (`xplatDevBridge` vite middleware in `@octane-xplat/cli`, included
|
|
173
|
+
in the `xplatNative` preset); the server scans the app's bridge session
|
|
174
|
+
files under `node_modules/.cache/xplat/dev-bridge/` and polls live
|
|
175
|
+
announcements — an empty registry is never confused with a disconnected app.
|
|
176
|
+
|
|
177
|
+
## Runtime (work item D)
|
|
178
|
+
|
|
179
|
+
The shared `runtime/` service (in `packages/cli/src/mcp/runtime/`, re-exported
|
|
180
|
+
here) implements build/launch/attach/logs/cleanup for consumer apps
|
|
181
|
+
on all six platforms. Adapters (`runtime/adapters/*`) own platform
|
|
182
|
+
mechanics and always spawn the app's own toolchain — `pnpm exec vite`,
|
|
183
|
+
`pnpm exec ns run …`, the app's installed `@octane-xplat/cli` dev entry, or
|
|
184
|
+
its `dev` script — so a session behaves like the app's installed framework
|
|
185
|
+
version. The shared `runtime/service` module owns the contract behavior: explicit
|
|
186
|
+
app+target binding, `target_busy` contention, job dedupe/cooperative
|
|
187
|
+
cancel, ownership-safe cleanup, bounded logs, and capability-matrix entries.
|
|
188
|
+
|
|
189
|
+
| Platform | Launch | Attach | Host gate |
|
|
190
|
+
| -------------- | ----------------------------------------------------------------- | -------------------------------------------------- | ---------- |
|
|
191
|
+
| web / Chromium | `pnpm exec vite` + headless Chromium (devtools endpoint reported) | probe common dev ports — identity heuristic | none |
|
|
192
|
+
| iOS | `ns run ios --device <udid>` | booted sim + app running → `simctl log stream` tap | macOS |
|
|
193
|
+
| Android | `ns run android --device <serial>` | package running → `adb logcat --pid` tap | none (adb) |
|
|
194
|
+
| macOS | `xplat.targets.macos.dev` → CLI dev entry, else `pnpm run dev` | pgrep on app root — no scrollback | macOS |
|
|
195
|
+
| Linux | `pnpm run dev` (app-owned script) | pgrep on app root | Linux |
|
|
196
|
+
| Windows | `ns run windows` | not yet qualified | Windows |
|
|
197
|
+
|
|
198
|
+
Readiness is probe/marker-confirmed (`ready` session state) — HTTP 200 for
|
|
199
|
+
web, the host-start marker for macOS, `Successfully synced application` /
|
|
200
|
+
first `CONSOLE` line for `ns run`. A timeout or pre-ready exit fails the job
|
|
201
|
+
and ends the owned session honestly. Chromium is located via
|
|
202
|
+
`XPLAT_MCP_CHROMIUM`, the Playwright browser cache, or system installs;
|
|
203
|
+
without it the web session still reports the server URL with an explicit
|
|
204
|
+
`browser.launched: false`.
|
|
205
|
+
|
|
206
|
+
Physical iOS devices, Windows attach detection, and non-simulator iOS log
|
|
207
|
+
taps are reported limitations, not silent gaps — the capability matrix
|
|
208
|
+
carries the detail and an alternative.
|
|
209
|
+
|
|
210
|
+
## Inspect and interact with Chromium
|
|
211
|
+
|
|
212
|
+
This development package adds `xplat_inspect`, `xplat_interact`, and
|
|
213
|
+
`xplat_screenshot` for the Chromium browser started by `xplat_launch`.
|
|
214
|
+
Select a DOM `id` or shared `testID` explicitly; duplicate names fail.
|
|
215
|
+
Inspection returns bounded text/value/geometry, a document identity, and
|
|
216
|
+
session/build provenance. Main-document DOM hosts are the qualified surface;
|
|
217
|
+
shadow roots, frames, component ownership and signals are excluded.
|
|
218
|
+
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"name": "xplat_inspect",
|
|
222
|
+
"arguments": {
|
|
223
|
+
"sessionId": "SESSION_FROM_LAUNCH",
|
|
224
|
+
"control": { "kind": "testID", "name": "counter.increment" }
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Pass the returned `documentId` when interacting. A `dom-event` interaction
|
|
230
|
+
clicks the control center through CDP. `os-input` sends Space or Enter through
|
|
231
|
+
the macOS event system to the owned headed Chromium process. It requires
|
|
232
|
+
Swift, OS event-posting permission, and a desktop-input reservation. The
|
|
233
|
+
server does not open permission prompts. Inspect the resulting app state
|
|
234
|
+
separately; sending input alone is not an assertion.
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"name": "xplat_interact",
|
|
239
|
+
"arguments": {
|
|
240
|
+
"sessionId": "SESSION_FROM_LAUNCH",
|
|
241
|
+
"documentId": "DOCUMENT_FROM_INSPECTION",
|
|
242
|
+
"control": { "kind": "testID", "name": "counter.increment" },
|
|
243
|
+
"mechanism": "os-input",
|
|
244
|
+
"key": "Space"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Screenshot requests require an explicit current-task `visual-capture` grant
|
|
250
|
+
before connecting or sending a capture command. No grant means no capture.
|
|
251
|
+
Password fields, hidden inputs and hosts marked `data-xplat-private` are
|
|
252
|
+
redacted in nonvisual inspection; this does not guarantee complete redaction
|
|
253
|
+
of arbitrary application data.
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{ "name": "xplat_screenshot", "arguments": { "sessionId": "SESSION_FROM_LAUNCH" } }
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Run the consumer acceptance lane
|
|
260
|
+
|
|
261
|
+
Use a fresh directory outside your existing app. These commands scaffold the
|
|
262
|
+
normal web starter and add one app-owned development action. The in-repo lane
|
|
263
|
+
links framework packages to this checkout; other dependencies
|
|
264
|
+
install normally. The runner checks docs and current code, build/readiness,
|
|
265
|
+
the counter's `0 → 1` transition, action discovery/invocation, screenshot
|
|
266
|
+
denial, logs, and owned browser/server/profile cleanup. It also checks that
|
|
267
|
+
the fixture declaration and handler are absent from production artifacts.
|
|
268
|
+
|
|
269
|
+
```sh
|
|
270
|
+
node packages/mcp/tests/prepare-consumer.mjs /tmp/new-xplat-mcp-app
|
|
271
|
+
pnpm --dir /tmp/new-xplat-mcp-app install
|
|
272
|
+
node packages/mcp/tests/consumer-workflow.mjs /tmp/new-xplat-mcp-app
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
The default run supplies browser-event evidence. On macOS, reserve the full
|
|
276
|
+
resource set and add `--os-input` for a headed Chromium OS keyboard journey.
|
|
277
|
+
Only the owned browser receives the events; the helper attempts to restore the
|
|
278
|
+
previously active application and reports when restoration is unconfirmed.
|
|
279
|
+
The runner captures no images.
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
goddard-agent resource run --json '{"resources":{"native_builds":1,"desktop_input":1},"purpose":"MCP consumer OS keyboard acceptance"}' -- node packages/mcp/tests/consumer-workflow.mjs /tmp/new-xplat-mcp-app --os-input
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The packed-artifact lane qualifies the same checks against release-evidence
|
|
286
|
+
packaging: `prepare-packed-consumer.mjs` packs the needed packages, scaffolds
|
|
287
|
+
through the packed `create-octane-xplat` bin, installs `file:` tarballs (no
|
|
288
|
+
registry/latest resolution for framework packages), and tags the framework
|
|
289
|
+
HEAD as `v<installed version>` in a local bare release fixture. The runner
|
|
290
|
+
spawns the consumer's own installed `xplat-mcp` bin over stdin/stdout and
|
|
291
|
+
redirects the canonical release-repo URL to the fixture through a per-process
|
|
292
|
+
`url.insteadOf` (never user git config). Snapshot cache and evidence roots are
|
|
293
|
+
isolated under the work dir. OS keyboard input additionally requires an
|
|
294
|
+
unlocked console — the window server refuses activation while the screen is
|
|
295
|
+
locked, and the run reports that block honestly.
|
|
296
|
+
|
|
297
|
+
```sh
|
|
298
|
+
goddard-agent resource run --json '{"resources":{"native_builds":1,"desktop_input":1},"purpose":"packed MCP stdio consumer acceptance"}' -- bash -c '
|
|
299
|
+
node packages/mcp/tests/prepare-packed-consumer.mjs /tmp/xplat-packed-mcp &&
|
|
300
|
+
node packages/mcp/tests/packed-stdio-consumer.mjs /tmp/xplat-packed-mcp'
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
For an existing consumer, declare actions behind the development build gate.
|
|
304
|
+
Registration automatically starts the bridge when the dev-server endpoint is
|
|
305
|
+
present. The action's contracts and effects appear in `xplat_dev_actions`;
|
|
306
|
+
no action-specific MCP tool definition is needed.
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
if (import.meta.env.DEV) {
|
|
310
|
+
const { registerDevAction } = await import('@octane-xplat/platform/dev-actions')
|
|
311
|
+
registerDevAction({
|
|
312
|
+
id: 'fixture.describe-counter',
|
|
313
|
+
title: 'Describe the counter',
|
|
314
|
+
description: 'Identify this test fixture without external effects.',
|
|
315
|
+
result: { fields: { label: { type: 'string' } } },
|
|
316
|
+
effects: { summary: 'Read fixture identity.' },
|
|
317
|
+
run: () => ({ label: 'starter-counter' }),
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Remaining acceptance
|
|
323
|
+
|
|
324
|
+
The Chromium lane is an incremental milestone. All six platforms remain
|
|
325
|
+
required by the original plan. Native inspection/input adapters, attached
|
|
326
|
+
Chromium inspection, approved screenshot qualification, and the complete
|
|
327
|
+
platform-by-capability acceptance matrix remain unfinished. Runtime adapters
|
|
328
|
+
and honest unavailable responses do not establish native behavior.
|
|
329
|
+
|
|
330
|
+
| Target | Inspection/input qualification boundary |
|
|
331
|
+
| --------------- | ------------------------------------------------------------------------------ |
|
|
332
|
+
| Chromium | Owned main-document DOM; browser events plus macOS scoped OS keyboard path |
|
|
333
|
+
| iOS / Android | Native host inspection and OS-input adapters still required |
|
|
334
|
+
| macOS | AppKit host inspection/input still required; Chromium on macOS is web evidence |
|
|
335
|
+
| Linux / Windows | Target-host adapters and independent consumer qualification still required |
|
|
336
|
+
|
|
337
|
+
## Boundaries
|
|
338
|
+
|
|
339
|
+
This server complements the agent's editing tools. It is not an autonomous
|
|
340
|
+
code editor or deployment system: no arbitrary shell execution, no arbitrary
|
|
341
|
+
runtime expression evaluation, no universal component tree, no hook/signal
|
|
342
|
+
inspection, no profiling API, no cloud indexing by default, no app-store
|
|
343
|
+
operations, no credential management. Screenshots are permission-gated —
|
|
344
|
+
capability existence never implies capture approval.
|
|
@@ -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";
|
package/dist/context.js
ADDED
|
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,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";
|