Govern an agent you bought
Put Joopler in front of your own MCP server, so an off-the-shelf agent gets tool-level permissions, run-scoped caps and a signed trace without the vendor changing anything.
Every other page here assumes the agent reports into Joopler, either because you built it or because the vendor shipped it with governance. This page is for the case where neither is true: you bought an agent, the vendor has not integrated anything, and it is about to touch systems that matter.
You do not need the vendor. If the agent reaches your systems through an MCP server you run, you can put the decision in front of that server instead of inside the agent. In healthcare that is usually the interesting one anyway: the MCP server exposing FHIR is yours, not theirs.
This is new. It is deployed and tested, and no customer has run production traffic through it yet. Read what it does not do before you put it in a path that matters, and talk to us first.
What changes
Nothing in the agent. You change one URL in its configuration: instead of pointing it at your MCP server, you point it at Joopler, and Joopler forwards to your MCP server.
before agent ─────────────────────────────▶ your MCP server
after agent ──▶ Joopler ──▶ your MCP serverEvery tools/call is checked before it is forwarded. A refused call never
reaches your server, and the agent receives a JSON-RPC error saying why.
Setting it up
-
Register the MCP server in Joopler, with its URL. Joopler needs to know where to forward, and the server must be reachable from the internet over https.
-
Register the agent and issue it a credential. It starts with
jpt_and is bound to that one agent, so stopping the agent revokes it in the same act. -
Point the agent at Joopler. Set its MCP server URL to:
https://api.joopler.com/v1/mcp/<your-server-key>and set the bearer token to the
jpt_credential. -
Set the policy on the agent: which tools it may call, how many steps and writes one run may make, whether an unapproved or drifted server is refused.
That is the whole integration. No SDK, no code change, no vendor.
What you get
Tool-level permissions. Allow and deny lists at server:tool, server, or
bare tool granularity, with deny winning. A tool that is not on the list is
refused before your server sees it.
Run-scoped caps. The limits count across the whole run, not per call. An agent can make four hundred calls that are each individually allowed, and the four hundred together are the incident. Steps and writes per run bound the blast radius, and the call that crosses the line is the one refused.
Manifest drift. When you approve a server, Joopler pins a fingerprint of every tool's name, description and input schema. On reconnect it recompares. The case worth alarming on is a tool that keeps its name and quietly changes what it tells the model it does, because the description is what the model reads. Drift is always flagged; refusing on it is a per-agent setting.
A signed trace. Every call lands in one hash-chained, KMS-signed run, including the refused ones, so the record shows what the agent tried as well as what it did.
What this does not do
It only covers servers you can put us in front of. A vendor-hosted MCP server, or an agent calling a plain REST API, is outside this. For those the controls are the ones that do not need the call path: discovery finds the agent, credential-scope drift catches the vendor widening what it holds, and containment revokes the credential. Those are detection and revocation, not prevention, and we would rather say so than let you assume otherwise.
The run boundary is inferred. The SDK is told where a run starts and ends by the agent host. A proxy is not: it sees a stream of tool calls and infers the boundary from the MCP session. That is usually right and never certain, so every run assembled this way is labelled as inferred in the timeline, and run-scoped numbers carry that caveat. Do not read an inferred run the way you would read a reported one.
stdio servers cannot be proxied. They run on the agent's own host, so there is no wire for us to sit on. Those need the SDK.
When Joopler cannot decide
If the decision itself fails, because our database is unreachable or our code has a bug, the default is to refuse. A control that disappears during an outage is not a control.
You can change that per agent, because for a clinical workflow you may decide
that blocking care during our outage is the worse risk. Set
onCheckUnavailable: "allow" on the agent's policy and the call is forwarded.
If it is forwarded unchecked it is recorded as unenforced, never as allowed, and shown that way in the run timeline. A trace that implies a decision nobody made would be worse than the gap it hides.
If we cannot read the agent at all we refuse regardless of the setting: there is no policy to honour if we cannot establish whose policy it is.
Ship your agent with governance built in
For companies that SELL agents. Your customer gives you a credential; your agent reports into their compliance workspace. You write it once, every customer gets their own evidence.
See AI usage without touching a runtime
Connect a read-only admin key and Joopler reads each provider's own usage report. No proxy, no gateway, no change to anything you ship.