The record comes first.
Everything the gateway knows is derived from append-only logs, one per project. This page is what that log guarantees, where the boundaries are, and how each part fails when it fails. Read it before you trust the rest of the site.
Example, not real data.
Written before the decision.
Every call lands in the project's log with its full request before any gate runs. Then the decision is appended, then the result. A refused call records which gate refused it and why; a failed call records the failure. Entries are only appended, never edited in place. A format migration that rewrites a log keeps the original as an archive.
The log keeps every body. Over 16 KiB it moves to a sidecar file with a digest the reader verifies; the agent, separately, gets a handle with a preview for anything over 64 KB, read with meta.python on base; on free the preview is what the agent gets. If the sidecar cannot be written, the body stays inline. The log is never pruned. Its size is shown per project and flagged past 500 MB. The history page exports it as newline-delimited JSON.
The model cannot say who it is.
The account, user, project, task and session on every entry are stamped by the server from its own configuration. The model can neither supply nor read an identifier. It writes three things into the log, all on request: the goal a person dictates, its own plan, and one reason sentence per call. Everything else on the entry is observed by the server.
Your account is the boundary.
Each project has its own configuration, downstream connections, credentials, goal and log. Sessions, the history API and token scopes all require membership of the project's account. Inside an account, members share what the account produced: history, response bodies, goals, plans, learned rules.
Three crossings exist, all declared. The evidence store is scoped to the account, not the project. An admin may name sibling projects whose calls appear as references when advice is given. And the operator of the hosted gateway can read every account, for support and to keep the service running; the operator never copies their own sign-ins into a customer's project. Nothing else crosses between projects, and no account's data, memory or history is shared with another account, free accounts included.
A server that asks for a sign-in gets one per person: each member authorizes it with their own account, and goal measurements a member starts run with that member's sign-in. When a server's URL changes, every token issued for the old URL is forgotten.
Named degradation, never a silent one.
What the Python sandbox blocks, and what it does not.
Sandboxed Python exists so an agent can work on a result too large to read. It runs with no network, writes only to a scratch directory that lives for one call, and cannot read the home directory, other users, mounted volumes, keychains, or the gateway's own code, data and secrets, including tokens and logs, so it cannot read another account's data. Output is capped and the process is killed at ten seconds.
It is a data mask, not a full jail: system directories stay readable and the interpreter runs as the gateway's own user. Where no sandbox backend exists the tool is not registered at all. There is no unsandboxed fallback.
Defaults as shipped.
Where the gateway connects.
The hosted gateway reaches remote and library servers only at public addresses: private, loopback, link-local and cloud metadata addresses are refused, and so is a redirect to one. It does not run local commands (stdio servers) on any plan. Running them under a network guard is what the secure plan will add; it is not on sale yet.
How it is hosted.
safe-mcp is a hosted service. You sign in with Google; nothing is deployed on your side. One gateway process serves every account behind TLS, one runtime per project, one log per project. It is a single node today: there is no high-availability mode and no horizontal scaling of one project's log. Your log is exportable at any time as newline-delimited JSON, and it is never pruned. A deleted project's data stays on disk. Backups are kept for 30 days.
What it does not have.
No SSE transport; Streamable HTTP only. No email: an invitation is a link the inviter copies and sends. It works once, expires after fourteen days by default, and an owner can revoke it. No retention policy; the log grows and says so. No horizontal scaling.
Start with one client and one server.
First sign-in creates an account and one project. Its MCP URL works at once.