Skip to main content
Glama
yyjeqhc

mcp-poll

by yyjeqhc
README.md
# MCP Goal Continuation Lab

A small, self-contained research implementation of durable **Goal continuation for MCP Apps**.

The project distills a longer sequence of ChatGPT/MCP experiments into one readable implementation. It focuses on the final model-managed design: the model owns semantic progress and completion, the server owns durable state and wake serialization, and the App View is only a resumable controller/adapter.

This is a research probe, not a production task runner.

## What it demonstrates

The central rule is simple:

> **Elapsed time never means business work completed.**

A Goal is divided into model-defined semantic phases. The model explicitly commits a phase, optionally checkpoints real progress, and then either:

- **completes** it with bounded evidence;
- **yields** the same unfinished phase to another model turn; or
- disappears, in which case a recovery watchdog may wake the **same unfinished phase** without claiming success.

The current design also demonstrates:

- exact `invocationKey -> goalId` binding rather than a global-current Goal;
- durable JSON state with atomic replacement and restart rehydration;
- a Goal-level single-active-wake gate;
- sticky View ownership for one wake event;
- a durable `leased -> dispatching -> delivered -> consumed` handoff state;
- fail-closed duplicate suppression after the dispatch fence;
- a server-owned controller generation lease that fences stale/reused iframes;
- foreground recovery for failures that happened **before** the irreversible dispatch fence;
- model `consume` as stronger proof than a View delivery acknowledgement.

## Why this repository exists

The design came from a sequence of live-host failures rather than from a single up-front abstraction. The important progression was:

| Experiment | What changed |
| --- | --- |
| v0.5.0 | Durable Goal, terminal event, sticky resume lease, dispatch fence |
| v0.5.1 | Exact invocation binding; removed global-current rehydration |
| v0.5.2 | Single active wake and queued/coalesced continuation |
| v0.5.3 | Model-defined semantic phases |
| v0.5.5 | Real/model-managed phases; timers cannot produce success |
| v0.5.7 | Controller generation lease fences stale App Views |
| v0.5.8 | Resume becomes an execution handoff, not just a narrative hint |
| v0.5.9 | Safe retry of pre-dispatch background/foreground Host failures |

This repository keeps only the converged contract rather than all historical compatibility implementations.

## Architecture

```text
model turn
   |
   | commit/checkpoint/yield/complete/consume
   v
+---------------------------+
| durable Goal state        |
| - semantic phases         |
| - terminal evidence       |
| - recovery deadline       |
| - active wake             |
| - dispatch state          |
| - controller generation   |
+-------------+-------------+
              |
              | exact Goal/event projection
              v
+---------------------------+
| MCP App controller View   |
| - exact attach binding    |
| - acquire wake            |
| - update model context    |
| - prepare dispatch fence  |
| - send one ui/message     |
| - delivery ack            |
+-------------+-------------+
              |
              v
        resumed model turn
              |
              | exact consume proves handoff
              +-------------------------------> durable Goal state
```

The detailed state/authority model is in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).

## Current MCP surface

The server intentionally advertises only the current 13-tool Goal surface:

- `ui_goal_phase_start_v055`
- `ui_goal_phase_controller_attach_v059`
- `ui_goal_phase_state_v055`
- `ui_goal_phase_commit_v055`
- `ui_goal_phase_checkpoint_v055`
- `ui_goal_phase_yield_v055`
- `ui_goal_phase_complete_v055`
- `ui_goal_phase_consume_v055`
- `ui_goal_phase_finish_v055`
- `ui_goal_phase_stop_v055`
- `ui_goal_phase_resume_acquire_v055`
- `ui_goal_phase_resume_prepare_v055`
- `ui_goal_phase_resume_ack_v055`

The `v055` names are deliberate: v0.5.5 established the stable model-managed business contract; v0.5.9 changes the controller/Host handoff without changing those business tool semantics.

## Run locally

Requires Node.js 22+.

```bash
npm install
npm run dev
```

Default endpoints:

```text
http://127.0.0.1:8790/healthz
http://127.0.0.1:8790/mcp
```

State defaults to `./data/goal-state.json`. Override it with:

```bash
MCP_GOAL_STATE_PATH=/some/private/path/goal-state.json npm run dev
```

Useful environment variables:

| Variable | Default | Purpose |
| --- | --- | --- |
| `MCP_GOAL_HOST` | `127.0.0.1` | Bind host |
| `MCP_GOAL_PORT` | `8790` | HTTP port |
| `MCP_GOAL_STATE_PATH` | `./data/goal-state.json` | Durable state file |
| `MCP_GOAL_RECOVERY_SECONDS` | `14400` | Default orphan/lost-turn fallback |
| `MCP_GOAL_WAKE_GRACE_MS` | `2000` | Delay before an App View may wake after terminal evidence |
| `MCP_APP_DOMAIN` | unset | Optional MCP App domain metadata for a deployed HTTPS origin |

## Validate

```bash
npm run typecheck
npm run smoke
```

The smoke test exercises the HTTP tool surface, controller-generation fencing, yield/same-phase continuation, explicit completion, dispatch fencing, consume semantics, final Goal completion, and restart persistence.

## What this does **not** prove

This lab deliberately leaves production concerns out of scope:

- the JSON store assumes a **single writer**;
- there is no tenant/account authorization model;
- the recovery watchdog is a heuristic because MCP Apps currently provide no authoritative "model turn ended" event;
- it does not execute arbitrary shell/code/business work itself;
- it does not replace a durable Job/Run activity lease in a real agent runtime;
- it does not prove exactly-once message transport; it instead makes duplicate automatic delivery fail closed after the durable dispatch fence.

Do not expose this raw probe directly to the public Internet without an authentication/authorization layer. Goal text and checkpoint/evidence summaries are durable user-supplied data.

## License

MIT. See [`LICENSE`](LICENSE).

Maintenance

ActivityMaintained
ResponsivenessNo issues