MCP reference

Endpoints, server fields, status values, and error codes for MCP Servers and the MCP Gateway.

Agentic Friendly

Two addresses are involved. Management endpoints live on the BSQAI API under /v1/mcp. MCP traffic goes to the MCP Gateway, which is a separate service with its own address.

Authenticate with a JWT or a BSQAI API key. Both are sent as Authorization: Bearer ....

Management endpoints

MethodPathWhoResult
POST/v1/mcp/serversAdmin200 with the server
GET/v1/mcp/serversMember200 with servers and count
GET/v1/mcp/servers/{server_id}Member200 with the server
PUT/v1/mcp/servers/{server_id}Admin200 with the server
DELETE/v1/mcp/servers/{server_id}Admin204
GET/v1/mcp/servers/{server_id}/available-toolsAdmin200 with tools and count
PUT/v1/mcp/servers/{server_id}/credentialMember204
DELETE/v1/mcp/servers/{server_id}/credentialMember204
POST/v1/mcp/servers/{server_id}/credential/oauthMember200 with authorize_url and state
POST/v1/mcp/credential/oauth/callbackMember200 with server_id

There is no PATCH. Updates use PUT and replace what they send.

DELETE /v1/mcp/servers/{server_id} is idempotent. An administrator gets 204 whether or not the server existed.

Gateway endpoint

MethodPath
GET, POST, DELETE/servers/{server_id}/mcp

POST carries messages, GET opens the server-to-client stream, and DELETE ends a session. The transport is Streamable HTTP.

The full URL is on gateway_url in every server response, and on the server's detail page in the Portal.

Fields on every server

FieldTypeRules
runtime"managed" or "remote"Chooses the request shape. Cannot change after creation
namestringLowercase DNS label, 1 to 63 characters, unique in the organization. Create only
display_namestring1 to 200 characters
descriptionstring or nullUp to 500 characters. Defaults to null
tool_allowlistarray of stringsDefaults to [], which permits every tool

Unknown fields, and fields belonging to the other runtime, are rejected with 422.

Sending name on an update is rejected. To rename what people read, change display_name.

Managed Server fields

FieldTypeRules
imagestringRequired. Registry-qualified with a tag or digest. Up to 512 characters
portintegerRequired. 1 to 65535
pathstringDefaults to /mcp. Must start with /
argumentsarray of stringsDefaults to []. Replaces the image's default command
envobject of stringsNames match ^[A-Za-z_][A-Za-z0-9_]*$. Write-only
resourcesobjectcpu_request, memory_request, cpu_limit, memory_limit. Each a string or null
securityobjectrun_as_non_root, run_as_user, run_as_group, read_only_root_filesystem. Each nullable

A null field in resources or security leaves the platform's default alone.

A Managed Server runs one replica.

Environment semantics on update

What you sendEffect
No env fieldKeep the stored environment
"env": nullKeep the stored environment
"env": {"A": "1"}Replace the whole environment with exactly those names
"env": {}Remove every environment variable

Values are never returned, so a read gives you nothing to resend. Omission preserving the environment is what makes a read, edit, and write cycle safe.

Remote Server fields

FieldTypeRules
addressstringRequired. Absolute http:// or https:// URL including the path, up to 2048 characters

The address is stored exactly as sent and is never normalized. It must carry no username or password, and its host must be publicly resolvable.

A Remote Server accepts none of the Managed fields.

Server response

{
  "id": "2ddb7c76-4fb1-41bc-bf04-c0ae2b4ee4f3",
  "organization_id": "...",
  "name": "linear",
  "display_name": "Linear",
  "description": null,
  "runtime": "remote",
  "address": "https://mcp.linear.app/mcp",
  "namespace": null,
  "image": null,
  "port": null,
  "path": null,
  "arguments": [],
  "env": [],
  "resources": { "cpu_request": null, "memory_request": null, "cpu_limit": null, "memory_limit": null },
  "security": { "run_as_non_root": null, "run_as_user": null, "run_as_group": null, "read_only_root_filesystem": null },
  "tool_allowlist": ["search_issues"],
  "created_at": "2026-08-28T09:14:22Z",
  "updated_at": "2026-08-28T09:14:22Z",
  "credential_mode": "per_user",
  "linked": true,
  "credential_last_used_at": "2026-08-28T10:02:11Z",
  "status": null,
  "gateway_url": "https://mcp-gateway.<platform-domain>/servers/2ddb7c76-4fb1-41bc-bf04-c0ae2b4ee4f3/mcp"
}
Response fieldMeaning
envNames only, each with configured: true. Values are never returned
namespaceWhere the platform runs a Managed Server. null for a Remote Server
credential_modeWhose identity reaches the Upstream. Servers report per_user
linkedWhether the calling user has linked a credential. Yours alone
credential_last_used_atWhen your credential was last used, or null
statusLive workload status, or null
gateway_urlThe address an MCP client uses. null when the deployment publishes none

Status

A Managed Server with a reported status carries this shape.

{
  "ready": true,
  "replicas": 1,
  "ready_replicas": 1,
  "url": "...",
  "conditions": [
    {
      "type": "Ready",
      "status": "True",
      "reason": "...",
      "message": "...",
      "last_transition_time": "2026-08-28T09:15:03Z"
    }
  ]
}

ready: true means the workload is up and the platform completed an MCP handshake with it. That is stricter than the container running.

status is null for a Remote Server, always. It is also null for a Managed Server the cluster has not reported on yet. The Portal renders these as Not reported and Status unknown.

status.url is the internal workload address. It is not reachable from outside the cluster. Use gateway_url.

Credential endpoints

Link or replace:

{ "credential": "<upstream token>" }

The value is 1 to 4096 characters and may not be blank. The response is 204 with no body.

Start OAuth Linking with POST /v1/mcp/servers/{server_id}/credential/oauth. It takes no body and answers:

{ "authorize_url": "https://...", "state": "..." }

Send the browser to authorize_url. The upstream system returns the browser to the Portal with code and state, which the Portal posts to /v1/mcp/credential/oauth/callback:

{ "state": "...", "code": "..." }

A state is valid once and for ten minutes. It is bound to the user and organization that started the flow, and is consumed before the code is exchanged, so a repeated post fails.

No endpoint returns a credential.

Agent integration

mcp_server_ids lists the MCP Servers an Agent may reach. On POST /v1/agents, omit the field or send [] to create an Agent without MCP Servers. On PUT /v1/agents/{config_id}, the update semantics are:

What you sendEffect
No mcp_server_ids fieldKeep the current list
nullKeep the current list
[]Remove every server
A list of identifiersReplace the list

Every identifier must name a server in the caller's organization. An identifier that does not returns agent_mcp_server_not_in_organization, naming every invalid entry.

At run time the agent reaches only the servers the running user has linked and may use. The rest contribute no tools.

Error codes

Management endpoints answer with the platform error envelope. Request validation failures answer 422 without an error code.

StatusCodeMeaning
400mcp_server_address_invalidThe Remote address broke a rule the message names
400mcp_server_image_invalidThe image reference is not one the cluster would accept
400mcp_server_runtime_mismatchThe update used the other runtime's shape
400mcp_server_does_not_use_oauthThe server presented no OAuth challenge
400mcp_oauth_state_invalidThe state is unknown, expired, already used, or another user's
400agent_mcp_server_not_in_organizationAn Agent referenced a server outside the organization
403mcp_server_access_deniedThe server is absent, another organization's, or not yours to use
403mcp_server_management_deniedThe caller is not a Platform Admin
403mcp_credential_not_linkedNo credential is linked for this server
403mcp_credential_rejectedThe upstream system refused the linked credential
403mcp_credential_expiredAn OAuth credential that can no longer be renewed
409mcp_server_name_conflictAnother server in the organization has that name
503mcp_server_environment_not_storedThe environment could not be written, so nothing was recorded
503mcp_server_not_readyThe Managed workload is not serving yet
503mcp_server_unreachableThe server did not answer or did not complete an MCP handshake
503mcp_oauth_upstream_errorOAuth discovery, registration, or exchange failed. Retrying is the remedy
503mcp_oauth_not_configuredThe deployment publishes no OAuth return address

A missing server and an inaccessible one both return mcp_server_access_denied, so probing for identifiers reveals nothing.

Gateway errors

The Gateway answers in JSON-RPC 2.0. The platform code appears on error.data.code.

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32003,
    "message": "No credential is linked for this MCP Server.",
    "data": { "code": "mcp_credential_not_linked" }
  }
}
JSON-RPC codePlatform code
-32002mcp_server_access_denied
-32003mcp_credential_not_linked
-32004mcp_credential_rejected
-32005mcp_credential_expired

A call to a tool outside the allowlist is the one exception. It answers HTTP 200 with JSON-RPC -32602 and the message Unknown tool: <name>, carrying no data, so it is indistinguishable from a tool the server never had.

The three credential refusals also carry a WWW-Authenticate bearer challenge whose error parameter matches the code in the body.

On this page