App Harness
БесплатноНе проверенExposes a support-desk application through MCP tools and resources with populate/snapshot/restore hooks for reproducible RL training episodes.
Описание
Exposes a support-desk application through MCP tools and resources with populate/snapshot/restore hooks for reproducible RL training episodes.
README
A small, working reference implementation of the pattern behind an RL-training sandbox: take a real application, run it in a container, and expose it to an agent through a FastMCP server — with populate / snapshot / restore hooks so every episode starts from an identical, known state and any trajectory can be checkpointed and rewound.
It's deliberately tiny (a support-desk service + its MCP integration) so the seams are visible. Swap the demo app for any web/desktop app and the harness structure is unchanged.
┌────────────────┐ MCP tools/resources ┌────────────────────┐
│ Agent / RL │ ───────────────────────────────▶ │ FastMCP harness │
│ policy │ create_ticket, populate, │ (mcp_harness/) │
└────────────────┘ snapshot, restore, tickets://all └─────────┬──────────┘
│ HTTP (httpx)
▼
┌────────────────────┐
│ App under test │
│ FastAPI + SQLite │
│ (app/) │
└────────────────────┘
Why this exists
Integrating an app into a sandbox has three hard parts, and this repo shows a clean answer to each:
- Expose the app to an agent. Every product operation is a typed MCP tool
(
mcp_harness/server.py) and live state is an MCP resource. Schemas come free from the type hints. - Make state reproducible.
populate()seeds a deterministic baseline;snapshot()captures full state;restore()re-applies it.restore(snapshot(x)) == xis asserted in the tests (tests/test_hooks.py). - Keep it testable locally. The HTTP client is transport-injectable, so the whole
stack runs in-process over
httpx.ASGITransportin CI — no sockets, no flakiness — while production uses real HTTP unchanged.
Layout
| Path | Role |
|---|---|
app/ |
The application under test — a FastAPI + SQLite support desk. Stands in for the third-party app you'd integrate. Ships an /admin state surface (dump/load/reset). |
mcp_harness/server.py |
The FastMCP server — product tools + lifecycle tools + resources. |
mcp_harness/client.py |
Transport-injectable async HTTP client to the app. |
mcp_harness/hooks.py |
populate / snapshot / restore — the sandbox lifecycle contract. |
mcp_harness/config.py |
Env-driven service configuration (12-factor). |
fixtures/seed_baseline.json |
Deterministic starting state for populate(). |
tests/ |
pytest: app, hooks, and the MCP tools driven via FastMCP's in-memory client. |
Dockerfile / docker-compose.yml |
One image, two services (app + harness), healthcheck-ordered boot. |
Run it
Tests (fastest way to see it work):
uv venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"
pytest -q
Locally, two processes:
# terminal 1 — the app under test
./scripts/run_app.sh # http://localhost:8080/health
# terminal 2 — an episode: populate → act → snapshot → reset → restore
./scripts/demo_episode.sh
The MCP server:
python -m mcp_harness.server # stdio (embed in an agent runtime)
MCP_TRANSPORT=http python -m mcp_harness.server # HTTP transport on :9000
In a sandbox (Docker):
docker compose up --build
# app → :8080 | MCP harness (HTTP) → :9000
The MCP surface
Tools: create_ticket, list_tickets, get_ticket, assign_ticket, close_ticket,
populate, snapshot, restore.
Resources: tickets://all (live ticket list), health://app (liveness).
An agent's loop looks like: populate() → read tickets://all → call ticket tools →
snapshot() to checkpoint. An RL runner scores the resulting state and restore()s to
branch a new rollout.
Configuration (all via env — no code changes between environments)
| Var | Default | Meaning |
|---|---|---|
APP_BASE_URL |
http://localhost:8080 |
Where the harness reaches the app |
APP_DB_PATH |
:memory: |
SQLite path for the app (/data/... to persist on a volume) |
MCP_TRANSPORT |
stdio |
stdio (embedded) or http (sandboxed port) |
MCP_HOST / MCP_PORT |
0.0.0.0 / 9000 |
HTTP transport bind |
HARNESS_FIXTURE |
fixtures/seed_baseline.json |
Baseline for populate() |
APP_HTTP_TIMEOUT |
10 |
Client timeout (short, so a wedged app fails fast) |
Adapting to a real app
app/ is the throwaway part. To integrate a real app:
- Point
AppClient(or a subclass) at the app's actual API. - Re-implement the three hooks against whatever state seam the app exposes — a DB
volume snapshot, a
docker commit, an export/import endpoint, or a management command. The tool/resource layer and the tests don't change.
License
MIT.
Установка App Harness
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/tachyurgy/mcp-app-harnessFAQ
App Harness MCP бесплатный?
Да, App Harness MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для App Harness?
Нет, App Harness работает без API-ключей и переменных окружения.
App Harness — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить App Harness в Claude Desktop, Claude Code или Cursor?
Открой App Harness на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare App Harness with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
