Patchbay
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Patchbaycompile my current routing policy and show the score"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Patchbay
Route every agent task to the model that should actually handle it.
Live App · Source · API · Agent Tools · Issues
Most agent setups send everything to one model. Patchbay is a routing patchbay: you
patch models onto fast, balanced, and deep lanes, and a deterministic compiler scores
the policy out of 100 using seven weighted factors — then you export a sealed manifest
you own.
Real prices, live. Normalized from OpenRouter and models.dev. Per-million input/output cost, context windows, and capabilities, with per-source attribution and a
live/fallbacklabel.Your keys stay yours. Provider keys are sealed with AES-256-GCM before they touch the database and are never returned by any read endpoint.
Every mutation is provable. Each agent carries a per-entity SHA-384 hash chain, and replay reports the first broken link.
An agent interface, not a chat box. Eight MCP-style JSON-RPC tools with read, analysis, and mutating paths that share the UI's service layer.
✨ Features
Outcome you get | How |
Stop overpaying for easy tasks | Patch a cheap classifier and a frontier model onto separate lanes, then read the real monthly projection. |
Catch a bad policy before it bills you |
|
Prove nothing was rewritten | Replay recomputes every seal from stored rows alone and names the first broken sequence number. |
Keep provider keys under your control | Store them encrypted; read paths return a label, last four characters, and a fingerprint. |
Drive it from your own assistant | Point an MCP client at |
Take the setup with you | Download a routing manifest with lanes, score, factors, provenance, and seals as JSON or a lane CSV. |
Related MCP server: wcc_mcp_server
🚀 Quickstart
git clone https://github.com/aniruddhaadak80/patchbay.git
cd patchbay
npm ci
npm run devOpen http://localhost:3000. No environment variables are required. Without
DATABASE_URL the app runs on an embedded Postgres (PGlite) persisted in
.patchbay/pglite, and the catalog serves a sealed offline sample when the upstreams are
unreachable.
Scripts
Command | What it does |
| Development server |
|
|
| ESLint |
| Vitest unit tests |
| Production build |
| Playwright journey on desktop, plus layout, navigation, validation and focus checks on mobile |
| Apply migrations explicitly (they also run on cold start) |
| Full HTTP proof against a deployment ( |
Production environment
Copy .env.example to .env.local. Only two variables matter:
Variable | Required | Purpose |
| Yes | Hosted Postgres connection string. The app refuses production traffic from the embedded adapter on a serverless host. |
| Yes | Signs the anonymous scope cookie and, by default, encrypts stored provider keys. |
| No | Dedicated key-encryption secret. Rotating it makes stored keys unreadable. |
| Yes | Absolute origin for metadata and Better Auth trusted origins. |
| No | Extra origins, comma separated, for preview deployments. |
Schema creation is idempotent and runs on cold start, so a fresh deploy needs no manual migration step.
📸 Product tour
The agent page: live catalog jacks on the left, three tier lanes on the right, and the compiled policy with its itemized factors and seal.
🗺️ How it works
System architecture
graph LR
Browser["Browser or MCP client"] --> Proxy["Edge proxy<br/>signed scope cookie"]
Proxy --> Pages["Server components<br/>/ /catalog /agents"]
Proxy --> API["Route handlers<br/>/api/*"]
Pages --> Repo["Repository layer"]
API --> Repo
API --> RPC["JSON-RPC 2.0<br/>/api/mcp"]
RPC --> Repo
Repo --> Engine["Policy compiler<br/>policy-compiler@1.0.0"]
Repo --> Store[("Adapter<br/>Neon or PGlite")]
Engine --> Manifest["Routing manifest<br/>+ SHA-384 seal"]
classDef live fill:#22d3ee,color:#06222a,stroke:#0e7490
classDef engine fill:#a78bfa,color:#1e1533,stroke:#6d28d9
classDef agent fill:#34d399,color:#0a2a1b,stroke:#15803d
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class Browser,API live
class Engine,Manifest engine
class RPC agent
class Proxy,Pages,Repo,Store infraData pipeline and honest fallback
graph TB
OpenRouter["OpenRouter<br/>/api/v1/models"] --> Merge["Normalize<br/>provider:model id"]
ModelsDev["models.dev<br/>/api.json"] --> Merge
Merge --> Snap["Catalog snapshot<br/>cached 15 min"]
Snap --> Decide{"Any source<br/>live?"}
Decide -->|yes| Live["status live<br/>with per-source<br/>latency and counts"]
Decide -->|no| Sample["Sealed offline sample<br/>frozen 2026-09-30"]
Live --> UI["Catalog UI and<br/>policy compiler"]
Sample --> Label["Labelled offline sample<br/>never presented as current"]
classDef live fill:#22d3ee,color:#06222a,stroke:#0e7490
classDef caution fill:#fbbf24,color:#2e1f05,stroke:#b45309
classDef engine fill:#a78bfa,color:#1e1533,stroke:#6d28d9
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class OpenRouter,ModelsDev,Live live
class Sample,Label caution
class UI engine
class Merge,Snap,Decide infraDeterministic policy compiler
graph TB
Lanes["Lane assignment<br/>tier, model, weight"] --> Price["Price a reference request<br/>1800 in / 700 out"]
Price --> Factors["Seven weighted factors<br/>cost coverage balance headroom<br/>context redundancy mobility"]
Factors --> Score["score = sum of contributions<br/>clamped 0 to 100"]
Score --> Verdict["Verdict<br/>ship / tune / rework"]
Verdict --> Seal["Seal the result<br/>SHA-384 over canonical JSON"]
classDef engine fill:#a78bfa,color:#1e1533,stroke:#6d28d9
classDef agent fill:#34d399,color:#0a2a1b,stroke:#15803d
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class Factors,Score,Price engine
class Verdict,Seal agent
class Lanes infraWeights: cost 24, coverage 18, balance 16, headroom 14, context 12, redundancy 10,
mobility 6. Full rationale is in src/lib/engine.ts and on /compile.
Agent sequence
graph LR
Client["MCP client"] --> Init["initialize<br/>protocolVersion, serverInfo"]
Init --> List["tools/list<br/>eight typed schemas"]
List --> Read["list_models<br/>read tool"]
Read --> Score["compile_policy<br/>analysis tool"]
Score --> Write["upsert_agent<br/>mutating tool"]
Write --> Same["Same service layer<br/>as the UI"]
Same --> Verify["verify_integrity<br/>replay the chain"]
classDef live fill:#22d3ee,color:#06222a,stroke:#0e7490
classDef agent fill:#34d399,color:#0a2a1b,stroke:#15803d
classDef engine fill:#a78bfa,color:#1e1533,stroke:#6d28d9
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class Init,List,Read live
class Write,Same,Verify agent
class Score engine
class Client infraIntegrity and seal replay
graph TB
Genesis["genesis = 96 zeros"] --> E1["event 1: created<br/>seal = SHA-384(prev or json)"]
E1 --> E2["event 2: updated"]
E2 --> E3["event 3: patched"]
E3 --> E4["event 4: deleted<br/>tombstone retained"]
E4 --> Replay{"Replay from<br/>stored rows"}
Replay -->|intact| Clean["ok: checked N events"]
Replay -->|rewritten| Broken["first broken seq<br/>with recomputed digest"]
classDef agent fill:#34d399,color:#0a2a1b,stroke:#15803d
classDef risk fill:#fb7185,color:#331014,stroke:#be123c
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class Clean,Replay agent
class Broken risk
class Genesis,E1,E2,E3,E4 infraUser journey
graph LR
Land["/"] --> New["/agents/new"]
New --> Detail["/agents/id<br/>patch a lane"]
Detail --> Compile["/compile<br/>read the factors"]
Compile --> Console["/agent<br/>drive over JSON-RPC"]
Console --> Verify["/verify<br/>replay the chain"]
Verify --> Desk["/export<br/>download the manifest"]
classDef live fill:#22d3ee,color:#06222a,stroke:#0e7490
classDef engine fill:#a78bfa,color:#1e1533,stroke:#6d28d9
classDef agent fill:#34d399,color:#0a2a1b,stroke:#15803d
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class Land,Detail,Desk live
class Compile engine
class Console,Verify agent
class New infra🔌 API
Errors share one envelope: { "error": { "code", "message", "details?" } }.
Create, then read back
BASE=http://localhost:3000
# What can we route to?
curl -s "$BASE/api/catalog?limit=3&capability=tools" | jq '.data.models[].id'
# Create a policy
curl -s -X POST "$BASE/api/agents" \
-H 'content-type: application/json' \
-H "idempotency-key: $(uuidgen)" \
-d '{
"name": "ticket-router",
"taskClass": "Route inbound support tickets to the cheapest adequate model.",
"budgetUsd": 300,
"lanes": {
"fast": { "modelId": "provider:cheap", "weight": 0.6, "dailyRequests": 1200 },
"balanced": { "modelId": "provider:mid", "weight": 0.3, "dailyRequests": 500 },
"deep": { "modelId": "provider:heavy", "weight": 0.1, "dailyRequests": 100 }
}
}' | jq '{id: .data.agent.id, score: .data.compiled.score, verdict: .data.compiled.verdict}'
# Read it back
curl -s "$BASE/api/agents/<id>" | jq '.data.agent.lanes'
# Patch one lane, guarding against a lost update
curl -s -X PATCH "$BASE/api/agents/<id>" \
-H 'content-type: application/json' \
-d '{"lanes":{"deep":{"modelId":null}},"expectedRevision":1}' | jq '.data.agent.revision'Compile a policy
curl -s -X POST "$BASE/api/compile" \
-H 'content-type: application/json' \
-d '{"agentId":"<id>","dailyRequests":4000}' \
| jq '.data.compiled | {engineVersion, score, verdict, projectedMonthlyUsd, warnings}'Verify and delete
curl -s "$BASE/api/verify?agentId=<id>" | jq '.data | {ok, checked, headSeal}'
curl -s -X DELETE "$BASE/api/agents/<id>" | jq '.data | {deleted, tombstone}'Credentials
curl -s -X POST "$BASE/api/credentials" \
-H 'content-type: application/json' \
-d '{"provider":"openai","label":"work key","secret":"sk-..."}' \
| jq '.data.credential | {provider, last4, fingerprint, keyValueReturned}'The response never contains the key. It returns keyValueReturned: false.
Full endpoint list
Method | Path | Purpose |
|
| Real write/read/delete round trip plus adapter state |
|
| Normalized catalog with provenance; filter by |
|
| Bypass the cache and refresh the feed |
|
| List (filter by |
|
| Read, update, soft-delete |
|
| Downloadable routing manifest |
|
| Score a stored agent or an inline lane board |
|
| Encrypted BYOK vault |
|
| Replay every chain, or one by |
|
| MCP-style JSON-RPC 2.0 |
|
| Move anonymous records into a new account |
|
| Better Auth (email and password) |
🤖 Agent interface
{
"mcpServers": {
"patchbay": {
"type": "http",
"url": "https://patchbay-zeta.vercel.app/api/mcp"
}
}
}public/mcp.json ships the same registration for MCP directories.
Tool | Kind | What it does |
| read | Normalized catalog with prices, context, capabilities, provenance |
| read | Your agents, newest first |
| read | One agent with a freshly compiled result |
| mutate | Create or patch lanes; honours |
| mutate | Soft delete, retaining a replayable tombstone |
| analysis | Versioned score with weighted factors and a seal |
| read | Replay chains and report the first broken link |
| read | The portable routing manifest |
curl -s -X POST https://patchbay-zeta.vercel.app/api/mcp \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"list_models","arguments":{"limit":3}}}' | jq '.result.structuredContent.models'📁 Project map
User routes
Route | Goal | States |
| Understand the product and start an agent | Live rack readout, honest catalog status |
| Browse live models and their provenance |
|
| Every policy, filterable in the URL | Filter, search, empty, bounded list |
| Create a policy | Validation, conflict on duplicate name, catalog-backed selects |
| Inspect, patch, compile, verify, delete | Patch bay, live score, audit chain, 409 on stale revision |
| Score a stored agent or an inline board | Versioned result, factor bars, warnings, per-lane recommendation |
| Encrypted BYOK vault | Format validation, masked list, delete, encryption explainer |
| Live JSON-RPC console | Preset calls, visible request and response, real errors |
| Build the takeaway artifact | JSON download, lane CSV, manifest preview |
| Replay every seal chain | Per-chain verdict with head seal and break point |
| Public read-only policy view | Score, factors, manifest, no owner notes |
| Optional account, adopts anonymous work | Create, sign in, adoption result |
API routes
Path | Responsibility |
| Live persistence round trip and adapter safety state |
| Catalog read, filters, cache bypass |
| List and create with catalog validation |
| Read, update with revision guard, soft delete |
| Attachment manifest download |
| Stored or inline policy compilation |
| Encrypted credential CRUD |
| Seal replay |
| JSON-RPC 2.0 and the eight tools |
| Anonymous-to-account adoption |
| Better Auth handler |
Core modules
Path | Responsibility |
|
|
| Canonical JSON, SHA-384 chain, replay |
| The portable routing manifest |
| Fetch, normalize, merge, fallback labelling |
| AES-256-GCM sealing and format validation |
| Signed anonymous scope cookie |
| Zod schemas, error envelopes, write throttle |
| Adapter selection, Neon and PGlite clients, migrations |
| Every query, ownership-scoped |
| Anonymous-to-account record migration |
| Single source of truth for links and metadata |
| Live end-to-end proof |
| Explicit migration runner |
🔐 Security model
Credential encryption. AES-256-GCM, random 12-byte IV per record, auth tag stored with the ciphertext so tampering fails closed. Key derived with SHA-256 from
CREDENTIAL_ENCRYPTION_KEY, falling back toAUTH_SECRET. Rotating either value destroys stored keys.No secret in a read path. Only a label, last four characters, and a SHA-256 fingerprint of the ciphertext are ever returned. Exports omit credentials entirely.
Signed ownership. Anonymous scopes use an HMAC-SHA256 signed, HTTP-only cookie, verified with a constant-time compare and never accepted from a query string.
Owner-scoped SQL. Every read and write filters by owner id. Cross-session reads return 404 rather than 403, so existence is not leaked.
Validated input. Model ids reject
..and trailing slashes; strings have length caps; enums are closed; queries are parameterized.Truthful errors. Stable codes and messages. No stack traces, SQL, or environment values in responses.
Abuse controls, honestly
Write throttling is an in-process counter: 120 writes per minute per scope. On serverless that is per-instance and resets on cold start, so it is a courtesy brake rather than a guarantee. A high-traffic deployment should put a hosted limiter in front of the write endpoints. Anonymous scopes are not accounts until someone signs up, and clearing cookies means losing access to anonymous work.
🗄️ Data provenance
Source | Used for | Endpoint |
Per-token prices, context length, modalities | Public, no key | |
Capability flags, release dates, open-weight status | Public, no key |
Both are fetched with a 6-second timeout, cached in-process for 15 minutes, and reported
per source with fetch time, record count, and a sample upstream id. When both fail, the
app serves a sealed offline sample frozen on 2026-09-30 and labels it fallback on every
surface. Prices are reference data, not quotes.
🗺️ Roadmap
Now
Live catalog merged from two public upstreams with honest fallback
Deterministic seven-factor policy compiler with itemized contributions
Patchbay interaction: patch a model onto a lane and watch the score recompute
Per-agent SHA-384 seal chain with replay and a public verify route
MCP-style JSON-RPC 2.0 with eight tools, including mutating paths
Encrypted BYOK vault with no secret in any read path
Routing manifest export as JSON and lane CSV
graph LR
Cat["Live catalog"] --> Patch["Patch bay"]
Patch --> Engine["Compiler"]
Engine --> Export["Manifest"]
Engine --> Seal["Seal chain"]
Seal --> MCP["MCP tools"]
Vault["Encrypted vault"] --> MCP
classDef live fill:#22d3ee,color:#06222a,stroke:#0e7490
classDef engine fill:#a78bfa,color:#1e1533,stroke:#6d28d9
classDef agent fill:#34d399,color:#0a2a1b,stroke:#15803d
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class Cat,Patch live
class Engine,Export engine
class Seal,MCP agent
class Vault infraNext
Latency probe — measure real time-to-first-token per patched model so the compiler can score latency instead of estimating it.
Traffic splitting rules — route by task length or estimated difficulty so a lane decides where a request goes, not just which model serves it.
Budget alerts — notify when projected spend crosses a fraction of the ceiling, before the month ends.
Team workspaces — share a patchbay across an organization with per-member ownership of the lanes they patch.
graph TB
Probe["Latency probe"] --> Engine["Compiler scores latency"]
Rules["Split rules<br/>by length and difficulty"] --> Router["Lane decides per request"]
Alerts["Budget alerts"] --> Ceiling["Act before the month ends"]
Workspaces["Team workspaces"] --> Shared["Shared bay, per-member ownership"]
Engine --> Router
Router --> Manifest["Better manifests"]
classDef live fill:#22d3ee,color:#06222a,stroke:#0e7490
classDef engine fill:#a78bfa,color:#1e1533,stroke:#6d28d9
classDef agent fill:#34d399,color:#0a2a1b,stroke:#15803d
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class Probe,Rules live
class Engine,Router engine
class Alerts,Ceiling agent
class Workspaces,Shared,Manifest infraLater
Shadow evaluation — run candidate lane assignments against a sample of real prompts and compare outcomes before committing to them.
Manifest consumers — first-class adapters that turn a manifest into an OpenRouter, LiteLLM, or OpenAI-compatible client configuration.
Provider health signals — route around an outage instead of discovering it in your logs.
Audit export — hand the whole chain to an external verifier.
graph LR
Shadow["Shadow evaluation"] --> Evidence["Evidence before committing"]
Consumers["Manifest consumers<br/>OpenRouter, LiteLLM"] --> Runtime["Existing runtimes"]
Health["Provider health"] --> Failover["Automatic lane failover"]
Audit["Audit export"] --> External["External verification"]
classDef live fill:#22d3ee,color:#06222a,stroke:#0e7490
classDef engine fill:#a78bfa,color:#1e1533,stroke:#6d28d9
classDef agent fill:#34d399,color:#0a2a1b,stroke:#15803d
classDef infra fill:#94a3b8,color:#10151c,stroke:#475569
class Shadow,Health live
class Consumers,Failover engine
class Audit,External agent
class Evidence,Runtime infraDeployment
The app runs anywhere Node 20.9+ runs.
Vercel. Connect the repository, set
DATABASE_URL,AUTH_SECRET, andNEXT_PUBLIC_SITE_URL, deploy. Schema creation runs on first request.Any Node host.
npm run build && npm start. WithoutDATABASE_URLthe embedded adapter runs, which suits a single machine but loses data on redeploy — the app tells you this at boot rather than failing silently.
The app refuses to serve production traffic from the embedded adapter on a serverless host, because cold starts would discard it.
🤝 Contributing
Issues and pull requests are welcome. Read CONTRIBUTING.md first: it documents where the engine, seal chain, and repository layer live, and the conventions that keep the UI, the REST API, and the MCP tools from disagreeing.
Security problems go to SECURITY.md, not the issue tracker.
License
MIT © 2026 aniruddhaadak80
Data courtesy of OpenRouter and models.dev. Both are independent projects; Patchbay is not affiliated with either.
This server cannot be deployed
Maintenance
Related MCP Connectors
Guarded MCP server for agent-readable business truth, provenance, readiness, and discovery.
Workflow diagnostics, capability routing, and x402 settlement for MCP-compatible agents.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
MCP server for Riveter's enrichment, scraping, and monitoring API
Related MCP Servers
AlicenseNot gradedqualityAmaintenanceMCP server for AgentMark. Exposes the full AgentMark API to AI editors: list traces and spans, manage datasets, write scores, run experiments, manage apps, deployments, environments, and annotation queues.352AGPL 3.0- FlicenseAqualityBmaintenanceExposes the WCC event, mentorship, and analytics pipeline tools as MCP endpoints with per-group authentication and dry-run support, enabling agents to manage events, mentors, and analytics.10-
- AlicenseAqualityBmaintenanceProvides a JSON-RPC MCP server that exposes policy-governed agent tools, including paid tools, tool muxing, and OpenAPI-to-MCP conversion, enabling agents to discover, coordinate, and execute tasks within the ProtoOS ecosystem.51Apache 2.0
- FlicenseNot gradedqualityCmaintenanceExposes a version-controlled knowledge base as MCP tools so agents can read merged identity/state summaries and next recommended actions at runtime, plus run deterministic schema validation and cross-reference link checks. This lets agents fetch live state and verify integrity via self-describing calls instead of re-reading raw files.-