Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

App Harness

БесплатноНе проверен

Exposes a support-desk application through MCP tools and resources with populate/snapshot/restore hooks for reproducible RL training episodes.

GitHubEmbed

Описание

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:

  1. 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.
  2. Make state reproducible. populate() seeds a deterministic baseline; snapshot() captures full state; restore() re-applies it. restore(snapshot(x)) == x is asserted in the tests (tests/test_hooks.py).
  3. Keep it testable locally. The HTTP client is transport-injectable, so the whole stack runs in-process over httpx.ASGITransport in 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.

from github.com/tachyurgy/mcp-app-harness

Установка App Harness

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/tachyurgy/mcp-app-harness

FAQ

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

Compare App Harness with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development