> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oao.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Remote MCP servers

> Connect HTTPS MCP servers through immutable toolsets and exact-origin credential policies.

OAO can expose a restricted set of tools from a remote Model Context Protocol
(MCP) server to a managed agent. The integration is provider-neutral: server,
credential, policy, and toolset records do not contain LangSmith-specific
behavior.

## Architecture

```text theme={null}
Agent version                  OAO control plane
┌──────────────────┐          ┌────────────────────────────────────┐
│ MCP binding      │─────────▶│ immutable toolset + server version │
│ namespace        │          │ exact credential-policy version    │
└────────┬─────────┘          └────────────────┬───────────────────┘
         │ session copies exact bindings       │ PostgreSQL + RLS
         ▼                                     ▼
┌──────────────────┐          ┌────────────────────────────────────┐
│ Flue durable run │─approval▶│ OAO MCP executor + egress broker   │
│ namespaced tool  │◀─result──│ live auth, fencing, audit, limits  │
└──────────────────┘          └────────────────┬───────────────────┘
                                              │ TLS; DNS/IP checked
                                              │ secret injected here
                                              ▼
                              ┌────────────────────────────────────┐
                              │ approved remote MCP HTTPS endpoint │
                              └────────────────────────────────────┘
```

Flue sees MCP tools as normal durable OAO tools. OAO owns MCP discovery,
authorization, credentials, approvals, transport policy, and recovery. The
decrypted credential is never added to the prompt, tool arguments, model-visible
results, sandbox environment, product events, audit details, or list responses.

## Add an MCP server in the console

Open **MCP connections** and select **Add MCP server**. Complete every wizard
screen in order:

<Steps>
  <Step title="Enter the server">
    Enter a display name, stable lowercase key, HTTPS MCP endpoint, and
    transport. Choose **Streamable HTTP** for current MCP servers or **Legacy
    SSE** only when the remote server requires it. Select **Next**.
  </Step>

  <Step title="Add authentication and review the policy">
    Choose **Bearer token** or **API-key header** and enter the write-only secret.
    For an API-key header, also enter its safe header name. Expand **Security
    policy and limits** and confirm the exact HTTPS origin, allowed path prefix,
    request timeout, and response-size limit. OAO never returns the secret after
    saving it. Select **Next**.
  </Step>

  <Step title="Connect and discover">
    Select **Test and discover**. OAO saves the encrypted credential and immutable
    server version, connects to the approved destination, and loads its tool
    schemas.
  </Step>

  <Step title="Choose the tools">
    Select only the tools the agent needs. For each selected tool, choose **Always
    require approval** or **Run without approval**. Use approval-free execution
    only for a narrowly allowlisted read-only tool. Select **Next**.
  </Step>

  <Step title="Attach it to an agent">
    To finish the connection without an agent, leave **Attach to agent** empty.
    Otherwise choose an agent and confirm its unique tool namespace. The wizard
    will publish a new immutable agent version containing the binding. Select
    **Finish setup**.
  </Step>

  <Step title="Verify it">
    Confirm the connection card reports **ready**, a discovered-tool count, and
    at least one restricted toolset. If you attached an agent, create a new
    session for that agent; existing sessions retain their previous version.
  </Step>
</Steps>

The **Connections** view summarizes configured endpoints, discovery status, and
restricted toolsets. The individual credential, policy, server, and toolset
records remain available under **Advanced resources** for inspection, rotation,
revocation, and manual administration. When manually creating an immutable
toolset, choose whether all selected tools always require approval or may run
without approval; use approval-free execution only for narrowly allowlisted,
read-only tools.

The wizard creates the server and server version, encrypted credential,
exact-origin credential-policy version, and restricted toolset in dependency
order. If testing fails after one of them is saved, retrying in the same open
wizard continues from the first incomplete resource instead of duplicating it.
Closing the wizard never rolls back already-saved resources; inspect them under
**Advanced resources** before starting again with the same key. Secret input is
cleared as soon as the credential is encrypted and is never returned to the
console.

## Add an MCP server through the API

The API follows the same dependency order as the wizard. The example below uses
a static bearer credential and requires `curl` plus `jq`. Set
`OAO_API_URL`, `OAO_PROJECT_ID`, and `OAO_API_KEY` first.

```bash theme={null}
read -r -s -p "MCP bearer token: " OAO_MCP_SECRET
echo

credential_id="$(
  curl --fail-with-body --silent \
    --request POST \
    --header "Authorization: Bearer $OAO_API_KEY" \
    --header 'Content-Type: application/json' \
    --header 'Idempotency-Key: create-example-mcp-credential-1' \
    --data "$(jq -n --arg secret "$OAO_MCP_SECRET" '{
      key: "example-mcp-credential",
      displayName: "Example MCP credential",
      kind: "static_bearer",
      headerName: null,
      secret: $secret
    }')" \
    "$OAO_API_URL/projects/$OAO_PROJECT_ID/mcp-credentials" \
  | jq -r '.id'
)"
unset OAO_MCP_SECRET

policy_version_id="$(
  curl --fail-with-body --silent \
    --request POST \
    --header "Authorization: Bearer $OAO_API_KEY" \
    --header 'Content-Type: application/json' \
    --header 'Idempotency-Key: create-example-mcp-policy-1' \
    --data "$(jq -n --arg credentialId "$credential_id" '{
      key: "example-mcp-policy",
      displayName: "Example MCP egress policy",
      credentialId: $credentialId,
      exactOrigin: "https://mcp.example.com",
      pathPrefix: "/mcp",
      timeoutMs: 30000,
      maximumResponseBytes: 1048576
    }')" \
    "$OAO_API_URL/projects/$OAO_PROJECT_ID/mcp-credential-policies" \
  | jq -r '.latestVersionId'
)"

server_id="$(
  curl --fail-with-body --silent \
    --request POST \
    --header "Authorization: Bearer $OAO_API_KEY" \
    --header 'Content-Type: application/json' \
    --header 'Idempotency-Key: create-example-mcp-server-1' \
    --data '{
      "key": "example-mcp",
      "displayName": "Example MCP",
      "endpointUrl": "https://mcp.example.com/mcp",
      "transport": "streamable_http"
    }' \
    "$OAO_API_URL/projects/$OAO_PROJECT_ID/mcp-servers" \
  | jq -r '.id'
)"

server_version_id="$(
  curl --fail-with-body --silent \
    --request POST \
    --header "Authorization: Bearer $OAO_API_KEY" \
    --header 'Content-Type: application/json' \
    --data "$(jq -n --arg policy "$policy_version_id" '{
      credentialPolicyVersionId: $policy
    }')" \
    "$OAO_API_URL/projects/$OAO_PROJECT_ID/mcp-servers/$server_id/discover" \
  | jq -r '.latestVersionId'
)"

toolset_version_id="$(
  curl --fail-with-body --silent \
    --request POST \
    --header "Authorization: Bearer $OAO_API_KEY" \
    --header 'Content-Type: application/json' \
    --header 'Idempotency-Key: create-example-mcp-toolset-1' \
    --data "$(jq -n --arg serverVersionId "$server_version_id" '{
      key: "example-read-tools",
      displayName: "Example read tools",
      serverVersionId: $serverVersionId,
      tools: [{remoteToolName: "list_items", approval: "always"}]
    }')" \
    "$OAO_API_URL/projects/$OAO_PROJECT_ID/mcp-toolsets" \
  | jq -r '.latestVersionId'
)"
```

Replace `list_items` with a name returned by discovery. Keep
`toolset_version_id` and `policy_version_id`; the agent-version request needs
both. Continue with [Connect MCP tools to an
agent](/agents/create-agent#connect-mcp-tools-to-an-agent).

<Note>
  MCP administration requires `credential:write`, `mcp:write`, and
  `mcp:discover`; reading resources requires `mcp:read`. Binding the resulting
  versions to an agent additionally requires `mcp:bind`.
</Note>

OAO prefixes bound tools as `mcp__<namespace>__<remote-name>` to prevent
collisions. A session copies the exact toolset and credential-policy versions;
later versions do not silently change an existing session.

Re-running discovery is idempotent while the remote metadata is unchanged. If
the remote server adds, removes, or changes a tool, OAO publishes the discovery
as the next immutable server version and makes it the latest version. Existing
toolsets and sessions remain pinned to their prior server version until an
operator deliberately publishes a replacement toolset and agent version.

## Egress and credential boundary

The broker requires TLS, resolves the hostname before each request, denies
private and special-purpose addresses, and pins the request to the validated IP
while retaining TLS server-name verification. This limits SSRF and DNS
rebinding. It strips caller-supplied authorization, cookie, and proxy
authorization headers before injecting the configured secret.

Credential-bearing requests must retain the exact scheme, host, and port and
remain under the policy path prefix. Redirects are not followed. Requests and
responses are size-limited, and calls honor cancellation and the policy timeout.
At execution time OAO rechecks the session binding, run creator's current
authorization, project membership, and every resource lifecycle before it
decrypts a credential.

Tool metadata and results are untrusted input. Discovery rejects duplicate tool
names, repeated pagination cursors, excessive tool counts, and unsupported JSON
schemas. Non-validating `$schema` and `default` annotations are removed, and a
simple nullable `anyOf` is canonicalized to a nullable type before validation;
other schema unions and unsupported combinators still fail closed. Descriptions
are bounded and control characters are removed. Tool arguments are validated
against the pinned schema. Remote result text may still contain prompt
injection, so the agent's instructions and approval policy must treat it as data
rather than authority.

## Recovery behavior

Every call has a deterministic tool-call identity and one PostgreSQL call-attempt
record. A process crash after dispatch can leave the remote outcome unknowable;
OAO marks that attempt `unknown` and refuses to replay it automatically. This
fail-closed behavior avoids repeating a non-idempotent remote action. Product
events contain resource IDs, safe error codes, duration/size metadata, and state,
never request arguments, results, credentials, or authorization headers.

## Current authentication support

The MVP supports static bearer credentials and arbitrary safe API-key headers.
OAuth, token refresh, dynamic client registration, stdio servers, per-user
delegated credentials, configurable retries/reconnects, and secret substitution
for sandbox commands are not implemented. OAO uses the MCP client pinned in
`@oao/mcp-remote`; compatibility tests lock behavior to that exact version.

See [HTTP API](/reference/http-api), [Authentication](/reference/authentication),
and [MVP limitations](/reference/mvp-limitations).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.