These endpoints let you inspect, create, update, enable, disable, import, probe and reconnect Model Context Protocol (MCP) servers in the agent’s settings layers. Use them to manage the tool surface an agent can reach: stdio subprocesses for local tools, and HTTP/SSE for remote ones.
A configured MCP server is an ordinary subprocess or outbound HTTP client running with the operator’s privileges. It is not sandboxed, confined or pre-approved. The daemon scrubs the child’s environment of ambient provider credentials and the platform token, which keeps a leaked secret from being passed to a child the operator did not author — that is the limit of the platform’s guarantee.
Four endpoints write the mcp_servers config: upsertMCPServer, deleteMCPServer, setMCPServerEnabled and importMCPServers. Every one of them requires both a single-use nonce from beginMCPWrite and the current mcp_servers hash passed as expect_hash.
expect_hash is always required. A first write into a settings file that does not exist yet states its expectation with the empty-array hash that listMCPServers or beginMCPWrite return for a missing file — omitting the field is a request error, not a no-op.
A mismatch returns 409 mcp_conflict. Re-read the current hash, re-apply your change on top of what is there now, and re-issue the write. A blind retry will not help.
beginMCPWrite binds the nonce to {session, op, resolved path}. A nonce minted for op:upsert cannot be used for op:delete, and a nonce minted for user cannot be used to write project.
Revocation lands in every live session before the write’s response returns. Reconnection for sessions other than the one you named is best-effort and may be skipped under sustained write pressure — those sessions pick the change up on the next write or an explicit reconnectMCP.
listMCPServers, parseMCPImport and probeMCPServer do not write. parseMCPImport is a pure parser — useful for previewing an import before committing. probeMCPServer is human-only: probing starts a subprocess (stdio) or makes an outbound request to a caller-chosen URL (http/sse), and the gateway stamps every forwarded HTTP call with the machine marker, so a machine caller receives 403 human_only. Get the same information from upsertMCPServer followed by listMCPServers.
Returns the EFFECTIVE merged mcp_servers config for a live session, the per-layer settings files behind it, and the LIVE runtime state of each server (connected, negotiated protocol_version, tool_count, pid, revocation reason, recent stderr_tail). Credential values are never returned — env and headers are reported as key NAMES only (env_keys, header_keys), because a redacted value invites a client to write the placeholder back as the real secret. Each files entry carries the content hash to pass as expect_hash on a subsequent write.
Live session id. The route folds against this session’s settings layers; foldHookSession reads ?session_id.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
X-Hoody-Cwd
header
string
No
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
Mints the single-use nonce every MCP write requires and returns the target settings path plus its current mcp_servers hash. The nonce binds {session, op, resolved path}: a write presenting a nonce minted for a different op or scope fails closed. Pass the returned hash back as expect_hash so a concurrent edit is reported as a conflict rather than silently overwritten.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
Live session id (MCP config is resolved against the session’s settings layers).
op
string
Yes
Which write the nonce authorizes. The minted nonce is valid for this op alone. One of: upsert, delete, set_enabled, import.
scope
string
No
Settings layer to write. Defaults to user, or project when there is no user layer (which is the case under --config-dir). One of: user, project, local.
The request was malformed or carried invalid parameters.
Correct the request body or query parameters.
realm_scope_unsupported
Realm scope unsupported
A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope.
Omit the realm header on this route, or open a session to scope by realm.
{
"code":"forbidden",
"message":"request must arrive through the Hoody proxy"
}
Error Code
Title
Description
Resolution
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"code":"not_found",
"message":"resource not found"
}
Error Code
Title
Description
Resolution
not_found
Not found
The requested resource does not exist.
Verify the path and identifier.
{
"code":"payload_too_large",
"message":"request body exceeds the configured size limit"
}
Error Code
Title
Description
Resolution
payload_too_large
Payload too large
The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error.
Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests.
{
"code":"rate_limited",
"message":"request rate limit exceeded"
}
Error Code
Title
Description
Resolution
rate_limited
Too many requests
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
Honor the Retry-After header and retry; reduce the request rate.
{
"code":"internal_error",
"message":"internal server error"
}
Error Code
Title
Description
Resolution
internal_error
Internal error
An unexpected error occurred while handling the request.
Retry; if persistent, inspect the daemon logs.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Writes one mcp_servers entry, merging FIELD BY FIELD over any existing entry of the same name so fields you omit keep their stored value — including fields this build does not model. Requires the beginMCPWrite nonce for op:upsert. A body carrying the redaction placeholder for a credential is REFUSED rather than stored.
On success a re-pointed server is REVOKED in every live session before the response, and the new config is APPLIED to the session you named before the response — its reconnect is AWAITED rather than merely started, so nothing is still pending when this returns. Awaited is NOT succeeded: a server that fails to start or handshake still returns 200, so read servers[].connected in this reply before calling its tools. A session that is MID-TURN keeps the tool set it was shown and picks the new one up at the next turn boundary. Other live sessions reconnect in the BACKGROUND, so this never waits out an unrelated session’s slow server; that background pass is best-effort and is skipped under sustained pressure, in which case those sessions pick the change up on the next write or an explicit reconnect. Revocation is never best-effort.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
Single-use nonce from beginMCPWrite minted for op:upsert and this scope; the RPC fails closed without it.
scope
string
No
Settings layer to write. Must match the scope the nonce was minted for. One of: user, project, local.
expect_hash
string
Yes
The mcp_servers hash you last read, as returned by beginMCPWrite or listMCPServers. Required: a mismatch returns a conflict instead of overwriting a concurrent edit, and a first write into a file that does not exist yet states its expectation with the empty-array hash rather than omitting this.
server
object
Yes
The server entry. Fields include: name (letters, digits, _ and -, max 64 chars, no __, may not be hoody or mcp — both are reserved namespaces, case-insensitive); type (stdio default, http aliases url, streamable, streamable-http for Streamable HTTP, or sse for the deprecated 2024-11-05 HTTP+SSE transport, matched case-insensitively); command + args for stdio, or url for the remote transports; env / headers (values support full ${VAR} expansion, so a token lives in your environment rather than in settings.json); allowed_tools (restrict which of the server’s tools are advertised AND dispatchable); require_confirmation (park every call from this server for human approval); enabled (defaults to true; a disabled server keeps its config but is neither connected nor advertised).
The request was malformed or carried invalid parameters.
Correct the request body or query parameters.
realm_scope_unsupported
Realm scope unsupported
A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope.
Omit the realm header on this route, or open a session to scope by realm.
{
"code":"forbidden",
"message":"request must arrive through the Hoody proxy"
}
Error Code
Title
Description
Resolution
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"code":"not_found",
"message":"resource not found"
}
Error Code
Title
Description
Resolution
not_found
Not found
The requested resource does not exist.
Verify the path and identifier.
{
"code":"mcp_conflict",
"message":"the MCP server list changed since you read it; refresh and try again"
}
Error Code
Title
Description
Resolution
mcp_conflict
MCP server list conflict
The mcp_servers content changed between the hash you read and this write. Another writer — a second client, the TUI, or a hand edit — got there first.
Re-read the current hash (listMCPServers, or beginMCPWrite which returns it with the nonce), re-apply your change on top of what is there now, and re-issue the write.
{
"code":"payload_too_large",
"message":"request body exceeds the configured size limit"
}
Error Code
Title
Description
Resolution
payload_too_large
Payload too large
The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error.
Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests.
{
"code":"rate_limited",
"message":"request rate limit exceeded"
}
Error Code
Title
Description
Resolution
rate_limited
Too many requests
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
Honor the Retry-After header and retry; reduce the request rate.
{
"code":"internal_error",
"message":"internal server error"
}
Error Code
Title
Description
Resolution
internal_error
Internal error
An unexpected error occurred while handling the request.
Retry; if persistent, inspect the daemon logs.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Removes one mcp_servers entry from the named settings layer. Requires the beginMCPWrite nonce for op:delete. The server is REVOKED in every live session before the response returns, so a caller mid-turn cannot still reach it; a stdio child is reaped when its last holder releases.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
The request was malformed or carried invalid parameters.
Correct the request body or query parameters.
realm_scope_unsupported
Realm scope unsupported
A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope.
Omit the realm header on this route, or open a session to scope by realm.
{
"code":"forbidden",
"message":"request must arrive through the Hoody proxy"
}
Error Code
Title
Description
Resolution
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"code":"not_found",
"message":"resource not found"
}
Error Code
Title
Description
Resolution
not_found
Not found
The requested resource does not exist.
Verify the path and identifier.
{
"code":"mcp_conflict",
"message":"the MCP server list changed since you read it; refresh and try again"
}
Error Code
Title
Description
Resolution
mcp_conflict
MCP server list conflict
The mcp_servers content changed between the hash you read and this write. Another writer — a second client, the TUI, or a hand edit — got there first.
Re-read the current hash (listMCPServers, or beginMCPWrite which returns it with the nonce), re-apply your change on top of what is there now, and re-issue the write.
{
"code":"payload_too_large",
"message":"request body exceeds the configured size limit"
}
Error Code
Title
Description
Resolution
payload_too_large
Payload too large
The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error.
Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests.
{
"code":"rate_limited",
"message":"request rate limit exceeded"
}
Error Code
Title
Description
Resolution
rate_limited
Too many requests
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
Honor the Retry-After header and retry; reduce the request rate.
{
"code":"internal_error",
"message":"internal server error"
}
Error Code
Title
Description
Resolution
internal_error
Internal error
An unexpected error occurred while handling the request.
Retry; if persistent, inspect the daemon logs.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Flips one entry’s enabled flag without touching the rest of its config, so credentials and options survive a disable. Requires the beginMCPWrite nonce for op:set_enabled. Disabling revokes the server in live sessions immediately.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
The request was malformed or carried invalid parameters.
Correct the request body or query parameters.
realm_scope_unsupported
Realm scope unsupported
A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope.
Omit the realm header on this route, or open a session to scope by realm.
{
"code":"forbidden",
"message":"request must arrive through the Hoody proxy"
}
Error Code
Title
Description
Resolution
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"code":"not_found",
"message":"resource not found"
}
Error Code
Title
Description
Resolution
not_found
Not found
The requested resource does not exist.
Verify the path and identifier.
{
"code":"mcp_conflict",
"message":"the MCP server list changed since you read it; refresh and try again"
}
Error Code
Title
Description
Resolution
mcp_conflict
MCP server list conflict
The mcp_servers content changed between the hash you read and this write. Another writer — a second client, the TUI, or a hand edit — got there first.
Re-read the current hash (listMCPServers, or beginMCPWrite which returns it with the nonce), re-apply your change on top of what is there now, and re-issue the write.
{
"code":"payload_too_large",
"message":"request body exceeds the configured size limit"
}
Error Code
Title
Description
Resolution
payload_too_large
Payload too large
The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error.
Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests.
{
"code":"rate_limited",
"message":"request rate limit exceeded"
}
Error Code
Title
Description
Resolution
rate_limited
Too many requests
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
Honor the Retry-After header and retry; reduce the request rate.
{
"code":"internal_error",
"message":"internal server error"
}
Error Code
Title
Description
Resolution
internal_error
Internal error
An unexpected error occurred while handling the request.
Retry; if persistent, inspect the daemon logs.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Imports a batch of servers from a pasted config document or an explicit array. Understands the hoody (mcp_servers list), Claude/Cursor (mcpServers map) and VS Code (servers map) dialects; a document carrying more than one of them is REFUSED rather than guessed at. Validation is WHOLE-BATCH — one bad entry aborts everything, because a partial import leaves a config the operator did not author. Imported servers land DISABLED for review; enable them with setMCPServerEnabled. Requires the beginMCPWrite nonce for op:import.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
The request was malformed or carried invalid parameters.
Correct the request body or query parameters.
realm_scope_unsupported
Realm scope unsupported
A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope.
Omit the realm header on this route, or open a session to scope by realm.
{
"code":"forbidden",
"message":"request must arrive through the Hoody proxy"
}
Error Code
Title
Description
Resolution
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"code":"not_found",
"message":"resource not found"
}
Error Code
Title
Description
Resolution
not_found
Not found
The requested resource does not exist.
Verify the path and identifier.
{
"code":"mcp_conflict",
"message":"the MCP server list changed since you read it; refresh and try again"
}
Error Code
Title
Description
Resolution
mcp_conflict
MCP server list conflict
The mcp_servers content changed between the hash you read and this write. Another writer — a second client, the TUI, or a hand edit — got there first.
Re-read the current hash (listMCPServers, or beginMCPWrite which returns it with the nonce), re-apply your change on top of what is there now, and re-issue the write.
{
"code":"payload_too_large",
"message":"request body exceeds the configured size limit"
}
Error Code
Title
Description
Resolution
payload_too_large
Payload too large
The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error.
Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests.
{
"code":"rate_limited",
"message":"request rate limit exceeded"
}
Error Code
Title
Description
Resolution
rate_limited
Too many requests
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
Honor the Retry-After header and retry; reduce the request rate.
{
"code":"internal_error",
"message":"internal server error"
}
Error Code
Title
Description
Resolution
internal_error
Internal error
An unexpected error occurred while handling the request.
Retry; if persistent, inspect the daemon logs.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Parses a pasted config document into the entries an import WOULD write, without touching any file. Credential values are stripped from the preview. Use it to show a user what they are about to import; it needs no nonce because it writes nothing.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
The request was malformed or carried invalid parameters.
Correct the request body or query parameters.
realm_scope_unsupported
Realm scope unsupported
A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope.
Omit the realm header on this route, or open a session to scope by realm.
{
"code":"forbidden",
"message":"request must arrive through the Hoody proxy"
}
Error Code
Title
Description
Resolution
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"code":"not_found",
"message":"resource not found"
}
Error Code
Title
Description
Resolution
not_found
Not found
The requested resource does not exist.
Verify the path and identifier.
{
"code":"payload_too_large",
"message":"request body exceeds the configured size limit"
}
Error Code
Title
Description
Resolution
payload_too_large
Payload too large
The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error.
Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests.
{
"code":"rate_limited",
"message":"request rate limit exceeded"
}
Error Code
Title
Description
Resolution
rate_limited
Too many requests
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
Honor the Retry-After header and retry; reduce the request rate.
{
"code":"internal_error",
"message":"internal server error"
}
Error Code
Title
Description
Resolution
internal_error
Internal error
An unexpected error occurred while handling the request.
Retry; if persistent, inspect the daemon logs.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Connects to a candidate server config and reports the tools it advertises and the protocol revision it negotiated, then tears the connection down. Nothing is written. HUMAN-ONLY: probing starts a process (stdio) or makes an outbound request to a caller-chosen URL (http/sse), so a machine caller may not self-approve it and receives 403 human_only. The deny list is enforced on the candidate config before anything is started.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
This route has no 2xx response. Every forwarded HTTP call is machine-stamped; the only path is 403 human_only. Other non-2xx statuses remain reachable for malformed input.
The request was malformed or carried invalid parameters.
Correct the request body or query parameters.
realm_scope_unsupported
Realm scope unsupported
A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope.
Omit the realm header on this route, or open a session to scope by realm.
{
"code":"human_only",
"message":"probing an MCP server requires direct human confirmation and is not available to machine callers"
}
Error Code
Title
Description
Resolution
human_only
Probing requires a human
Probing starts a process (stdio) or makes an outbound request to a caller-chosen URL, so an autonomous caller may not self-approve it. The gateway stamps the machine marker on every call it forwards, so there is no successful HTTP probe path — this refusal is not a transient condition to retry (other non-2xx statuses remain reachable for malformed input).
Do not probe over HTTP; get the same information from the write itself. Create the entry with upsertMCPServer, then read listMCPServers: it reports connected, the negotiated protocol_version, tool_count, and stderr_tail when a stdio child dies — which is what a probe would have told you. Note a disabled entry is never started, so it will never report connected; enable it to learn anything.
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"code":"not_found",
"message":"resource not found"
}
Error Code
Title
Description
Resolution
not_found
Not found
The requested resource does not exist.
Verify the path and identifier.
{
"code":"payload_too_large",
"message":"request body exceeds the configured size limit"
}
Error Code
Title
Description
Resolution
payload_too_large
Payload too large
The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error.
Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests.
{
"code":"rate_limited",
"message":"request rate limit exceeded"
}
Error Code
Title
Description
Resolution
rate_limited
Too many requests
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
Honor the Retry-After header and retry; reduce the request rate.
{
"code":"internal_error",
"message":"internal server error"
}
Error Code
Title
Description
Resolution
internal_error
Internal error
An unexpected error occurred while handling the request.
Retry; if persistent, inspect the daemon logs.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).
Re-reads the settings layers and reconciles every live session’s MCP pool: servers that vanished or were re-pointed are revoked, the rest are reconnected, and a healthy unchanged server is NOT restarted. Revocation lands in EVERY live session before the response. Reconnection is AWAITED only for the session you named — awaited, not guaranteed: a server that will not start leaves connected: false and still returns 200. Other sessions reconnect in the background, best-effort.
Use this after editing a settings file by hand, or to recover a server that died.
Per-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-Dir
header
string
No
Per-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-Container
header
string
No
Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-Realm
header
string
No
Per-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realm
query
string
No
Per-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): global or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
The request was malformed or carried invalid parameters.
Correct the request body or query parameters.
realm_scope_unsupported
Realm scope unsupported
A per-request realm header was supplied to an active-only / global-no-realm RPC, which has no realm dimension to scope.
Omit the realm header on this route, or open a session to scope by realm.
{
"code":"forbidden",
"message":"request must arrive through the Hoody proxy"
}
Error Code
Title
Description
Resolution
forbidden
Forbidden (not via the Hoody proxy)
Forbidden — the request did not reach the service through the public endpoint.
Reach the agent through hoody-proxy (e.g. hoody agent … → platform → proxy), not by connecting to the container directly.
{
"code":"not_found",
"message":"resource not found"
}
Error Code
Title
Description
Resolution
not_found
Not found
The requested resource does not exist.
Verify the path and identifier.
{
"code":"payload_too_large",
"message":"request body exceeds the configured size limit"
}
Error Code
Title
Description
Resolution
payload_too_large
Payload too large
The request body exceeds the configured size cap (MaxBodyBytes). The gateway rejects an oversized body at the edge (http.MaxBytesReader) before the handler reads it — a well-formed-but-large body is a size violation, not a JSON syntax error.
Reduce the request body below the configured limit (default 8 MiB); split a large payload into smaller requests.
{
"code":"rate_limited",
"message":"request rate limit exceeded"
}
Error Code
Title
Description
Resolution
rate_limited
Too many requests
The per-client request rate limit was exceeded; the gateway throttled the request before dispatch.
Honor the Retry-After header and retry; reduce the request rate.
{
"code":"internal_error",
"message":"internal server error"
}
Error Code
Title
Description
Resolution
internal_error
Internal error
An unexpected error occurred while handling the request.
Retry; if persistent, inspect the daemon logs.
{
"code":"service_unavailable",
"message":"service unavailable"
}
Error Code
Title
Description
Resolution
service_unavailable
Service unavailable
The daemon could not service the request (too busy, or a per-client stream concurrency cap was hit).