Skip to content
mcp-data-platform composable mcp data platform
v1.x part of txn2 ↗

Self-Configuration (the platform-admin connection)

The platform's premise is that an AI agent helps people operate their data and infrastructure. Self-configuration turns that capability inward: an admin connected over MCP can configure and maintain the platform itself, driving the same /api/v1/admin/* REST API the Portal uses, through the existing API gateway discovery and invoke tools.

"Create an analyst persona that can query Trino but cannot run any delete tool" or "add an S3 connection for bucket reports and grant it to the finance persona" becomes a sentence to the agent rather than a click-path through the Portal.

How it works

On startup the platform registers a built-in API gateway connection named platform-admin whose OpenAPI catalog is sourced from the spec embedded in the binary. Because that spec is generated from the same source tree at build time, the catalog is, by construction, the exact admin API of the running version. A release that adds admin endpoints ships a new embedded spec, which is re-indexed automatically at startup — no URL fetch, no scheduled poll, no operator catalog upkeep.

The connection's base_url is the loopback address of the platform's own admin listener (e.g. http://127.0.0.1:8080), so an api_invoke_endpoint call is a loopback round-trip to /api/v1/admin/*.

In the Portal's Connections view the built-in connection carries a fixed description explaining its purpose and is attributed to system (it is provisioned by the binary, not authored by an operator), distinguishing it from connections an admin creates.

Admin Connections, where the built-in platform-admin connection appearsAdmin Connections, where the built-in platform-admin connection appears

flowchart LR
    A[Admin in MCP session] -->|api_invoke_endpoint| G[API gateway toolkit]
    G -->|loopback + acting admin's token| H[/api/v1/admin/*/]
    H --> S[(personas / connections / config / prompts)]

Caller identity

Admin API mutations must be attributed to and authorized as the acting admin, not a shared connection identity. The platform-admin connection is configured with identity_passthrough: true: instead of applying a shared credential, api_invoke_endpoint forwards the acting caller's inbound bearer token (the token that authenticated the MCP session) as the Authorization header on the loopback call. The admin API authenticates that token through the same authenticator the MCP transport uses, so authorization and audit logging attribute the change to the real admin.

A saved script's run has no token: it presents the roles its owner held when the script was saved. A call it makes on platform-admin, from run_script or a schedule, is served inside the platform process instead of over the loopback, as the script's own identity, and the admin and portal APIs check that identity the way they check a token. A script owned by an administrator reaches the admin routes; any other script is answered 403 with the persona the admin API requires and the roles that reach it. The api_invoke_endpoint audit row names the script (script:<name>) and its owner, as every call a run makes does. A draft run (run_draft) runs in its caller's session and forwards their token as before, so a draft and a saved run are authorized by the same rule.

Any other identity-passthrough connection forwards the token to an upstream that checks it, so a saved script's call on one is refused, naming the connection and saying to use a connection that holds its own credentials. manage_script validate and every save warn of such a connection (passthrough-connection) before the script's first scheduled run.

A passthrough call with no authenticated caller fails fast rather than calling anonymously.

Discovery and invocation

The connection behaves like any other API gateway connection:

  • api_discover — discover admin operations and, with operation_id, inspect an operation's parameters and request body.
  • api_invoke_endpoint — call an operation (e.g. POST /api/v1/admin/personas).

The operation_id that api_discover and search report is relative to the API prefix (GET /admin/tools), while a raw path is joined to the loopback root, which also serves the portal. A raw path must therefore start with /api/v1. The connection sets required_path_prefix: /api/v1, so a raw path: /admin/tools is refused before it is sent, and the refusal names /api/v1/admin/tools and the operation's operation_id. Address the operation by operation_id, or send the full path. When base_url is overridden with a URL whose path already ends with /api/v1, raw paths are relative to it and nothing is refused.

Access control

Connections are deny-by-default (Personas): a persona reaches a connection only when its connections.allow matches the name. The platform-admin connection carries no special flag — it is reachable only by personas that explicitly allow it. Grant it to the persona that should operate the platform (the built-in admin persona allows *, so it has it); leave it out of every other persona and self-configuration stays admin-only.

Configuration

Auto-enabled when the prerequisites are met: HTTP transport with the admin API mounted (admin.enabled: true), a database, and the API gateway toolkit.

apigateway:
  self_connection:
    enabled: true            # nil/auto: on when prerequisites are met; false to opt out
    base_url: ""             # override the loopback admin URL; empty derives http://127.0.0.1:<port>

Set enabled: false to opt out. Set base_url only when the admin API is reachable at a different loopback address than the main listener (for example, when admin.path_prefix has been changed from its /api/v1/admin default and the embedded spec's base path no longer matches the live routes).

Security considerations

  • Default scope is admin only. Granting the connection to another persona is an explicit admin action.
  • Mutations are attributed to the acting admin through the existing audit middleware (identity passthrough), so the audit trail names the real user. A saved script's call is attributed to the script and its owner.
  • A script adds no reach its owner did not have. A script's run keeps the roles its owner held at the save for every tool it calls; the admin API checks those roles, so only a script saved by someone holding the admin persona's role reaches it.
  • Destructive admin operations run through the same audit and authorization path as any other admin API call.