Govern MCP tool calls in 5 minutes
Your agent can call tools now. So what stops it from deleting a customer, or reading a credit card number it was never meant to see?
DVARA is an AI governance platform. Its MCP Gateway sits between your agents and your MCP servers and checks every tool call on the way through. This page gets you a working setup on your own machine, then shows you three calls: one the gateway allows, one it cleans up, and one it refuses.
You need no licence key and no AI provider account. Without a licence, DVARA runs every feature for non-production use, up to 3 workspaces and 100,000 governed calls a month. See Get and apply a license.
What you need
- Docker with Compose v2
- JBang. It runs the demo MCP server from a single Java file, and downloads a JDK for you if you don't have Java 21 or later.
curlandopenssl, which most systems already have- Ports
8060,8080and8090free
The DVARA images are built for linux/amd64. On an Apple Silicon Mac, Docker Desktop runs them
under emulation, so the first start is slower.
Start everything
git clone --depth 1 https://github.com/dvarahq/dvara-examples.git
cd dvara-examples/docker-compose/mcp-quickstart
./start.sh
The first run downloads the images, so give it a few minutes. When it's done, you'll see:
✓ Ready. DVARA is governing the demo MCP server.
MCP endpoint http://localhost:8080/mcp (Streamable HTTP)
API key gw_5c0e7a91d2b84f36a1e9c7d04b6f2a8e3d1c95b7f0a4e612
Flightdeck http://localhost:8090 sign in as owner@quickstart.local / 8d41f0b29ce7a6153e0f7b2c
Your key and password will be different. The script makes new ones for you and saves them in
.env.
Watch it govern
./demo.sh
The script plays the part of an agent. It sends four requests to the gateway:
1. tools/list: the agent sees the demo server's tools, namespaced by server
demo-tools__delete_customer
demo-tools__lookup_customer
demo-tools__get_order_status
2. get_order_status: a harmless tool. Allowed, and recorded.
Order A-1001: shipped, arriving Thursday.
3. lookup_customer: the server returns an email, a phone and a card number.
The gateway redacts them before the agent sees the result:
Customer C-42: Jane Doe, [REDACTED_EMAIL], [REDACTED_PHONE_NUMBER], card on file [REDACTED_CREDIT_CARD], plan Enterprise.
4. delete_customer: a policy denies it. The server is never called.
REFUSED (MCP_POLICY_DENIED): delete_customer is irreversible and not allowed in this workspace
Here's what happened:
| Call | What the gateway did | Why |
|---|---|---|
get_order_status | Passed it through | Nothing in the workspace restricts it |
lookup_customer | Removed the email, phone number and card number from the result | The workspace's PII action is set to REDACT. The default is LOG, which records PII without changing it |
delete_customer | Refused it before it reached the server | A policy on the workspace denies this tool |
Check the record
Open http://localhost:8090 and sign in with the email and password from
start.sh. Go to MCP → Tool Calls. Every call from the demo is there with its server, tool,
workspace, status and latency. The refused call shows status 403, and the redacted one is marked
in the PII column.
Call it from your own client
Point any MCP client that speaks Streamable HTTP at the gateway, with your key as a bearer token. This is the raw request for the refused call:
curl -s http://localhost:8080/mcp \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"demo-tools__delete_customer","arguments":{"customerId":"C-42"}}}'
{"jsonrpc":"2.0","id":1,"error":{"code":-32001,"message":"delete_customer is irreversible and not allowed in this workspace","data":{"dvara_code":"MCP_POLICY_DENIED","http_status":403,"trace_id":"3054f7e845e4437ea9ec3fb704fe9a0e"}}}
Replace <your-api-key> with DEMO_API_KEY from .env. Tool names have the form
<server>__<tool>, so one endpoint can serve tools from many MCP servers.
What the script set up
start.sh writes .env, starts the demo MCP server, starts PostgreSQL, Flightdeck and the gateway
with Docker Compose, then loads seed-config.json into Flightdeck. That file holds three things:
- the demo MCP server, registered in the
quickstartworkspace - a policy that denies
delete_customer pii.action: REDACTon the workspace
To try your own MCP server, add it in Flightdeck under MCP → Servers and select Sync Tools. Its tools appear on the same endpoint. The native MCP endpoint page explains the endpoint in full.
If something goes wrong
| What you see | What to do |
|---|---|
jbang is not installed | Install JBang, then run ./start.sh again |
Flightdeck did not come up or The gateway did not come up | Check that ports 8080 and 8090 are free, then look at docker compose logs |
MCP server failed | Check that port 8060 is free. The server log is in .quickstart/mcp-server.log |
The gateway does not list the demo tools yet | Wait a few seconds and run ./start.sh again. It is safe to run more than once |
To stop, run ./stop.sh. To start over from nothing, run ./stop.sh --reset. That also deletes
the database and .env.
Next steps
- Run the full platform locally with a real model provider
- Agents and MCP in Flightdeck, to manage servers, tools and approvals
- The native MCP endpoint, for the full protocol and error reference