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

# Troubleshooting: MCP server registration rejected

> A POST to register an external MCP server for an agent returns 422 INVALID_MCP_SERVER_URL, 422 INVALID_MCP_OAUTH_TOKEN_URL, or 409 MCP_SERVER_NAME_CONFLICT — the write-time SSRF guard reject classes, the decision checklist, and the name-conflict fix.

# Troubleshooting: MCP server registration rejected

Agents can call external tool servers you register yourself. Registration
goes through `POST /api/v1/agents/:agentId/mcp-servers`, and the request is
validated at write time. Three errors account for nearly every rejected
registration:

| Error (HTTP)                      | What rejected it                                                  |
| --------------------------------- | ----------------------------------------------------------------- |
| `422 INVALID_MCP_SERVER_URL`      | The `server_url` failed the SSRF guard.                           |
| `422 INVALID_MCP_OAUTH_TOKEN_URL` | The OAuth2 grant's `token_url` failed the same SSRF guard.        |
| `409 MCP_SERVER_NAME_CONFLICT`    | A server with the same name is already registered for this agent. |

The first two are guard rejections on a URL field; the third is a
uniqueness conflict on the server name. Work the checklist below.

## The SSRF guard — every reject class

A registered `server_url` is a server-side fetch target: the agent runtime
discovers tools and executes calls against it. An OAuth2 `token_url` is a
fetch target too — the platform exchanges it for an access token. The
write-time guard keeps an authenticated operator from steering either
request into internal network addresses, and runs on both fields. A URL is
rejected if any of the following holds:

* **Non-HTTPS scheme** — `http://`, `file:`, `ftp:`, `gopher:`, or any
  scheme that is not `https://`.
* **Loopback or private address** — `127.x`, `10.x`, `172.16–172.31`,
  `192.168.x`, or the CGN block `100.64.0.0/10`.
* **Link-local or cloud-metadata host** — `169.254.x`, `localhost`,
  `metadata.google.internal`, and other blocked hostnames.
* **Internal-only hostname suffix** — a `.internal` or `.local` suffix, or
  a trailing-dot FQDN.
* **DNS-rebind** — the DNS record resolved at register time returns a
  private or internal IP. The check runs at registration, not deferred to
  call time.

The 422 response carries a `failure_code` naming which class tripped
(`protocol`, `blocked_host`, `internal_suffix`, `dns_invalid`, or
`private_ip`) alongside the user-safe message — the raw resolved address
is deliberately left out of the response. Read `error.details.failure_code`
to identify what your URL hit.

## Decision checklist

1. **Read the failure class.** Look at `error.details.failure_code` in the
   422 response before changing anything — it names the reject class.
2. **Check the URL is public HTTPS end to end.** Scheme `https://`, a
   publicly resolvable hostname, and a public A/AAAA record. Test resolution
   from outside your own network if the class is `private_ip` or
   `dns_invalid`.
3. **Repeat for the OAuth2 `token_url`** when you supplied one — it is
   validated identically to `server_url`, and the error code switches to
   `INVALID_MCP_OAUTH_TOKEN_URL` when that is the field that failed.
4. **For a 409 name conflict,** list the agent's servers with
   `GET /api/v1/agents/:agentId/mcp-servers` and either rename the new
   server or update the existing registration
   (`PATCH /api/v1/agents/:agentId/mcp-servers/:id`). The conflict never
   overwrites the earlier registration.

## What NOT to do

* **Do not point the URL at a redirect chain that resolves to a private
  address.** The register-time DNS check sees the resolved record; a
  redirect to internal infrastructure is the exact traffic the guard
  blocks.
* **Do not retry the exact same payload.** The guard is deterministic —
  the same URL fails the same class every time. Fix the URL first.
* **Do not delete and re-post to dodge a 409** unless you want the old
  registration gone. Use `PATCH` to update the existing server in place.

## When to escalate

Escalate to support when a genuinely public `https://` URL is rejected
with `private_ip` or `dns_invalid` after you confirmed public resolution
from outside your network. Include the `failure_code`, the `request_id`
from the response `meta`, and the hostname (not the resolved address).
Support can check whether the public DNS answer changed — a public DNS
record that returns a private IP is a DNS configuration change on your
side, not a guard defect.

## See also

* [Error Code Reference — Agents](/reference/error-codes) — the three
  codes with their HTTP statuses.
* [MCP server concepts](/concepts/mcp-hosted-server) — what an external
  tool server registration is.
* [Agent runtime errors](/troubleshooting/agent-errors) — tool-call
  failures on already-registered servers.
