Restrict MCP by network origin
By default, the MCP surface is protected by token possession alone: any origin on the internet that
presents a valid PAT opens a session and runs your organization’s tools. A leaked token — in a committed
.mcp.json, a CI log, a laptop config backup — is read access to your infrastructure, from anywhere.
The origin allowlist does not replace the token. It adds a second factor: besides having the credential, you must be on your network. A leaked token stops being enough.
How it works
Section titled “How it works”You declare the CIDR blocks (IPv4 and IPv6) allowed to talk to the MCP server, under Governance → Network origin access.
The check runs on every request, not only when the session opens. An MCP session is long and stateful, but origin authorization is not: a token that changes network mid-investigation is refused from that point on.
Before turning it on: start from the observed origins
Section titled “Before turning it on: start from the observed origins”The failure mode here is lockout — configuring the wrong list and shutting your whole team out. Office NAT, cluster egress and VPN exits are rarely the address people assume, and guessing the block is the fastest way to lock yourself out.
That is what the observed origins screen is for: the last address each of your tokens reached us from. Start there. It is the real address, measured on our side, rather than the one someone assumes — just connect once with your MCP client before configuring the list.
It is also useful for something else, and that part was always real: it confirms the IP reading is correct end to end (a wrong hop count shows up there as an obviously wrong value) and it surfaces a use coming from somewhere nobody expected.
And if you do lock yourself out, the way back does not depend on it: the refusal echoes the caller’s own IP and becomes an audit entry, so the missing block is readable from the refusal itself.
What we keep of that origin, and for how long
Section titled “What we keep of that origin, and for how long”Recording the address of every authorized connection is what makes the screen above work for someone who does not have a list yet — and it is collection, so it comes declared and with a switch.
- One address per token, the last one. There is no history: each connection overwrites the previous value. We do not keep route, geolocation, or the address of every request.
- It does not leave your organization. Owners and admins of your organization read it, and nobody else: it feeds no cross-customer aggregate and is never sent to a model provider.
- It lives as long as the token does. Revoking a token erases the address in the same action; deleting the organization erases everything; and an origin not seen again for 90 days is erased on its own — where your team connected from three months ago is not evidence of today’s egress, and offering that as a starting point would be lockout with an extra step.
- The address of a REFUSED connection stays in the audit log regardless: that is how a leaked token being used from outside becomes visible to you, and an access control that does not record the refusal is not verifiable.
To turn it off: Governance → MCP connection origin, the “Record the origin of each connection” switch. Turning it off also erases what was already observed in your organization, and the change lands in your audit log. The cost is the one from the first section: the origins list goes empty, and configuring the allowlist goes back to depending on you finding your own egress elsewhere.
When a request is refused
Section titled “When a request is refused”The response is 403 with error: "origin_not_allowed", and it does not echo the list — someone on
the outside learns nothing about what would be accepted. It does echo the observed IP of that request,
which belongs to the caller, and is what lets a legitimate person ask for their block to be added.
Every refusal becomes an audit entry with the observed address. That is how a leaked token being used from outside becomes visible to you — an allowlist that blocked silently would hide precisely the event that matters.
What happens if we cannot read the policy
Section titled “What happens if we cannot read the policy”The request is refused (503), not allowed.
Failing to read the policy is ambiguous between “there is no list” and “I don’t know whether there is one”, and in an access control those two cannot have the same effect. Refusing is visible and reversible; allowing silently would turn an outage of ours into a hole in your control.
Who enforces it, and what that means for you
Section titled “Who enforces it, and what that means for you”What it does not cover
Section titled “What it does not cover”- The Agent (runner) connection does not go through this. It connects over mTLS with a per-organization certificate, which is stronger proof than a network address — restricting it by IP would add operational fragility (the fleet is ephemeral and egress moves) without adding a guarantee.
- It does not replace token rotation. If you suspect a leak, revoke the PAT; the allowlist narrows the window, it does not close it.
- It is not network isolation. It filters who talks to the MCP server, not what happens afterwards — for what can be read, see the tool denylist.