Munin
Munin developer portal
Get a key →
Guide · Integrations

Connect your own system.

A customer emails asking about their subscription. The answer lives in a CRM you wrote yourself, that no vendor adapter will ever cover. You don’t need to export it, mirror it, or sync it into Munin — you put a small MCP server in front of it and the agent reads it live, mid-conversation.

First, the thing people get wrong this is a customer-facing surface

Tools from the server you connect are offered to the agent while it answers your customers on chat, email and SMS. This is not a toolbox for your own admin agent. Point it at a general-purpose MCP server you happen to use internally — a database MCP, a GitHub MCP, an internal ops MCP — and you have handed those capabilities to whoever writes into your support inbox.

Munin’s protection is that a connection exposes nothing by default. You name the individual tools customers may reach; a server with an empty allow-list stays connected and completely silent. Before adding a tool, ask: would I be comfortable if any member of the public could call this, about themselves, with no further checks? If you want extra tools for your own agent, add that MCP server to your client (Claude, ChatGPT) next to Munin instead — that is what Connect Claude is for.

The model live reads, nothing stored

Munin stores the connection — a URL and an encrypted bearer token — and nothing else. No contact import, no nightly sync, no copy of your data. Every answer is a request to your server at the moment the agent needs it, so a subscription cancelled ninety seconds ago is already cancelled in the reply.

What you build
An MCP server over streamable HTTP with a handful of read tools. Any MCP SDK works; the reference implementation is about eighty lines.
What Munin sends
A bearer token you minted, plus a signed assertion naming the customer the agent is currently serving.
What the agent gets
Your tools, namespaced ext_<connection>_*, alongside its built-in ones — but only the ones you explicitly allow.
When your server is down
The agent answers without those tools. A broken connector never breaks a conversation.

1 · Connect the server

In the dashboard, Integrations → Customer self-service MCP server. Paste the endpoint URL. The bearer token is entered in the dashboard through a one-time credential link, never pasted into a chat with an agent.

2 · Test, and read the exposure line

Munin connects and lists every tool your server offers. The result will say 0 exposed to customers. That is correct — a fresh connection exposes nothing.

3 · Choose what customers may reach

Open Choose tools on the connection’s menu. Munin asks your server what it offers and lists every tool with a checkbox; tick the ones customers may call. This is the safety mechanism: a server you misconfigured, or pointed at the wrong system, stays silent until a human deliberately ticks something. Agents do the same thing with connectors_list_server_tools and connectors_set_allowed_tools.

Not marked read-only
Any tool your server hasn’t marked readOnlyHint is flagged in the picker — a customer asking a question could change data on your side.
Muting a server
Empty the allow-list to silence it while keeping the credential and the URL.

Who is asking and how much to trust it

Your tools must not take an email or customerId argument. An argument is something a confused or manipulated model can fill in with somebody else’s identity. Instead every call carries an X-Munin-Identity header — a short-lived ES256 JWT you verify against a public per-org JWKS document — naming the person the agent is serving and, crucially, how well that name is known.

authenticated
Your backend vouched for them: an identity-verified widget session, or a delegated token you minted after logging them in. Treat as signed in.
channel_asserted
Taken from the channel envelope — an email From: header, an SMS sender, a caller ID. All spoofable. Anyone can send mail claiming to be someone. Fine for order status; not sufficient on its own for anything you wouldn’t put on a postcard.
self_reported
An address typed into a chat by an anonymous visitor. Worthless as identity.

Provenance describes the turn happening right now, not the person’s history. If a customer once signed in through the widget and someone later emails pretending to be them, that email arrives as channel_asserted — never authenticated. Decide per tool what the minimum is and enforce it server-side; for anything sensitive, do your own step-up first.

The full contract with a server you can fork

The complete specification — bearer auth, assertion verification, tool-shape rules, latency budgets, and a working reference server — lives in the skill your agent reads: Connect a custom MCP server. For the built-in vendors — Shopify, Magento, Gastroplanner — see Connect an external system.