---
title: Connecting to MCP
description: Step-by-step MCP connection walkthrough for agents — endpoint, the three-step JSON-RPC handshake with complete curl commands, auth header, and a symptom-cause-action table.
locale: en
version: 0.2.0
canonical: https://enterium-developer-docs.pages.dev/developers/mcp/connecting/
---

> Documentation index: https://enterium-developer-docs.pages.dev/developers/llms.txt — every page of this portal has a Markdown twin at <route>.md; the frozen API contract is at https://enterium-developer-docs.pages.dev/developers/api/openapi.json.

The platform exposes an MCP server over **Streamable HTTP** (JSON-RPC). This
page is written for agents of any capability: follow the steps literally, in
order. Every command is complete — nothing is assumed from outside this page.

## Facts you need

| Fact | Value |
| --- | --- |
| Endpoint | `https://entherium.duckdns.org:8443/mcp/` |
| Transport | MCP Streamable HTTP (JSON-RPC over POST; responses are SSE) |
| Auth | `Authorization: Bearer <AGENT_TOKEN>` on **every** request |
| Discovery without auth | `GET /mcp-info` (onboarding page), `GET /llms.txt` |
| What you get | 14 tools + 5 resources ([full reference](../tools/)) |
| Read-only mount | `https://entherium.duckdns.org:8443/mcp/readonly/` — same token, only the 7 read tools ([why](#read-only-mount)) |
| Docs MCP, **no token** | `https://entherium.duckdns.org:8443/mcp/docs/` — this documentation as `search` / `fetch` / `submit_feedback` ([details](#the-docs-mcp-no-token)) |

## Preconditions

- You have an agent token (`<AGENT_TOKEN>` below). Without one, every call
  returns `401` — request a token from the platform owner first.
- Your HTTP client can send POST with custom headers and read the response
  body as text. Responses arrive as Server-Sent Events: take the lines that
  start with `data: ` and parse the rest of each line as JSON.

## Step 1 — initialize the session

```sh
curl -sS -D headers.txt https://entherium.duckdns.org:8443/mcp/ \
  -H "Authorization: Bearer <AGENT_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0"}}}'
```

Expected: an SSE body whose `data:` line contains `"serverInfo"`, and a
response header **`mcp-session-id`** in `headers.txt`. Copy that value — it is
`<SESSION_ID>` in the next steps. If you got `401`, your token is missing or
expired — see the table below. Do not proceed until this step returns 200.

## Step 2 — confirm initialization

```sh
curl -sS https://entherium.duckdns.org:8443/mcp/ \
  -H "Authorization: Bearer <AGENT_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: <SESSION_ID>" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'
```

Expected: HTTP 2xx with an empty or trivial body. This step is required —
skipping it makes some clients' later calls fail.

## Step 3 — make your first tool call

Always call `start_here` first: it returns the ordered plan for using the
platform and the capability version of the read surface.

```sh
curl -sS https://entherium.duckdns.org:8443/mcp/ \
  -H "Authorization: Bearer <AGENT_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: <SESSION_ID>" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"start_here","arguments":{}}}'
```

Expected: a `data:` line whose JSON contains the plan. From here, use the
[tools reference](../tools/) — every tool page shows the exact `tools/call`
payload for that tool.

## Connect from a client in one step

The three curl steps above are what every client does under the hood. With a
client you only give it the URL and the header:

**Claude Code**

```sh
claude mcp add --transport http enterium https://entherium.duckdns.org:8443/mcp/readonly/ \
  --header "Authorization: Bearer <AGENT_TOKEN>"
```

**Cursor / VS Code / any `mcp.json`-style client**

```json
{
  "mcpServers": {
    "enterium": {
      "url": "https://entherium.duckdns.org:8443/mcp/readonly/",
      "headers": { "Authorization": "Bearer <AGENT_TOKEN>" }
    }
  }
}
```

Replace `readonly/` with `/mcp/` only when you actually need the write tools.
For the token-less docs server the install links work as-is:
[Add to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=enterium-docs&config=eyJ1cmwiOiJodHRwczovL2VudGhlcml1bS5kdWNrZG5zLm9yZzo4NDQzL21jcC9kb2NzLyJ9) · [Add to VS Code](vscode:mcp/install?%7B%22name%22%3A%22enterium-docs%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fentherium.duckdns.org%3A8443%2Fmcp%2Fdocs%2F%22%7D) ·
Claude Code: `claude mcp add --transport http enterium-docs https://entherium.duckdns.org:8443/mcp/docs/`.

## Read-only mount

`/mcp/readonly/` serves the same server with the write tools removed: only
tools whose `readOnlyHint` is `true` are listed, and calling a write tool by
name fails. Same bearer token, same handshake, same `start_here`. Use it as the
default for evaluation, for research assistants and for any client that must
never file a ticket or move a task by accident — the choice is made by the URL,
not by trusting the client to respect hints. The full server stays at `/mcp/`.

## The docs MCP (no token)

`/mcp/docs/` turns this documentation into three tools and needs **no token**:

| Tool | What it does |
| --- | --- |
| `search(query, limit)` | Ranks portal pages for a query; returns `{results: [{id, title, url}]}` — `id` is the page route |
| `fetch(id)` | Returns a page as Markdown (`{id, title, text, url, metadata}`) — the `.md` twin, fewer tokens than HTML |
| `submit_feedback(page, message)` | Files a suggestion for the documentation team; anonymous, at most 5 per hour per client; asks the user first |

The tool names and shapes follow the deep-research connector contract, so the
server can be added to ChatGPT or Claude as a connector unchanged. It never
reads or writes platform data — everything comes from the published portal —
which is why it sits outside the token gate.

## If it fails

| Symptom | Cause | Action |
| --- | --- | --- |
| `401` on a plain browser `GET /mcp/` | Auth is checked at the mount, before content negotiation — without a token you never reach the transport | Expected. There is nothing to see in a browser; the human page is `GET /mcp-info` |
| `406 Not Acceptable` on `GET /mcp/` **with** a token | This is not a browser URL; the server requires the JSON-RPC handshake | Use the three steps above, or an MCP client library |
| `401` on **every** call | Token missing, malformed or expired (auth is checked at the mount, before any tool runs) | Tokens are issued by the platform owner (`POST /api/v1/auth/agent-token` is superuser-only) — ask for a re-issue. ⚠️ A new token **replaces** your grant set — re-check `my_capabilities` after |
| `403` or a capability error inside a tool result | Token is valid but lacks the capability or the per-contract grant for that tool | Call `my_capabilities` to see what you may do; request the missing grant from the owner |
| Tools list suddenly empty after a platform deploy | The deploy restarted the API container and killed your live MCP session; sessions are not restored | Re-run the handshake from Step 1 (new `mcp-session-id`) |
| Response body looks unparseable | You are reading raw SSE | Parse only lines starting with `data: `; join multi-line events before JSON-parsing |
| `307` on `/mcp` (no trailing slash) | The transport lives at `/mcp/`; the server redirects | Use `/mcp/` directly — some clients do not follow redirects on POST |

## Two reading rules that save agents

1. **Read payload values, not schemas.** Explanatory context lives in the
   JSON responses themselves (for example, status notes inside the data) —
   the platform puts meaning in the payload because many agents never
   introspect tool descriptions.
2. **Re-check `start_here` after upgrades.** Pass your cached
   `capability_version` as `last_seen_version`; if the surface changed, the
   response lists what to adopt before you act.
