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

# MCP Server Connection

> Connect an AI agent to the MCP server that Aether provides.

Aether exposes an [MCP](https://modelcontextprotocol.io) server, so AI agents can report Deltas and request Trigger Plans as ordinary tools, without the Python SDK.

**Before you start:** create a Connected System in the Aether Dashboard and copy its **API key**.

## Server details

| | |
| - | - |
| URL | `https://aether-mcp-production.up.railway.app/mcp` |
| Transport | Streamable HTTP |
| Authentication | `Authorization: Bearer <system_api_key>` header |

The API key goes on the connection, never in a tool argument, so it stays out of the LLM's context. Each connection speaks for the system that owns the key.

## Connect your agent

> [tab] Claude Code
>
> ```bash theme={null}
> claude mcp add --transport http aether https://aether-mcp-production.up.railway.app/mcp \
>   --header "Authorization: Bearer <system_api_key>"
> ```

> [tab] Cursor
>
> In `.cursor/mcp.json`:
>
> ```json theme={null}
> {
>   "mcpServers": {
>     "aether": {
>       "url": "https://aether-mcp-production.up.railway.app/mcp",
>       "headers": {
>         "Authorization": "Bearer <system_api_key>"
>       }
>     }
>   }
> }
> ```

> [tab] n8n
>
> 1. Create a **Bearer Auth** credential with the system's API key as the token.
> 2. Add an **MCP Client Tool** node to your AI Agent.
> 3. Set the endpoint to `https://aether-mcp-production.up.railway.app/mcp`, the transport to **HTTP Streamable**, and select the credential.

> [!WARNING]
>
> Never commit a config file that contains your API key.

## Available tools

### `emit_delta`

Reports one event to Aether.

| Argument | Type | Description |
| - | - | - |
| `event` | `string` | Event name, e.g. `"scan.completed"`. |
| `workspace_revision` | `string` | Revision of the workspace the event happened on. |
| `payload` | `string` | A **JSON-encoded object**, e.g. `"{\"findings_count\": 3}"`. Max 64 KiB. |

Returns the Delta's `id` and `received_at`. If the payload does not match the event's contract, the tool returns an error telling the agent what to fix, so it can retry.

### `trigger_plan`

Asks Aether which systems should run.

| Argument | Type | Description |
| - | - | - |
| `intent` | `string` | Why you are asking, in plain words. Max 2000 characters. |

Returns the Trigger Plan. Only the environment's **top-level orchestrator** can call it.

## Example prompts

When a Connected System is an AI agent, its system prompt tells it when and how to call the Aether tools. Adapt these examples to your agents.

> [tab] Agent: emit\_delta
>
> An agent that reports what it did after finishing its work. Here, a newsroom writer.
>
> ```text theme={null}
> After you finish writing or revising a draft, call the emit_delta tool exactly once:
> - event: the event from your System Contract that matches what you did.
> - workspace_revision: the revision you were given in the input.
> - payload: a JSON-encoded object string that matches the event's payload_schema.
>
> If the tool returns an error, read it, fix the arguments and call it again.
> Never invent events or fields that are not in your System Contract.
>
> Your System Contract:
> {
>   "capabilities": [
>     {
>       "code": "write_article",
>       "description": "Writes or revises a draft from sources and verdicts.",
>       "reads": ["sources", "verdicts"],
>       "writes": ["drafts"]
>     }
>   ],
>   "emit_events": [
>     {
>       "event": "draft.written",
>       "kind": "COMPLETION",
>       "payload_schema": {
>         "type": "object",
>         "required": ["draft_id", "revision", "title"],
>         "properties": {
>           "draft_id": { "type": "integer" },
>           "revision": { "type": "integer" },
>           "title": { "type": "string" }
>         }
>       }
>     }
>   ]
> }
> ```

> [tab] Orchestrator: trigger\_plan
>
> The top-level orchestrator, asking Aether which agents to wake.
>
> ```text theme={null}
> You are the orchestrator of an automated newsroom. Before waking any agent,
> call the trigger_plan tool exactly once, with the editor's request as the intent.
> Never call it twice in the same run.
>
> Then, for each system in the plan:
> - RUN: wake the agent.
> - SKIP: do not wake the agent.
> - UNKNOWN or NO_DELTAS: Aether leaves the decision to you. Decide RUN or SKIP
>   from the request and the agent descriptions below.
>
> Agents:
> - scout: polls the news feed and stores one new news item. Writes sources.
> - writer: writes or revises drafts. Reads sources and verdicts, writes drafts.
> - checker: fact-checks drafts not checked yet. Reads drafts, writes verdicts.
> - illustrator: makes images for drafts without one. Reads drafts, writes images.
>
> Waking an agent costs money. Wake it only when the request calls for its work.
> ```

> [!NOTE]
>
> Always include the system's **System Contract** in the prompt of an agent that calls `emit_delta`. It lists the events the system may report and the schema of each payload, so the AI knows which `event` to send and how to build `payload`. Without it, the AI may invent events or send payloads that do not match the contract. Invented events are not rejected: [they are added to the contract](https://documentation.aibydna.com/desp/concepts/system-contract.md#how-deltas-are-checked-against-the-contract). Copy it from the system's contract in the Aether Dashboard, with **View JSON**.

## Troubleshooting

> [accordion] 401 Unauthorized when connecting
>
> The `Authorization` header is missing, is not `Bearer`, or the key is invalid, revoked or expired. Check the header and copy the key again, without stray spaces.

> [accordion] trigger\_plan returns a permission error
>
> Only the top-level orchestrator can request a plan. Connect with the orchestrator system's API key.

> [accordion] emit\_delta says the payload must be a JSON-encoded object string
>
> `payload` is a string, not an object. Encode the object as JSON first, e.g. `"{\"status\": \"ok\"}"`.

> [accordion] Payload rejected
>
> The payload does not match the event's contract. Fix the fields named in the error and retry.


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