MCP Servers
Connect agents to remote tool servers using the Model Context Protocol, bearer tokens, OAuth, or custom auth.
Overview
MCP (Model Context Protocol) is an open standard for tool servers. An MCP server exposes a list of tools over HTTP and the agent can call them at runtime, without you defining a custom tool for each one.
ArchAgents lets you add an MCP server to an agent the same way you add any other tool. You either reference a system MCP server that ArchAgents already knows about, or declare your own MCPServer config in YAML. The platform handles authentication and tool discovery, and the agent gets access to everything the server exposes.
Use MCP when:
- you want to use tools from a third-party service that already speaks MCP (Stripe, Linear, Sentry, Notion, and many others)
- you have an internal tool server speaking MCP and want to expose it to agents
- you want one connection to provide many related tools instead of defining each tool by hand
How it works
- You attach the builtin
mcp_servertool to the agent. - The tool points at an MCP server config with
builtin_tool_config.mcp_server_ref, or at an existing connected MCP integration withbuiltin_tool_config.integration_id. - The platform connects to the server's URL and discovers the tools it exposes.
- Each discovered tool becomes available to the agent's LLM.
- When the agent invokes a tool, the platform calls the MCP server with the right credentials and returns the result.
You don't write a tool definition for each remote tool. The server is the source of truth.
Use a system MCP server
Some common MCP servers are available as system configs. Connect and authorize the system integration, then attach that integration to the agent's mcp_server builtin tool.
Connect the OAuth credential
Adding the mcp_server tool gives the agent a place to use the MCP server. OAuth-backed servers such as Atlassian also need a connected integration credential.
If the agent template creates the MCP integration for you, find it and authorize it:
archagent list integrations --provider mcp:system:mcp-atlassian
archagent authorize integration <integration_id>
Or create and authorize the integration directly before attaching it to a tool:
archagent create integration \
--provider mcp:system:mcp-atlassian \
--auth-type oauth \
--org <org_id>
archagent authorize integration <integration_id>
Use the owner scope that matches how the credential should be shared: --org for an organization-scoped Atlassian connection, --agent for one agent, or --user for a personal connection.
Then copy the connected integration ID into the agent tool config:
tools:
- tool_type: builtin
builtin_tool_key: mcp_server
builtin_tool_config:
integration_id: <integration_id>
status: active
That attaches the system Atlassian MCP server to the agent. Atlassian uses OAuth discovery at https://mcp.atlassian.com, so you should not configure it with auth.atlassian.com credentials. The platform discovers Atlassian's OAuth endpoints, completes the connect flow, and then exposes the Jira and Confluence tools returned by Atlassian's MCP server.
Other system MCP servers use the same pattern:
tools:
- tool_type: builtin
builtin_tool_key: mcp_server
builtin_tool_config:
integration_id: <integration_id>
status: active
Add your own MCP server
For an internal or unsupported MCP server, define a separate MCPServer config, deploy it, then reference that config from the agent.
If the server uses a static bearer token, store it as an org environment variable, then reference that variable from the config:
archagent create orgenvvar --org <org_id> --key INTERNAL_MCP_TOKEN --value "<token>"
kind: MCPServer
key: internal-tools
name: Internal Tools
url: https://mcp.example.com/mcp
auth:
type: bearer
token:
secret_env!: INTERNAL_MCP_TOKEN
headers:
X-Custom-Header: "value"
timeout: 30000
Then attach it to the agent:
tools:
- tool_type: builtin
builtin_tool_key: mcp_server
builtin_tool_config:
mcp_server_ref: internal-tools
status: active
mcp_server_ref can be the MCPServer config's lookup key, config ID, public ID, or virtual path.
Authentication modes
MCP servers in ArchAgents support three authentication patterns. Pick the one that matches the server you're connecting to.
Static bearer token
The simplest option. Use it when the server accepts a long-lived API key or personal access token.
First create an org-scoped environment variable for the token:
archagent create orgenvvar --org <org_id> --key INTERNAL_MCP_TOKEN --value "<token>"
Then reference that key in the MCPServer config:
auth:
type: bearer
token:
secret_env!: INTERNAL_MCP_TOKEN
The value is stored as a write-only org secret and resolved when the platform makes a request to the server.
For one-off configs where you intentionally need an embedded encrypted value instead of an org env-var reference, use secret_value!:
archagent create configsecret <token>
That command calls the platform encryption API and prints ciphertext scoped to the current app and org. Paste the ciphertext into secret_value!; do not paste the plaintext token.
OAuth 2.0
For services that require OAuth, declare an OAuth client and the platform handles the authorize, token-exchange, and refresh flow per user. The agent picks up the right token automatically.
auth:
type: oauth
client:
kind: OAuthClient
authorize_url: https://accounts.google.com/o/oauth2/v2/auth
token_url: https://oauth2.googleapis.com/token
client_id:
secret_value!: <encrypted>
client_secret:
secret_value!: <encrypted>
scopes:
- https://www.googleapis.com/auth/calendar
pkce: true
If the server publishes OAuth authorization-server metadata or supports dynamic client registration, you can omit the client block and give the platform the authorization server to discover. Servers that publish a .well-known/oauth-authorization-server endpoint work this way.
auth:
type: oauth
authorization_server: https://mcp.atlassian.com
Atlassian MCP uses this discovery-based pattern.
Script-based auth
For service-account flows or anything else that needs custom logic to mint a token, point the auth at a script. The script runs at request time and must return a bearer token string.
auth:
type: bearer
client:
kind: ScriptAuthClient
script: |
let jwt = import("jwt")
let http = import("requests")
let claims = {
iss: $.client_email,
scope: $.scope,
aud: "https://oauth2.googleapis.com/token",
iat: datetime.unix(),
exp: datetime.unix() + 3600
}
let signed = unwrap(jwt.sign(claims, $.private_key, "RS256"))
let resp = unwrap(http.post("https://oauth2.googleapis.com/token", {
body: "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=" + signed,
headers: {"Content-Type": "application/x-www-form-urlencoded"}
}))
resp.body.access_token
data:
client_email:
secret_value!: <encrypted>
private_key:
secret_value!: <encrypted>
scope: "https://www.googleapis.com/auth/cloud-platform"
Use the script when no built-in auth mode covers the server's flow, for example, JWT bearer assertions for Google service accounts or signed-request schemes used by older enterprise tools.
Connecting to existing integrations
When you already have an integration credential for a service (because you connected it through ArchAgents Portal or archagent authorize agentinstallation), the MCP server can reuse that credential instead of asking for tokens again.
In ArchAgents Portal, open the agent's tool configuration, choose MCP server, and pick the existing integration from the picker. ArchAgents Portal wires the connection and shows the discovered tools without you copying tokens around.
This is the cleanest setup for servers like GitHub, Slack, or Google services where the integration credential already exists for other purposes.
Other fields
kind: MCPServer
name: my-tools
url: https://mcp.example.com/mcp
auth:
type: bearer
token:
secret_value!: <encrypted>
headers:
X-Custom-Header: "value"
timeout: 30000
| Field | Purpose |
|---|---|
name |
Human-readable identifier shown in logs and the portal |
url |
The MCP server endpoint URL |
auth |
One of the three authentication modes above |
headers |
Additional HTTP headers attached to every request |
timeout |
Request timeout in milliseconds (default: 30000) |
name and url are required. Everything else is optional.
Where MCP fits with other tool kinds
MCP is one of several tool kinds the platform supports:
| Tool kind | When to use |
|---|---|
| Builtin | The platform already provides the capability (search, knowledge, memory, computer use) |
| Custom (script or workflow) | You need to call your own product logic from the agent |
| MCP server | You want a third-party tool server's full capability without defining each tool |
You can mix them on the same agent. An agent can have a builtin search tool, a custom workflow-backed validation tool, and one or more MCP servers, all available at the same time.
Reviewing the discovered tools
After deploying an agent that uses MCP servers, inspect what the platform discovered:
archagent setup
Then invoke embed inside your coding agent:
# Claude Code
/embed
# Codex
$embed
# Cursor
@archagents embed
The MCP-provided tools appear in the same list as builtin and custom tools. Each entry shows the tool name and a one-line description provided by the server.
This is the same operator workflow as for any other tool. See Tools for the full embed pattern.
Best practices
- One MCP server per coherent capability set. Don't bundle unrelated tool surfaces into a single server.
- Encrypt all credentials with
secret_value!. Never paste plain tokens into config YAML. - Prefer integration-backed credentials over static tokens when the service already has an ArchAgents integration.
- Review the discovered tool list before activation: the LLM will see every tool the server exposes, including ones you may not want it to call.
- Set sensible timeouts. A slow MCP server stalls every agent message that reaches for one of its tools.
Where to go next
- Tools: the underlying tool model and embed loop.
- Extensions & Integrations: the broader external-system surface.
- Field Guards: validate what an agent does with tool results before they reach the user.
- Scripts: for the script-based auth mode and custom token minting.
Have feedback?
Help us make this page even more useful.
Tell us what you'd like to see expanded, which examples would help, or what workflow you want covered next. Every message gets read.