Skip to main content

MCP endpoint

A Worker can optionally serve an MCP endpoint at /mcp, so that AI agents can call selected local functions as tools. It uses stateless Streamable HTTP and returns synchronous results; the REST API is unchanged and keeps its own authentication.

A Worker used behind a Load Balancer does not need this endpoint: the Load Balancer calls Workers through /task and can expose their functions through its own MCP endpoint.

Configure​

  1. Generate a distinct token with openssl rand -hex 32 and set MCP_AUTH_KEY in .env. Restart the Worker after changing it. See Authentication for the rules this token must follow.
  2. Create mcp.json in the Worker's application root, next to its package.json (or point MCP_CONFIG_PATH to another location):
{
"functions": ["hello"]
}

Connect the agent to https://worker.example.com/mcp with the header Authorization: Bearer <MCP_AUTH_KEY>. See Connect a client for client configuration examples.

Use {} to expose all local functions or {"functions":[]} to expose none. No Worker credentials or routing fields belong in this file. The existing AUTH_KEY remains for REST.

The application root is the parent of the source directory passed to bootstrap (src/ with npm run dev, dist/ after a build), which is the folder containing package.json in the Base Worker layout.

The selection reloads without a restart. See Live configuration.

Docker​

Use the supplied optional Compose override:

mkdir -p .mcp
cp mcp.example.json .mcp/mcp.json
docker compose -f docker-compose.yml -f docker-compose.mcp.yml up --build

The override loads environment values from .env, sets MCP_CONFIG_PATH=/app/mcp/mcp.json and mounts the directory read-only at /app/mcp. A directory mount lets editors replace the file atomically without leaving the container attached to an old inode. Edit .mcp/mcp.json on the host to update selection live.

The container runs as the non-root node user: the mounted file must be readable by that user, otherwise MCP is disabled.

Authentication​

Set MCP_AUTH_KEY to a distinct, randomly generated token and store it in your process environment or deployment secret settings. Agents send:

Authorization: Bearer <MCP_AUTH_KEY>

MCP_AUTH_KEY must contain no whitespace and must differ from the Worker's internal keys, AUTH_KEY and LB_AUTH_KEY. Otherwise MCP stays disabled and a warning is logged at startup.

The MCP key does not grant REST administration, logs or maintenance access: it cannot call /on, /off or /logs. MCP calls use the same contract validation, queue, maintenance checks and execution engine as REST.

Use HTTPS outside a trusted local network. A bearer token grants access to all tools selected by this endpoint; there are no per-user permissions. Keep the token in client configuration, not in prompts or URLs.

Function selection​

SettingMeaning
No readable mcp.json or no valid MCP_AUTH_KEYMCP is disabled; requests receive HTTP 404
functions omittedAll discovered functions, including future additions
"functions": ["hello"]Only the named functions
"functions": []No functions

Use explicit lists when new functions should require a review before becoming available to agents. A requested function must exist in the current catalog and still be allowed when called.

A Worker's allowlist only controls that Worker's MCP endpoint. It does not change REST permissions or restrict a Load Balancer's independent MCP selection.

Live configuration​

By default, mcp.json is read from the application root described above. MCP_CONFIG_PATH overrides its location; relative paths resolve from that root. The file is limited to 64 KiB.

The file is watched, and checked again before requests:

  • Adding or editing a valid file changes the catalog without restarting.
  • Atomic saves (write a new file and rename it) are supported.
  • Invalid edits keep the last valid configuration. A sanitized error appears in authenticated health.
  • Invalid configuration at startup leaves MCP disabled.
  • Deleting the file, or making it unreadable, disables new MCP requests.
  • Removing a function prevents subsequent calls even if a client cached it.
  • Already dispatched tasks can finish; revocation is not cancellation.

Clients may need to refresh or reconnect to show a new catalog. Environment values, including tokens, are loaded at startup: restart to rotate those secrets.

Function discovery itself still happens at Worker startup. Editing mcp.json changes exposure, not the loaded business code.

Connect a client​

Claude Code​

In your client-side .mcp.json:

{
"mcpServers": {
"andera": {
"type": "http",
"url": "https://worker.example.com/mcp",
"headers": {
"Authorization": "Bearer ${ANDERA_MCP_TOKEN}"
}
}
}
}

Set ANDERA_MCP_TOKEN in the environment from which you launch Claude Code.

This client file is different from the server-side Andera mcp.json that selects functions. See the Claude Code MCP documentation.

Codex​

In your Codex config.toml:

[mcp_servers.andera]
url = "https://worker.example.com/mcp"
bearer_token_env_var = "ANDERA_MCP_TOKEN"
tool_timeout_sec = 60

Make ANDERA_MCP_TOKEN available to the local Codex host. tool_timeout_sec is how long Codex waits for a tool result; raise it for functions that run longer. See the official MCP configuration documentation.

Other clients​

ClientNative token setup
Claude CodeHTTP headers
Codex local clientsbearer_token_env_var
CursorHTTP headers in mcp.json
Claude hosted connectorsStatic request headers are in a limited organization beta
ChatGPT web custom connectorsStatic-token setup is not documented; authenticated connections use OAuth

Andera does not implement OAuth, so hosted connectors that require it cannot connect. See Claude request headers, Cursor MCP, and ChatGPT developer mode.

Tool names and arguments​

Worker tools normally keep their function name, such as hello. Names outside MCP's supported character/length limits, or starting with the reserved __andera_ prefix, receive a stable hash-based name to avoid shadowing other functions. Use the exact name returned by the MCP tool catalog.

The agent supplies only the function's input parameters. It cannot override the Worker credential, delivery mode or priority.

Function results are returned as readable JSON text and as structuredContent.result. Tool failures use MCP's isError flag. Internal HTTP errors and credentials are not returned to clients.

Describe your functions​

Existing function handlers work without modification. Optional descriptions help agents choose tools and arguments:

export const hello = defineFunction({
description: "Return a greeting for the given name.",
params: {
name: {
type: "string",
description: "The person to greet.",
default: "World",
},
},
handler: async ({ name }) => ({ message: `Hello ${name}!` }),
});

Andera derives JSON Schema from the existing types, required fields, defaults, enums, patterns, and min/max constraints. Object properties and array item types remain unconstrained when the existing parameter definition does not describe them. A function without params is exposed with an empty input schema. Arguments not declared in params are rejected.

Inspect and troubleshoot​

Authenticated GET /health (with the Worker's AUTH_KEY) includes an mcp section with:

  • Enabled state, endpoint path, transport and whether a dedicated key is configured.
  • Last successful configuration reload and any sanitized configuration error.
  • Exposed tools, descriptions and parameter schemas.

The MCP-only token receives public health information, not administrative metadata.

SymptomCheck
HTTP 404File exists and is readable, JSON is valid, and MCP_AUTH_KEY is set, has no whitespace and differs from the internal keys
HTTP 401Correct Authorization: Bearer … header
HTTP 403Browser Origin is explicitly allowed
Empty catalogAllowlist and Worker function discovery
Tool unavailableWorker maintenance or services
Task failureAvailable slots and function logs
Reload errorFix the file; the last valid settings remain active

Native clients normally send no Origin. Browser requests with an Origin are rejected unless listed in comma-separated MCP_ALLOWED_ORIGINS. Exact allowed origins receive the CORS preflight and response headers needed to send the bearer token; * is not supported.

Limits​

  • Stateless Streamable HTTP with JSON responses; GET/DELETE receive 405.
  • Synchronous calls only. No business-output streaming, webhook mode or resumable MCP tasks.
  • MCP request bodies are limited to 1 MB (HTTP 413 above that) and serialized function results to 1 MiB (tool error above that).
  • Up to 32 admitted MCP tool calls per process, including calls waiting in the Worker queue; excess calls receive a busy tool error. The Worker queue has no separate waiting deadline: maintenance or a failed service can leave already admitted calls waiting until recovery.
  • A function deadline aborts context.signal and returns a tool error. Cancellation is cooperative: handlers must pass the signal to cancellable APIs or check it between steps. Client deadlines and disconnections do not send cancellation to the Worker. Do not blindly retry a write whose outcome is unknown.
  • Worker slots remain occupied until timed-out handlers settle. A handler that ignores cancellation can occupy a slot indefinitely; detached child operations are outside this accounting. Authenticated /health lists these handlers in executions.timedOutRunning. See cancellation guidance.
  • REST queues have no configured admission cap, and there is no built-in per-client rate limiter. Apply request limits at the reverse proxy and isolate long-running or untrusted business code.