REST API and MCP
Use REST and MCP when an Opfield workflow must be repeatable, attributable, and independent of one operator’s browser. The automation owner maintains the client, resource owners approve its boundaries, and platform operators own runtime recovery. Success is a reconciled product outcome with durable evidence—not merely an accepted HTTP request or completed tool call.
The REST API exposes documented resource operations with session, API-token, or OAuth authentication as appropriate. Remote MCP provides task-oriented tools over the same scopes, validation, entitlements, and audit trail.
Automation should:
- use a dedicated least-privilege identity;
- treat
202or task creation as accepted work, then poll durable state; - retry only idempotent operations, send an
Idempotency-Keywith the creates that accept one, or use the operation’s retry contract; - handle
401,403,409,422, and node-offline failures distinctly; - avoid parsing UI text when a structured API field exists;
- record resource IDs and request IDs without logging secrets.
Use the OpenAPI document served by the running Opfield instance for exact request and response schemas. The schema version must match the instance being automated; do not copy request bodies from a different release. Product guides describe the required resource ordering and operational consequences that schemas alone cannot capture.
Authentication and discovery
Section titled “Authentication and discovery”Choose a session, API token, or OAuth client according to the caller. Remote MCP clients authorize through OAuth and discover task-oriented tools filtered by the same scopes and product state. Tool presence is not proof that a particular resource mutation will be admitted.
Start automation by reading the target resource and capability state. Resolve stable IDs rather than scraping names from the UI. Keep the base URL, token, and environment separate so a development script cannot accidentally target production.
Find out what the caller can access
Section titled “Find out what the caller can access”Access limited to folders, Nodes, or individual resources is normal for automation and agents. Read the caller’s access summary before creating resources, and whenever a list comes back empty or a create at the root is refused:
- REST:
GET /api/auth/me/access, with a session, an API token, or an OAuth token. - MCP and the AI Workspace: the
get_my_accesstool, optionally with anareasuch asdocker_containersorroutes. - MCP resource:
gateway://access.
The summary groups access by product area. For each area it says whether access is broad or limited, lists the granted folders (ID, name, and path), Nodes, accounts, and resources with the actions allowed on each, and says where the caller may create: create.atRoot, create.folders, and create.nodes, with a howTo hint. The principal object names the credential type (session, api-token, oauth-token, mcp, or assistant). Only a browser session and the AI Workspace also receive the user’s ID, name, email, and permission group; API tokens, OAuth tokens, and MCP clients get just principal: { credential, boundedByOwner: true }, because their access never exceeds the owner’s current access. When an MCP connection is limited, Opfield also adds a short version of the summary to the MCP server instructions at connect time.
Work inside the listed grants:
- List endpoints and tools return only what the caller may access; an empty list is not a denial.
list_resource_foldersshows every folder the caller holds any grant on, including empty ones, withaccess.actionsandaccess.canCreate.- A create without
folderIdtargets the root. PassfolderId, andnodeIdwhere the operation takes one, when create access is limited. - A refusal of a limited caller—a create at the root or a read of a resource outside its grants—names the folders, Nodes, and resources the caller may use and says to pass
folderId, in REST responses and in MCP and AI Workspace tool errors alike. Treat a permission as missing only when the summary shows no grant for the action anywhere.
Connect Codex or Claude Code through MCP
Section titled “Connect Codex or Claude Code through MCP”Opfield exposes its authenticated remote MCP server at:
https://gateway.example.com/api/mcpReplace gateway.example.com with the canonical public hostname of your Opfield installation. Use the same HTTPS origin that operators use to open Opfield. Do not append another /mcp, and do not point the client at the REST API root.
Once connected, the client can discover Opfield tools and perform only operations allowed to the signed-in user. MCP does not grant administrator access or bypass resource scopes, plan entitlements, confirmations, or audit logging.
Prepare Opfield
Section titled “Prepare Opfield”An administrator completes these one-time steps:
- Open Settings, select Features, and find OAuth and MCP access.
- Enable MCP server.
- Keep Extended MCP compatibility enabled for normal clients. Disable it only when a client loads the entire tool catalog into its context and cannot handle its size.
- Leave OAuth extended callback compatibility disabled for Codex and Claude Code. Their local loopback callbacks work with the safer default policy.
- Grant the connecting user Use MCP (
mcp:use) plus the ordinary scopes for the resources that client may read or change.
The user must also be able to sign in to Opfield in a browser. If the connection works but a tool or resource is missing, review group membership and resource scopes instead of broadening the OAuth callback policy.
Connect Codex
Section titled “Connect Codex”Add Opfield, complete OAuth login, and verify the connection:
codex mcp add good-gateway --url https://gateway.example.com/api/mcpcodex mcp login good-gatewaycodex mcp listThe login command opens Opfield in your browser. Sign in as the intended Opfield user, review the requested access, and approve it. Codex stores the resulting OAuth credential; you do not create or paste an API token.
In the Codex desktop app or IDE extension, you can instead add a Streamable HTTP MCP server with the same URL and select Authenticate. The desktop app, CLI, and IDE extension share the Codex MCP configuration.
Connect Claude Code
Section titled “Connect Claude Code”Add Opfield as a remote HTTP server for your user account:
claude mcp add --transport http good-gateway --scope user https://gateway.example.com/api/mcpclaude mcp login good-gatewayclaude mcp get good-gatewayYou can also open an interactive Claude Code session, enter /mcp, select good-gateway, and complete authentication in the browser. Use --scope project instead of --scope user only when the repository should share the server definition through .mcp.json; each developer still signs in with their own Opfield account.
How the OAuth flow works
Section titled “How the OAuth flow works”You do not need to register an OAuth client manually for Codex or Claude Code:
- the client contacts
/api/mcpand receives Opfield’s OAuth discovery information; - the client registers itself and starts Authorization Code with PKCE;
- Opfield opens a browser sign-in and consent screen;
- the user approves access bounded by their current Opfield scopes and can limit it to folders or resources, for example with Limit selected scopes to folder…; see Restrict tokens and OAuth grants;
- Opfield issues an OAuth access token for the MCP resource;
- the client stores that credential and sends it to
/api/mcpon later requests.
Opfield accepts only OAuth access tokens issued for its MCP resource. Browser cookies, ordinary gw_ API tokens, gwl_ logging tokens, and gwi_ Opfield Inference tokens are rejected. The server rechecks the user’s current scopes and mcp:use, so removing access stops future MCP operations even if the client discovered the tools earlier.
Verify the connection
Section titled “Verify the connection”Start with a read-only request:
List the Opfield nodes I can access and summarize their current status. Do not change anything.Confirm that the client reports good-gateway as connected, only expected resources are visible, a read succeeds, an action outside the user’s scopes is denied, and Opfield attributes the call to the expected user in the audit log.
MCP connection troubleshooting
Section titled “MCP connection troubleshooting”- The endpoint returns 404: enable Settings → Features → OAuth and MCP access → MCP server and verify that the URL ends in
/api/mcp. - The client requires authentication: run
codex mcp login good-gatewayorclaude mcp login good-gateway. In an interactive client, use/mcp. - Login succeeds but Opfield returns 403: the account needs
mcp:useand at least one effective resource scope. A grant limited to a folder sees only that folder’s resources; creating elsewhere is denied. Ask the agent to callget_my_accessand to create in one of the folders it lists; see Find out what the caller can access. - A client sends a scope name that no longer exists: Opfield 2.11 still accepts the retired scope names for two releases and grants their replacements.
- The client exhausts its context with too many tools: disable Extended MCP compatibility to use the compact initial catalog and category discovery.
- Opfield rejects the OAuth callback: update the client and retry first. Normal Codex and Claude Code loopback callbacks do not require OAuth extended callback compatibility.
- A saved connection stopped working: check whether the OAuth authorization,
mcp:use, resource scopes, or canonical Opfield URL changed. Re-authenticate instead of substituting a normal API token.
Durable operations
Section titled “Durable operations”Many infrastructure mutations return an accepted task or operation instead of a completed result:
- submit the validated request;
- store the returned resource, task, operation, and request IDs;
- poll or subscribe to the durable operation state;
- inspect structured failure details;
- verify the resulting resource state independently;
- retry only according to the operation’s idempotency contract.
Do not translate a transport timeout directly into a second create/delete request. The first request may have reached the owning daemon and be awaiting reconciliation. A create sent to an endpoint that accepts an Idempotency-Key is the exception: retry it with the same key.
Safe retries with Idempotency-Key
Section titled “Safe retries with Idempotency-Key”Selected create endpoints accept an optional Idempotency-Key header of 1–255 printable ASCII characters, for example a UUID. The OpenAPI document lists the header on exactly these operations:
- Docker: creating and duplicating containers, and creating Deployments, Compose Projects, resources from a Git source, volumes, networks, and registries;
- Ingress and certificates: Routes (
POST /api/proxy-hosts), Route folders, Domains, ACME certificates, and root and intermediate certificate authorities; - Databases and storage: database connections, managed databases, storage connections, and managed storage;
- Other: Page Projects, alert rules, and SIEM destinations.
Generate a new key for each logical operation, and send the same key again only when retrying that request after a timeout or a dropped connection:
curl -X POST https://gateway.example.com/api/domains \ -H "Authorization: Bearer $GATEWAY_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 5f0c6c1e-8a55-4c43-9d4e-2f1f8c3d9b10" \ -d '{"domain":"app.example.com"}'- A key belongs to the API token, OAuth token, or browser session that sent it, together with that caller’s current effective scopes, the method, and the exact path. After a scope change, the same key starts fresh, so a replay never outlives revoked access.
- A retry with the same key and the same request—the same query string and JSON body, in any key order—returns the stored response with the header
Idempotency-Replayed: trueand creates nothing new. Opfield keeps the result for 24 hours, encrypted with its master key, and writes every replay to the audit log asapi.idempotency.replay. - The same key with a different request returns
422 IDEMPOTENCY_KEY_REUSED. The same key while the first request is still running returns409 IDEMPOTENCY_KEY_IN_PROGRESSwithRetry-After. An invalid key returns400 IDEMPOTENCY_KEY_INVALID. - Opfield never stores a response that looks like it carries secret material, such as a token, password, private key, or credentials, nor one larger than 1 MiB. It records only that the request completed, and a retry returns
409 IDEMPOTENCY_RESPONSE_WITHHELDwith the original status andLocationwhen known: look the resource up instead of retrying. - Only
2xxresponses and400,404,409, and422responses with a JSON or empty body are recorded.401,403,5xx, streamed, and download responses are not, so a retry after them runs the request again. - Not covered: every endpoint outside the list above, which runs normally and ignores the header. This deliberately includes endpoints that return a secret once or echo sensitive input: API, inference, logging-ingest, and Pages deploy tokens, Node enrollment, access keys and credentials, bindings, Access Lists, and notification webhooks. Request bodies over 1 MiB and non-JSON uploads also run without idempotency, and so does everything while Redis, which stores the keys, is unavailable.
MCP create tools take an optional idempotencyKey argument with the same rules. The key is bound to the MCP token and its scopes, the owner’s current scopes, and the tool. Only successful results are stored, so a tool error can be retried with the same key; a replayed result carries _meta.idempotencyReplayed: true and is audited. A result that looks like it carries a secret is not stored, and a retry returns IDEMPOTENCY_RESULT_WITHHELD. The argument is offered on:
- Docker:
create_docker_container,duplicate_docker_container, and the create operation ofmanage_docker_deployment,manage_docker_compose,manage_docker_source,manage_docker_volume,manage_docker_network, andmanage_docker_registry; - Ingress:
create_route,create_route_folder, andcreate_domain; - Certificates:
request_acme_cert, the upload operation ofmanage_ssl_certificate,create_root_ca, andcreate_intermediate_ca; - Databases and storage: the create operation of
manage_database_connection,manage_managed_database,manage_storage_connection, andmanage_managed_storage; - Other: the
project_createoperation ofmanage_pages,create_alert_rule, andcreate_siem_destination.
Tools that return a secret or echo sensitive input—create_node, create_access_list, create_webhook, binding creation, token and access-key creation, and issue_certificate—do not take the argument. The Compose lifecycle operations of manage_docker_compose keep their own idempotencyKey argument with its previous meaning.
Move large payloads through one-time links
Section titled “Move large payloads through one-time links”Tool calls are a poor channel for files. For large payloads, MCP tools return a one-time link with a ready curl command that a shell on the agent’s side runs; the bytes stream through Opfield, never through the model:
- Pages: the
linkoperation ofupload_pages_artifactaccepts an archive, a packed build folder, or a single HTML file. The upload may be as large as the File upload limit (100 MB by default, at most 500 MB); see Pages overview. Without a shell, the begin, chunk, and finalize operations take at most 1 MiB per chunk. - Container archives: the
linkoperations ofdownload_docker_archiveandupload_docker_container_archiveexport and import.gwcaarchives. - Storage objects:
download_storage_objectreturns a link, valid for 15 minutes, that downloads an object of any size, andupload_storage_objectuploads in chunks that Opfield verifies.
A link works once, belongs to the token that requested it, and is checked again against the owner’s current permissions when it is used. Treat it like a short-lived credential.
Error handling
Section titled “Error handling”400or422: correct request shape or validation input;401: refresh or replace authentication;403: distinguish missing scope from missing plan entitlement;404: verify resource visibility as well as existence;409: inspect lifecycle conflict, quota, or current state;429: apply bounded backoff and respect server guidance;5xxor node offline: preserve request IDs and check durable task state before retrying.
MCP and AI Workspace tool errors start with the same code as the REST response, for example NOT_FOUND, STORAGE_NOT_FOUND, or NGINX_CONFIG_FAILED, followed by the message and details; a schema error reads VALIDATION_ERROR with the failing fields. A request to an unknown /api path returns a JSON 404 NOT_FOUND instead of the Console page.
MCP operating rules
Section titled “MCP operating rules”In 2.11, MCP tools cover every resource and management operation that the OAuth grant’s scopes allow, including Node configuration and files, Docker migrations, the logging backend, Opfield settings, users and groups, Relay Pool and update operations, inference administration, hosting, and the GitLab, GitHub, generic Git, Cloudflare, and external SSH connectors. MCP does not expose AI Workspace internals such as conversations, plans, and sandboxes, or tools that mint API tokens or OAuth authorizations. See What tokens can and cannot do.
Creating Routes and Domains does not require Node permissions: create_route and create_domain can omit the Node when a registered Domain or the only eligible Ingress Node decides it (for Routes, that node must be online), and list_route_ingress_nodes lists the Nodes the caller may create Routes on. See Choose the Ingress Node.
The MCP server reports the Opfield release as its version. manage_gateway_diagnostics inspects Opfield itself; see Opfield diagnostics. When an MCP tool sets the environment of a Deployment, it merges with the saved environment, unlike the REST deploy route; see Release a new version.
Use MCP for goal-oriented operations where the tool schema adds safety and resource context. Read tool descriptions and returned warnings, pass exact resource identifiers, and treat external content as untrusted input. MCP calls are audited and must not be used to bypass confirmation, permission, entitlement, or lifecycle checks.
Verification
Section titled “Verification”For every automation path, test one allowed action, one denied action, one validation failure, one asynchronous success, and one interrupted operation. Confirm audit attribution and make sure logs redact credentials and sensitive request fields.
Designing reliable clients
Section titled “Designing reliable clients”Model automation as reconciliation rather than a sequence of blind button presses. Read the current resource, compare it with the desired state, submit the smallest required mutation, and verify the resulting owner-reported state. Use stable IDs in stored state and human-readable names only for display. When an API exposes an operation or Task ID, persist it alongside the automation run so an operator can correlate a timeout with Opfield history.
Set bounded connection, request, and overall operation deadlines separately. A short HTTP deadline can coexist with a long-running durable Task. Retry reads and explicitly idempotent updates with capped exponential backoff and jitter. Do not automatically retry creates, deletes, migrations, restores, or credential rotation after an ambiguous timeout unless the request carried an Idempotency-Key to an endpoint that accepts one, or the existing operation has been reconciled.
Version the client against the OpenAPI document and the Opfield releases it has actually tested. Reject unknown destructive fields and states rather than silently ignoring them. If a release changes a lifecycle contract, update the client and its acceptance tests before rolling it across all installations.
Safe rollout and rollback
Section titled “Safe rollout and rollback”Run new automation against a disposable Folder or resource set with production-like scopes. Capture the intended request, resulting Task, audit record, and independent state verification. Roll out to one installation or failure domain first, then observe errors and reconciliation lag before expanding.
Rollback normally means disabling the caller, stopping new submissions, and applying a supported product rollback to already changed resources. It does not mean deleting Tasks or editing desired state in PostgreSQL. Preserve request IDs and failed payload metadata with secrets removed so the product owner can distinguish a client defect from an Opfield or daemon failure.