Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Release publication and catalog notification

Publish only an accepted plugin package bound to its reviewed source/tag and exact archive digest.
Keep an existing public tag and archive immutable. A candidate, draft or notification receipt does
not establish authenticated vendor or installed-host acceptance.

The Validate and package workflow produces candidate artifacts; it does not make a release public. After the accepted release becomes public,
`notify-catalog.yml` requests a complete catalog reconciliation. It also observes public edits,
channel promotion, unpublishing and deletion; those events never authorize catalog withdrawal by
themselves. The central publisher retains verified history and applies its reviewed withdrawal
policy. It verifies actual GitHub release sources rather than trusting an event payload.

## Notification authority

The workflow pins the website's central notification action to a reviewed full commit. Publish that
central commit before enabling a plugin workflow that references it. Review and update this pin
when adopting changes to the notification contract. The caller checks its immutable repository ID,
does not check out package code, and grants its own job token no repository permissions.

Supply `CATALOG_DISPATCH_TOKEN` using existing reviewed authority with Actions write access to
`computer-mcp/computer-mcp.github.io` only. Website Contents write access is unnecessary. The action
can also receive an existing temporary token directly from a publishing job. Neither workflow
creates or persists credentials. Missing or rejected authority fails visibly; the
publisher's independent schedule still reconciles missed notifications.

## Publication and retry

A manual public release emits the release event. Publication performed with a repository's
`GITHUB_TOKEN` does not trigger ordinary release-event workflows. After that publication succeeds,
its automation must explicitly call this reusable workflow as a dependent job:

```yaml
notify-catalog:
needs: publish
uses: ./.github/workflows/notify-catalog.yml
secrets:
CATALOG_DISPATCH_TOKEN: ${{ secrets.CATALOG_DISPATCH_TOKEN }}
```

Here `publish` is the job that actually makes the accepted release public, not the candidate-build
or draft-upload job. When using an existing short-lived token within that publishing job, invoke
the same pinned central action directly after publication instead. Keep token values out of command
arguments, printed output and release metadata.

For an operator-driven publication or a missed/failed notification, explicitly dispatch:

```sh
gh workflow run notify-catalog.yml --repo computer-mcp/plugin-cursor --ref main
```

This schedules notification using its configured authority; it does not publish or rewrite a
release. Inspect the notification run and its returned central `run_url`. A successful dispatch
proves request acceptance only. Verify the central run completed successfully and the public index
contains the exact expected release identities and generation. If the release is already public and
notification fails, retry notification without changing or republishing the release. Complete
reconciliation is idempotent and repairs duplicate/missed events.

See the central [catalog publication and notification contract](https://github.com/computer-mcp/computer-mcp.github.io/blob/main/docs/plugin-catalog.md)
for provenance, credentials, retry bounds and deployment semantics.
28 changes: 28 additions & 0 deletions .github/workflows/notify-catalog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Notify official plugin catalog
on:
release:
types: [published, edited, released, unpublished, deleted]
workflow_dispatch:
workflow_call:
secrets:
CATALOG_DISPATCH_TOKEN:
description: Existing receiver-scoped Actions write authority
required: true
outputs:
run_url:
description: Accepted central run; verify its deployment separately
value: ${{ jobs.notify.outputs.run_url }}
permissions: {}
jobs:
notify:
if: github.repository_id == '1384745559'
runs-on: ubuntu-latest
timeout-minutes: 3
outputs:
run_url: ${{ steps.catalog.outputs.run-url }}
steps:
- name: Request complete catalog reconciliation
id: catalog
uses: computer-mcp/computer-mcp.github.io/.github/actions/notify-catalog@fc27dd0f370d028a3e5021e3585274891f696578
with:
token: ${{ secrets.CATALOG_DISPATCH_TOKEN }}
7 changes: 7 additions & 0 deletions Documentation/Architecture/Package.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ The package is independently maintained and distributed. Computer MCP owns regis

`bin/cursor-mcp-adapter` owns native sessions, one active operation per session, bounded events and pending permission/question/plan responses. `bin/plugin_runtime.py` is a package-private standard-library implementation of bounded MCP framing/validation, process ownership and retention; it is distributed with this plugin, not installed into or imported from Computer MCP. Each package can update independently. Python 3.13+ is a runtime dependency selected by the launch PATH.

The standard MCP work resource projects these same session owners. The adapter
binds each session to its creation request's host correlation and supplies live
or uncertain state; the MCP server bounds and versions complete snapshots.
Background threads and unconfirmed cleanup remain owned even after the creating
tool returns. Host configuration generations and continuation routing remain
host responsibilities. The resource does not introduce another task lifecycle.

The supervisor lifeline and cleanup receipt are private implementation channels, not plugin-host protocol extensions. Vendor subprocesses inherit neither channel nor host private descriptors. Explicit cleanup acknowledgement is separate from exit status. Runtime errors do not authorize retries or privilege escalation.

Scripts provide deterministic packaging, non-model native interface checks and isolated unchanged-host integration checks. Tests exercise deterministic peers and lifecycle failures. The distribution excludes build/test/evidence files. No full native GUI, Windows backend or hosted API is claimed by this package.
17 changes: 14 additions & 3 deletions Documentation/Reference/Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ The example exposes this plugin's complete MCP tool catalog with no extra prefix

On Computer MCP 1.2.2, plugin activation/selection changes require idle Gateway client admission. Finish or safely pause clients before production installation changes. No host binary replacement or host release is required. Do not restart the active development control connection merely to test installation.

Computer MCP 1.3.0 publishes plugin configuration changes to connected clients atomically. New calls use the current configuration; existing work keeps its owning runtime until release. Installation does not grant access, and later calls use current authorization.

## Build

```sh
Expand All @@ -28,16 +30,25 @@ CI runs deterministic fixture tests and packaging; it does not install a vendor

## Isolated host interoperability

After packaging, validate the exact ZIP with an unchanged installed Computer MCP 1.2.2 binary:
After packaging, validate the exact ZIP against the reviewed Computer MCP binary. Select its release version explicitly; a mismatch fails before package extraction:

```sh
python3 Scripts/validate_host.py \
--host "/Applications/Computer MCP.app/Contents/Resources/computer-mcp" \
--host "/absolute/path/to/candidate/computer-mcp" \
--expected-host-version 1.3.0 \
--archive /output/PLUGIN.zip \
--output /new/evidence/directory
```

Replace `PLUGIN.zip` with the package's actual archive name. This uses a temporary directory and the installed host's archive worker and standalone MCP entrypoint. It does not connect to the production App's control socket or database. Vendor tool execution is replaced with inert fixtures; the native version/help check is a separate command. A new evidence directory is required to avoid overwriting an earlier run.
Replace `PLUGIN.zip` with the package's actual archive name. This uses a temporary directory and the selected host's archive worker and standalone MCP entrypoint. It does not connect to the production App's control socket or database. Vendor tool execution is replaced with inert fixtures; the native version/help check is a separate command. A new evidence directory is required to avoid overwriting an earlier run.

For a candidate host implementing the provider-work contract, add
`--require-work-ownership`. This gate verifies the same connection retains an
opened session, a detached prompt waiting for input and an idle session, then
observes no owners after confirmed session close. It also checks that the
gateway does not reexport the downstream-only resource declaration. Hosts
without this observation surface can still run the ordinary interoperability
gate without that option.

A real ACP handshake can be checked independently, without authenticating, opening a conversation or invoking a model:

Expand Down
67 changes: 64 additions & 3 deletions Documentation/Reference/Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,54 @@ The CLI contribution preserves the declared argv order, optional native flags an

The MCP adapter implements standard newline-delimited JSON-RPC over stdio, with MCP initialization, tools/list, tools/call, ping and cancellation notifications. Supported MCP dates are 2024-11-05, 2025-03-26 and 2025-06-18. An unsupported proposed date receives the adapter's supported date rather than an unimplemented echo. Tool results use `structuredContent.result`; tool failures set `isError` and include an error code. Protocol errors remain JSON-RPC errors. Tool schemas are the callable source of truth.

## Host risk metadata

Every MCP tool declares `_meta["io.github.computer-mcp/risk"]`. Model execution
and continuation declare `full-shell`: native permission defaults are not a
host-enforced sandbox. Catalog, result, event and pending-request inspection
declare `read-only`. Cancellation and owned-process retirement declare
`destructive`. The host applies these as minimum classifications, intersects
its own grants, and retains approval authority. Standard MCP annotations remain
hints rather than permissions.

Session open/load, mode changes and interactive responses also declare
`full-shell`; they can initialize native tools or continue executable work.

## Runtime work resource

The adapter advertises ordinary MCP resources and the version-1 declaration in
`_meta["io.github.computer-mcp/work"]` on its tool definitions. `resources/list`
lists `computer-mcp://runtime/work/v1`; `resources/read` returns one JSON text
content entry. The report has `format_version`, a connection-local UUID
`instance_id`, a nonnegative exact integer `revision`, and the complete
`resources` array. Unchanged resource sets keep their revision; changed sets
advance it. At most 1,024 resources and 512 KiB of report text are allowed.

Each live resource has kind `cursor.session`, the adapter `session` handle as
`id`, the opening call's host-supplied
`_meta["io.github.computer-mcp/work-invocation"]` UUID as `acquired_by`, and
state `active` or `uncertain`. This reference binds lifecycle observation; it
grants no authority and is not a native session ID. It is never read from tool
arguments or forwarded to the vendor process.

A session is owned from pending startup through idle periods, repeated or
background prompts and interactive requests. Completing a prompt does not close
its session. Removal requires confirmed process cleanup, settled startup and
completion of the owned background thread. Closing with unconfirmed cleanup
reports `uncertain` and keeps the session against capacity. A one-shot prompt
releases its session after the same cleanup boundary. No report can substitute
for permission, native execution success or authenticated model evidence.

Ordinary clients may continue to call tools without work-invocation metadata.
If such a client creates a live session, the work resource returns unavailable
evidence until unbound work is released; it never reports a falsely empty
snapshot. Malformed invocation metadata is rejected before execution. Report
reads do not launch a vendor, terminate a session, change permissions or replay
work. The adapter does not require resource subscriptions; hosts may poll.

See the host's [provider work contract](https://github.com/computer-mcp/computer-mcp/blob/master/Documentation/Reference/MCPProtocol.md#downstream-provider-work)
for acquisition expiry, snapshot validation and host-side uncertainty.

## Tools

| Native MCP tool | Behavior |
Expand Down Expand Up @@ -39,15 +87,15 @@ The default permission policy is `reject-once`. Explicit `allow-once`/`allow-alw
{"session":"ADAPTER_HANDLE","request_id":"PENDING_REQUEST","response":{"outcome":{"outcome":"selected","optionId":"EXACT_OFFERED_OPTION"}}}
```

Question answers must use the offered question and option IDs and obey single/multiple selection. Plans accept `accepted`, `rejected` or `cancelled` and their documented optional fields. Duplicate, stale and unoffered replies fail. Unknown vendor requests receive method-not-found, not fabricated success.
Question answers must use the offered question and option IDs and obey single/multiple selection. Plans accept `accepted`, `rejected` or `cancelled` and their documented optional fields. Duplicate, stale and unoffered replies fail. Each request is bound to its active native operation and session; response delivery and operation retirement are serialized. Unknown vendor requests receive method-not-found, not fabricated success.

## Bounds, cancellation and failures

An ACP frame is bounded to 1 MiB before waiting for a newline. Event retention is bounded by both 256 events and 256 KiB. Text accumulation is bounded to 128 KiB; omissions/truncation are reported. Pages use absolute cursors, `next_cursor`, `has_more` and `missed_events`. An event larger than the requested page becomes explicit omission metadata so pagination can progress. Responses retain the bounded native prompt result; absent stopReason is an error, and native cancellation is not successful task completion.
An ACP frame is bounded to 1 MiB before waiting for a newline. Event retention is bounded by both 256 events and 256 KiB. Text accumulation and its serialized JSON value are each bounded to 128 KiB; omissions/truncation are reported. Pages use absolute cursors, `next_cursor`, `has_more` and `missed_events`. An event larger than the requested page becomes explicit omission metadata so pagination can progress. Responses retain the bounded native prompt result; absent stopReason is an error, and native cancellation is not successful task completion.

Prompts default to 300 seconds and accept up to 1800 seconds. Session setup defaults to 45 seconds. Transport startup and cleanup can add bounded latency. Pending requests expire with their native operation. Cancellation sends ACP session/cancel, waits for native settlement, and retires the owned process if it cannot settle within its grace period. A cancelled background request is not automatically replayed. Cancelling the start call after it returned does not identify the background task: use the returned session/prompt handle.

The private supervisor observes adapter EOF/termination and owns the vendor process group. It retains the leader until termination and reaping, then sends a separate bounded cleanup acknowledgement. Missing acknowledgement is `cleanup_unconfirmed`, never a clean success inferred from exit alone. Escaped, independently reparented processes are not claimed as owned. Host callback descriptors/COMPUTER_MCP metadata are not forwarded to the vendor. The process working directory is not an OS sandbox.
The private supervisor observes adapter EOF/termination and owns the vendor process group. It retains the leader until termination and reaping, then sends a separate bounded cleanup acknowledgement. Missing acknowledgement is `cleanup_unconfirmed`, never a clean success inferred from exit alone. A session with unconfirmed cleanup remains retained and counts against admission capacity; repeating close cannot erase the failure. Escaped, independently reparented processes are not claimed as owned. Host callback descriptors/COMPUTER_MCP metadata are not forwarded to the vendor. The process working directory is not an OS sandbox.

Representative errors include invalid_arguments, unknown_session, busy, incompatible_vendor, vendor_failed, invalid_vendor_response, frame_too_large, result_too_large, timeout, cancelled and cleanup_unconfirmed. Failed/unknown writes are not automatically retried. Native output may contain sensitive user content; callers must handle it accordingly.

Expand All @@ -58,3 +106,16 @@ Representative errors include invalid_arguments, unknown_session, busy, incompat
- The installed native `agent --help`, `agent --version` and `agent acp --help` used to maintain the pinned CLI tree.

Vendor protocol observations, fixture tests, host interoperability and authenticated backend execution are separate evidence classes.

## Continuation binding

Tools that accept an existing adapter handle declare
`_meta["io.github.computer-mcp/continuation"]` with format version 1. The selector
matches kind `cursor.session` and primary resource `id` against argument
`session` using JSON Pointer `/session`. This identifies the actual
connection-owned lifetime; it does not rebind acquisition or grant permissions.
New work and unscoped listings do not claim an existing owner. The declaration
uses ordinary MCP metadata and requires no private Host Services. Hosts validate
and retain it on its originating connection; gateway reexports strip it. Runtime
generation selection remains host-owned, and this declaration alone does not
enable live configuration changes.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ The CLI contribution describes verified non-interactive commands. The native bas

The adapter provides ACP session open/load, repeated prompts, background prompt start/result, session listing/mode/cancel/close, cursor-paginated events and explicit responses to permission/question/plan requests. `cursor.acp.prompt` remains the one-shot convenience path. Twelve tools are discovered through MCP; discovery does not start a vendor process.

The ordinary MCP work resource reports connection-owned sessions through confirmed
cleanup, including idle sessions, background prompts and interactive requests.
Hosts that support this resource can account for work after a tool reply. It
requires no private Host Services permission and does not itself enable host
configuration changes.

`permission_policy` defaults to `reject-once`. `allow-once` and `allow-always` are explicit native decisions and only select offered options. `manual` exposes pending permission requests for an explicit response. Questions and plans always require an explicit response; no answer is invented. Use `session.open` plus `session.prompt.start` for these workflows.

## Use and verify
Expand Down
Loading
Loading