From 234322a32bc85e9af22c71d217bd8c77eb0964e3 Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Mon, 26 Oct 2026 17:01:11 -0400 Subject: [PATCH 1/3] docs: rename Gateway result feature fields to cache and compression Match iris RED-222240: the Gateway settings and tool policy members are now cache and compression. Operator config keys, metrics, and the resultCache _meta member keep their names. --- .../context-gateway/concepts.md | 8 ++++---- .../context-engine/context-gateway/limits.md | 2 +- .../context-gateway/manage-gateways.md | 20 +++++++++---------- .../self-managed/api-examples.md | 2 +- .../self-managed/configuration.md | 2 +- .../self-managed/operations.md | 4 ++-- .../context-gateway/self-managed/reference.md | 6 +++--- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/content/develop/ai/context-engine/context-gateway/concepts.md b/content/develop/ai/context-engine/context-gateway/concepts.md index 9bb3a3b31c..8ed288c834 100644 --- a/content/develop/ai/context-engine/context-gateway/concepts.md +++ b/content/develop/ai/context-engine/context-gateway/concepts.md @@ -85,11 +85,11 @@ In `search` mode the agent calls `search_tools` and receives complete tool defin A **tool policy** sets optional behavior for one tool of one Upstream. Both behaviors need a Gateway database, selected with the Gateway's `databaseId`. -Each Gateway also turns the result cache and result handles on or off for all of its tools with its `resultCache` and `resultHandles` settings, `enabled` or `disabled`. A Gateway created with a `databaseId` starts with both enabled, and a Gateway without one has both disabled. A feature serves a Gateway only when the Gateway's setting is `enabled` and the deployment turns the feature on. +Each Gateway also turns the result cache and result handles on or off for all of its tools with two settings, `enabled` or `disabled`: `cache` for the result cache and `compression` for result handles. A Gateway created with a `databaseId` starts with both enabled, and a Gateway without one has both disabled. A feature serves a Gateway only when the Gateway's setting is `enabled` and the deployment turns the feature on. ### Result cache -The result cache serves a repeated call from the Gateway database instead of calling the Upstream again. Each tool opts in with a `resultCache` policy and a time to live (TTL). +The result cache serves a repeated call from the Gateway database instead of calling the Upstream again. Each tool opts in with a `cache` policy and a time to live (TTL). A tool can be cached unless its definition says `readOnlyHint: false` or `destructiveHint: true`. An absent hint does not block caching, and no annotation turns caching on. An entry is served until its TTL expires or the Upstream's revision changes. @@ -102,7 +102,7 @@ All callers with access to a Gateway share its cache entries. A result handle holds a large tool result in the Gateway database. When result handles are on for a Gateway, every eligible result over 32 kibibytes (KiB) becomes a handle. The agent receives a small stub with the handle and reads the result in pages, queries, counts, or aggregates. -A tool opts out with a `resultHandle` policy of `capture: never`, or sets its own handle lifetime with `ttlSeconds`. An agent can also hold a result of any size with `run_tool_as_handle`. +A tool opts out with a `compression` policy of `capture: never`, or sets its own handle lifetime with `ttlSeconds`. An agent can also hold a result of any size with `run_tool_as_handle`. A handle is bound to the caller that created it, and it survives a rotation of that caller's agent key. It ends when the agent releases it or its TTL expires. Handles are bounded by their TTL and the Gateway database's memory. @@ -116,7 +116,7 @@ A handle is bound to the caller that created it, and it survives a rotation of t | Namespace | The prefix that makes an Upstream's tool names unique within a Gateway. | | Catalog | The stored list of an Upstream's tools. | | Tool policy | Per-tool settings for the result cache and result handles. | -| `resultCache`, `resultHandles` | Per-Gateway settings that turn the result cache and result handles on or off. | +| `cache`, `compression` | Per-Gateway settings that turn the result cache and result handles on or off. | | Gateway database | The Redis database that holds cached results and result handles. | ## Next steps diff --git a/content/develop/ai/context-engine/context-gateway/limits.md b/content/develop/ai/context-engine/context-gateway/limits.md index edb12c7df3..619686a788 100644 --- a/content/develop/ai/context-engine/context-gateway/limits.md +++ b/content/develop/ai/context-engine/context-gateway/limits.md @@ -23,7 +23,7 @@ The [API reference](/content/develop/ai/context-engine/context-gateway/api-refer | Upstream namespace | 1 to 63 lowercase letters and digits, with single hyphens between them | | Gateway `databaseId` | 1 to 32 letters, digits, and hyphens | | `search_tools` query | 1 to 200 characters. `limit` 1 to 100, default 5. | -| Result cache time to live (TTL) (`resultCache.ttlSeconds`) | 1 to 86400 seconds | +| Result cache time to live (TTL) (`cache.ttlSeconds`) | 1 to 86400 seconds | | Result handle threshold | Results over 32 kibibytes (KiB) become handles when the deployment turns handles on. | | Largest result a handle holds | 8 mebibytes (MiB). A larger result comes back whole. | | Result handle lifetime | 15 minutes by default, at most 24 hours. A tool policy can set 1 to 86400 seconds. | diff --git a/content/develop/ai/context-engine/context-gateway/manage-gateways.md b/content/develop/ai/context-engine/context-gateway/manage-gateways.md index 69a55f322c..119e8dd9a2 100644 --- a/content/develop/ai/context-engine/context-gateway/manage-gateways.md +++ b/content/develop/ai/context-engine/context-gateway/manage-gateways.md @@ -32,7 +32,7 @@ Create a Gateway and save its `id` and `mcpEndpoint`. The Gateway serves Model C *Example set `iris_gateway_manage`, step `gateway-create`, in Python (Iris), cURL (Iris), and CLI (Iris).* -To use the result cache or result handles, select a Gateway database with `databaseId`. Your administrator names the available databases. A Gateway created with a `databaseId` has `resultCache` and `resultHandles` enabled unless you send them as `disabled`. Sending `enabled` without a `databaseId` returns `400`. +To use the result cache or result handles, select a Gateway database with `databaseId`. Your administrator names the available databases. A Gateway created with a `databaseId` has `cache` and `compression` enabled unless you send them as `disabled`. Sending `enabled` without a `databaseId` returns `400`. ## List and inspect Gateways and Upstreams @@ -42,22 +42,22 @@ List the deployment's Gateways and a Gateway's Upstreams, and read one by ID. Ev ## Change a Gateway -Update a Gateway's `toolExposureMode` to `full` or `search`, its display name, its `databaseId`, or its `resultCache` and `resultHandles` settings. Agents see a new mode on their next request. See [Tool exposure modes](/content/develop/ai/context-engine/context-gateway/concepts.md#tool-exposure-modes). +Update a Gateway's `toolExposureMode` to `full` or `search`, its display name, its `databaseId`, or its `cache` and `compression` settings. Agents see a new mode on their next request. See [Tool exposure modes](/content/develop/ai/context-engine/context-gateway/concepts.md#tool-exposure-modes). *Example step `gateway-update-mode`.* ### Turn the result cache and result handles on or off -Set `resultCache` or `resultHandles` to `enabled` or `disabled` on a Gateway update. Every Gateway response returns both settings. A Gateway's setting takes effect only when the deployment also turns the feature on. See [Result cache and result handles](/content/operate/iris/context-gateway/self-managed/configuration.md#result-cache-and-result-handles). +Set `cache` or `compression` to `enabled` or `disabled` on a Gateway update. Every Gateway response returns both settings. A Gateway's setting takes effect only when the deployment also turns the feature on. See [Result cache and result handles](/content/operate/iris/context-gateway/self-managed/configuration.md#result-cache-and-result-handles). ```json -{"revision": "", "resultCache": "enabled", "resultHandles": "disabled"} +{"revision": "", "cache": "enabled", "compression": "disabled"} ``` | Change | What to send | | --- | --- | -| Remove the Gateway database | `"databaseId": null` with `"resultCache": "disabled"` and `"resultHandles": "disabled"` in the same request. Without them, the update returns `400`. | -| Add a Gateway database to a Gateway that had none | `databaseId` with `"resultCache": "enabled"`, `"resultHandles": "enabled"`, or both. Adding a database alone keeps both settings as they were, which is `disabled` for a Gateway created without one. | +| Remove the Gateway database | `"databaseId": null` with `"cache": "disabled"` and `"compression": "disabled"` in the same request. Without them, the update returns `400`. | +| Add a Gateway database to a Gateway that had none | `databaseId` with `"cache": "enabled"`, `"compression": "enabled"`, or both. Adding a database alone keeps both settings as they were, which is `disabled` for a Gateway created without one. | | Stop caching or handles for a Gateway | `"disabled"` for that setting. The Gateway stops reading and writing cache entries, or stops creating handles and removes the handle tools from `tools/list`. Stored entries and handles stay until their TTL. | *Example step `gateway-update-features`.* @@ -97,15 +97,15 @@ Set a tool's policies with `toolPolicies` on an Upstream update. The result cach | Policy | Member | Effect | | --- | --- | --- | -| `resultCache` | `ttlSeconds`, 1 to 86400 | Caches the tool's results for that long. | -| `resultHandle` | `capture: never` | Always returns the tool's results whole, also from `run_tool_as_handle`. | -| `resultHandle` | `ttlSeconds`, 1 to 86400 | Keeps the tool's handles for that long instead of the deployment's default. | +| `cache` | `ttlSeconds`, 1 to 86400 | Caches the tool's results for that long. | +| `compression` | `capture: never` | Always returns the tool's results whole, also from `run_tool_as_handle`. | +| `compression` | `ttlSeconds`, 1 to 86400 | Keeps the tool's handles for that long instead of the deployment's default. | *Example step `gateway-tool-policy`.* - Cache only tools whose data changes more slowly than the time to live (TTL). All callers with access to the Gateway share its cache entries. - A tool whose definition says `readOnlyHint: false` or `destructiveHint: true` is never cached. -- A new or changed `resultCache` policy returns `400` while the Gateway's `resultCache` is `disabled`, including on a Gateway without a `databaseId`. A stored policy sent back unchanged is kept. +- A new or changed `cache` policy returns `400` while the Gateway's `cache` setting is `disabled`, including on a Gateway without a `databaseId`. A stored policy sent back unchanged is kept. - When you move an Upstream to a new endpoint, the response lists any policies it removed in `droppedToolPolicies`. ## Rotate an Upstream credential diff --git a/content/operate/iris/context-gateway/self-managed/api-examples.md b/content/operate/iris/context-gateway/self-managed/api-examples.md index e9bf27f2ad..9dbf1a1718 100644 --- a/content/operate/iris/context-gateway/self-managed/api-examples.md +++ b/content/operate/iris/context-gateway/self-managed/api-examples.md @@ -51,7 +51,7 @@ export OPERATIONS_ID="$(jq -er '.id' operations.json)" jq '{id, mcpEndpoint, toolExposureMode}' front-desk.json operations.json ``` -The `search` mode Gateway has a `databaseId`, so it starts with `resultCache` and `resultHandles` enabled. Result handles also need `result_handles.enabled` on the Data Plane. See [Result cache and result handles](/content/operate/iris/context-gateway/self-managed/configuration.md#result-cache-and-result-handles). +The `search` mode Gateway has a `databaseId`, so it starts with `cache` and `compression` enabled. Result handles also need `result_handles.enabled` on the Data Plane. See [Result cache and result handles](/content/operate/iris/context-gateway/self-managed/configuration.md#result-cache-and-result-handles). diff --git a/content/operate/iris/context-gateway/self-managed/configuration.md b/content/operate/iris/context-gateway/self-managed/configuration.md index bbbf14bd59..3e26651d89 100644 --- a/content/operate/iris/context-gateway/self-managed/configuration.md +++ b/content/operate/iris/context-gateway/self-managed/configuration.md @@ -118,7 +118,7 @@ dataplane: | `result_handles.max_capture_bytes` | `8388608` | Results above this size come back whole. | | `result_handles.preview_items`, `preview_bytes` | `3`, `2048` | The size of a handle stub's preview. | -These settings turn each feature on for the deployment. Each Gateway then has its own `resultCache` and `resultHandles` settings, and a feature serves a Gateway only when both the deployment and the Gateway turn it on. Both need the Gateway's `databaseId` to name a registered database. +These settings turn each feature on for the deployment. Each Gateway then has its own `cache` and `compression` settings, and a feature serves a Gateway only when both the deployment and the Gateway turn it on. Both need the Gateway's `databaseId` to name a registered database. The result cache still needs a policy for each tool. Result handles apply to every eligible result on a Gateway that has them on, unless a tool's policy opts out. See [Turn the result cache and result handles on or off](/content/develop/ai/context-engine/context-gateway/manage-gateways.md#turn-the-result-cache-and-result-handles-on-or-off). diff --git a/content/operate/iris/context-gateway/self-managed/operations.md b/content/operate/iris/context-gateway/self-managed/operations.md index 0d53cc0a23..314ff26497 100644 --- a/content/operate/iris/context-gateway/self-managed/operations.md +++ b/content/operate/iris/context-gateway/self-managed/operations.md @@ -51,7 +51,7 @@ A cache hit carries `resultCache` in the call's invocation metadata. Every other | Bypass `reason` | What to check | | --- | --- | | `not_opted_in` | The tool has no result cache policy. | -| `disabled` | The Gateway's `resultCache` is `disabled`. | +| `disabled` | The Gateway's `cache` setting is `disabled`. | | `no_database` | The Gateway has no `databaseId`. | | `unknown_database` | The Gateway's database is not registered on the Data Plane. Declare it on both planes. | | `vetoed_by_annotation` | The tool's definition says it is not read-only, or that it is destructive. | @@ -89,7 +89,7 @@ Upgrade both planes together and roll forward, not back. An older Data Plane can After an upgrade, refresh an Upstream's catalog when the release notes ask for it. -Gateways stored before the per-Gateway `resultCache` and `resultHandles` settings read as `enabled` when they have a `databaseId` and `disabled` otherwise, so their behavior does not change. Scripts that remove or add a Gateway's `databaseId`, or set `resultCache` tool policies, may need the changes in [Turn the result cache and result handles on or off](/content/develop/ai/context-engine/context-gateway/manage-gateways.md#turn-the-result-cache-and-result-handles-on-or-off). +Gateways stored before the per-Gateway `cache` and `compression` settings read as `enabled` when they have a `databaseId` and `disabled` otherwise, so their behavior does not change. Scripts that remove or add a Gateway's `databaseId`, or set `resultCache` tool policies, may need the changes in [Turn the result cache and result handles on or off](/content/develop/ai/context-engine/context-gateway/manage-gateways.md#turn-the-result-cache-and-result-handles-on-or-off). ```bash helm upgrade gateway redis-ai/redis-context-gateway \ diff --git a/content/operate/iris/context-gateway/self-managed/reference.md b/content/operate/iris/context-gateway/self-managed/reference.md index 697b69b455..4c84b53b90 100644 --- a/content/operate/iris/context-gateway/self-managed/reference.md +++ b/content/operate/iris/context-gateway/self-managed/reference.md @@ -39,9 +39,9 @@ Each file reference accepts a Kubernetes Secret or a Secrets Store Container Sto | A tool call returns `upstream_rejected_credentials` | The Upstream refused the stored credential | Rotate the Upstream credential. | | Cached results keep coming back after a secret rotation | The secret was rotated in place under the same reference | Refresh the Upstream's catalog. | | Handles stop being created | The Gateway database is above 90 percent of `maxmemory`, refused a write, has another eviction policy than `noeviction`, or has no JSON support | Raise `maxmemory`, shorten the handle lifetime, set `noeviction`, or move handles to a dedicated database with JSON. | -| Large results suddenly come back as stubs | `result_handles.enabled` was turned on, which applies to every Gateway whose `resultHandles` is `enabled` | Opt tools out with a `resultHandle` policy of `capture: never`, or set the Gateway's `resultHandles` to `disabled`. | -| Removing a Gateway's `databaseId` returns `400` | The Gateway's `resultCache` or `resultHandles` is still `enabled` | Send both as `disabled` in the same update. | -| A `resultCache` tool policy returns `400` | The Gateway's `resultCache` is `disabled`, or the Gateway has no `databaseId` | Select a database and enable `resultCache` on the Gateway first. | +| Large results suddenly come back as stubs | `result_handles.enabled` was turned on, which applies to every Gateway whose `compression` setting is `enabled` | Opt tools out with a `compression` policy of `capture: never`, or set the Gateway's `compression` to `disabled`. | +| Removing a Gateway's `databaseId` returns `400` | The Gateway's `cache` or `compression` setting is still `enabled` | Send both as `disabled` in the same update. | +| A `cache` tool policy returns `400` | The Gateway's `cache` setting is `disabled`, or the Gateway has no `databaseId` | Select a database and enable `cache` on the Gateway first. | | Data Plane does not become ready | It cannot reach the Identity Service, or an `http://` Identity Service URL is used without `identityService.allowInsecureTransport: true` | Check `identityService.baseURL` and the network path. | | Context Surface search tools return partial results | Redis is still indexing existing keys after a create, a data model change, or a refresh | Wait until `FT.INFO` on the Surface database shows `percent_indexed` at `1`. | | Deleting a Context Surface keeps answering `503` | Its indexes cannot be dropped, often because the Control Plane's Redis user lacks `FT._LIST` or `FT.DROPINDEX` | Grant the commands, or repeat the delete with `ignoreIndexSweepFailure=true`. | From edde1b11cf5bd71dbc0e451683128a44a07ea94e Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Mon, 26 Oct 2026 22:57:16 -0400 Subject: [PATCH 2/3] docs: rename the last resultCache policy reference to cache --- content/operate/iris/context-gateway/self-managed/operations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/operate/iris/context-gateway/self-managed/operations.md b/content/operate/iris/context-gateway/self-managed/operations.md index 314ff26497..b18937b761 100644 --- a/content/operate/iris/context-gateway/self-managed/operations.md +++ b/content/operate/iris/context-gateway/self-managed/operations.md @@ -89,7 +89,7 @@ Upgrade both planes together and roll forward, not back. An older Data Plane can After an upgrade, refresh an Upstream's catalog when the release notes ask for it. -Gateways stored before the per-Gateway `cache` and `compression` settings read as `enabled` when they have a `databaseId` and `disabled` otherwise, so their behavior does not change. Scripts that remove or add a Gateway's `databaseId`, or set `resultCache` tool policies, may need the changes in [Turn the result cache and result handles on or off](/content/develop/ai/context-engine/context-gateway/manage-gateways.md#turn-the-result-cache-and-result-handles-on-or-off). +Gateways stored before the per-Gateway `cache` and `compression` settings read as `enabled` when they have a `databaseId` and `disabled` otherwise, so their behavior does not change. Scripts that remove or add a Gateway's `databaseId`, or set `cache` tool policies, may need the changes in [Turn the result cache and result handles on or off](/content/develop/ai/context-engine/context-gateway/manage-gateways.md#turn-the-result-cache-and-result-handles-on-or-off). ```bash helm upgrade gateway redis-ai/redis-context-gateway \ From efb1c9aa62f18b2a54a070b7bbd66ab401962191 Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Mon, 26 Oct 2026 23:08:02 -0400 Subject: [PATCH 3/3] docs: sync the Gateway Control Plane OpenAPI contract with cache and compression Copy openapi-context-gateway.json from the SDK repository, regenerated from the Control Plane rename, without the cloud-only account databases route and its schemas. --- .../openapi-control-plane.json | 5302 +++++++++-------- 1 file changed, 2677 insertions(+), 2625 deletions(-) diff --git a/content/operate/iris/context-gateway/self-managed/control-plane-api-reference/openapi-control-plane.json b/content/operate/iris/context-gateway/self-managed/control-plane-api-reference/openapi-control-plane.json index d89d7cf966..9d573a88be 100644 --- a/content/operate/iris/context-gateway/self-managed/control-plane-api-reference/openapi-control-plane.json +++ b/content/operate/iris/context-gateway/self-managed/control-plane-api-reference/openapi-control-plane.json @@ -1,1522 +1,1289 @@ { - "openapi": "3.0.2", - "info": { - "title": "ContextGatewayControlPlaneService", - "version": "0.0.1", - "description": "Administration API for Context Gateway resources and their Upstreams.\n\nEvery write completes synchronously and returns the final state. Creating an\nUpstream, changing its connection or authentication, and refreshing its catalog\nrun live discovery against the Upstream, bounded by the discovery timeout.\nThe tenant comes from the control-plane configuration, never from the request,\nand no response shows it.\n" - }, - "paths": { - "/v1/gateways": { - "get": { - "operationId": "ListGateways", - "parameters": [ - { - "name": "nextToken", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "maxResults", - "in": "query", - "schema": { - "type": "integer", - "format": "int32" - } + "components": { + "schemas": { + "ActiveCatalog": { + "description": "The published catalog. Its catalog revision stays internal: no operation accepts it.", + "properties": { + "toolCount": { + "format": "int64", + "minimum": 0, + "type": "integer" } + }, + "required": [ + "toolCount" ], - "responses": { - "200": { - "description": "ListGateways 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListGatewaysResponseContent" - } - } - } + "type": "object" + }, + "AuthenticationErrorResponseContent": { + "description": "Authentication credentials are missing, malformed, or invalid.", + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, + "properties": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "status": { + "default": 401, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32", + "type": "integer" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } + "type": { + "$ref": "#/components/schemas/AuthenticationErrorType" } - } + }, + "required": [ + "status", + "title", + "type" + ], + "type": "object" }, - "post": { - "operationId": "CreateGateway", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGatewayRequestContent" - } - } - }, - "required": true + "AuthenticationErrorType": { + "description": "Problem type URI for authentication errors.", + "enum": [ + "/errors/authentication-failed" + ], + "type": "string" + }, + "AuthenticationInput": { + "description": "One authentication method per header the Upstream receives. At most one method may send each header, compared case-insensitively; bearer sends Authorization.", + "properties": { + "methods": { + "items": { + "$ref": "#/components/schemas/AuthenticationMethodInput" + }, + "type": "array" + } }, - "responses": { - "201": { - "description": "CreateGateway 201 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGatewayResponseContent" - } - } - } - }, - "400": { - "description": "BadRequestError 400 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BadRequestErrorResponseContent" - } - } - } - }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } - }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } - }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } + "type": "object" + }, + "AuthenticationMethodInput": { + "description": "One member per method kind, each with exactly its own fields. A later kind, such\nas basic or oauth2ClientCredentials, is a new member, which is additive.", + "oneOf": [ + { + "properties": { + "bearer": { + "$ref": "#/components/schemas/BearerMethodInput" } - } + }, + "required": [ + "bearer" + ], + "title": "bearer", + "type": "object" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } + { + "properties": { + "header": { + "$ref": "#/components/schemas/HeaderMethodInput" } - } + }, + "required": [ + "header" + ], + "title": "header", + "type": "object" } - } - } - }, - "/v1/gateways/{gatewayId}": { - "delete": { - "operationId": "DeleteGateway", - "parameters": [ + ] + }, + "AuthenticationMethodOutput": { + "oneOf": [ { - "name": "gatewayId", - "in": "path", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." + "properties": { + "bearer": { + "$ref": "#/components/schemas/BearerMethodOutput" + } }, - "required": true + "required": [ + "bearer" + ], + "title": "bearer", + "type": "object" }, { - "name": "expectedRevision", - "in": "query", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + "properties": { + "header": { + "$ref": "#/components/schemas/HeaderMethodOutput" + } + }, + "required": [ + "header" + ], + "title": "header", + "type": "object" + } + ] + }, + "AuthenticationOutput": { + "description": "Shows which headers the Upstream receives, never a value or a credential ID. A rotation shows as a new revision and updatedAt.", + "properties": { + "methods": { + "items": { + "$ref": "#/components/schemas/AuthenticationMethodOutput" }, - "required": true + "type": "array" } + }, + "required": [ + "methods" ], - "responses": { - "204": { - "description": "DeleteGateway 204 response" - }, - "400": { - "description": "BadRequestError 400 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BadRequestErrorResponseContent" - } - } - } - }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "type": "object" + }, + "BadRequestErrorResponseContent": { + "description": "Request validation or input decoding failed.", + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, + "properties": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "fields": { + "description": "Optional field-level validation errors.", + "items": { + "$ref": "#/components/schemas/FieldError" + }, + "type": "array" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" }, - "409": { - "description": "ContextGatewayConflictError 409 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" - } - } - } + "status": { + "default": 400, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32", + "type": "integer" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } + "type": { + "$ref": "#/components/schemas/BadRequestErrorType" } - } + }, + "required": [ + "status", + "title", + "type" + ], + "type": "object" }, - "get": { - "operationId": "GetGateway", - "parameters": [ - { - "name": "gatewayId", - "in": "path", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "BadRequestErrorType": { + "description": "Problem type URI for bad request errors.", + "enum": [ + "/errors/invalid-data" + ], + "type": "string" + }, + "BearerMethodInput": { + "description": "A secret is required on create and for a new method. Omitted on update keeps the current secret, unless the endpoint changes.", + "properties": { + "value": { + "description": "A secret value. Write-only: no output shape has a member that can carry it.", + "format": "password", + "minLength": 1, + "type": "string" + } + }, + "type": "object" + }, + "BearerMethodOutput": { + "type": "object" + }, + "CachePolicy": { + "properties": { + "ttlSeconds": { + "description": "How long a cached result lives, in seconds.", + "format": "int32", + "maximum": 86400, + "minimum": 1, + "type": "integer" } + }, + "required": [ + "ttlSeconds" ], - "responses": { - "200": { - "description": "GetGateway 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetGatewayResponseContent" - } - } - } - }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "type": "object" + }, + "CatalogFailure": { + "description": "The outcome of a failed initial catalog (discovery or tool generation), in the RFC 9457 shape. Only CreateUpstreamOutput carries it; it is not stored.", + "properties": { + "detail": { + "type": "string" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "occurredAt": { + "format": "date-time", + "type": "string" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "status": { + "format": "int32", + "type": "integer" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "title": { + "type": "string" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } + "type": { + "type": "string" } - } + }, + "required": [ + "occurredAt", + "status", + "title", + "type" + ], + "type": "object" }, - "patch": { - "operationId": "UpdateGateway", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateGatewayRequestContent" - } - } + "CompressionCapture": { + "enum": [ + "never" + ], + "type": "string" + }, + "CompressionPolicy": { + "description": "Set exactly one member. An empty compression is refused with 400.", + "properties": { + "capture": { + "$ref": "#/components/schemas/CompressionCapture" }, - "required": true + "ttlSeconds": { + "description": "How long a result handle of this tool lives, in seconds, in place of the deployment's result_handles.ttl. Refused together with capture never.", + "format": "int32", + "maximum": 86400, + "minimum": 1, + "type": "integer" + } }, - "parameters": [ + "type": "object" + }, + "Connection": { + "description": "Exactly one connection variant. The variant determines the kind on create; an explicit kind must agree. An update cannot change the stored kind.", + "oneOf": [ { - "name": "gatewayId", - "in": "path", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "$ref": "#/components/schemas/MCPConnection" + }, + { + "$ref": "#/components/schemas/ContextSurfaceConnection" + } + ] + }, + "ConnectionDatabase": { + "additionalProperties": false, + "description": "The Surface database of a context-surface Upstream.", + "properties": { + "id": { + "description": "An unknown ID and an ID the tenant does not own are refused with the same 400.", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9-]+$", + "type": "string" } + }, + "required": [ + "id" ], - "responses": { - "200": { - "description": "UpdateGateway 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateGatewayResponseContent" - } - } - } - }, - "400": { - "description": "BadRequestError 400 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BadRequestErrorResponseContent" - } - } - } + "type": "object" + }, + "ContextGatewayConflictErrorResponseContent": { + "description": "One schema per HTTP status preserves the complete problem catalog in generated\nclients, following the Playbook data plane's dedicated error-type enum pattern.", + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, + "properties": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "status": { + "default": 409, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32", + "type": "integer" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" }, - "409": { - "description": "ContextGatewayConflictError 409 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" - } - } - } + "type": { + "$ref": "#/components/schemas/ContextGatewayConflictErrorType" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "upstreamId": { + "description": "Set only for namespace-conflict: the Upstream that holds the namespace, so that a client that lost a create response can read it.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } + }, + "required": [ + "status", + "title", + "type" + ], + "type": "object" + }, + "ContextGatewayConflictErrorType": { + "description": "Distinguish resource state conflicts by type, never by human-readable title.", + "enum": [ + "/errors/revision-conflict", + "/errors/namespace-conflict", + "/errors/gateway-not-empty", + "/errors/catalog-publication-conflict" + ], + "type": "string" + }, + "ContextGatewayNotFoundErrorResponseContent": { + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, + "properties": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" + }, + "status": { + "default": 404, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32", + "type": "integer" + }, + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorType" } - } - } - }, - "/v1/gateways/{gatewayId}/upstreams": { - "get": { - "operationId": "ListUpstreams", - "parameters": [ - { - "name": "gatewayId", - "in": "path", + }, + "required": [ + "status", + "title", + "type" + ], + "type": "object" + }, + "ContextGatewayNotFoundErrorType": { + "description": "Distinguish missing resources by type, never by human-readable title. A Gateway\nID owned by another tenant returns gateway-not-found with a body byte-identical\nto an unknown Gateway ID, so the response never discloses that the ID exists.", + "enum": [ + "/errors/gateway-not-found", + "/errors/upstream-not-found" + ], + "type": "string" + }, + "ContextGatewayUnprocessableErrorResponseContent": { + "description": "The request is well formed, but the work it asks for cannot succeed until the\nrejected credentials are fixed: an mcp Upstream's credentials with an update,\nor, for a context-surface Upstream, the Surface database login, which the\ndeployment administrator fixes in the Secret that supplies the deployment's\ndatabases registry. Nothing was changed.", + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, + "properties": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" + }, + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" + }, + "status": { + "default": 422, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32", + "type": "integer" + }, + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ContextGatewayUnprocessableErrorType" + } + }, + "required": [ + "status", + "title", + "type" + ], + "type": "object" + }, + "ContextGatewayUnprocessableErrorType": { + "enum": [ + "/errors/resource-unavailable" + ], + "type": "string" + }, + "ContextSurface": { + "description": "The settings of kind context-surface.", + "properties": { + "dataModel": { + "description": "The data model, a JSON object. The API schema does not describe it: the\ncontrol plane validates it and names each error by its path under\ncontextSurface.dataModel." + } + }, + "type": "object" + }, + "ContextSurfaceConnection": { + "additionalProperties": false, + "properties": { + "database": { + "$ref": "#/components/schemas/ConnectionDatabase" + } + }, + "required": [ + "database" + ], + "type": "object" + }, + "CreateGatewayRequestContent": { + "properties": { + "cache": { + "$ref": "#/components/schemas/GatewayFeatureState" + }, + "compression": { + "$ref": "#/components/schemas/GatewayFeatureState" + }, + "databaseId": { + "description": "Selects the Gateway database for the Gateway's result state. Omitted means the Gateway has no Gateway database. An ID that is not in the registry is refused with 400.", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9-]+$", + "type": "string" + }, + "description": { + "type": "string" + }, + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "toolExposureMode": { + "$ref": "#/components/schemas/ToolExposureMode" + } + }, + "required": [ + "displayName" + ], + "type": "object" + }, + "CreateGatewayResponseContent": { + "properties": { + "cache": { + "$ref": "#/components/schemas/GatewayFeatureState" + }, + "compression": { + "$ref": "#/components/schemas/GatewayFeatureState" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "databaseId": { + "description": "Present only when the Gateway has a Gateway database.", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9-]+$", + "type": "string" + }, + "databaseName": { + "description": "The registry entry's name. Present only when databaseId is present and the registry still holds it; a stored ID that the registry no longer holds is returned without it.", + "type": "string" + }, + "description": { + "type": "string" + }, + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "id": { "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - { - "name": "nextToken", - "in": "query", - "schema": { - "type": "string" - } + "mcpEndpoint": { + "description": "The URL of this Gateway's MCP endpoint on the data plane: the data plane's public base URL, a deployment setting, plus /v1/gateways/{gatewayId}/mcp.", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", + "type": "string" }, - { - "name": "maxResults", - "in": "query", - "schema": { - "type": "integer", - "format": "int32" - } + "revision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + }, + "toolExposureMode": { + "$ref": "#/components/schemas/ToolExposureMode" + }, + "updatedAt": { + "format": "date-time", + "type": "string" } + }, + "required": [ + "cache", + "compression", + "createdAt", + "displayName", + "id", + "mcpEndpoint", + "revision", + "toolExposureMode", + "updatedAt" ], - "responses": { - "200": { - "description": "ListUpstreams 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListUpstreamsResponseContent" - } - } - } + "type": "object" + }, + "CreateUpstreamRequestContent": { + "properties": { + "authentication": { + "$ref": "#/components/schemas/AuthenticationInput" }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "connection": { + "$ref": "#/components/schemas/Connection" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "contextSurface": { + "$ref": "#/components/schemas/ContextSurface" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "enabled": { + "description": "Defaults to true.", + "type": "boolean" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } - } - } - }, - "post": { - "description": "Registers the Upstream, then discovers and publishes its first catalog. A failed\nor timed-out initial discovery, or a failed tool generation, still creates the Upstream, with no activeCatalog,\nand reports the failure in initialCatalogFailure.\n", - "operationId": "CreateUpstream", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateUpstreamRequestContent" - } - } + "kind": { + "$ref": "#/components/schemas/UpstreamKind" }, - "required": true - }, - "parameters": [ - { - "name": "gatewayId", - "in": "path", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "namespace": { + "description": "Derived from displayName when omitted. A collision is a namespace-conflict; no suffix is generated.", + "maxLength": 63, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "type": "string" + }, + "toolPolicies": { + "$ref": "#/components/schemas/ToolPolicies" } + }, + "required": [ + "connection", + "displayName" ], - "responses": { - "201": { - "description": "CreateUpstream 201 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateUpstreamResponseContent" - } - } - } - }, - "400": { - "description": "BadRequestError 400 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BadRequestErrorResponseContent" - } - } - } + "type": "object" + }, + "CreateUpstreamResponseContent": { + "description": "Only create returns initialCatalogFailure, so no other operation's generated client\nshows it. A persisted discovery outcome (open item O14) needs a new member, such\nas lastDiscovery, rather than a new meaning for this one.", + "properties": { + "activeCatalog": { + "$ref": "#/components/schemas/ActiveCatalog" }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "authentication": { + "$ref": "#/components/schemas/AuthenticationOutput" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "connection": { + "$ref": "#/components/schemas/Connection" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "contextSurface": { + "$ref": "#/components/schemas/ContextSurface" }, - "409": { - "description": "ContextGatewayConflictError 409 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" - } - } - } + "createdAt": { + "format": "date-time", + "type": "string" }, - "423": { - "description": "ResourceSuspendedError 423 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResourceSuspendedErrorResponseContent" - } - } - } + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "enabled": { + "type": "boolean" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } - } - } - } - }, - "/v1/gateways/{gatewayId}/upstreams/{upstreamId}": { - "delete": { - "description": "Marks the Upstream as being deleted, which every reader treats as absent, then\nreleases its namespace, removes its catalogs and current credentials, deletes\nthe record, and removes its Gateway index entry last. A retry of an Upstream\nthat is being deleted resumes the cleanup and returns 204.\n", - "operationId": "DeleteUpstream", - "parameters": [ - { - "name": "gatewayId", - "in": "path", + "gatewayId": { "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - { - "name": "upstreamId", - "in": "path", + "id": { "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - { - "name": "expectedRevision", - "in": "query", - "description": "Required for a readable Upstream; otherwise 400. Omitted for an unreadable record, whose revision cannot be read. Not checked when the Upstream is already being deleted.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Required for a readable Upstream; otherwise 400. Omitted for an unreadable record, whose revision cannot be read. Not checked when the Upstream is already being deleted." - } + "initialCatalogFailure": { + "$ref": "#/components/schemas/CatalogFailure" }, - { - "name": "ignoreIndexSweepFailure", - "in": "query", - "description": "For a context-surface Upstream whose delete keeps answering 503 because its Surface index sweep fails. true still runs the sweep, but when it fails the delete goes on and leaves every index named idx::* on the Surface database, and the control plane logs that prefix. Omitted or false fails the delete with 503 instead. Ignored for an mcp Upstream.", - "schema": { - "type": "boolean", - "description": "For a context-surface Upstream whose delete keeps answering 503 because its Surface index sweep fails. true still runs the sweep, but when it fails the delete goes on and leaves every index named idx::* on the Surface database, and the control plane logs that prefix. Omitted or false fails the delete with 503 instead. Ignored for an mcp Upstream." - } + "kind": { + "$ref": "#/components/schemas/UpstreamKind" + }, + "namespace": { + "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name.", + "maxLength": 63, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "type": "string" + }, + "revision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + }, + "toolPolicies": { + "$ref": "#/components/schemas/ToolPolicies" + }, + "updatedAt": { + "format": "date-time", + "type": "string" } + }, + "required": [ + "authentication", + "connection", + "createdAt", + "displayName", + "enabled", + "gatewayId", + "id", + "kind", + "namespace", + "revision", + "toolPolicies", + "updatedAt" ], - "responses": { - "204": { - "description": "DeleteUpstream 204 response" + "type": "object" + }, + "DroppedToolPolicy": { + "description": "The members of a stored tool policy that an endpoint change or a data model swap deleted, and why.", + "properties": { + "notCacheableReason": { + "$ref": "#/components/schemas/NotCacheableReason" }, - "400": { - "description": "BadRequestError 400 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BadRequestErrorResponseContent" - } - } - } + "policy": { + "$ref": "#/components/schemas/ToolPolicy" }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "reason": { + "$ref": "#/components/schemas/DroppedToolPolicyReason" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "tool": { + "description": "The original tool name, exact and case-preserved.", + "type": "string" + } + }, + "required": [ + "policy", + "reason", + "tool" + ], + "type": "object" + }, + "DroppedToolPolicyReason": { + "enum": [ + "not-in-catalog", + "not-cacheable" + ], + "type": "string" + }, + "FailedDependencyErrorResponseContent": { + "description": "A dependent resource required to process the request is unavailable or unhealthy.", + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, + "properties": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" }, - "409": { - "description": "ContextGatewayConflictError 409 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" - } - } - } + "status": { + "default": 424, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32", + "type": "integer" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } + "type": { + "$ref": "#/components/schemas/FailedDependencyErrorType" } - } + }, + "required": [ + "status", + "title", + "type" + ], + "type": "object" }, - "get": { - "operationId": "GetUpstream", - "parameters": [ - { - "name": "gatewayId", - "in": "path", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "FailedDependencyErrorType": { + "description": "Problem type URI for failed-dependency errors.", + "enum": [ + "/errors/resource-unavailable", + "/errors/database-out-of-memory" + ], + "type": "string" + }, + "FieldError": { + "description": "Validation error details for a single request field.", + "properties": { + "field": { + "description": "Name of the invalid request field.", + "type": "string" }, - { - "name": "upstreamId", - "in": "path", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "message": { + "description": "Human-readable validation error message.", + "type": "string" + }, + "rule": { + "description": "Validation rule that was violated.", + "type": "string" } + }, + "required": [ + "field", + "message", + "rule" ], - "responses": { - "200": { - "description": "GetUpstream 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetUpstreamResponseContent" - } - } - } - }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "type": "object" + }, + "ForbiddenErrorResponseContent": { + "description": "The caller is authenticated but not allowed to access the requested resource.", + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, + "properties": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "status": { + "default": 403, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32", + "type": "integer" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } + "type": { + "$ref": "#/components/schemas/ForbiddenErrorType" } - } + }, + "required": [ + "status", + "title", + "type" + ], + "type": "object" }, - "patch": { - "description": "displayName and enabled are metadata-only and run no discovery. A change to\nconnection or authentication discovers with the candidate configuration, and a\ncontextSurface swaps the data model of a context-surface Upstream and generates\nits catalog; either commits configuration and catalog together, or commits\nnothing.\n", - "operationId": "UpdateUpstream", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateUpstreamRequestContent" - } - } + "ForbiddenErrorType": { + "description": "Problem type URI for authorization errors.", + "enum": [ + "/errors/insufficient-permissions" + ], + "type": "string" + }, + "GatewayFeatureState": { + "description": "Whether a Gateway serves one of its result features: the result cache or\nresult handles. Each needs a Gateway database (databaseId), and the data plane\nserves it only while the deployment's own switch for it (result_cache.enabled\nor result_handles.enabled) is on as well. Turning a feature off deletes\nnothing: stored entries expire on their TTL, so turning it back on with the\nsame Gateway database finds the ones still live.", + "enum": [ + "enabled", + "disabled" + ], + "type": "string" + }, + "GatewayOutput": { + "properties": { + "cache": { + "$ref": "#/components/schemas/GatewayFeatureState" }, - "required": true - }, - "parameters": [ - { - "name": "gatewayId", - "in": "path", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "compression": { + "$ref": "#/components/schemas/GatewayFeatureState" }, - { - "name": "upstreamId", - "in": "path", + "createdAt": { + "format": "date-time", + "type": "string" + }, + "databaseId": { + "description": "Present only when the Gateway has a Gateway database.", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9-]+$", + "type": "string" + }, + "databaseName": { + "description": "The registry entry's name. Present only when databaseId is present and the registry still holds it; a stored ID that the registry no longer holds is returned without it.", + "type": "string" + }, + "description": { + "type": "string" + }, + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "id": { "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true - } - ], - "responses": { - "200": { - "description": "UpdateUpstream 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateUpstreamResponseContent" - } - } - } + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "400": { - "description": "BadRequestError 400 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BadRequestErrorResponseContent" - } - } - } + "mcpEndpoint": { + "description": "The URL of this Gateway's MCP endpoint on the data plane: the data plane's public base URL, a deployment setting, plus /v1/gateways/{gatewayId}/mcp.", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", + "type": "string" }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "revision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "toolExposureMode": { + "$ref": "#/components/schemas/ToolExposureMode" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "cache", + "compression", + "createdAt", + "displayName", + "id", + "mcpEndpoint", + "revision", + "toolExposureMode", + "updatedAt" + ], + "type": "object" + }, + "GetGatewayResponseContent": { + "properties": { + "cache": { + "$ref": "#/components/schemas/GatewayFeatureState" }, - "408": { - "description": "TimeoutError 408 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TimeoutErrorResponseContent" - } - } - } + "compression": { + "$ref": "#/components/schemas/GatewayFeatureState" }, - "409": { - "description": "ContextGatewayConflictError 409 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" - } - } - } + "createdAt": { + "format": "date-time", + "type": "string" }, - "422": { - "description": "ContextGatewayUnprocessableError 422 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayUnprocessableErrorResponseContent" - } - } - } + "databaseId": { + "description": "Present only when the Gateway has a Gateway database.", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9-]+$", + "type": "string" }, - "423": { - "description": "ResourceSuspendedError 423 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResourceSuspendedErrorResponseContent" - } - } - } + "databaseName": { + "description": "The registry entry's name. Present only when databaseId is present and the registry still holds it; a stored ID that the registry no longer holds is returned without it.", + "type": "string" }, - "424": { - "description": "FailedDependencyError 424 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FailedDependencyErrorResponseContent" - } - } - } + "description": { + "type": "string" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } - } - } - } - }, - "/v1/gateways/{gatewayId}/upstreams/{upstreamId}/refresh": { - "post": { - "description": "Discovers with the current configuration and publishes every offered tool, only\nif neither the configuration revision nor the active catalog revision changed\nmeanwhile. A 200 means the active catalog matches this discovery. Allowed on a\ndisabled Upstream.\n", - "operationId": "RefreshUpstreamCatalog", - "parameters": [ - { - "name": "gatewayId", - "in": "path", + "id": { "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - { - "name": "upstreamId", - "in": "path", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true - } - ], - "responses": { - "200": { - "description": "RefreshUpstreamCatalog 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RefreshUpstreamCatalogResponseContent" - } - } - } + "mcpEndpoint": { + "description": "The URL of this Gateway's MCP endpoint on the data plane: the data plane's public base URL, a deployment setting, plus /v1/gateways/{gatewayId}/mcp.", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", + "type": "string" }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } + "revision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "toolExposureMode": { + "$ref": "#/components/schemas/ToolExposureMode" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "cache", + "compression", + "createdAt", + "displayName", + "id", + "mcpEndpoint", + "revision", + "toolExposureMode", + "updatedAt" + ], + "type": "object" + }, + "GetUpstreamResponseContent": { + "description": "The members that every Upstream response shares.", + "properties": { + "activeCatalog": { + "$ref": "#/components/schemas/ActiveCatalog" }, - "408": { - "description": "TimeoutError 408 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TimeoutErrorResponseContent" - } - } - } + "authentication": { + "$ref": "#/components/schemas/AuthenticationOutput" }, - "409": { - "description": "ContextGatewayConflictError 409 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" - } - } - } + "connection": { + "$ref": "#/components/schemas/Connection" }, - "422": { - "description": "ContextGatewayUnprocessableError 422 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayUnprocessableErrorResponseContent" - } - } - } + "contextSurface": { + "$ref": "#/components/schemas/ContextSurface" }, - "423": { - "description": "ResourceSuspendedError 423 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResourceSuspendedErrorResponseContent" - } - } - } + "createdAt": { + "format": "date-time", + "type": "string" }, - "424": { - "description": "FailedDependencyError 424 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FailedDependencyErrorResponseContent" - } - } - } + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "enabled": { + "type": "boolean" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } - } - } - } - }, - "/v1/gateways/{gatewayId}/upstreams/{upstreamId}/tools": { - "get": { - "description": "Lists every tool of the active catalog in one page, ordered by name, with no\npaging. An Upstream with no published catalog answers an empty list. Each tool\nshows the result of the cacheable rule and, only when one is stored, its policy.\n", - "operationId": "ListUpstreamTools", - "parameters": [ - { - "name": "gatewayId", - "in": "path", + "gatewayId": { "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - { - "name": "upstreamId", - "in": "path", + "id": { "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", - "schema": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "required": true - } - ], - "responses": { - "200": { - "description": "ListUpstreamTools 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListUpstreamToolsResponseContent" - } - } - } - }, - "401": { - "description": "AuthenticationError 401 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthenticationErrorResponseContent" - } - } - } - }, - "403": { - "description": "ForbiddenError 403 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenErrorResponseContent" - } - } - } + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "404": { - "description": "ContextGatewayNotFoundError 404 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" - } - } - } + "kind": { + "$ref": "#/components/schemas/UpstreamKind" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "namespace": { + "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name.", + "maxLength": 63, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "type": "string" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } - } - } - } - }, - "/v1/health/live": { - "get": { - "operationId": "Live", - "responses": { - "200": { - "description": "Live 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LiveResponseContent" - } - } - } + "revision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } + "toolPolicies": { + "$ref": "#/components/schemas/ToolPolicies" }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } + "updatedAt": { + "format": "date-time", + "type": "string" } }, - "security": [] - } - }, - "/v1/health/ready": { - "get": { - "operationId": "Ready", - "responses": { - "200": { - "description": "Ready 200 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReadyResponseContent" - } - } - } - }, - "500": { - "description": "UnexpectedError 500 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnexpectedErrorResponseContent" - } - } - } - }, - "503": { - "description": "ServiceUnavailableError 503 response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" - } - } - } + "required": [ + "authentication", + "connection", + "createdAt", + "displayName", + "enabled", + "gatewayId", + "id", + "kind", + "namespace", + "revision", + "toolPolicies", + "updatedAt" + ], + "type": "object" + }, + "HeaderMethodInput": { + "properties": { + "name": { + "description": "Compared case-insensitively and stored lowercase. Authorization is rejected beside a bearer method.", + "pattern": "^[!#$%&'*+.^_`|~0-9A-Za-z-]+$", + "type": "string" + }, + "value": { + "description": "Required on create and for a new method. Omitted on update keeps the current secret, unless the endpoint changes.", + "format": "password", + "minLength": 1, + "type": "string" } }, - "security": [] - } - } - }, - "components": { - "schemas": { - "ActiveCatalog": { - "type": "object", - "description": "The published catalog. Its catalog revision stays internal: no operation accepts it.", + "required": [ + "name" + ], + "type": "object" + }, + "HeaderMethodOutput": { "properties": { - "toolCount": { - "type": "integer", - "minimum": 0, - "format": "int64" + "name": { + "description": "Lowercase.", + "pattern": "^[!#$%&'*+.^_`|~0-9A-Za-z-]+$", + "type": "string" } }, "required": [ - "toolCount" - ] + "name" + ], + "type": "object" }, - "AuthenticationErrorResponseContent": { - "type": "object", - "description": "Authentication credentials are missing, malformed, or invalid.", + "ListGatewaysResponseContent": { "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." - }, - "status": { - "type": "integer", - "default": 401, - "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" - }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." - }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "gateways": { + "items": { + "$ref": "#/components/schemas/GatewayOutput" + }, + "type": "array" }, - "type": { - "$ref": "#/components/schemas/AuthenticationErrorType" + "nextToken": { + "description": "Present when more items follow. A client must follow it. This iteration never sets it.", + "type": "string" } }, "required": [ - "status", - "title", - "type" + "gateways" ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" - } - }, - "AuthenticationErrorType": { - "type": "string", - "description": "Problem type URI for authentication errors.", - "enum": [ - "/errors/authentication-failed" - ] + "type": "object" }, - "AuthenticationInput": { - "type": "object", - "description": "One authentication method per header the Upstream receives. At most one method may send each header, compared case-insensitively; bearer sends Authorization.", + "ListUpstreamToolsResponseContent": { "properties": { - "methods": { - "type": "array", + "tools": { + "description": "Every tool of the active catalog, ordered by name. [] when no catalog is published.", "items": { - "$ref": "#/components/schemas/AuthenticationMethodInput" - } + "$ref": "#/components/schemas/UpstreamTool" + }, + "type": "array" } - } + }, + "required": [ + "tools" + ], + "type": "object" }, - "AuthenticationMethodInput": { - "description": "One member per method kind, each with exactly its own fields. A later kind, such\nas basic or oauth2ClientCredentials, is a new member, which is additive.", - "oneOf": [ - { - "type": "object", - "title": "bearer", - "properties": { - "bearer": { - "$ref": "#/components/schemas/BearerMethodInput" - } + "ListUpstreamsResponseContent": { + "properties": { + "nextToken": { + "description": "Present when more items follow. A client must follow it. This iteration never sets it.", + "type": "string" + }, + "unreadable": { + "description": "Upstream records that do not match the stored format. Omitted when empty. A client deletes such a record without expectedRevision.", + "items": { + "$ref": "#/components/schemas/UnreadableUpstream" }, - "required": [ - "bearer" - ] + "type": "array" }, - { - "type": "object", - "title": "header", - "properties": { - "header": { - "$ref": "#/components/schemas/HeaderMethodInput" - } + "upstreams": { + "description": "The readable Upstreams. An Upstream that is being deleted is in neither list.", + "items": { + "$ref": "#/components/schemas/UpstreamSummary" }, - "required": [ - "header" - ] + "type": "array" } - ] + }, + "required": [ + "upstreams" + ], + "type": "object" }, - "AuthenticationMethodOutput": { - "oneOf": [ - { - "type": "object", - "title": "bearer", - "properties": { - "bearer": { - "$ref": "#/components/schemas/BearerMethodOutput" - } - }, - "required": [ - "bearer" - ] + "LiveResponseContent": { + "properties": { + "status": { + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + }, + "MCPConnection": { + "additionalProperties": false, + "properties": { + "endpoint": { + "description": "An absolute http or https URL without user information. Any other scheme, such as redis or rediss, is refused. The outbound destination policy, required before GA, is open item O8 in the contract.", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", + "type": "string" }, - { - "type": "object", - "title": "header", - "properties": { - "header": { - "$ref": "#/components/schemas/HeaderMethodOutput" - } - }, - "required": [ - "header" - ] + "transport": { + "$ref": "#/components/schemas/Transport" } - ] + }, + "required": [ + "endpoint" + ], + "type": "object" }, - "AuthenticationOutput": { - "type": "object", - "description": "Shows which headers the Upstream receives, never a value or a credential ID. A rotation shows as a new revision and updatedAt.", + "NotCacheableReason": { + "enum": [ + "destructive", + "not-read-only", + "invalid-annotation" + ], + "type": "string" + }, + "ReadyResponseContent": { "properties": { - "methods": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AuthenticationMethodOutput" - } + "status": { + "type": "string" } }, "required": [ - "methods" - ] + "status" + ], + "type": "object" + }, + "RefreshUpstreamCatalogResponseContent": { + "description": "The members that every Upstream response shares.", + "properties": { + "activeCatalog": { + "$ref": "#/components/schemas/ActiveCatalog" + }, + "authentication": { + "$ref": "#/components/schemas/AuthenticationOutput" + }, + "connection": { + "$ref": "#/components/schemas/Connection" + }, + "contextSurface": { + "$ref": "#/components/schemas/ContextSurface" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "gatewayId": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + }, + "id": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + }, + "kind": { + "$ref": "#/components/schemas/UpstreamKind" + }, + "namespace": { + "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name.", + "maxLength": 63, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "type": "string" + }, + "revision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + }, + "toolPolicies": { + "$ref": "#/components/schemas/ToolPolicies" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "authentication", + "connection", + "createdAt", + "displayName", + "enabled", + "gatewayId", + "id", + "kind", + "namespace", + "revision", + "toolPolicies", + "updatedAt" + ], + "type": "object" }, - "BadRequestErrorResponseContent": { - "type": "object", - "description": "Request validation or input decoding failed.", + "ResourceSuspendedErrorResponseContent": { + "description": "The requested resource exists but is suspended by an administrator.", + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" + }, + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" }, "status": { - "type": "integer", - "default": 400, + "default": 423, "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" - }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + "format": "int32", + "type": "integer" }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" }, "type": { - "$ref": "#/components/schemas/BadRequestErrorType" - }, - "fields": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FieldError" - }, - "description": "Optional field-level validation errors." + "$ref": "#/components/schemas/ResourceSuspendedErrorType" } }, "required": [ @@ -1524,119 +1291,83 @@ "title", "type" ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" - } + "type": "object" }, - "BadRequestErrorType": { - "type": "string", - "description": "Problem type URI for bad request errors.", + "ResourceSuspendedErrorType": { + "description": "Problem type URI for suspended resources.", "enum": [ - "/errors/invalid-data" - ] - }, - "BearerMethodInput": { - "type": "object", - "description": "A secret is required on create and for a new method. Omitted on update keeps the current secret, unless the endpoint changes.", - "properties": { - "value": { - "type": "string", - "minLength": 1, - "description": "A secret value. Write-only: no output shape has a member that can carry it.", - "format": "password" - } - } - }, - "BearerMethodOutput": { - "type": "object" + "/errors/resource-suspended" + ], + "type": "string" }, - "CatalogFailure": { - "type": "object", - "description": "The outcome of a failed initial catalog (discovery or tool generation), in the RFC 9457 shape. Only CreateUpstreamOutput carries it; it is not stored.", + "ServiceUnavailableErrorResponseContent": { + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, "properties": { - "type": { + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", "type": "string" }, - "title": { + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", "type": "string" }, "status": { - "type": "integer", - "format": "int32" + "default": 503, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32", + "type": "integer" }, - "detail": { + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", "type": "string" }, - "occurredAt": { - "type": "string", - "format": "date-time" + "type": { + "$ref": "#/components/schemas/ServiceUnavailableErrorType" } }, "required": [ - "occurredAt", "status", "title", "type" - ] - }, - "Connection": { - "description": "Exactly one connection variant. The variant determines the kind on create; an explicit kind must agree. An update cannot change the stored kind.", - "oneOf": [ - { - "$ref": "#/components/schemas/MCPConnection" - }, - { - "$ref": "#/components/schemas/ContextSurfaceConnection" - } - ] + ], + "type": "object" }, - "ConnectionDatabase": { - "type": "object", - "description": "The Surface database of a context-surface Upstream.", - "properties": { - "id": { - "type": "string", - "maxLength": 32, - "minLength": 1, - "pattern": "^[A-Za-z0-9-]+$", - "description": "An unknown ID and an ID the tenant does not own are refused with the same 400." - } - }, - "required": [ - "id" + "ServiceUnavailableErrorType": { + "enum": [ + "/errors/service-unavailable" ], - "additionalProperties": false + "type": "string" }, - "ContextGatewayConflictErrorResponseContent": { - "type": "object", - "description": "One schema per HTTP status preserves the complete problem catalog in generated\nclients, following the Playbook data plane's dedicated error-type enum pattern.", + "TimeoutErrorResponseContent": { + "description": "The request timed out before the service could complete it.", + "externalDocs": { + "description": "RFC 9457", + "url": "https://www.rfc-editor.org/rfc/rfc9457.html" + }, "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" + }, + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" }, "status": { - "type": "integer", - "default": 409, + "default": 408, "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" - }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + "format": "int32", + "type": "integer" }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" }, "type": { - "$ref": "#/components/schemas/ContextGatewayConflictErrorType" - }, - "upstreamId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Set only for namespace-conflict: the Upstream that holds the namespace, so that a client that lost a create response can read it." + "$ref": "#/components/schemas/TimeoutErrorType" } }, "required": [ @@ -1644,88 +1375,75 @@ "title", "type" ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" - } + "type": "object" }, - "ContextGatewayConflictErrorType": { - "type": "string", - "description": "Distinguish resource state conflicts by type, never by human-readable title.", + "TimeoutErrorType": { + "description": "Problem type URI for timeout errors.", "enum": [ - "/errors/revision-conflict", - "/errors/namespace-conflict", - "/errors/gateway-not-empty", - "/errors/catalog-publication-conflict" - ] + "/errors/timeout" + ], + "type": "string" }, - "ContextGatewayNotFoundErrorResponseContent": { - "type": "object", + "ToolExposureMode": { + "description": "How a Gateway's clients find tools: the two modes the data plane serves. Adding\nanother mode later is an additive change.", + "enum": [ + "full", + "search" + ], + "type": "string" + }, + "ToolPolicies": { + "additionalProperties": { + "$ref": "#/components/schemas/ToolPolicy" + }, + "description": "Maps the original name of a tool in the Upstream's catalog, exact and case-preserved, to its policy.", + "type": "object" + }, + "ToolPolicy": { + "description": "One member per feature, each optional. A policy with no member is refused with 400.", "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." - }, - "status": { - "type": "integer", - "default": 404, - "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" - }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + "cache": { + "$ref": "#/components/schemas/CachePolicy" }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." - }, - "type": { - "$ref": "#/components/schemas/ContextGatewayNotFoundErrorType" + "compression": { + "$ref": "#/components/schemas/CompressionPolicy" } }, - "required": [ - "status", - "title", - "type" + "type": "object" + }, + "Transport": { + "enum": [ + "streamable-http" ], + "type": "string" + }, + "UnexpectedErrorResponseContent": { + "description": "The service failed with an unexpected internal error.", "externalDocs": { "description": "RFC 9457", "url": "https://www.rfc-editor.org/rfc/rfc9457.html" - } - }, - "ContextGatewayNotFoundErrorType": { - "type": "string", - "description": "Distinguish missing resources by type, never by human-readable title. A Gateway\nID owned by another tenant returns gateway-not-found with a body byte-identical\nto an unknown Gateway ID, so the response never discloses that the ID exists.", - "enum": [ - "/errors/gateway-not-found", - "/errors/upstream-not-found" - ] - }, - "ContextGatewayUnprocessableErrorResponseContent": { - "type": "object", - "description": "The request is well formed, but the work it asks for cannot succeed until the\nrejected credentials are fixed: an mcp Upstream's credentials with an update,\nor, for a context-surface Upstream, the Surface database login, which the\ndeployment administrator fixes in the Secret that supplies the deployment's\ndatabases registry. Nothing was changed.", + }, "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + "detail": { + "description": "A human-readable explanation specific to this occurrence of the problem.", + "type": "string" + }, + "instance": { + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.", + "type": "string" }, "status": { - "type": "integer", - "default": 422, + "default": 500, "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" + "format": "int32", + "type": "integer" }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." - }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "title": { + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4).", + "type": "string" }, "type": { - "$ref": "#/components/schemas/ContextGatewayUnprocessableErrorType" + "$ref": "#/components/schemas/UnexpectedErrorType" } }, "required": [ @@ -1733,116 +1451,138 @@ "title", "type" ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" - } + "type": "object" }, - "ContextGatewayUnprocessableErrorType": { - "type": "string", + "UnexpectedErrorType": { + "description": "Problem type URI for unexpected internal errors.", "enum": [ - "/errors/resource-unavailable" - ] + "/errors/unexpected-error" + ], + "type": "string" }, - "ContextSurface": { - "type": "object", - "description": "The settings of kind context-surface.", - "properties": { - "dataModel": { - "description": "The data model, a JSON object. The API schema does not describe it: the\ncontrol plane validates it and names each error by its path under\ncontextSurface.dataModel." - } - } + "UnreadableReason": { + "enum": [ + "invalid-stored-metadata" + ], + "type": "string" }, - "ContextSurfaceConnection": { - "type": "object", + "UnreadableUpstream": { + "description": "An Upstream record that ListUpstreams cannot read. It never carries the stored data.", "properties": { - "database": { - "$ref": "#/components/schemas/ConnectionDatabase" + "id": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + }, + "reason": { + "$ref": "#/components/schemas/UnreadableReason" } }, "required": [ - "database" + "id", + "reason" ], - "additionalProperties": false + "type": "object" }, - "CreateGatewayRequestContent": { - "type": "object", + "UpdateGatewayRequestContent": { "properties": { + "cache": { + "$ref": "#/components/schemas/GatewayFeatureState" + }, + "compression": { + "$ref": "#/components/schemas/GatewayFeatureState" + }, + "databaseId": { + "description": "Omitted leaves it unchanged. null clears it, which is refused with 400 on databaseId while cache or compression stays enabled: send them as disabled in the same request. Selecting a database on a Gateway that had none leaves cache and compression as they were, disabled for a Gateway created without one: send them as enabled in the same request to turn them on. An ID that is not in the registry is refused with 400.", + "maxLength": 32, + "minLength": 1, + "nullable": true, + "pattern": "^[A-Za-z0-9-]+$", + "type": "string" + }, + "description": { + "description": "Omitted leaves it unchanged; null clears it.", + "nullable": true, + "type": "string" + }, "displayName": { - "type": "string", + "description": "Operator-facing label.", "maxLength": 200, "minLength": 1, - "description": "Operator-facing label." + "type": "string" }, - "description": { + "expectedRevision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", "type": "string" }, "toolExposureMode": { "$ref": "#/components/schemas/ToolExposureMode" - }, - "databaseId": { - "type": "string", - "maxLength": 32, - "minLength": 1, - "pattern": "^[A-Za-z0-9-]+$", - "description": "Selects the Gateway database for the Gateway's result state. Omitted means the Gateway has no Gateway database. An ID that is not in the registry is refused with 400." } }, "required": [ - "displayName" - ] + "expectedRevision" + ], + "type": "object" }, - "CreateGatewayResponseContent": { - "type": "object", + "UpdateGatewayResponseContent": { "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." + "cache": { + "$ref": "#/components/schemas/GatewayFeatureState" }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." + "compression": { + "$ref": "#/components/schemas/GatewayFeatureState" }, - "description": { + "createdAt": { + "format": "date-time", "type": "string" }, - "toolExposureMode": { - "$ref": "#/components/schemas/ToolExposureMode" - }, "databaseId": { - "type": "string", + "description": "Present only when the Gateway has a Gateway database.", "maxLength": 32, "minLength": 1, "pattern": "^[A-Za-z0-9-]+$", - "description": "Present only when the Gateway has a Gateway database." + "type": "string" }, "databaseName": { - "type": "string", - "description": "The registry entry's name. Present only when databaseId is present and the registry still holds it; a stored ID that the registry no longer holds is returned without it." + "description": "The registry entry's name. Present only when databaseId is present and the registry still holds it; a stored ID that the registry no longer holds is returned without it.", + "type": "string" + }, + "description": { + "type": "string" + }, + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "id": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, "mcpEndpoint": { - "type": "string", + "description": "The URL of this Gateway's MCP endpoint on the data plane: the data plane's public base URL, a deployment setting, plus /v1/gateways/{gatewayId}/mcp.", "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", - "description": "The URL of this Gateway's MCP endpoint on the data plane: the data plane's public base URL, a deployment setting, plus /v1/gateways/{gatewayId}/mcp." + "type": "string" }, "revision": { - "type": "string", + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + "type": "string" }, - "createdAt": { - "type": "string", - "format": "date-time" + "toolExposureMode": { + "$ref": "#/components/schemas/ToolExposureMode" }, "updatedAt": { - "type": "string", - "format": "date-time" + "format": "date-time", + "type": "string" } }, "required": [ + "cache", + "compression", "createdAt", "displayName", "id", @@ -1850,1258 +1590,1570 @@ "revision", "toolExposureMode", "updatedAt" - ] + ], + "type": "object" }, - "CreateUpstreamRequestContent": { - "type": "object", + "UpdateUpstreamRequestContent": { "properties": { - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." - }, - "namespace": { - "type": "string", - "maxLength": 63, - "minLength": 1, - "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", - "description": "Derived from displayName when omitted. A collision is a namespace-conflict; no suffix is generated." - }, - "enabled": { - "type": "boolean", - "description": "Defaults to true." - }, - "kind": { - "$ref": "#/components/schemas/UpstreamKind" - }, - "connection": { - "$ref": "#/components/schemas/Connection" - }, "authentication": { "$ref": "#/components/schemas/AuthenticationInput" }, - "toolPolicies": { - "$ref": "#/components/schemas/ToolPolicies" + "connection": { + "$ref": "#/components/schemas/Connection" }, "contextSurface": { "$ref": "#/components/schemas/ContextSurface" - } - }, - "required": [ - "connection", - "displayName" - ] - }, - "CreateUpstreamResponseContent": { - "type": "object", - "description": "Only create returns initialCatalogFailure, so no other operation's generated client\nshows it. A persisted discovery outcome (open item O14) needs a new member, such\nas lastDiscovery, rather than a new meaning for this one.", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "gatewayId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "kind": { - "$ref": "#/components/schemas/UpstreamKind" }, "displayName": { - "type": "string", + "description": "Operator-facing label.", "maxLength": 200, "minLength": 1, - "description": "Operator-facing label." - }, - "namespace": { - "type": "string", - "maxLength": 63, - "minLength": 1, - "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", - "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name." + "type": "string" }, "enabled": { "type": "boolean" }, - "revision": { - "type": "string", + "expectedRevision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." - }, - "connection": { - "$ref": "#/components/schemas/Connection" - }, - "authentication": { - "$ref": "#/components/schemas/AuthenticationOutput" - }, - "contextSurface": { - "$ref": "#/components/schemas/ContextSurface" - }, - "activeCatalog": { - "$ref": "#/components/schemas/ActiveCatalog" + "type": "string" }, "toolPolicies": { "$ref": "#/components/schemas/ToolPolicies" - }, - "createdAt": { - "type": "string", - "format": "date-time" - }, - "updatedAt": { - "type": "string", - "format": "date-time" - }, - "initialCatalogFailure": { - "$ref": "#/components/schemas/CatalogFailure" } }, "required": [ - "authentication", - "connection", - "createdAt", - "displayName", - "enabled", - "gatewayId", - "id", - "kind", - "namespace", - "revision", - "toolPolicies", - "updatedAt" - ] + "expectedRevision" + ], + "type": "object" }, - "DroppedToolPolicy": { - "type": "object", - "description": "The members of a stored tool policy that an endpoint change or a data model swap deleted, and why.", + "UpdateUpstreamResponseContent": { + "description": "The members that every Upstream response shares.", "properties": { - "tool": { - "type": "string", - "description": "The original tool name, exact and case-preserved." + "activeCatalog": { + "$ref": "#/components/schemas/ActiveCatalog" }, - "reason": { - "$ref": "#/components/schemas/DroppedToolPolicyReason" + "authentication": { + "$ref": "#/components/schemas/AuthenticationOutput" }, - "notCacheableReason": { - "$ref": "#/components/schemas/NotCacheableReason" + "connection": { + "$ref": "#/components/schemas/Connection" }, - "policy": { - "$ref": "#/components/schemas/ToolPolicy" - } - }, - "required": [ - "policy", - "reason", - "tool" - ] - }, - "DroppedToolPolicyReason": { - "type": "string", - "enum": [ - "not-in-catalog", - "not-cacheable" - ] - }, - "FailedDependencyErrorResponseContent": { - "type": "object", - "description": "A dependent resource required to process the request is unavailable or unhealthy.", - "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + "contextSurface": { + "$ref": "#/components/schemas/ContextSurface" }, - "status": { - "type": "integer", - "default": 424, - "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" + "createdAt": { + "format": "date-time", + "type": "string" }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + "displayName": { + "description": "Operator-facing label.", + "maxLength": 200, + "minLength": 1, + "type": "string" }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "droppedToolPolicies": { + "description": "The stored policies, or policy members, this update deleted, in tool name\norder. Only a connection.endpoint change or a data model swap (contextSurface) that does not send toolPolicies\ndeletes any: it keeps each stored policy the new endpoint's catalog allows\nand deletes the rest in the same commit as the new configuration. For a\ntool the cacheable rule vetoes, only cache is deleted and\ncompression stays stored. A policy is deleted whole only when the tool is\nnot in the catalog or nothing is left. Omitted when nothing was deleted.", + "items": { + "$ref": "#/components/schemas/DroppedToolPolicy" + }, + "type": "array" }, - "type": { - "$ref": "#/components/schemas/FailedDependencyErrorType" - } - }, - "required": [ - "status", - "title", - "type" - ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" - } - }, - "FailedDependencyErrorType": { - "type": "string", - "description": "Problem type URI for failed-dependency errors.", - "enum": [ - "/errors/resource-unavailable", - "/errors/database-out-of-memory" - ] - }, - "FieldError": { - "type": "object", - "description": "Validation error details for a single request field.", - "properties": { - "field": { - "type": "string", - "description": "Name of the invalid request field." + "enabled": { + "type": "boolean" }, - "rule": { - "type": "string", - "description": "Validation rule that was violated." + "gatewayId": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "message": { - "type": "string", - "description": "Human-readable validation error message." - } - }, - "required": [ - "field", - "message", - "rule" - ] - }, - "ForbiddenErrorResponseContent": { - "type": "object", - "description": "The caller is authenticated but not allowed to access the requested resource.", - "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + "id": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "status": { - "type": "integer", - "default": 403, - "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" + "kind": { + "$ref": "#/components/schemas/UpstreamKind" + }, + "namespace": { + "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name.", + "maxLength": 63, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "type": "string" }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + "revision": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "toolPolicies": { + "$ref": "#/components/schemas/ToolPolicies" }, - "type": { - "$ref": "#/components/schemas/ForbiddenErrorType" + "updatedAt": { + "format": "date-time", + "type": "string" } }, "required": [ - "status", - "title", - "type" + "authentication", + "connection", + "createdAt", + "displayName", + "enabled", + "gatewayId", + "id", + "kind", + "namespace", + "revision", + "toolPolicies", + "updatedAt" ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" - } + "type": "object" }, - "ForbiddenErrorType": { - "type": "string", - "description": "Problem type URI for authorization errors.", + "UpstreamKind": { "enum": [ - "/errors/insufficient-permissions" - ] + "mcp", + "context-surface" + ], + "type": "string" }, - "GatewayOutput": { - "type": "object", + "UpstreamSummary": { "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." + "activeCatalog": { + "$ref": "#/components/schemas/ActiveCatalog" + }, + "createdAt": { + "format": "date-time", + "type": "string" }, "displayName": { - "type": "string", + "description": "Operator-facing label.", "maxLength": 200, "minLength": 1, - "description": "Operator-facing label." - }, - "description": { "type": "string" }, - "toolExposureMode": { - "$ref": "#/components/schemas/ToolExposureMode" - }, - "databaseId": { - "type": "string", - "maxLength": 32, - "minLength": 1, - "pattern": "^[A-Za-z0-9-]+$", - "description": "Present only when the Gateway has a Gateway database." + "enabled": { + "type": "boolean" }, - "databaseName": { - "type": "string", - "description": "The registry entry's name. Present only when databaseId is present and the registry still holds it; a stored ID that the registry no longer holds is returned without it." + "id": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" }, - "mcpEndpoint": { - "type": "string", - "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", - "description": "The URL of this Gateway's MCP endpoint on the data plane: the data plane's public base URL, a deployment setting, plus /v1/gateways/{gatewayId}/mcp." + "namespace": { + "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name.", + "maxLength": 63, + "minLength": 1, + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "type": "string" }, "revision": { - "type": "string", + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." - }, - "createdAt": { - "type": "string", - "format": "date-time" + "type": "string" }, "updatedAt": { - "type": "string", - "format": "date-time" + "format": "date-time", + "type": "string" } }, "required": [ "createdAt", "displayName", + "enabled", "id", - "mcpEndpoint", + "namespace", "revision", - "toolExposureMode", "updatedAt" - ] + ], + "type": "object" }, - "GetGatewayResponseContent": { - "type": "object", + "UpstreamTool": { + "description": "A tool of the active catalog. It carries no input or output schema.", "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." + "annotations": { + "description": "The annotations object as stored in the catalog. Present when the tool definition has one." }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." + "cacheable": { + "description": "The result of the cacheable rule, which reads only readOnlyHint and\ndestructiveHint. An absent hint vetoes nothing; an annotation never turns\ncaching on, only a cache policy does.", + "type": "boolean" }, "description": { + "description": "Present when the tool definition has one.", "type": "string" }, - "toolExposureMode": { - "$ref": "#/components/schemas/ToolExposureMode" + "name": { + "description": "The original tool name, exact and case-preserved.", + "type": "string" }, - "databaseId": { - "type": "string", - "maxLength": 32, - "minLength": 1, - "pattern": "^[A-Za-z0-9-]+$", - "description": "Present only when the Gateway has a Gateway database." + "notCacheableReason": { + "$ref": "#/components/schemas/NotCacheableReason" }, - "databaseName": { - "type": "string", - "description": "The registry entry's name. Present only when databaseId is present and the registry still holds it; a stored ID that the registry no longer holds is returned without it." + "policy": { + "$ref": "#/components/schemas/ToolPolicy" }, - "mcpEndpoint": { - "type": "string", - "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", - "description": "The URL of this Gateway's MCP endpoint on the data plane: the data plane's public base URL, a deployment setting, plus /v1/gateways/{gatewayId}/mcp." + "title": { + "description": "Present when the tool definition has one.", + "type": "string" + } + }, + "required": [ + "cacheable", + "name" + ], + "type": "object" + } + }, + "securitySchemes": { + "smithy.api.httpBearerAuth": { + "description": "HTTP Bearer authentication", + "scheme": "Bearer", + "type": "http" + } + } + }, + "info": { + "description": "Administration API for Context Gateway resources and their Upstreams.\n\nEvery write completes synchronously and returns the final state. Creating an\nUpstream, changing its connection or authentication, and refreshing its catalog\nrun live discovery against the Upstream, bounded by the discovery timeout.\nThe tenant comes from the control-plane configuration, never from the request,\nand no response shows it.\n", + "title": "ContextGatewayControlPlaneService", + "version": "0.0.1" + }, + "openapi": "3.0.2", + "paths": { + "/health/liveness": { + "get": { + "operationId": "Live", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LiveResponseContent" + } + } + }, + "description": "Live 200 response" }, - "revision": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "createdAt": { - "type": "string", - "format": "date-time" + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" + } + }, + "security": [] + } + }, + "/health/readiness": { + "get": { + "operationId": "Ready", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReadyResponseContent" + } + } + }, + "description": "Ready 200 response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" + } + }, + "security": [] + } + }, + "/v1/gateways": { + "get": { + "operationId": "ListGateways", + "parameters": [ + { + "in": "query", + "name": "nextToken", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "maxResults", + "schema": { + "format": "int32", + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListGatewaysResponseContent" + } + } + }, + "description": "ListGateways 200 response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "updatedAt": { - "type": "string", - "format": "date-time" + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "createdAt", - "displayName", - "id", - "mcpEndpoint", - "revision", - "toolExposureMode", - "updatedAt" - ] + } }, - "GetUpstreamResponseContent": { - "type": "object", - "description": "The members that every Upstream response shares.", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." + "post": { + "operationId": "CreateGateway", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGatewayRequestContent" + } + } }, - "gatewayId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGatewayResponseContent" + } + } + }, + "description": "CreateGateway 201 response" }, - "kind": { - "$ref": "#/components/schemas/UpstreamKind" + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + }, + "description": "BadRequestError 400 response" }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "namespace": { - "type": "string", - "maxLength": 63, - "minLength": 1, - "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", - "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name." + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "enabled": { - "type": "boolean" + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "revision": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" + } + } + } + }, + "/v1/gateways/{gatewayId}": { + "delete": { + "operationId": "DeleteGateway", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "connection": { - "$ref": "#/components/schemas/Connection" + { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "in": "query", + "name": "expectedRevision", + "required": true, + "schema": { + "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "DeleteGateway 204 response" }, - "authentication": { - "$ref": "#/components/schemas/AuthenticationOutput" + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + }, + "description": "BadRequestError 400 response" }, - "contextSurface": { - "$ref": "#/components/schemas/ContextSurface" + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "activeCatalog": { - "$ref": "#/components/schemas/ActiveCatalog" + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "toolPolicies": { - "$ref": "#/components/schemas/ToolPolicies" + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" }, - "createdAt": { - "type": "string", - "format": "date-time" + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" + } + } + }, + "description": "ContextGatewayConflictError 409 response" }, - "updatedAt": { - "type": "string", - "format": "date-time" - } - }, - "required": [ - "authentication", - "connection", - "createdAt", - "displayName", - "enabled", - "gatewayId", - "id", - "kind", - "namespace", - "revision", - "toolPolicies", - "updatedAt" - ] - }, - "HeaderMethodInput": { - "type": "object", - "properties": { - "name": { - "type": "string", - "pattern": "^[!#$%&'*+.^_`|~0-9A-Za-z-]+$", - "description": "Compared case-insensitively and stored lowercase. Authorization is rejected beside a bearer method." + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "value": { - "type": "string", - "minLength": 1, - "description": "Required on create and for a new method. Omitted on update keeps the current secret, unless the endpoint changes.", - "format": "password" - } - }, - "required": [ - "name" - ] - }, - "HeaderMethodOutput": { - "type": "object", - "properties": { - "name": { - "type": "string", - "pattern": "^[!#$%&'*+.^_`|~0-9A-Za-z-]+$", - "description": "Lowercase." + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "name" - ] + } }, - "ListGatewaysResponseContent": { - "type": "object", - "properties": { - "gateways": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GatewayOutput" + "get": { + "operationId": "GetGateway", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetGatewayResponseContent" + } + } + }, + "description": "GetGateway 200 response" }, - "nextToken": { - "type": "string", - "description": "Present when more items follow. A client must follow it. This iteration never sets it." - } - }, - "required": [ - "gateways" - ] - }, - "ListUpstreamToolsResponseContent": { - "type": "object", - "properties": { - "tools": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UpstreamTool" + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } }, - "description": "Every tool of the active catalog, ordered by name. [] when no catalog is published." - } - }, - "required": [ - "tools" - ] - }, - "ListUpstreamsResponseContent": { - "type": "object", - "properties": { - "upstreams": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UpstreamSummary" + "description": "AuthenticationError 401 response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } }, - "description": "The readable Upstreams. An Upstream that is being deleted is in neither list." + "description": "ForbiddenError 403 response" }, - "unreadable": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UnreadableUpstream" + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } }, - "description": "Upstream records that do not match the stored format. Omitted when empty. A client deletes such a record without expectedRevision." + "description": "ContextGatewayNotFoundError 404 response" }, - "nextToken": { - "type": "string", - "description": "Present when more items follow. A client must follow it. This iteration never sets it." - } - }, - "required": [ - "upstreams" - ] - }, - "LiveResponseContent": { - "type": "object", - "properties": { - "status": { - "type": "string" - } - }, - "required": [ - "status" - ] - }, - "MCPConnection": { - "type": "object", - "properties": { - "endpoint": { - "type": "string", - "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", - "description": "An absolute http or https URL without user information. Any other scheme, such as redis or rediss, is refused. The outbound destination policy, required before GA, is open item O8 in the contract." + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "transport": { - "$ref": "#/components/schemas/Transport" + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "endpoint" - ], - "additionalProperties": false - }, - "NotCacheableReason": { - "type": "string", - "enum": [ - "destructive", - "not-read-only", - "invalid-annotation" - ] + } }, - "ReadyResponseContent": { - "type": "object", - "properties": { - "status": { - "type": "string" + "patch": { + "operationId": "UpdateGateway", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } } - }, - "required": [ - "status" - ] - }, - "RefreshUpstreamCatalogResponseContent": { - "type": "object", - "description": "The members that every Upstream response shares.", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "gatewayId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "kind": { - "$ref": "#/components/schemas/UpstreamKind" - }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateGatewayRequestContent" + } + } }, - "namespace": { - "type": "string", - "maxLength": 63, - "minLength": 1, - "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", - "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name." + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateGatewayResponseContent" + } + } + }, + "description": "UpdateGateway 200 response" }, - "enabled": { - "type": "boolean" + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + }, + "description": "BadRequestError 400 response" }, - "revision": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "connection": { - "$ref": "#/components/schemas/Connection" + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "authentication": { - "$ref": "#/components/schemas/AuthenticationOutput" + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" }, - "contextSurface": { - "$ref": "#/components/schemas/ContextSurface" + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" + } + } + }, + "description": "ContextGatewayConflictError 409 response" }, - "activeCatalog": { - "$ref": "#/components/schemas/ActiveCatalog" + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "toolPolicies": { - "$ref": "#/components/schemas/ToolPolicies" + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" + } + } + } + }, + "/v1/gateways/{gatewayId}/upstreams": { + "get": { + "operationId": "ListUpstreams", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "createdAt": { - "type": "string", - "format": "date-time" + { + "in": "query", + "name": "nextToken", + "schema": { + "type": "string" + } }, - "updatedAt": { - "type": "string", - "format": "date-time" + { + "in": "query", + "name": "maxResults", + "schema": { + "format": "int32", + "type": "integer" + } } - }, - "required": [ - "authentication", - "connection", - "createdAt", - "displayName", - "enabled", - "gatewayId", - "id", - "kind", - "namespace", - "revision", - "toolPolicies", - "updatedAt" - ] - }, - "ResourceSuspendedErrorResponseContent": { - "type": "object", - "description": "The requested resource exists but is suspended by an administrator.", - "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListUpstreamsResponseContent" + } + } + }, + "description": "ListUpstreams 200 response" }, - "status": { - "type": "integer", - "default": 423, - "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" }, - "type": { - "$ref": "#/components/schemas/ResourceSuspendedErrorType" + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "status", - "title", - "type" - ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" } }, - "ResourceSuspendedErrorType": { - "type": "string", - "description": "Problem type URI for suspended resources.", - "enum": [ - "/errors/resource-suspended" - ] - }, - "ResultCachePolicy": { - "type": "object", - "properties": { - "ttlSeconds": { - "type": "integer", - "maximum": 86400, - "minimum": 1, - "description": "How long a cached result lives, in seconds.", - "format": "int32" + "post": { + "description": "Registers the Upstream, then discovers and publishes its first catalog. A failed\nor timed-out initial discovery, or a failed tool generation, still creates the Upstream, with no activeCatalog,\nand reports the failure in initialCatalogFailure.\n", + "operationId": "CreateUpstream", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateUpstreamRequestContent" + } + } + }, + "required": true }, - "required": [ - "ttlSeconds" - ] - }, - "ResultHandleCapture": { - "type": "string", - "enum": [ - "never" - ] - }, - "ResultHandlePolicy": { - "type": "object", - "description": "Set exactly one member. An empty resultHandle is refused with 400.", - "properties": { - "capture": { - "$ref": "#/components/schemas/ResultHandleCapture" + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateUpstreamResponseContent" + } + } + }, + "description": "CreateUpstream 201 response" }, - "ttlSeconds": { - "type": "integer", - "maximum": 86400, - "minimum": 1, - "description": "How long a result handle of this tool lives, in seconds, in place of the deployment's result_handles.ttl. Refused together with capture never.", - "format": "int32" - } - } - }, - "ServiceUnavailableErrorResponseContent": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + }, + "description": "BadRequestError 400 response" }, - "status": { - "type": "integer", - "default": 503, - "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" }, - "type": { - "$ref": "#/components/schemas/ServiceUnavailableErrorType" + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" + } + } + }, + "description": "ContextGatewayConflictError 409 response" + }, + "423": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResourceSuspendedErrorResponseContent" + } + } + }, + "description": "ResourceSuspendedError 423 response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "status", - "title", - "type" - ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" } - }, - "ServiceUnavailableErrorType": { - "type": "string", - "enum": [ - "/errors/service-unavailable" - ] - }, - "TimeoutErrorResponseContent": { - "type": "object", - "description": "The request timed out before the service could complete it.", - "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." - }, - "status": { - "type": "integer", - "default": 408, - "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" + } + }, + "/v1/gateways/{gatewayId}/upstreams/{upstreamId}": { + "delete": { + "description": "Marks the Upstream as being deleted, which every reader treats as absent, then\nreleases its namespace, removes its catalogs and current credentials, deletes\nthe record, and removes its Gateway index entry last. A retry of an Upstream\nthat is being deleted resumes the cleanup and returns 204.\n", + "operationId": "DeleteUpstream", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "upstreamId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + { + "description": "Required for a readable Upstream; otherwise 400. Omitted for an unreadable record, whose revision cannot be read. Not checked when the Upstream is already being deleted.", + "in": "query", + "name": "expectedRevision", + "schema": { + "description": "Required for a readable Upstream; otherwise 400. Omitted for an unreadable record, whose revision cannot be read. Not checked when the Upstream is already being deleted.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "type": { - "$ref": "#/components/schemas/TimeoutErrorType" + { + "description": "For a context-surface Upstream whose delete keeps answering 503 because its Surface index sweep fails. true still runs the sweep, but when it fails the delete goes on and leaves every index named idx::* on the Surface database, and the control plane logs that prefix. Omitted or false fails the delete with 503 instead. Ignored for an mcp Upstream.", + "in": "query", + "name": "ignoreIndexSweepFailure", + "schema": { + "description": "For a context-surface Upstream whose delete keeps answering 503 because its Surface index sweep fails. true still runs the sweep, but when it fails the delete goes on and leaves every index named idx::* on the Surface database, and the control plane logs that prefix. Omitted or false fails the delete with 503 instead. Ignored for an mcp Upstream.", + "type": "boolean" + } } - }, - "required": [ - "status", - "title", - "type" ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" - } - }, - "TimeoutErrorType": { - "type": "string", - "description": "Problem type URI for timeout errors.", - "enum": [ - "/errors/timeout" - ] - }, - "ToolExposureMode": { - "type": "string", - "description": "How a Gateway's clients find tools: the two modes the data plane serves. Adding\nanother mode later is an additive change.", - "enum": [ - "full", - "search" - ] - }, - "ToolPolicies": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/ToolPolicy" - }, - "description": "Maps the original name of a tool in the Upstream's catalog, exact and case-preserved, to its policy." - }, - "ToolPolicy": { - "type": "object", - "description": "One member per feature, each optional. A policy with no member is refused with 400.", - "properties": { - "resultCache": { - "$ref": "#/components/schemas/ResultCachePolicy" + "responses": { + "204": { + "description": "DeleteUpstream 204 response" }, - "resultHandle": { - "$ref": "#/components/schemas/ResultHandlePolicy" - } - } - }, - "Transport": { - "type": "string", - "enum": [ - "streamable-http" - ] - }, - "UnexpectedErrorResponseContent": { - "type": "object", - "description": "The service failed with an unexpected internal error.", - "properties": { - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + }, + "description": "BadRequestError 400 response" }, - "status": { - "type": "integer", - "default": 500, - "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", - "format": "int32" + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "detail": { - "type": "string", - "description": "A human-readable explanation specific to this occurrence of the problem." + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "instance": { - "type": "string", - "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" }, - "type": { - "$ref": "#/components/schemas/UnexpectedErrorType" + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" + } + } + }, + "description": "ContextGatewayConflictError 409 response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "status", - "title", - "type" - ], - "externalDocs": { - "description": "RFC 9457", - "url": "https://www.rfc-editor.org/rfc/rfc9457.html" } }, - "UnexpectedErrorType": { - "type": "string", - "description": "Problem type URI for unexpected internal errors.", - "enum": [ - "/errors/unexpected-error" - ] - }, - "UnreadableReason": { - "type": "string", - "enum": [ - "invalid-stored-metadata" - ] - }, - "UnreadableUpstream": { - "type": "object", - "description": "An Upstream record that ListUpstreams cannot read. It never carries the stored data.", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." + "get": { + "operationId": "GetUpstream", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "reason": { - "$ref": "#/components/schemas/UnreadableReason" + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "upstreamId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } } - }, - "required": [ - "id", - "reason" - ] - }, - "UpdateGatewayRequestContent": { - "type": "object", - "properties": { - "expectedRevision": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetUpstreamResponseContent" + } + } + }, + "description": "GetUpstream 200 response" }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "description": { - "type": "string", - "description": "Omitted leaves it unchanged; null clears it.", - "nullable": true + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "toolExposureMode": { - "$ref": "#/components/schemas/ToolExposureMode" + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "databaseId": { - "type": "string", - "maxLength": 32, - "minLength": 1, - "pattern": "^[A-Za-z0-9-]+$", - "description": "Omitted leaves it unchanged; null clears it. An ID that is not in the registry is refused with 400.", - "nullable": true + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "expectedRevision" - ] + } }, - "UpdateGatewayResponseContent": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." - }, - "description": { - "type": "string" + "patch": { + "description": "displayName and enabled are metadata-only and run no discovery. A change to\nconnection or authentication discovers with the candidate configuration, and a\ncontextSurface swaps the data model of a context-surface Upstream and generates\nits catalog; either commits configuration and catalog together, or commits\nnothing.\n", + "operationId": "UpdateUpstream", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "toolExposureMode": { - "$ref": "#/components/schemas/ToolExposureMode" + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "upstreamId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateUpstreamRequestContent" + } + } }, - "databaseId": { - "type": "string", - "maxLength": 32, - "minLength": 1, - "pattern": "^[A-Za-z0-9-]+$", - "description": "Present only when the Gateway has a Gateway database." + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateUpstreamResponseContent" + } + } + }, + "description": "UpdateUpstream 200 response" }, - "databaseName": { - "type": "string", - "description": "The registry entry's name. Present only when databaseId is present and the registry still holds it; a stored ID that the registry no longer holds is returned without it." + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + }, + "description": "BadRequestError 400 response" }, - "mcpEndpoint": { - "type": "string", - "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://.+$", - "description": "The URL of this Gateway's MCP endpoint on the data plane: the data plane's public base URL, a deployment setting, plus /v1/gateways/{gatewayId}/mcp." + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "revision": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "createdAt": { - "type": "string", - "format": "date-time" + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" }, - "updatedAt": { - "type": "string", - "format": "date-time" - } - }, - "required": [ - "createdAt", - "displayName", - "id", - "mcpEndpoint", - "revision", - "toolExposureMode", - "updatedAt" - ] - }, - "UpdateUpstreamRequestContent": { - "type": "object", - "properties": { - "expectedRevision": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + "408": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TimeoutErrorResponseContent" + } + } + }, + "description": "TimeoutError 408 response" }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" + } + } + }, + "description": "ContextGatewayConflictError 409 response" }, - "enabled": { - "type": "boolean" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayUnprocessableErrorResponseContent" + } + } + }, + "description": "ContextGatewayUnprocessableError 422 response" }, - "connection": { - "$ref": "#/components/schemas/Connection" + "423": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResourceSuspendedErrorResponseContent" + } + } + }, + "description": "ResourceSuspendedError 423 response" }, - "authentication": { - "$ref": "#/components/schemas/AuthenticationInput" + "424": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FailedDependencyErrorResponseContent" + } + } + }, + "description": "FailedDependencyError 424 response" }, - "toolPolicies": { - "$ref": "#/components/schemas/ToolPolicies" + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "contextSurface": { - "$ref": "#/components/schemas/ContextSurface" + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "expectedRevision" - ] - }, - "UpdateUpstreamResponseContent": { - "type": "object", - "description": "The members that every Upstream response shares.", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "gatewayId": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "kind": { - "$ref": "#/components/schemas/UpstreamKind" - }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." + } + } + }, + "/v1/gateways/{gatewayId}/upstreams/{upstreamId}/refresh": { + "post": { + "description": "Discovers with the current configuration and publishes every offered tool, only\nif neither the configuration revision nor the active catalog revision changed\nmeanwhile. A 200 means the active catalog matches this discovery. Allowed on a\ndisabled Upstream.\n", + "operationId": "RefreshUpstreamCatalog", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "namespace": { - "type": "string", - "maxLength": 63, - "minLength": 1, - "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", - "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name." + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "upstreamId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefreshUpstreamCatalogResponseContent" + } + } + }, + "description": "RefreshUpstreamCatalog 200 response" }, - "enabled": { - "type": "boolean" + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "revision": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "connection": { - "$ref": "#/components/schemas/Connection" + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" }, - "authentication": { - "$ref": "#/components/schemas/AuthenticationOutput" + "408": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TimeoutErrorResponseContent" + } + } + }, + "description": "TimeoutError 408 response" }, - "contextSurface": { - "$ref": "#/components/schemas/ContextSurface" + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayConflictErrorResponseContent" + } + } + }, + "description": "ContextGatewayConflictError 409 response" }, - "activeCatalog": { - "$ref": "#/components/schemas/ActiveCatalog" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayUnprocessableErrorResponseContent" + } + } + }, + "description": "ContextGatewayUnprocessableError 422 response" }, - "toolPolicies": { - "$ref": "#/components/schemas/ToolPolicies" + "423": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResourceSuspendedErrorResponseContent" + } + } + }, + "description": "ResourceSuspendedError 423 response" }, - "createdAt": { - "type": "string", - "format": "date-time" + "424": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FailedDependencyErrorResponseContent" + } + } + }, + "description": "FailedDependencyError 424 response" }, - "updatedAt": { - "type": "string", - "format": "date-time" + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "droppedToolPolicies": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DroppedToolPolicy" + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } }, - "description": "The stored policies, or policy members, this update deleted, in tool name\norder. Only a connection.endpoint change or a data model swap (contextSurface) that does not send toolPolicies\ndeletes any: it keeps each stored policy the new endpoint's catalog allows\nand deletes the rest in the same commit as the new configuration. For a\ntool the cacheable rule vetoes, only resultCache is deleted and\nresultHandle stays stored. A policy is deleted whole only when the tool is\nnot in the catalog or nothing is left. Omitted when nothing was deleted." + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "authentication", - "connection", - "createdAt", - "displayName", - "enabled", - "gatewayId", - "id", - "kind", - "namespace", - "revision", - "toolPolicies", - "updatedAt" - ] - }, - "UpstreamKind": { - "type": "string", - "enum": [ - "mcp", - "context-surface" - ] - }, - "UpstreamSummary": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients." - }, - "displayName": { - "type": "string", - "maxLength": 200, - "minLength": 1, - "description": "Operator-facing label." - }, - "namespace": { - "type": "string", - "maxLength": 63, - "minLength": 1, - "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", - "description": "Gateway-unique lowercase kebab-case name without dots. It prefixes every exposed tool name." - }, - "enabled": { - "type": "boolean" - }, - "revision": { - "type": "string", - "pattern": "^[0-9a-f]{32}$", - "description": "Configuration revision. Opaque: each effective change writes a new random value, and a resource never gets a value it had before. Compare for equality only." - }, - "activeCatalog": { - "$ref": "#/components/schemas/ActiveCatalog" - }, - "createdAt": { - "type": "string", - "format": "date-time" + } + } + }, + "/v1/gateways/{gatewayId}/upstreams/{upstreamId}/tools": { + "get": { + "description": "Lists every tool of the active catalog in one page, ordered by name, with no\npaging. An Upstream with no published catalog answers an empty list. Each tool\nshows the result of the cacheable rule and, only when one is stored, its policy.\n", + "operationId": "ListUpstreamTools", + "parameters": [ + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "gatewayId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } }, - "updatedAt": { - "type": "string", - "format": "date-time" + { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "in": "path", + "name": "upstreamId", + "required": true, + "schema": { + "description": "A UUID v4 as 32 lowercase hexadecimal characters, allocated by the control plane. Opaque to clients.", + "pattern": "^[0-9a-f]{32}$", + "type": "string" + } } - }, - "required": [ - "createdAt", - "displayName", - "enabled", - "id", - "namespace", - "revision", - "updatedAt" - ] - }, - "UpstreamTool": { - "type": "object", - "description": "A tool of the active catalog. It carries no input or output schema.", - "properties": { - "name": { - "type": "string", - "description": "The original tool name, exact and case-preserved." - }, - "title": { - "type": "string", - "description": "Present when the tool definition has one." + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListUpstreamToolsResponseContent" + } + } + }, + "description": "ListUpstreamTools 200 response" }, - "description": { - "type": "string", - "description": "Present when the tool definition has one." + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + }, + "description": "AuthenticationError 401 response" }, - "annotations": { - "description": "The annotations object as stored in the catalog. Present when the tool definition has one." + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + }, + "description": "ForbiddenError 403 response" }, - "cacheable": { - "type": "boolean", - "description": "The result of the cacheable rule, which reads only readOnlyHint and\ndestructiveHint. An absent hint vetoes nothing; an annotation never turns\ncaching on, only a resultCache policy does." + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContextGatewayNotFoundErrorResponseContent" + } + } + }, + "description": "ContextGatewayNotFoundError 404 response" }, - "notCacheableReason": { - "$ref": "#/components/schemas/NotCacheableReason" + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + }, + "description": "UnexpectedError 500 response" }, - "policy": { - "$ref": "#/components/schemas/ToolPolicy" + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + }, + "description": "ServiceUnavailableError 503 response" } - }, - "required": [ - "cacheable", - "name" - ] - } - }, - "securitySchemes": { - "smithy.api.httpBearerAuth": { - "type": "http", - "description": "HTTP Bearer authentication", - "scheme": "Bearer" + } } } },