Outbound servers
Mount a third-party MCP server into your workspace so your own agents can call its tools, with trust, refresh and reconnect under your control.
Your workspace can be an MCP client too. Connect a remote server and every tool it serves becomes available to the agents that opt in, next to their built-in tools. This has no effect on the inbound endpoint described on MCP: connecting a server outward exposes nothing inward.
Every operation on this page needs the connectors system permission on your key or session: read to list, create to connect, update to refresh, rename, trust or reconnect, delete to disconnect.
Connect a server
Two sources:
- The catalog. A searchable list of curated entries — Notion, Linear, Stripe, Sentry, Supabase and around forty-five more — all on their official hosted endpoints and all OAuth, grouped by category. Picking one starts OAuth at once and brings you back to the same page after consent. An entry you already connected stays pickable ("Add another"), so a second Notion workspace is a second connection; another member connecting the same entry never blocks you either. The list is vendored with Standards, not fetched from a registry, so a server you cannot find there is still connectable as a custom server. Every entry is one whose OAuth flow Standards can start on its own. That leaves out Atlassian, whose published endpoint speaks Server-Sent Events, which this client does not, and servers such as GitHub, Vercel, Figma and Asana, which accept only OAuth clients registered with them in advance; connect those as a custom server if you hold credentials for them.
- A custom server. Any MCP server reachable over HTTPS. You give it a name, a slug, the URL and an auth mode.
A connection is all-or-nothing. The server is saved only after its first tools/list succeeds, so a listed server was reachable and authenticated at least once.
Auth modes
| Mode | What Standards sends |
|---|---|
none | Nothing. The server takes unauthenticated requests. |
header | One header, headerName: secret, verbatim on every request. Include the Bearer prefix in the secret yourself when the server expects one. The secret is write-only: once saved it is never shown again, including to you. |
oauth | The server's own OAuth flow, Authorization Code with PKCE. Tokens are stored encrypted and refreshed for you. |
From a terminal, standards mcp connect takes --auth-type none or header; OAuth servers are connected from the app. See CLI: MCP servers.
Visibility
visibility is workspace or private. A workspace server is visible to every member and to every agent that opts in. A private server is visible to you alone and only to an agent acting on your behalf. To anyone else it does not exist: no error, no id in a log, the same rule that applies to private records.
Slug and tool names
The slug is the server's identifier and the prefix of every tool it mounts. It is lowercase letters, digits and hyphens, starting with a letter or digit, unique per workspace. Underscores are not allowed, which is what keeps the tool name unambiguous:
mcp__<slug>__<tool>A server with slug notion that serves search mounts mcp__notion__search. Two servers can both serve search without colliding.
An OAuth connection — every catalog entry, or a custom OAuth server — picks its slug when it completes. It keeps the one it asked for when that slug is free in the workspace; otherwise it gets the slug plus a random six-character suffix, such as notion-3fa9c1, and its tools mount as mcp__notion-3fa9c1__search. The suffix is random rather than a count, so it does not tell you how many servers hold the name, including ones you cannot see. A derived slug does tell you the base slug is held by someone in the workspace, since slugs stay unique per workspace. The server's name stays the catalog name, with (2), (3) appended when you can already see a server by that name, as in "Notion (2)". Servers you cannot see are never counted. If five derivations in a row are all taken, the connect fails with mcp_oauth_slug_unavailable. A none or header connection is not derived: a slug already in use is refused.
Rename a connection
The name is only a label, so you can change it at any time to tell two connections of the same kind apart: Rename in a connection's menu in the app, or PATCH /mcp-servers/:id with { "name": "Notion — Sales" }, which returns the updated server. Renaming needs connectors:update.
- Only the name changes. The slug, and so every
mcp__<slug>__<tool>name an agent already uses, stays as it is. - The name is trimmed and must be between 1 and 100 characters; anything else is refused with
400. - A name another server you can see already carries is refused with
409and the codeSCHEMA_DUPLICATE. Servers you cannot see never block a name, the same rule as the automatic(2)suffix above. Renaming a server to the name it already has succeeds and changes nothing. - A server you cannot see answers
404, exactly like an id that does not exist.
Egress policy
Standards applies the same egress rules to every outbound MCP request:
- the URL must be
https://; localhost,*.localhost, loopback and private IP addresses are refused, and the resolved address is pinned for the connection;- an optional hostname allowlist can restrict which hosts may be connected at all;
- at most three redirects are followed, each hop re-validated against the rules above;
- the auth header is dropped the moment a hop changes origin, so a credential is never replayed to a host you did not configure;
- an OAuth credential request must not redirect at all.
Trust
A server is trusted on creation. Its tools go into the mutation tier: the same tier as a built-in tool that writes data, approved once per session rather than once per call, so "always allow here" is an offer Standards can actually keep. A remote tool is never placed in the outward tier. The annotations the server declares about its own tools (readOnlyHint, destructiveHint, and so on) are shown in the tool's description for you to read and are never used to decide the tier: they are written by the party being fenced.
Trust is pinned to the tool list you connected, not to the server itself. If a later refresh finds that list changed, the server is demoted and Standards re-arms confirmation on every one of its tools until a person trusts it again — see Tool groups and refresh for exactly what counts as a change.
A trusted server's tools are all treated as writes
Every remote tool is classified the same way, and none is classified as destructive. A session running in auto-approve mode will therefore run any tool of a trusted server without asking you first — including one that deletes something on the other side. If a server serves tools you would not want run unattended, take its trust away: standards mcp trust <id> --revoke puts every one of its calls back behind an explicit approval.
From a terminal: standards mcp trust <id> grants trust to a server that lost it, and standards mcp trust <id> --revoke withdraws it.
Tool groups and refresh
Each server is a tool group. A defined agent granted a server has its tools from the first step. The default chat has no grants of its own and loads servers on demand, rather than carrying every remote tool in every turn.
The tool list is synced when you connect and whenever you ask for a refresh: the Refresh action in the app, POST /mcp-servers/:id/refresh, or standards mcp refresh <id>. A refresh never disarms an agent:
- if it fails, the previous tool list stays in place and the error is stored in
lastSyncError, shown on the server's row until a later refresh succeeds; - if a trusted server changed a tool's description or input schema, or added a tool, the server is demoted to untrusted. The new definitions are stored; what you vetted is no longer what the server serves, so its tools go back to per-call approval until a person trusts it again. A tool that merely disappeared does not demote the server.
One resync is automatic. When an agent calls a tool and the remote answers that it does not know it (unknown_tool), Standards refreshes the server once and checks the refreshed list. If the tool is gone, the agent is told the catalog was stale and has been refreshed. If it is still there, the underlying remote error is reported as is.
Status and reconnect
A server is active, needs_reauth or error.
needs_reauth means the remote rejected the stored credential. For a header server, replace the secret. For an oauth server, start a reconnect attempt with POST /mcp-servers/:id/oauth/attempts; it reuses the server row, so nothing has to be removed and added again. An attempt can carry either completionMode or returnUrl, not both, and its progress is readable at GET /mcp-servers/oauth/attempts/:id.
When the flow returns to your returnUrl, three query parameters report the outcome:
| Parameter | Value |
|---|---|
mcp_oauth_status | connected or error. |
mcp_server_id | The server's id, on success. |
mcp_oauth_error | An error code such as mcp_oauth_needs_reauth, on failure. mcp_oauth_slug_unavailable means no free slug was found for a new connection (see Slug and tool names); connecting again usually succeeds. |
Which agents can use a server
An agent gets a server's tools only when it is granted that server: mcp:<serverId> in its toolGroups, one server at a time. An agent with no grant gets none, so connecting a server never changes an existing agent. A defined agent has its granted servers active from the first step; the default chat loads them on demand. A shared (workspace) agent can only be granted workspace servers; to use a private one, make the agent private. Deleting a server removes its grants from every agent. See Tools and connectors.
import { agent } from "@standards/schema";
export const assistant = agent({ name: "assistant" })
.toolGroups(["memory", "mcp:<notion-server-id>", "mcp:<linear-server-id>"]);Next steps
- CLI: MCP servers —
standards mcp list,connect,refresh,trust,renameanddisconnect. - MCP — the inbound direction: Standards as a server.
- Tools — the built-in tools your agents carry next to the remote ones.
- Workspaces and API keys — where the
connectorspermission lives. - Book a demo