PluginWorld
Ro

rosetta-mcp

MCP

Turns a HAR capture of an undocumented web system into an MCP server whose tools automatically handle hidden CSRF tokens, ETags, and rotating nonces, with write actions gated behind confirmation and exercised only against a sandbox. Verified tools are shipped alongside an honest report of the actions that could not be automated and still need a human.

@Anuragt1104 · MIT License · updated today

SECURITY

B

SCORE

60

STARS

▲ 0

PLUG IN

git clone https://github.com/Anuragt1104/rosetta-mcp.git

See the README to configure this MCP server

README

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

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.

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 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

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 for the design decisions and algorithms.

Related work

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.

SIMILAR PLUGINS