openapi: 3.2.0 info: title: AI Gateway MCP Server Setup API description: Universal MCP Gateway with OAuth integration - Modern Architecture version: 2.0.3290 tags: - name: Setup paths: /setup: get: summary: Setup Redirect description: Redirect to current wizard step. operationId: setup_redirect_setup_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/status: get: summary: Setup Status description: 'Read-only setup diagnostics. Shows both the operator-local wizard position and the instance-wide readiness snapshot so refactors can be validated without changing redirect behaviour first.' operationId: setup_status_setup_status_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/welcome: get: summary: Setup Welcome description: 'Step 0: Welcome + login options. Unauthenticated landing for fresh installs: renders the OIDC provider tiles (or the env-var config hint when nothing is configured yet). Authenticated visitors should never see this page — Phase A''s unified panel owns every post-login surface — so we redirect them straight to `/admin`. Without the redirect, client-side JS would flicker the login tiles into view before hiding them, and the "Continue setup →" link below the fold would send them to the legacy `/setup/branding` instead of the canonical `/admin/branding`.' operationId: setup_welcome_setup_welcome_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/branding: get: summary: Setup Branding description: 'Step 1: Company branding.' operationId: setup_branding_setup_branding_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup post: summary: Setup Branding Save description: Save branding and advance to next step. operationId: setup_branding_save_setup_branding_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/branding/place: get: summary: Setup Branding Place description: 'The place name for a coordinate pair, resolved by the GATEWAY. The browser cannot ask a geocoder itself: the app''s CSP allows outbound connections to `''self''` only, and widening `connect-src` for every page to fill one read-only field is the wrong trade. The gateway is also the better asker — it already fetches the forecast for these coordinates from an external endpoint, so this adds no egress the feature did not already need, and it keeps working in a browser whose network is locked down. Fixed host, two validated floats. Nothing a caller sends reaches the URL except the numbers, and only after they parse and fall inside the real range. This is a preview. What gets STORED is resolved again on save from the coordinates the save is storing, so nothing a caller returns here can become the name beside a pair it does not describe.' operationId: setup_branding_place_setup_branding_place_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/team: get: summary: Setup Team description: 'Step 2: Team configuration.' operationId: setup_team_setup_team_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup post: summary: Setup Team Save description: Save team config and advance. operationId: setup_team_save_setup_team_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/services: get: summary: Setup Services description: 'Step 3: Service connections. Uses YAML meta as single source of truth (SSOT). Services are grouped by ``meta.category``: gateway, oauth, google.' operationId: setup_services_setup_services_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/sign-in: get: summary: Setup Sign In Overview description: 'Sign-in section landing page: tile-per-provider grid plus a bootstrap-admin card. Mirrors the services tab so the gray / yellow / green semantics + ''Active'' badge are visually consistent across the entire Settings hub.' operationId: setup_sign_in_overview_setup_sign_in_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/sign-in/{provider}: get: summary: Setup Sign In Provider description: 'Per-provider config page. One ``setup-card`` with the provider''s fields, plus a footer-bar with Save / Make active / Test sign-in / Back-to-overview buttons depending on state.' operationId: setup_sign_in_provider_setup_sign_in__provider__get parameters: - name: provider in: path required: true schema: type: string title: Provider responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Setup post: summary: Setup Sign In Provider Save operationId: setup_sign_in_provider_save_setup_sign_in__provider__post parameters: - name: provider in: path required: true schema: type: string title: Provider responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Setup /setup/sign-in/bootstrap-admin: post: summary: Setup Sign In Bootstrap Admin operationId: setup_sign_in_bootstrap_admin_setup_sign_in_bootstrap_admin_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/sign-in/{provider}/activate: post: summary: Setup Sign In Provider Activate operationId: setup_sign_in_provider_activate_setup_sign_in__provider__activate_post parameters: - name: provider in: path required: true schema: type: string title: Provider responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Setup /setup/logging: get: summary: Setup Logging operationId: setup_logging_setup_logging_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup post: summary: Setup Logging Save operationId: setup_logging_save_setup_logging_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/data-sanitization: get: summary: Setup Data Sanitization description: 'Step 5: Customer data sanitization (PII protection layer). Pure render — admin API endpoints under ``/admin/api/pii-sanitization`` do all the state changes; this page is just chrome around them.' operationId: setup_data_sanitization_setup_data_sanitization_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/internal-domains: post: summary: Setup Internal Domains Save description: 'Save the colleague-whitelist domain list used by the PII sanitizer. Lives on the PII tab because that''s the only feature that consumes it; routing here means the admin doesn''t have to keep two halves of the same idea (sign-in eligibility vs. PII exemption) cross-linked across tabs.' operationId: setup_internal_domains_save_setup_internal_domains_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/ai_clients: get: summary: Setup Ai Clients description: Legacy redirect — AI clients step merged into dashboard. operationId: setup_ai_clients_setup_ai_clients_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/complete: get: summary: Setup Complete description: 'Step 5: Summary and config export.' operationId: setup_complete_setup_complete_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/register-dcr-client: post: summary: Setup Register Dcr Client description: 'Register a service''s OAuth client via Dynamic Client Registration. Setup-time, on-demand counterpart to the lazy connect-time DCR: lets an admin click "Register automatically" and immediately see the client_id the gateway registered, instead of it happening invisibly on first use. Idempotent — reuses the cached client if one is already registered.' operationId: setup_register_dcr_client_setup_register_dcr_client_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/service-scope-gap: post: summary: Setup Service Scope Gap description: 'Scopes this service''s actions need that the consent will not request. Called before saving, with the extra-scopes value as typed, so the answer describes the state the operator is about to be in rather than the one they are leaving. Read-only and advisory: the save is never blocked, because an operator may knowingly run an incomplete set (no board features, say) and only they know that.' operationId: setup_service_scope_gap_setup_service_scope_gap_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/service-scope-plan: get: summary: Setup Service Scope Plan description: What an operator would have to grant for what they switched on. operationId: setup_service_scope_plan_setup_service_scope_plan_get responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/service-scope-adopt: post: summary: Setup Service Scope Adopt description: 'Add the derived permissions to what this install requests. The operator never types a scope name. What they confirm is the half that cannot be derived: that the provider''s app now allows these — and that confirmation is only as good as the reconnect that follows, which is why the previous value is recorded before the write.' operationId: setup_service_scope_adopt_setup_service_scope_adopt_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/service-scope-rollback: post: summary: Setup Service Scope Rollback description: 'Restore the request set to what it was before the adoption. Exact, not reconstructed: the recorded previous value goes back verbatim, so a scope the operator had added by hand earlier survives an undo of a later automatic addition.' operationId: setup_service_scope_rollback_setup_service_scope_rollback_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/service-scope-settle: post: summary: Setup Service Scope Settle description: 'Drop the undo offer once a grant proves the adoption worked. Deliberately server-checked rather than taken on the client''s word: the dialog cannot see the grants, and "the popup closed" is not evidence that a consent succeeded.' operationId: setup_service_scope_settle_setup_service_scope_settle_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/check-provider: post: summary: Setup Check Provider description: 'Ask ONE provider in the routing map whether it actually answers. THE CHECK IS A REAL CALL — one COMPLETION token plus whatever the three-word prompt costs, not one token in total; `max_tokens` caps only the answer — through the ordinary path — `get_executor("ai").execute("chat_completion", …)`. The connector''s own hooks therefore govern it: the routing hook picks the entry and the egress guard confines the request to the endpoint that entry declares. A bespoke HTTP client here would be a second way out of the gateway, with its own copy of those rules to drift from — which is the whole reason a connection check on an operator-entered URL is usually a new SSRF surface. This one adds none: it reaches exactly where a completion for that model would already go. TWO THINGS DO NOT COME WITH THAT PATH, because they live one layer up, in `src/mcp/tool_executor.py`, where an MCP tool call arrives: * The daily token budget is not consulted. Deliberate — a diagnostic has to stay available on the day the budget runs out, which is exactly a day somebody needs to know whether a provider answers. It costs one completion token, it is behind the admin gate, and the operator pressed the button themselves. * The measured consumption is not recorded by that layer, so this records it here. Without it the one call an operator makes by hand would be the one call the Data Usage view cannot see, and a view that is silent about a real spend is worse than one that is absent. An earlier version of this docstring claimed both of them happened. Neither did. THE SAVED MAP, never the form. A model id that is not in the stored registry is refused before anything is sent, so a URL an operator has typed but not saved can never be fetched from here. It also answers the question `/models` cannot: an entry that names a provider has its endpoint deliberately short of the version segment the translation layer adds, so a model listing there asks for a path outside the API. A one-token completion takes the path the real calls take, for both kinds of entry, and costs about that much.' operationId: setup_check_provider_setup_check_provider_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/verify-service-credentials: post: summary: Setup Verify Service Credentials description: 'Ask the upstream whether the OPERATOR credentials actually work. The per-user "Verify connection" button next to this one answers a different question — whether the signed-in person''s own connection works — and reaches `_verify_credentials` through the per-user connect routes. A connector credentialed by the operator has no per-user connection to verify, so nothing ran its declared check and the only way to find out was to call one of its actions by hand. Deliberately resolved through ``resolve_secret``, not by reading the submitted form or Redis alone: that is the same lookup an actual call performs (per-user Redis, then server-wide Redis, then the environment), so a green answer here means the credential the connector would really use is the one that worked.' operationId: setup_verify_service_credentials_setup_verify_service_credentials_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/configure-service: post: summary: Setup Configure Service description: Configure a gateway-managed service by setting ENV vars at runtime. operationId: setup_configure_service_setup_configure_service_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup /setup/configure-instance: post: summary: Setup Configure Instance description: 'Configure instance-level settings (BASE_URL, OIDC, ADMIN_USERS). Persists to /data/gateway.env so the config survives restarts. Only admins can access this.' operationId: setup_configure_instance_setup_configure_instance_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Setup components: schemas: HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type input: title: Input ctx: type: object title: Context type: object required: - loc - msg - type title: ValidationError