# Jumping Beans ChatGPT app/plugin prototype

This is a thin, local MCP-style connector for the Jumping Beans allowable-action
thesis. It shows how a ChatGPT-style tool surface can carry a small,
reviewable action journey without turning a read into an unreviewed write.

The server is a deterministic mock with no network requests, secrets, accounts,
browser storage, partner API calls, page navigation, or commit operation.
Matching returns fixture offers with explicit mock provenance. Preferences are
request-only. A handoff stops at a review packet and requires approval of the
exact offer, target price, and destination before a destination URL is prepared.

## Included surface

| Tool | Purpose | Side effect | Approval boundary |
| --- | --- | --- | --- |
| `match_deals` | Match fixture offers by category and ceiling | None | Read-only |
| `stage_preferences` | Stage a display/context proposal from fields or a short natural-language preference | None; persistence is `none` | Approval before sharing |
| `build_offer_journey` | Show the permitted sequence and boundaries | None | Review and partner confirmation are explicit |
| `prepare_partner_handoff` | Prepare a packet for mock Watch Co | No open, send, save, or commit | Exact fields must be approved |

There is intentionally no `commit`, `register_interest`, checkout, reservation,
or silent navigation tool. A real partner-owned consequential action would need
its own page review, explicit confirmation, idempotency, and authoritative
receipt, matching the existing Watch Co action contract.

## MCP connector vs page-native WebMCP

These are separate claims:

| This prototype proves | This prototype does not prove |
| --- | --- |
| A local stdio JSON-RPC tool contract can expose bounded Jumping Beans actions. | Native browser WebMCP discovery or invocation. |
| Tool schemas and responses can preserve provenance, retention, and approval state. | `document.modelContext.registerTool()`, `getTools({ fromOrigins })`, or `executeTool()`. |
| The connector fails closed on unknown fields and unsupported offers. | Cross-origin iframe delegation, `Permissions-Policy`, `allow="tools"`, or `exposedTo`. |
| A handoff can remain a reviewable, non-committed packet. | A partner page receiving or persisting the handoff. |

The native WebMCP claim belongs to the existing engine and partner documents in
`products/jumping-beans/engine/` and `products/jumping-beans/partners/`. This
prototype has no browser bridge, `postMessage` path, direct capability HTTP
endpoint, or substitute WebMCP registry.

## Run locally

From this directory:

```bash
node demo.mjs
node --test server.test.mjs
```

`stage_preferences` accepts a short `preferenceText` such as “Show price proof
and keep it under $30 for coffee”; the server returns the interpreted fields as
an editable, request-only proposal. `demo.mjs` starts the stdio server, performs the full read → stage → plan →
approval-gated handoff journey, and exits. It requires only Node.js and no
credentials or network connection. `.mcp.json` is the host configuration for
the local stdio server; a host that does not set this directory as its working
directory should use the absolute path to `server.mjs`.

`.codex-plugin/plugin.json` supplies presentation metadata. No marketplace
entry or installation is part of this experiment.

## Expected demo evidence

The output should show four tools, two Watch Co fixture offers under `$800`, a
`request-only` preference stage, `connectorCanCommit: false`, and a handoff that
ends with `committed: false`, `opened: false`, and no contacted origins.
