Register an upstream MCP server
Answers 404 where the mcp-upstreams feature is off. Registers a remote MCP server (Streamable HTTP, https) and lists its tools: initialize and tools/list, reads only. Each tool is classified and hashed by the risk engine anlyon.dev runs. Nothing is adopted, so no agent can call anything yet. Headers carry credentials only as {{secret:NAME}} references, checked against the secret’s allowed hosts and placements, and naming one needs secrets:read. A server whose tools cannot be listed is not registered (400), and one that asks for an OAuth sign-in without OAuth settings is refused with that reason. From a credential it applies at once, except that a stored secret, or a server that signs people in with OAuth, answers 202 and waits for a person’s sign-off.
/api/v2/mcp-upstreamsAuthorizationBearer token (Anlyon API key) · headerrequiredWorkspace API key sent as Authorization: Bearer <key>.
better-auth.session_tokenAPI key · cookierequiredBrowser session used by dashboard-only operations.
X-Request-IdstringOptional caller correlation ID. Unsafe or oversized values are replaced.
application/jsonnamestringrequiredurlstring<uri>requiredheadersobjectregistryNamestring | nulloauthobject | nullFor a server that signs people in with OAuth (ADR 0026). With clientId, the client registered with the vendor, whose secret must have allowed hosts. Without it, this deployment's own client metadata document on a verified vendor's server whose authorization server accepts one, else a client registered with it dynamically (RFC 7591).
Show propertiesHide properties
clientIdstring | nullclientSecretstring | nullA confidential client's secret as a secret reference. Omit for a public client (PKCE).
scopesstring[]redirectUristring<uri> | nullThe redirect URI the client is registered with
authorizationServerstring<uri> | nullWhich of the resource's authorization servers to use, when it names several. Default: the first.
Registered, with its tools listed.
successbooleanrequireddataMcpUpstreamrequiredShow propertiesHide properties
idstringrequirednamestringrequiredurlstring<uri>requiredheadersobjectrequiredSent on every request. Credentials appear only as secret references.
registryNamestring | nullrequiredprotocolVersionstring | nullrequiredtransportstring | nullrequiredHow the server is reached, as the last listing found: Streamable HTTP, or the older HTTP+SSE transport (MCP 2024-11-05) Anlyon falls back to when the server answers 400, 404 or 405. Null until a listing has worked.
streamable-httpssenullserverInfoobject | nullrequiredtoolsMcpToolSnapshot[]requiredShow propertiesHide properties
McpToolSnapshotnamestringrequiredhashstringrequiredsha256 of the tool's normalised definition
definitionobjectrequiredsuggestedClassstringrequiredreadwriteirreversibledestructivereasonsstring[]requiredschemaCheckMcpSchemaCheckrequiredHow a tool's arguments are checked. full: against its whole input schema (JSON Schema drafts 2020-12, 2019-09, 07 and 04). loose: the schema uses something Anlyon does not check, so only that the arguments are a JSON object of at most 256 KiB. A loose tool is still pinned by hash, and approval is always suggested for it.
fulllooseschemaCheckReasonMcpSchemaCheckReason | nullrequiredWhy a tool is loosely checked; null when it is checked in full. remote_ref: a $ref points outside the schema, and nothing is fetched. too_large: the schema is past a size, depth or reference limit. unsafe_pattern: a pattern could backtrack catastrophically or is too long. invalid_schema: the schema is not valid JSON Schema. unsupported_keyword: $dynamicRef or $recursiveRef. unknown_dialect: $schema names a dialect Anlyon does not know. ref_cycle: a $ref leads back to itself without moving into the value.
remote_reftoo_largeunsafe_patterninvalid_schemaunsupported_keywordunknown_dialectref_cyclenulltoolsHashstring | nullrequiredThe hash of the whole listing
listedAtstring<date-time> | nullrequiredlastErrorobject | nullrequiredlistedWithstring | nullrequiredHow the last listing was made: without a credential, with the headers, or with the operator's own OAuth grant.
anonymousheadersoperatornullcheckobjectrequiredWhether Anlyon can re-list the server by itself, and when it last tried.
Show propertiesHide properties
statusstringrequiredfailed: nothing is known since listedAt. needs_sign_in: it cannot be checked until someone connects their own account. An end user's sign-in is never used for it.
okfailedneeds_sign_inpendingcheckedAtstring<date-time> | nullrequirednextCheckAtstring<date-time> | nullrequiredfailuresintegerrequiredFailed checks in a row.
changesobject[]requiredHow the last listing differs from what was adopted. Finding a change adopts nothing and enables nothing. tool and before are the server's text, untrusted.
Show propertiesHide properties
objecttoolstringrequiredkindstringrequiredchanged and removed are adopted tools, refused at dispatch until re-adopted. added is shown and never adopted.
changedremovedaddedactionstring | nullrequiredactionIdstring | nullrequiredpinnedHashstring | nullrequiredcurrentHashstring | nullrequiredsuggestedClassstring | nullrequiredreadwriteirreversibledestructivenullbeforeobject | nullrequiredThe definition at the pin
detectedAtstring<date-time>requiredoauthobject | nullrequiredSet for an upstream that signs people in with OAuth (ADR 0026). Never a token or a secret.
Show propertiesHide properties
resourcestring<uri>requiredissuerstring<uri>requiredauthorizationServersstring[]requiredEvery authorization server the resource named; issuer is the one in use.
authorizationEndpointstring<uri>requiredtokenEndpointstring<uri>requiredscopesSupportedstring[]requiredscopesstring[]requiredclientIdstringrequiredThe operator's client id
clientRegistrationstringrequiredpre_registeredclient_metadata_documentdynamicadvertisedobjectrequiredShow propertiesHide properties
dynamicRegistrationbooleanrequiredclientIdMetadataDocumentsbooleanrequiredpkceS256booleanrequiredpublicClientbooleanrequiredredirectUristring<uri>requiredoperatorConnectedbooleanrequiredadoptedobject[]requiredShow propertiesHide properties
objecttoolstringrequiredactionstringrequiredactionIdstringrequiredenabledbooleanrequiredstatestringrequiredcurrentchangedmissingtoolHashstringrequiredThe definition this action is pinned to.
requiresApprovalbooleanrequiredschemaCheckMcpSchemaCheckrequiredHow a tool's arguments are checked. full: against its whole input schema (JSON Schema drafts 2020-12, 2019-09, 07 and 04). loose: the schema uses something Anlyon does not check, so only that the arguments are a JSON object of at most 256 KiB. A loose tool is still pinned by hash, and approval is always suggested for it.
fulllooseschemaCheckReasonMcpSchemaCheckReason | nullrequiredWhy a tool is loosely checked; null when it is checked in full. remote_ref: a $ref points outside the schema, and nothing is fetched. too_large: the schema is past a size, depth or reference limit. unsafe_pattern: a pattern could backtrack catastrophically or is too long. invalid_schema: the schema is not valid JSON Schema. unsupported_keyword: $dynamicRef or $recursiveRef. unknown_dialect: $schema names a dialect Anlyon does not know. ref_cycle: a $ref leads back to itself without moving into the value.
remote_reftoo_largeunsafe_patterninvalid_schemaunsupported_keywordunknown_dialectref_cyclenullarchivedAtstring<date-time> | nullrequiredcreatedAtstring<date-time>requiredupdatedAtstring<date-time>requiredAccepted, not applied: the change loosens a guardrail, so a workspace admin has to approve it. Location is the request to poll.
successbooleanrequiredtruesignOffRequiredbooleanrequiredtruedataSignOffRequestrequiredA governance change that loosens a guardrail, asked for by an API key, a CLI login or an MCP session, waiting for a workspace admin. Give signOffUrl to a person; poll pollUrl.
Show propertiesHide properties
objectstringrequiredsign_off_requestidstringrequiredstatusstringrequiredpending until a workspace admin decides. applied: approved and in effect. rejected, expired (after 24 hours), cancelled (withdrawn by the credential) and failed (approved but could not be applied, see error): nothing changed.
pendingappliedrejectedexpiredcancelledfailedoperationstringrequiredpolicy.createpolicy.updatepolicy.deletepolicy_file.applyimpact_limit.updateimpact_limit.archivebudget.putbudget.deleteenvironment.resumeaction.createaction.updateaction.importsecret.putsecret_store.createsecret_store.updatesecret_store_settings.updateoauth_app.putenvironmentIdstring<uuid>requiredresourceobject | nullrequiredShow propertiesHide properties
typestringrequiredidstringrequirednamestringsummarystringrequiredchangesSignOffChange[]requiredShow propertiesHide properties
SignOffChangefieldstringrequiredfromany | nullrequiredThe value before. Never a secret value.
toany | nullrequiredThe value after. Never a secret value.
directionstringrequiredtighteninglooseningneutralreasonstringrequireddiffstringrequiredThe changes as plain text
signOffUrlstring<uri>requiredThe console page where a workspace admin approves or rejects it. Give this to a person.
pollUrlstringrequiredpollAfterSecondsintegerrequiredrequestedByobjectrequiredShow propertiesHide properties
typestringrequiredapi_keyoauth_clientsystemidstring | nullrequiredonBehalfOfstring | nullFor a CLI login or an MCP session
createdAtstring<date-time>requiredexpiresAtstring<date-time>requireddecidedAtstring<date-time> | nullrequireddecidedByobject | nullrequiredShow propertiesHide properties
typestringrequireduseridstringrequiredviastringrequiredconsoleemail_linkdecisionNotestring | nullrequiredresultany | nullrequiredWhen applied, what the original request would have returned: the limit, budget, policy or action as it now is.
errorobject | nullrequiredShow propertiesHide properties
codestringrequiredmessagestringrequiredBad Request - Invalid input data
successbooleanrequiredrequestIdstringrequiredCorrelation ID matching the X-Request-Id response header.
errorobjectrequiredShow propertiesHide properties
codestringmessagestringdetailsobjectfixErrorFixHow to get past this error, for a person or an agent. Present on refusals with a known next step, such as a missing scope or role, a plan or billing limit, a halted environment, or a missing secret, connected account, OAuth app or end-user header. Absent when there is no fix to give. Kept in production responses, unlike details.
Show propertiesHide properties
summarystringrequiredOne sentence that says what to do.
commandstringAn exact anlyon CLI command that fixes it. Absent when no command does.
urlstring<uri>An absolute console link where a person fixes it.
docsstring<uri>A docs page that explains it.
Unauthorized - Invalid or missing API key
successbooleanrequiredrequestIdstringrequiredCorrelation ID matching the X-Request-Id response header.
errorobjectrequiredShow propertiesHide properties
codestringmessagestringdetailsobjectfixErrorFixHow to get past this error, for a person or an agent. Present on refusals with a known next step, such as a missing scope or role, a plan or billing limit, a halted environment, or a missing secret, connected account, OAuth app or end-user header. Absent when there is no fix to give. Kept in production responses, unlike details.
Show propertiesHide properties
summarystringrequiredOne sentence that says what to do.
commandstringAn exact anlyon CLI command that fixes it. Absent when no command does.
urlstring<uri>An absolute console link where a person fixes it.
docsstring<uri>A docs page that explains it.
Authenticated credential lacks the required scope or workspace access.
successbooleanrequiredrequestIdstringrequiredCorrelation ID matching the X-Request-Id response header.
errorobjectrequiredShow propertiesHide properties
codestringmessagestringdetailsobjectfixErrorFixHow to get past this error, for a person or an agent. Present on refusals with a known next step, such as a missing scope or role, a plan or billing limit, a halted environment, or a missing secret, connected account, OAuth app or end-user header. Absent when there is no fix to give. Kept in production responses, unlike details.
Show propertiesHide properties
summarystringrequiredOne sentence that says what to do.
commandstringAn exact anlyon CLI command that fixes it. Absent when no command does.
urlstring<uri>An absolute console link where a person fixes it.
docsstring<uri>A docs page that explains it.
Not Found - Resource does not exist
successbooleanrequiredrequestIdstringrequiredCorrelation ID matching the X-Request-Id response header.
errorobjectrequiredShow propertiesHide properties
codestringmessagestringdetailsobjectfixErrorFixHow to get past this error, for a person or an agent. Present on refusals with a known next step, such as a missing scope or role, a plan or billing limit, a halted environment, or a missing secret, connected account, OAuth app or end-user header. Absent when there is no fix to give. Kept in production responses, unlike details.
Show propertiesHide properties
summarystringrequiredOne sentence that says what to do.
commandstringAn exact anlyon CLI command that fixes it. Absent when no command does.
urlstring<uri>An absolute console link where a person fixes it.
docsstring<uri>A docs page that explains it.
The request conflicts with current resource state or a concurrent decision.
successbooleanrequiredrequestIdstringrequiredCorrelation ID matching the X-Request-Id response header.
errorobjectrequiredShow propertiesHide properties
codestringmessagestringdetailsobjectfixErrorFixHow to get past this error, for a person or an agent. Present on refusals with a known next step, such as a missing scope or role, a plan or billing limit, a halted environment, or a missing secret, connected account, OAuth app or end-user header. Absent when there is no fix to give. Kept in production responses, unlike details.
Show propertiesHide properties
summarystringrequiredOne sentence that says what to do.
commandstringAn exact anlyon CLI command that fixes it. Absent when no command does.
urlstring<uri>An absolute console link where a person fixes it.
docsstring<uri>A docs page that explains it.
Too Many Requests - Rate limit exceeded. A workspace's API requests are limited per minute and per UTC clock hour by plan; Retry-After says when to try again, and an hourly refusal names the limit and when the count resets. Successful responses carry the same limits in X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (the minute) and X-RateLimit-Limit-Hour, X-RateLimit-Remaining-Hour, X-RateLimit-Reset-Hour (the hour).
successbooleanrequiredrequestIdstringrequiredCorrelation ID matching the X-Request-Id response header.
errorobjectrequiredShow propertiesHide properties
codestringmessagestringdetailsobjectfixErrorFixHow to get past this error, for a person or an agent. Present on refusals with a known next step, such as a missing scope or role, a plan or billing limit, a halted environment, or a missing secret, connected account, OAuth app or end-user header. Absent when there is no fix to give. Kept in production responses, unlike details.
Show propertiesHide properties
summarystringrequiredOne sentence that says what to do.
commandstringAn exact anlyon CLI command that fixes it. Absent when no command does.
urlstring<uri>An absolute console link where a person fixes it.
docsstring<uri>A docs page that explains it.

