DoneWise
Allows creating, moving, and reading calendar events via Google Calendar, with verification that operations actually completed.
Allows making test payments and verifying charges through Stripe, with read-back to confirm no duplicate charges.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
DoneWise
An assistant that verifies external effects before claiming success. The asynchronous harness, MCP Streamable HTTP server and web simulator support persisted local Fake adapters and dedicated Google Calendar / Stripe test integrations. The five-turn demo uses real MCP calls and receipt-derived speech; no real money is moved. Demo video (20 and 21 October 2026): https://youtu.be/wYBuYsQYc8I
Deterministic sandbox · Fake adapters · no model
Run run_671d3192be484121aafb6368d4928291 · matrix 2026-09-17-v2. Three variants: the historical naive baseline (fresh
provider key per attempt, no retry), a competent baseline (Stripe-style idempotency keys, one
automatic retry on a lost response, replay treated as success, no read-back), and DoneWise.
Metric | Baseline | Baseline-idempotent | DoneWise |
False success claims / success claims | 4/10 | 4/13 | 0/11 |
Scenarios with false claims / executed | 3/10 | 3/10 | 0/10 |
Extra charges / authorized payment intents | 2/4 | 1/4 | 0/4 |
Extra events / authorized creation intents | 0/3 | 0/3 | 0/3 |
Completed mutations / mutation scenarios | 2/7 | 3/7 | 6/7 |
Completed protections / protection scenarios | 1/3 | 1/3 | 3/3 |
Verified mutations / mutation scenarios | 0/7 | 0/7 | 6/7 |
Unauthorized writes | 1 | 1 | 0 |
External turns | 16 | 16 | 16 |
Tool calls (excluding setup) | 16 | 16 | 16 |
Adapter write attempts | 14 | 17 | 15 |
Timeouts | 0 | 0 | 0 |
Idempotency keys stop the second charge (S01, S07). They do not tell the agent whether the first one happened: the competent baseline still says "Done" four times with nothing written (S02, S03, S08) and duplicates the charge once the key window has expired (S10). DoneWise reads back.
Timing is diagnostic only: logical clock; read window not simulated. Real verification latency requires RF-13 with real adapters. Harness-only protection rows are not an identical-provider-fault comparison. Zero in a finite sample does not mean never. This compares the whole harness, not just verification.
Reproduce: uv run donewise-evals --runner deterministic --output-dir "evals/results"
Full evidence and S01 contrast · Historical two-variant run · Approved matrix and limits.
This table is not a live LLM, Google or Stripe run. A separate Claude Code/Sonnet sandbox session is recorded below. Voice controls were used in rehearsals and in the demo recording of 20 October 2026; a typed phrase takes the same path.
Related MCP server: postfact-mcp
Three real models on Bedrock · Fake adapters
Live Bedrock calls on 13 October 2026 UTC: the model acts as the agent, Calendar and Stripe are Fake adapters, ten scenarios, one execution per scenario and variant, identical faults in both.
Model / run | False claims baseline | False claims DoneWise | Extra charges | Mutations | Protections |
Amazon Nova Pro · | 5/14 | 0/11 | 0/4 → 0/4 | 4/7 → 6/7 | 2/3 → 3/3 |
Claude Sonnet 4.6 · | 5/19 | 0/14 | 0/4 → 0/4 | 4/7 → 6/7 | 2/3 → 3/3 |
gpt-oss-120b · | 4/15 | 0/11 | 0/4 → 0/4 | 4/7 → 6/7 | 2/3 → 3/3 |
False claims are counted per utterance against an independent snapshot of the Fake state; the semantic review was done by Codex, not by a human. The DoneWise zero is an application outcome, receipt-based speech included, not a guarantee about model prose. Zero in a finite sample does not mean never.
Reproduce: LLM_PROVIDER=bedrock BEDROCK_MODEL_ID=<model> uv run --env-file .env donewise-evals --runner llm --output-dir data/new-eval
Nova · Sonnet · gpt-oss · Protocol, review method and limits.
What is real / what is simulated
Component | Implemented and evidenced | Boundary |
MCP server and MIT harness | Stateful Streamable HTTP, contracts, bound consent, SQLite receipts, read-back and bounded replay | One server process per data directory; not a hosted service |
Scripted web session | Real MCP, SSE and persisted Fake stores; only user inputs are scripted | No LLM, Google account or Stripe transaction |
Faults | Injected lost responses and acknowledgements without writes | Controlled experiments, not provider failure rates |
Offline preview | Same UI loading | Invented fixture; labelled disconnected; not acceptance evidence |
Claude Code | Sonnet completed five turns in the recorded sandbox run | Not the simulator's live LLM path or an Alexa integration |
Google Calendar / Stripe test | Connected provider smoke passed: calendar create/move/read and one $1 Stripe test payment, replayed with the same identity | Five connected fault turns and measured remote latency; finite sample |
Voice / Alexa+ | Browser speech controls and a simulated Alexa+ experience | No official Alexa+ integration, account linking or certification; no Echo test |
Quickstart: no keys, no real money
Install Docker with Compose, then from the repository root:
docker compose up --buildOpen the simulator. Leave Scripted selected and press Continue five times, waiting for each result. The sequence books, requests consent, recovers a lost payment response, refuses to confirm a failed move, retries on request, and recaps receipts. The second Continue is the scripted human approval. Payments are local Fake records.
The screen has three columns from 1200px wide: your conversation with the assistant on the left, the receipt that backs each answer in the centre, and a grey rail of demo controls on the right (labelled as not part of the product). Back and Continue step through the states already received; only at the latest state does Continue ask the server for the next scripted step. The approval button appears only while an approval is pending. Changing mode or timezone starts a new conversation; the previous one stays readable but accepts no more actions.
In free voice mode the OK for a charge is classified without the model: natural affirmations ("yes, please charge it", "go ahead") grant it, a decline ("no, cancel that") clears it and says so, and a bare "ok" counts only as the first answer to the question. Tapping the microphone while the assistant speaks interrupts it and listens; a turn that is still working after 1.5 s says "One moment, I'm checking that." and turn errors are spoken as well as shown. Receipt phrases are written for the ear: relative day, no timezone in the voice, confirmation by its last four characters; the receipt column keeps the full detail.
Compose reads .env.example directly: DONEWISE_MODE=sandbox, LLM_PROVIDER=none and a public
local-demo admin capability. That value is not a production secret. MCP is at
http://localhost:8765/mcp; only loopback ports are published. Do not expose this configuration
publicly. ./data stores SQLite and Fake JSON. docker compose down preserves it. Simulator
sessions are in memory; restarting the simulator starts a new conversation, while receipts persist.
If host ports are occupied, use PowerShell overrides (internal ports remain 8765/8080):
$env:DONEWISE_SERVER_PORT = '18765'
$env:DONEWISE_SIM_PORT = '18080'
docker compose up --buildThen open http://localhost:18080. These ports were used in the
Docker acceptance, preserving existing servers. Compose does not
use private .env values as its service environment; connected instructions use uv --env-file.
Never put private credentials in .env.example.
Screenshots from the real UI
Captured on 13 October 2026 from sim/static served by Docker, Scripted mode, sandbox adapters,
live MCP; voice off. These are application screenshots, not the mockup or offline fixture. They
show the previous visual design: on 18 October 2026 the simulator moved to the three-column
"Editorial plano" layout specified in design/mockups/B2-Editorial.dc.html. The flow and the
receipts are unchanged; the demo video recorded on 20 October 2026 shows the current layout.



Capture conditions and persisted-store checks: Docker acceptance.
Video claims → evidence
Every narration segment from PRD §9.1 is mapped below. The demo video recorded on 20 and 21 October 2026 uses a shorter script over the same scenario. Use the qualified wording. The table preserves the original sandbox evidence; the AWS section below adds connected/cloud proof. Official Alexa+ integration remains unsupported.
Segment / planned claim | Receipt, trace or test | Supported wording today |
0:00 “This one charged twice” / “Nothing was checked” | S01 baseline result and companion JSON | Deterministic Fake baseline recorded two charges totaling $120; not Stripe or a model-generated quote |
0:08 “MCP add-on for Alexa+… reads… never does it twice” | MCP verification harness in a simulated Alexa+ UI; zero duplicates in this finite suite, no universal guarantee | |
0:15 “Real MCP… 2025-11-25… real calendar and test payment… two faults” | Real MCP; original trace uses Fake providers. Connected faults also verified | |
0:25 “Books, reads back, asks… exact amount and payee… nothing charged” | Verified sandbox event and bound $60 approval with zero writes before consent | |
0:45 “Response lost… recovered by reading… one test charge” | Client turn 2, | One Fake charge recovered through read-back and bounded identity-preserving replay |
1:15 “Calendar said OK… twice… retried once… then asked… showed ten” | NOT_OBSERVED after two false acknowledgements; explicit retry of the same operation verified 10–11 | |
1:40 “Only repeats what it checked, and when” | Recap reports stored observations and timestamps without writes; not a fresh provider read | |
1:55 “Any MCP client gets the same receipt” | These clients received structured receipts; Desktop and arbitrary clients unvalidated | |
2:20 “Zero false confirmations, zero duplicates… numbers… compose” | Table above, matrix, Docker trace | Zero observed in the published deterministic sample, with denominators and whole-harness comparison limits |
Connect an MCP client
Saved receipts in a new session
receipts_recap can receive an explicit previous run_id, with the same MCP bearer
and user as the original session. It reports saved observations with full date,
time and timezone, and states how many operations remain unverified or pending.
It performs no new calendar/payment reads or writes. A new MCP connection needs
no chat history: the second-session regression exercises this.
This server is a single-user demo: its authenticated MCP context is user_id=demo.
Knowing a run ID is not authorization. Keep the bearer private and provision a
separate server/data directory for another user; production requires an authenticated
account-to-run ownership mapping. The new Strands client must retain this explicit
boundary instead of treating an arbitrary user ID/header as authorization.
Start Compose first. The demo has no MCP bearer token. If configured, supply
Authorization: Bearer <your-token> through the client, never a model prompt. Keep the MCP session
and operation ID when polling PENDING; a late response is not permission to submit another write.
Inspector (CLI tested):
npx --yes @modelcontextprotocol/inspector@1.0.2 --cli http://127.0.0.1:8765/mcp --transport http --method tools/listFor the UI, run npx @modelcontextprotocol/inspector@1.0.2, select Streamable HTTP and enter that
URL. The pin matches the recorded run; newer versions remain
unvalidated here. Official CLI reference.
Claude Desktop (example, unvalidated here): add this to its MCP configuration and restart.
Node.js/npx and the external mcp-remote bridge are required.
{"mcpServers":{"donewise":{"command":"npx","args":["-y","mcp-remote","http://127.0.0.1:8765/mcp"]}}}This assumes no bearer token. Obtain consent through a trusted human UI; never give the model admin or consent tokens. Setup and limitations.
Claude Code (five-turn sandbox run recorded):
claude mcp add --transport http donewise http://127.0.0.1:8765/mcpSee official HTTP configuration and our
client trace for tested JSON, version, --strict-mcp-config,
session reuse, receipt-only prompting and operator-managed approval. That run used port 8766.
Without form elicitation, a trusted operator must supply consent via the token flow; a model's
“yes” is not capability. The historical provenance issue in the trace predates the current
mcp_client/session_ui distinction in the server guide.
Run connected with your own keys (opt-in)
Use Python 3.12 and uv. Stop Compose if you need its ports. Copy .env.example to ignored .env:
DONEWISE_MODE=connected
GOOGLE_SERVICE_ACCOUNT_JSON=/absolute/path/to/private-service-account.json
GOOGLE_CALENDAR_ID=your-dedicated-test-calendar-id
STRIPE_SECRET_KEY=sk_test_your_own_key
DEMO_ADMIN_TOKEN=your-own-local-admin-secret
MCP_BEARER_TOKEN=your-own-local-mcp-secret
DONEWISE_DATA_DIR=./data/connected
LLM_PROVIDER=none
USER_TIMEZONE=America/Los_AngelesEnable Google Calendar API and share a dedicated test calendar with the service account with event
edit permission. Do not invite attendees. Use only Stripe test-mode secrets; startup rejects other
keys. Supported prefixes are sk_test_ and the CLI's temporary rkcs_test_ sandbox keys;
production and publishable keys are rejected. Keep credential JSON outside the repository.
The Stripe sandbox setup and evidence covers account-free provisioning,
expiry, local configuration, and the connected smoke check recorded on 18 September 2026.
Run in two terminals from the repository root:
uv sync --frozen
uv run --env-file .env donewise-server
# Second terminal:
uv run --env-file .env donewise-simThe scripted path needs no model. Explicit connected smoke test:
uv run --env-file .env pytest -m connectedIt creates/moves/deletes a calendar event and records a $1 Stripe test payment, then repeats the
payment request with the same idempotency key and checks that it returns the same PaymentIntent.
Five connected fault turns and independent Stripe read-back are now recorded. For free input, set
LLM_PROVIDER=anthropic, ANTHROPIC_API_KEY and an available ANTHROPIC_MODEL, or use Bedrock below;
select Free voice to start a new session. USER_TIMEZONE (America/Los_Angeles by default, or
America/Santiago) sets the clock the model, the scripted story, the recap and the page use.
Normal CI requires no provider credentials.
The model never sees submission_id or approval_id: the simulator generates the submission per
call and only the consent path adds an approval. A rejected tool call returns the violated rule
(never the value) and, when the turn produced no receipt, the model's question is shown. A small
manual eval, scripts/eval_tool_calls.py, measured this with Sonnet 4.6 in sandbox mode (3 runs
per scenario, 18-sep-2026): a future time books on the first call 3/3; a past time yields a
visible question with zero writes 3/3 and books only after the user answers 3/3.
Measured cloud latency
Per-tool p50/p95, sample counts and full-turn latency were measured from Chile against Lightsail us-east-1 with Google Calendar and Stripe test. The small sample includes injected faults; initial tool responses and pending polls are separate. These are diagnostic measurements, not production percentile estimates.
AgentCore returned the saved recap in 2579 ms on the first new-session call and 1358/1804/1606 ms on three warm calls. Warm latency passed the 6500 ms gate. Deterministic eval timing uses a logical clock and is not this benchmark.
AWS integration: observed results and deployment gates
Component | Verified evidence | Remaining boundary |
Amazon Bedrock | Nova Pro, Sonnet 4.6 and gpt-oss-120b passed Converse/tool smoke; three live-model fault evaluations with reviewed claims | Finite Fake-adapter evaluation; billing cost not retrieved |
Connected simulator | Five backend/MCP turns with Nova on Bedrock and Sonnet via Anthropic, real Google Calendar and Stripe test; configured model shown in header | Nova needed a corrected tool call; the demo video (20 October 2026) ran on Claude Haiku 5.5 |
Strands SDK | Native MCP client, five connected turns, exact receipt speech; new-session recap without history | Separate dependency environment; single-user demo, not multi-tenant authorization |
AgentCore Runtime | Deployed ARM64 Strands/Nova agent, exact receipt, one recap per trace; 50 actual exported spans | Small first-session/warm sample; read-only historical recap, no multi-user account binding |
Lightsail | HTTPS MCP deployed, persistent SQLite, five remote connected turns; bearer and private-admin boundaries verified | Single instance, no high availability; temporary Stripe sandbox must be renewed |
Classic Alexa Skill | Development skill → Lambda → AgentCore; 3/3 real Test-console text requests returned exact receipt speech | Classic skill, not Alexa+ add-on; no Echo test. The video (21 October 2026) uses the Developer Console simulator with typed text: its microphone returned "No Content" (friction log 23) |
The demo video was recorded on 20 October 2026 with Claude Haiku 5.5 · Anthropic API; the 18 October rehearsals used Sonnet 5.5 and the recorded sandbox runs above used Sonnet 4.6. Bedrock development and Strands use Nova Pro. GPT frontier models are unavailable to this account and are excluded; gpt-oss-120b is the third evaluated model. Existing AWS budget alerts were left unchanged at Walter's request; this work does not assert a hard spending cap.
The three-model comparison observed no duplicate charges in either variant. Baseline false-claim counts were Nova 5/14, Sonnet 5/19 and gpt-oss 4/15; DoneWise was 0/11, 0/14 and 0/11. These are application outcomes, including speech presentation, not a claim that the models always obey receipt instructions. Review method, denominators, run IDs and all limitations are in evals/README.md.
A second adapter in ~30 lines
ports.py requires source, write, read and replay_is_safe.
This educational in-memory calendar-create adapter reads its store separately from the write
acknowledgement. It is not wired into the server and refuses rescheduling and automatic replay.
from datetime import UTC, datetime
from donewise_harness.contracts import Action, EvidenceSource
from donewise_harness.ports import ReadResult, WriteResult
class TinyCalendar:
source = EvidenceSource.FAKE_CALENDAR
def __init__(self):
self.events = {}
def write(self, req):
if req.action != Action.CALENDAR_CREATE:
return WriteResult(status="error", provider_ref=None, version=None, error="Create only")
key = req.target.event_id
if key in self.events:
return WriteResult(status="already_exists", provider_ref=key, version="1", error=None)
self.events[key] = req.target.model_copy(deep=True)
return WriteResult(status="acked", provider_ref=key, version="1", error=None)
def read(self, req):
key = req.provider_ref or req.target.event_id
observed = self.events.get(key)
return ReadResult(
found=observed is not None,
observed=observed,
version="1" if observed else None,
observed_at=datetime.now(UTC),
source=self.source,
)
def replay_is_safe(self, req):
return FalseProduction adapters need durable identity, scoped reads, error classification, concurrency control, conditional updates and proven replay horizons. See Google and Stripe test plus their mocked HTTP tests. A new provider source also needs an explicit evidence-contract change; 30 lines illustrates the interface only.
Development and CI
uv sync --frozen
uv run ruff check .
uv run ruff format --check .
uv run pytest -m "not connected"
uv run donewise-evals --runner deterministic --output-dir data/evalsCI checks Windows/Ubuntu, excludes connected tests and uploads Markdown
tables plus JSON evidence per OS. Local Windows and Linux container results are in the Docker
trace. The reusable MIT package is in core/;
schemas document the contracts.
Known limits and delivery status
Finite deterministic sample, not a reliability guarantee or isolated-verifier experiment.
SQLite runs in one Lightsail server process on persistent disk; no distributed workers or high availability.
Simulator sessions/SSE history do not survive restart. Recap is historical evidence.
Replay windows are bounded; unresolved effects can remain UNKNOWN rather than be resent.
Google/Stripe smoke and five connected backend/MCP fault turns passed with Nova and Sonnet. Cloud latency and classic Alexa Test are recorded; the demo video was recorded on 20 and 21 October 2026.
Inspector CLI, Python ClientSession and Claude Code have evidence; Desktop and official Alexa+ do not.
Authenticated MCP is hosted; the skill stays in Development. No package release claimed; the demo video is public at https://youtu.be/wYBuYsQYc8I. Source: https://github.com/Walter102202/alexa-donewise.
Related MCP Connectors
Remote MCP for A2A failure replay MCP, structured receipts, audit logs, and reviewer-ready evidence.
Read-after-write receipts for agents: did your write actually land? Free, signed, re-checkable.
Resolve whether an uncertain side-effecting action completed before software retries it.
Read-only Remote MCP for externally grounded AI agent trust receipts.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceAn MCP server that checks whether the world changed after a tool call by declaring observable outcomes, verifying them with read-only verifiers, and keeping hash-chained receipts.6 npmMIT
- AlicenseNot gradedqualityBmaintenanceMCP server that resolves ambiguous outcomes of side-effecting API/tool calls, returning DONE, NOT_DONE, or UNKNOWN with retry safety guidance.MIT
- AlicenseAqualityBmaintenanceOwner-signed authorization before agent actions. Hosted Vizier v0.5.13 MCP: https://vizier.agendamcp.dpdns.org/mcp. ALLOW/BLOCK/REVIEW; anonymous calls never ALLOW. Your integration enforces the decision. SDK v0.5.13: https://www.npmjs.com/package/@agenda-intelligence/vizier-sdk. Grants are signed; legacy receipts are unsigned. Python stdio is a separate catalog.38 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP consumers to recover the outcome of a tool call when the server's reply is lost after the effect was committed, using a SQLite-backed operation ledger and identity-bound status queries to avoid duplicate side effects.MIT