Rosetta
by Anuragt1104
README.md
# Rosetta
**Turn the traffic of an undocumented web system into a verified, safety-gated MCP server, and get an honest report of what could not be automated.**
Web systems without API documentation are difficult to automate. Browser requests depend on hidden CSRF tokens, rotating nonces, and record-version headers that have to be traced and handled by hand. Rosetta turns a HAR capture of that traffic into MCP tools, tests them against a sandbox, repairs supported failures, and reports the actions that still need human work.
```
HAR capture ──▶ data-flow graph ──▶ MCP tools ──▶ verify ⇄ repair loop ──▶ deployable server + report
(what the (which value (plumbing (tested against a (and a list of what
browser did) came from where) hidden) sandbox, regression- needs a human)
gated)
```
## What it does on the demo system
The demo target (`demo/portal.py`) is a deliberately awkward "treasury ops" portal with seven real-world quirks: a login CSRF field hidden in HTML, a session CSRF header, an ETag precondition, single-use rotating nonces, a strict decimal-string format, rate limiting, and a request signature computed by front-end JavaScript.
| | |
|---|---|
| Requests in the capture | 9 |
| Raw endpoints found | 9 |
| Tools the agent sees | **5** (plus 1 quarantined) |
| Token bindings hidden from the agent | 7 (CSRF, ETag, nonce) |
| Verification, first generation | **5 / 12** cases pass |
| Verification, after the repair loop | **10 / 10** cases pass (2 iterations, ~4.5 s, 97 upstream calls) |
| Repairs applied automatically | 3: retry on 429, "latest value" tracking for single-use nonces, decimal-string coercion |
| Escalated to a human | 1: `create_payout`, whose `X-Sig` header is not derivable from traffic |
10/10 is over the tools that remain enabled. The quarantined tool is counted as unresolved, not as a pass. Three consecutive runs gave identical numbers. The first-pass figure depends on timing (rate limiting), so expect it to vary a little on other machines; the loop's outcome does not.
The agent-facing result, from a real MCP client:
```
agent sees 5 tools: list_payouts, get_payout, approve_payout, get_ledger, cancel_payout
approve_payout (no confirm) -> POST /api/payouts/P-1002/approve [preview only]
approve_payout(P-1001, 1250, confirm=true) -> approved # a number, coerced to "1250.00"
approve_payout(P-1002, 3400.0, confirm=true) -> approved # nonce rotated correctly between calls
create_payout -> tool create_payout is quarantined: header 'x-sig' is high-entropy, has no source ...
```
## How it works
```mermaid
flowchart TD
s0("ingest") --> s1("analyze") --> s2["synthesize"]
s2 -->|verify| s3["verify_repair"] --> s4["emit"]
s2 -->|skip| s4
```
**1. Data-flow graph.** For every value in every request, Rosetta looks for the earlier response it was copied from. Those links form a graph between endpoints (below for the demo). Echoes (a response repeating the id you just sent) are ignored. Business fields such as amounts are never auto-linked, only plumbing-shaped values are.
```mermaid
flowchart LR
login("GET /login") -->|"_csrf"| post_login{{"POST /login"}}
session("GET /api/session") -->|"csrf, x-nonce"| approve["POST …/approve"]
list["GET /api/payouts"] -.->|"choose an id"| detail["GET …/{payout_id}"]
detail -->|"etag → if-match"| approve
approve -->|"x-nonce"| create["POST /api/payouts (needs human)"]
create -->|"x-nonce"| cancel["POST …/cancel"]
```
**2. Tools, not endpoints.** The graph collapses plumbing: `approve_payout(payout_id, approved_amount)` fetches the CSRF token, the record's current ETag and the nonce itself. One tool per business action rather than one per HTTP call, which [Speakeasy's lessons from 50 production servers](https://www.speakeasy.com/blog/generating-mcp-from-openapi-lessons-from-50-production-servers) flag as a problem. A planner rule keeps this safe: **a state-changing endpoint is never run automatically as a prerequisite.**
**3. Verify and repair, with a contract.** The first generation is deliberately optimistic. It is then tested against a sandbox with cases from the capture (replay), from live data (the same tool on a different record), and agent-style inputs (numbers where the capture had numeric strings). Failures are diagnosed from evidence, and a proposer suggests a typed patch:
| Role | Who | Authority |
|---|---|---|
| Evaluator | plain code (`verify.py`) | defines "pass"; cannot be overridden |
| Proposer | heuristics, or Claude for what the rules cannot classify | proposes patches from a fixed, validated schema |
| Gate | `loop.regression_gate` | keeps a patch only if nothing that passed now fails and the pass count rises |
| Stop | converged · no proposals · no progress · budget · iteration cap | whatever is still failing is escalated to a human, with evidence |
**4. Ship.** `ir.json` (secret-free), a stdio MCP `server.py`, a `Dockerfile`, an MCP client config snippet, the data-flow graph, the loop trace, and `REPORT.md`.
> One finding worth stating plainly: replaying the captured `create_payout` request *passes*, because the capture's exact bytes carry a valid signature. Only a request with different content exposes that the signature cannot be reproduced. A replay-only test suite would have shipped a tool that fails on every real use. Rosetta therefore mixes in different inputs.
## Safety model
- State-changing tools return a **preview** unless `confirm=true`; nothing is sent upstream on a preview.
- Outbound requests are limited to allow-listed hosts, including across redirects.
- Captured secrets never enter the IR, the report, the trace or tool output. The emit step scans every output file against the capture's secrets and fails the build on a match. Credentials come from environment variables at run time.
- Write tools are only exercised by the verifier against a sandbox (loopback, or explicitly declared).
- Every call is appended to an audit log (`ROSETTA_AUDIT_LOG`) with the tool, status and a hash of the arguments.
- Upstream error text is treated as untrusted data, including when it is shown to a model.
## Run it
```bash
pip install -e ".[dev]"
python -m demo.run_demo # portal + capture + build + agent session, ~6 s
pytest # 69 tests, ~8 s
# on your own capture (Chrome DevTools: Network → Save all as HAR)
export ROSETTA_USERNAME=... ROSETTA_PASSWORD=...
rosetta build capture.har --name myapp --target https://sandbox.example.com \
--reset-url https://sandbox.example.com/__reset --allow-writes --sandbox
rosetta serve out/ir.json # stdio MCP server
rosetta graph capture.har # data-flow graph as Mermaid
```
`--brain claude` lets Claude propose repairs for failures the rules cannot classify (needs `ANTHROPIC_API_KEY` or an `ant auth login` profile).
## Limitations, stated plainly
- Developed and measured against one purpose-built target. The heuristics are real, but how they fare on messy third-party systems is unproven.
- Capture is HAR in, JSON and form bodies only. No multipart, GraphQL, MFA or OAuth flows. The recorder in `rosetta.capture` is for scripted sessions; a Playwright recorder for live sites is not included.
- Provenance is value matching. A value that is transformed before reuse (beyond simple prefixes like `Bearer`) is not linked.
- Path templating is pattern-based (numeric, UUID, `P-1001`-style ids). Slugs are not detected.
- Verifying write tools needs a resettable sandbox. Without one, writes are reported as unverified.
- `ClaudeBrain` is tested against a stub client (request shape, constraint handling, degradation). It has not been run against the live API.
- Signatures computed in client-side JavaScript are *escalated*, not solved. Reading the JS bundle is the obvious next step.
## Layout
```
src/rosetta/ har · templating · schema · dataflow (provenance graph) · synth · ir · runtime
verify · diagnose · repair · probe · brain · claude_brain · loop
stategraph · pipeline · emit · report · server · cli
demo/ portal (target), make_capture, run_demo
tests/ analysis · synthesis · runtime safety · loop contract · Claude brain · state graph · e2e · MCP
docs/ ARCHITECTURE.md
```
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design decisions and algorithms.
## Related work
[Integuru](https://github.com/Integuru-AI/Integuru) builds a request dependency graph from a HAR and generates code for a goal; tools like `har-mcp` and FastMCP's OpenAPI import turn traffic and specs into MCP servers. Rosetta's emphasis is what comes after generation: testing the result against a sandbox, repairing it under a regression gate, gating writes, and saying clearly what it could not do.
MIT licensed.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues