Skip to main content
MCP does not mandate one authentication scheme, so real servers take credentials in different places. The examples in this section cover every shape you are likely to meet. The Agent code barely changes; what changes is where the key goes.

The env: prefix

Anywhere swarms takes a credential, "env:VAR_NAME" reads it from the environment when the connection is made, instead of embedding it in your source:
"${VAR_NAME}" works too. Prefer either over os.getenv(...) at construction time: the literal never enters the agent object, so it cannot leak through a serialized config or a printed repr.

No authentication

Bearer token

The most common shape. The token is sent as Authorization: Bearer <key>.
mcp_api_key applies to every server that does not define its own credential, which makes it the right choice for a single server and the wrong one when servers need different keys.

Query parameter

Some hosted servers want the key in the URL’s query string. Build the URL from the environment:

URL path segment

Firecrawl takes the key as part of the path:
When the key lives in the URL — path or query string — never log the constructed URL. URLs end up in application logs, error traces, and crash reports far more readily than headers do. Check for the variable up front so a missing key fails with a clear message instead of a malformed URL.

Optional authentication

For a server that serves anonymous traffic, a missing key should lower your rate limit, not crash your program:

Custom header

When a server wants its key in something other than Authorization, use an MCPConnection and set the header and prefix explicitly:
MCPConnection is also where per-server timeouts and transports live:

OAuth 2.1

For servers that speak the MCP authorization spec. The browser flow runs once and the tokens are cached under ~/.swarms/mcp_auth/, so later runs are silent:
Headless, for servers that issue machine tokens:
And when you already hold a token from elsewhere, pass it directly with access_token= and no flow is run.

Different credentials per server

Mix plain URLs and connection objects in the same mcp_urls list:

Troubleshooting

Confirm the variable is exported in the shell that runs the script (echo $TOKEN), and that you used the shape the server expects — a Bearer token sent as a query parameter fails exactly like a missing one. Note that servers change their requirements: Semgrep once accepted anonymous traffic and no longer does.
An unset environment variable interpolates as the string None. Check for the variable and exit with a clear message before constructing the URL.
Set open_browser=False on MCPOAuthConfig — the authorization URL is logged instead — or use the client_credentials grant.

See also