Configure the workspace
MCP servers
Connect tools with credentials, OAuth and tool policies.
On this page
Connect an Environment tool server
MCP servers belong to the Environment and apply across its harness Sessions. Manage them in TUI Settings or the Platform console, or use the MCP API details. Hosted Environments support HTTP, SSE and local stdio commands, secret header credentials, OAuth and exact-name tool allow/deny policies. MCP credentials are separate from model provider credentials. Checks and authorization execute inside the Environment under its network policy.
Updates require the current configuration revision and conflict while a Run or rollback holds the Environment lifecycle lock. Restart an open terminal after changing the tool catalog. A fork copies configuration without credentials; rollback retains the current configuration. Read APIs never reveal secret values.
Create an Environment MCP server
/v1/environments/{environmentId}/mcp-serversMCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
Request example
curl -X POST \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers" \
-H "Authorization: Bearer $SANDPI_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "tools",
"transport": "http",
"url": "https://mcp.example.com/mcp",
"enabled": true,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": []
}
}'Request body · required application/json
MCP configuration and optional write-only credentials for creation.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
name | stringValidation pattern^[a-z][a-z0-9_-]{0,47}$ | Yes | Human-readable name for this resource. |
transport | string · values: "stdio" | "http" | "sse" | Yes | MCP transport: sandbox-local stdio, HTTP or legacy SSE. |
url | string · format: uri; max length 2048 | No | Remote MCP endpoint for HTTP or SSE transport; not used for sandbox-local stdio. |
command | string · min length 1; max length 2048 | No | Command executable to launch inside the Environment for stdio transport. |
args | array · max 64 items | No | Arguments passed to the stdio command inside the Environment. |
args[] | string · max length 4096 | Yeseach array item | — |
enabled | boolean | Yes | Whether this configuration is enabled for future use. |
authentication | string · values: "none" | "headers" | "oauth" | Yes | Authentication mode used for this MCP connection. |
oauth | object · extra fields rejected | No | OAuth client configuration for an HTTP or SSE MCP server. |
oauth.clientId | string · min length 1; max length 512 | Nowithin oauth | OAuth client identifier; provide one when the upstream service requires it. |
oauth.scopes | array · max 32 items | Nowithin oauth | OAuth scopes requested from the upstream service. |
oauth.scopes[] | string · min length 1; max length 128 | Yeseach array item | — |
toolPolicy | object · extra fields rejected | Yes | Managed MCP policy: all tools, exact-name allow list or exact-name deny list. |
toolPolicy.mode | string · values: "all" | "allow" | "deny" | Yeswithin toolPolicy | Selected behavior variant; use one of the allowed values. |
toolPolicy.tools | array · max 256 items | Yeswithin toolPolicy | Tool names associated with this resource or policy. |
toolPolicy.tools[] | string · min length 1; max length 128 | Yeseach array item | — |
material | object · write only; extra fields rejected | No | Write-only MCP credentials. Reads expose only credential presence. |
material.headers | object · max 32 keys | Nowithin material | Header definitions or secret header values applied by this configuration. |
material.headers.{key} | string · max length 8192 | Noadditional keys | — |
material.env | object · max 64 keys | Nowithin material | Write-only environment variables supplied to a stdio MCP command. |
material.env.{key} | string · max length 8192 | Noadditional keys | — |
material.clientSecret | string · max length 8192 | Nowithin material | Write-only OAuth client secret, when the service requires one. |
Example
{
"name": "tools",
"transport": "http",
"url": "https://mcp.example.com/mcp",
"enabled": true,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": []
}
}Responses
201 Successful response.Response body application/json
| Field | Type and constraints | Required | Description |
|---|---|---|---|
data | object · extra fields rejected | Yes | Non-secret MCP configuration, revision and observed connection state. |
data.name | stringValidation pattern^[a-z][a-z0-9_-]{0,47}$ | Yeswithin data | Human-readable name for this resource. |
data.transport | string · values: "stdio" | "http" | "sse" | Yeswithin data | MCP transport: sandbox-local stdio, HTTP or legacy SSE. |
data.url | string · format: uri; max length 2048 | Nowithin data | Remote MCP endpoint for HTTP or SSE transport; not used for sandbox-local stdio. |
data.command | string · min length 1; max length 2048 | Nowithin data | Command executable to launch inside the Environment for stdio transport. |
data.args | array · max 64 items | Nowithin data | Arguments passed to the stdio command inside the Environment. |
data.args[] | string · max length 4096 | Yeseach array item | — |
data.enabled | boolean | Yeswithin data | Whether this configuration is enabled for future use. |
data.authentication | string · values: "none" | "headers" | "oauth" | Yeswithin data | Authentication mode used for this MCP connection. |
data.oauth | object · extra fields rejected | Nowithin data | OAuth client configuration for an HTTP or SSE MCP server. |
data.oauth.clientId | string · min length 1; max length 512 | Nowithin data | OAuth client identifier; provide one when the upstream service requires it. |
data.oauth.scopes | array · max 32 items | Nowithin data | OAuth scopes requested from the upstream service. |
data.oauth.scopes[] | string · min length 1; max length 128 | Yeseach array item | — |
data.toolPolicy | object · extra fields rejected | Yeswithin data | Managed MCP policy: all tools, exact-name allow list or exact-name deny list. |
data.toolPolicy.mode | string · values: "all" | "allow" | "deny" | Yeswithin data | Selected behavior variant; use one of the allowed values. |
data.toolPolicy.tools | array · max 256 items | Yeswithin data | Tool names associated with this resource or policy. |
data.toolPolicy.tools[] | string · min length 1; max length 128 | Yeseach array item | — |
data.id | string | Yeswithin data | Resource identifier used to read or manage this resource. |
data.environmentId | string | Yeswithin data | Environment identifier. It must belong to the caller’s account or Project. |
data.revision | integer · ≥ 1 | Yeswithin data | Configuration revision. MCP updates must use the currently observed revision. |
data.credentialConfigured | boolean | Yeswithin data | Whether secret or OAuth credentials have been configured; values are not returned. |
data.lastCheck | object · extra fields rejected | Nowithin data | Observed connectivity and tool-discovery result from inside the Environment. |
data.lastCheck.status | string · values: "connected" | "authentication-required" | "unavailable" | Yeswithin data | Current resource state; inspect the allowed values and the operation’s lifecycle notes. |
data.lastCheck.tools | array | Yeswithin data | Tool names associated with this resource or policy. |
data.lastCheck.tools[] | object · extra fields rejected | Yeseach array item | — |
data.lastCheck.tools[].name | string | Yeseach array item | Human-readable name for this resource. |
data.lastCheck.tools[].description | string | Noeach array item | Skill description from SKILL.md frontmatter, used by native discovery. |
data.lastCheck.tools[].inputSchema | object · additional fields allowed | Yeseach array item | JSON Schema accepted by this discovered MCP tool. |
data.lastCheck.checkedAt | string · format: date-time | Yeswithin data | Time of the most recent MCP connection check. |
data.lastCheck.message | string | Nowithin data | Human-readable diagnostic text. |
Example
{
"data": {
"name": "",
"transport": "stdio",
"enabled": false,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": [
"example"
]
},
"id": "",
"environmentId": "",
"revision": 1,
"credentialConfigured": false
}
}Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}Check connectivity before a Run
Run a connection check to discover tools and validate the transport. Checks and OAuth discovery happen inside the Environment, under its network policy. For stdio, install the command in that workspace first; it does not run on the Sandpi control plane.
Check MCP connectivity and list allowed tools inside the Environment
/v1/environments/{environmentId}/mcp-servers/{serverId}/checkMCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
path: serverId | string · min length 1 | Yes | MCP server identifier within this Environment. |
Request example
curl -X POST \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers/$SERVER_ID/check" \
-H "Authorization: Bearer $SANDPI_API_TOKEN"No request body.
Responses
200 Successful response.Response body application/json
| Field | Type and constraints | Required | Description |
|---|---|---|---|
data | object · extra fields rejected | Yes | Observed connectivity and tool-discovery result from inside the Environment. |
data.status | string · values: "connected" | "authentication-required" | "unavailable" | Yeswithin data | Current resource state; inspect the allowed values and the operation’s lifecycle notes. |
data.tools | array | Yeswithin data | Tool names associated with this resource or policy. |
data.tools[] | object · extra fields rejected | Yeseach array item | — |
data.tools[].name | string | Yeseach array item | Human-readable name for this resource. |
data.tools[].description | string | Noeach array item | Skill description from SKILL.md frontmatter, used by native discovery. |
data.tools[].inputSchema | object · additional fields allowed | Yeseach array item | JSON Schema accepted by this discovered MCP tool. |
data.checkedAt | string · format: date-time | Yeswithin data | Time of the most recent MCP connection check. |
data.message | string | Nowithin data | Human-readable diagnostic text. |
Example
{
"data": {
"status": "connected",
"tools": [
{
"name": "",
"inputSchema": {}
}
],
"checkedAt": "2026-10-12T01:00:00Z"
}
}Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}Authenticate
HTTP and SSE servers can use secret headers or OAuth. Secret values are write-only. For OAuth, begin authorization, follow the returned flow, and complete the exchange using the API details’s completion operation. Removing stored credentials clears Sandpi’s local grant; revoke remote consent using the upstream provider’s account controls.
Update tool access
Read the configuration and use its current revision when replacing it. Exact-name allow and deny policies filter discovery and calls for Sandpi-managed MCP connections. They do not restrict the agent’s shell or other native tool connections. A changed revision fences existing managed connections. Subsequent Runs receive the current configuration.
Fork and rollback
Forks copy configuration with new server IDs and no credentials. Authorize each child separately. RootFS rollback retains the current MCP configuration. Managed tool calls have no fixed elapsed-time limit; initialization and discovery retain short timeouts.
Inspect and replace server configuration
List the Environment’s servers and read the server you want to update. Send its current revision when replacing the configuration.
List Environment MCP servers
/v1/environments/{environmentId}/mcp-serversMCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
Request example
curl \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers" \
-H "Authorization: Bearer $SANDPI_API_TOKEN"No request body.
Responses
200 Successful response.Response body application/json
| Field | Type and constraints | Required | Description |
|---|---|---|---|
data | array | Yes | Successful result wrapped by the API. The child fields describe its content. |
data[] | object · extra fields rejected | Yeseach array item | Non-secret MCP configuration, revision and observed connection state. |
data[].name | stringValidation pattern^[a-z][a-z0-9_-]{0,47}$ | Yeseach array item | Human-readable name for this resource. |
data[].transport | string · values: "stdio" | "http" | "sse" | Yeseach array item | MCP transport: sandbox-local stdio, HTTP or legacy SSE. |
data[].url | string · format: uri; max length 2048 | Noeach array item | Remote MCP endpoint for HTTP or SSE transport; not used for sandbox-local stdio. |
data[].command | string · min length 1; max length 2048 | Noeach array item | Command executable to launch inside the Environment for stdio transport. |
data[].args | array · max 64 items | Noeach array item | Arguments passed to the stdio command inside the Environment. |
data[].args[] | string · max length 4096 | Yeseach array item | — |
data[].enabled | boolean | Yeseach array item | Whether this configuration is enabled for future use. |
data[].authentication | string · values: "none" | "headers" | "oauth" | Yeseach array item | Authentication mode used for this MCP connection. |
data[].oauth | object · extra fields rejected | Noeach array item | OAuth client configuration for an HTTP or SSE MCP server. |
data[].oauth.clientId | string · min length 1; max length 512 | Noeach array item | OAuth client identifier; provide one when the upstream service requires it. |
data[].oauth.scopes | array · max 32 items | Noeach array item | OAuth scopes requested from the upstream service. |
data[].oauth.scopes[] | string · min length 1; max length 128 | Yeseach array item | — |
data[].toolPolicy | object · extra fields rejected | Yeseach array item | Managed MCP policy: all tools, exact-name allow list or exact-name deny list. |
data[].toolPolicy.mode | string · values: "all" | "allow" | "deny" | Yeseach array item | Selected behavior variant; use one of the allowed values. |
data[].toolPolicy.tools | array · max 256 items | Yeseach array item | Tool names associated with this resource or policy. |
data[].toolPolicy.tools[] | string · min length 1; max length 128 | Yeseach array item | — |
data[].id | string | Yeseach array item | Resource identifier used to read or manage this resource. |
data[].environmentId | string | Yeseach array item | Environment identifier. It must belong to the caller’s account or Project. |
data[].revision | integer · ≥ 1 | Yeseach array item | Configuration revision. MCP updates must use the currently observed revision. |
data[].credentialConfigured | boolean | Yeseach array item | Whether secret or OAuth credentials have been configured; values are not returned. |
data[].lastCheck | object · extra fields rejected | Noeach array item | Observed connectivity and tool-discovery result from inside the Environment. |
data[].lastCheck.status | string · values: "connected" | "authentication-required" | "unavailable" | Yeseach array item | Current resource state; inspect the allowed values and the operation’s lifecycle notes. |
data[].lastCheck.tools | array | Yeseach array item | Tool names associated with this resource or policy. |
data[].lastCheck.tools[] | object · extra fields rejected | Yeseach array item | — |
data[].lastCheck.tools[].name | string | Yeseach array item | Human-readable name for this resource. |
data[].lastCheck.tools[].description | string | Noeach array item | Skill description from SKILL.md frontmatter, used by native discovery. |
data[].lastCheck.tools[].inputSchema | object · additional fields allowed | Yeseach array item | JSON Schema accepted by this discovered MCP tool. |
data[].lastCheck.checkedAt | string · format: date-time | Yeseach array item | Time of the most recent MCP connection check. |
data[].lastCheck.message | string | Noeach array item | Human-readable diagnostic text. |
Example
{
"data": [
{
"name": "",
"transport": "stdio",
"enabled": false,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": [
"example"
]
},
"id": "",
"environmentId": "",
"revision": 1,
"credentialConfigured": false
}
]
}Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}Get an Environment MCP server
/v1/environments/{environmentId}/mcp-servers/{serverId}MCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
path: serverId | string · min length 1 | Yes | MCP server identifier within this Environment. |
Request example
curl \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers/$SERVER_ID" \
-H "Authorization: Bearer $SANDPI_API_TOKEN"No request body.
Responses
200 Successful response.Response body application/json
| Field | Type and constraints | Required | Description |
|---|---|---|---|
data | object · extra fields rejected | Yes | Non-secret MCP configuration, revision and observed connection state. |
data.name | stringValidation pattern^[a-z][a-z0-9_-]{0,47}$ | Yeswithin data | Human-readable name for this resource. |
data.transport | string · values: "stdio" | "http" | "sse" | Yeswithin data | MCP transport: sandbox-local stdio, HTTP or legacy SSE. |
data.url | string · format: uri; max length 2048 | Nowithin data | Remote MCP endpoint for HTTP or SSE transport; not used for sandbox-local stdio. |
data.command | string · min length 1; max length 2048 | Nowithin data | Command executable to launch inside the Environment for stdio transport. |
data.args | array · max 64 items | Nowithin data | Arguments passed to the stdio command inside the Environment. |
data.args[] | string · max length 4096 | Yeseach array item | — |
data.enabled | boolean | Yeswithin data | Whether this configuration is enabled for future use. |
data.authentication | string · values: "none" | "headers" | "oauth" | Yeswithin data | Authentication mode used for this MCP connection. |
data.oauth | object · extra fields rejected | Nowithin data | OAuth client configuration for an HTTP or SSE MCP server. |
data.oauth.clientId | string · min length 1; max length 512 | Nowithin data | OAuth client identifier; provide one when the upstream service requires it. |
data.oauth.scopes | array · max 32 items | Nowithin data | OAuth scopes requested from the upstream service. |
data.oauth.scopes[] | string · min length 1; max length 128 | Yeseach array item | — |
data.toolPolicy | object · extra fields rejected | Yeswithin data | Managed MCP policy: all tools, exact-name allow list or exact-name deny list. |
data.toolPolicy.mode | string · values: "all" | "allow" | "deny" | Yeswithin data | Selected behavior variant; use one of the allowed values. |
data.toolPolicy.tools | array · max 256 items | Yeswithin data | Tool names associated with this resource or policy. |
data.toolPolicy.tools[] | string · min length 1; max length 128 | Yeseach array item | — |
data.id | string | Yeswithin data | Resource identifier used to read or manage this resource. |
data.environmentId | string | Yeswithin data | Environment identifier. It must belong to the caller’s account or Project. |
data.revision | integer · ≥ 1 | Yeswithin data | Configuration revision. MCP updates must use the currently observed revision. |
data.credentialConfigured | boolean | Yeswithin data | Whether secret or OAuth credentials have been configured; values are not returned. |
data.lastCheck | object · extra fields rejected | Nowithin data | Observed connectivity and tool-discovery result from inside the Environment. |
data.lastCheck.status | string · values: "connected" | "authentication-required" | "unavailable" | Yeswithin data | Current resource state; inspect the allowed values and the operation’s lifecycle notes. |
data.lastCheck.tools | array | Yeswithin data | Tool names associated with this resource or policy. |
data.lastCheck.tools[] | object · extra fields rejected | Yeseach array item | — |
data.lastCheck.tools[].name | string | Yeseach array item | Human-readable name for this resource. |
data.lastCheck.tools[].description | string | Noeach array item | Skill description from SKILL.md frontmatter, used by native discovery. |
data.lastCheck.tools[].inputSchema | object · additional fields allowed | Yeseach array item | JSON Schema accepted by this discovered MCP tool. |
data.lastCheck.checkedAt | string · format: date-time | Yeswithin data | Time of the most recent MCP connection check. |
data.lastCheck.message | string | Nowithin data | Human-readable diagnostic text. |
Example
{
"data": {
"name": "",
"transport": "stdio",
"enabled": false,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": [
"example"
]
},
"id": "",
"environmentId": "",
"revision": 1,
"credentialConfigured": false
}
}Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}Update an Environment MCP server with revision checking
/v1/environments/{environmentId}/mcp-servers/{serverId}MCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
path: serverId | string · min length 1 | Yes | MCP server identifier within this Environment. |
Request example
curl -X PUT \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers/$SERVER_ID" \
-H "Authorization: Bearer $SANDPI_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "tools",
"transport": "http",
"url": "https://mcp.example.com/mcp",
"enabled": true,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": []
},
"revision": 1
}'Request body · required application/json
Replacement MCP configuration with the currently observed revision.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
name | stringValidation pattern^[a-z][a-z0-9_-]{0,47}$ | Yes | Human-readable name for this resource. |
transport | string · values: "stdio" | "http" | "sse" | Yes | MCP transport: sandbox-local stdio, HTTP or legacy SSE. |
url | string · format: uri; max length 2048 | No | Remote MCP endpoint for HTTP or SSE transport; not used for sandbox-local stdio. |
command | string · min length 1; max length 2048 | No | Command executable to launch inside the Environment for stdio transport. |
args | array · max 64 items | No | Arguments passed to the stdio command inside the Environment. |
args[] | string · max length 4096 | Yeseach array item | — |
enabled | boolean | Yes | Whether this configuration is enabled for future use. |
authentication | string · values: "none" | "headers" | "oauth" | Yes | Authentication mode used for this MCP connection. |
oauth | object · extra fields rejected | No | OAuth client configuration for an HTTP or SSE MCP server. |
oauth.clientId | string · min length 1; max length 512 | Nowithin oauth | OAuth client identifier; provide one when the upstream service requires it. |
oauth.scopes | array · max 32 items | Nowithin oauth | OAuth scopes requested from the upstream service. |
oauth.scopes[] | string · min length 1; max length 128 | Yeseach array item | — |
toolPolicy | object · extra fields rejected | Yes | Managed MCP policy: all tools, exact-name allow list or exact-name deny list. |
toolPolicy.mode | string · values: "all" | "allow" | "deny" | Yeswithin toolPolicy | Selected behavior variant; use one of the allowed values. |
toolPolicy.tools | array · max 256 items | Yeswithin toolPolicy | Tool names associated with this resource or policy. |
toolPolicy.tools[] | string · min length 1; max length 128 | Yeseach array item | — |
material | object · write only; extra fields rejected | No | Write-only MCP credentials. Reads expose only credential presence. |
material.headers | object · max 32 keys | Nowithin material | Header definitions or secret header values applied by this configuration. |
material.headers.{key} | string · max length 8192 | Noadditional keys | — |
material.env | object · max 64 keys | Nowithin material | Write-only environment variables supplied to a stdio MCP command. |
material.env.{key} | string · max length 8192 | Noadditional keys | — |
material.clientSecret | string · max length 8192 | Nowithin material | Write-only OAuth client secret, when the service requires one. |
revision | integer · ≥ 1 | Yes | Configuration revision. MCP updates must use the currently observed revision. |
Example
{
"name": "tools",
"transport": "http",
"url": "https://mcp.example.com/mcp",
"enabled": true,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": []
},
"revision": 1
}Responses
200 Successful response.Response body application/json
| Field | Type and constraints | Required | Description |
|---|---|---|---|
data | object · extra fields rejected | Yes | Non-secret MCP configuration, revision and observed connection state. |
data.name | stringValidation pattern^[a-z][a-z0-9_-]{0,47}$ | Yeswithin data | Human-readable name for this resource. |
data.transport | string · values: "stdio" | "http" | "sse" | Yeswithin data | MCP transport: sandbox-local stdio, HTTP or legacy SSE. |
data.url | string · format: uri; max length 2048 | Nowithin data | Remote MCP endpoint for HTTP or SSE transport; not used for sandbox-local stdio. |
data.command | string · min length 1; max length 2048 | Nowithin data | Command executable to launch inside the Environment for stdio transport. |
data.args | array · max 64 items | Nowithin data | Arguments passed to the stdio command inside the Environment. |
data.args[] | string · max length 4096 | Yeseach array item | — |
data.enabled | boolean | Yeswithin data | Whether this configuration is enabled for future use. |
data.authentication | string · values: "none" | "headers" | "oauth" | Yeswithin data | Authentication mode used for this MCP connection. |
data.oauth | object · extra fields rejected | Nowithin data | OAuth client configuration for an HTTP or SSE MCP server. |
data.oauth.clientId | string · min length 1; max length 512 | Nowithin data | OAuth client identifier; provide one when the upstream service requires it. |
data.oauth.scopes | array · max 32 items | Nowithin data | OAuth scopes requested from the upstream service. |
data.oauth.scopes[] | string · min length 1; max length 128 | Yeseach array item | — |
data.toolPolicy | object · extra fields rejected | Yeswithin data | Managed MCP policy: all tools, exact-name allow list or exact-name deny list. |
data.toolPolicy.mode | string · values: "all" | "allow" | "deny" | Yeswithin data | Selected behavior variant; use one of the allowed values. |
data.toolPolicy.tools | array · max 256 items | Yeswithin data | Tool names associated with this resource or policy. |
data.toolPolicy.tools[] | string · min length 1; max length 128 | Yeseach array item | — |
data.id | string | Yeswithin data | Resource identifier used to read or manage this resource. |
data.environmentId | string | Yeswithin data | Environment identifier. It must belong to the caller’s account or Project. |
data.revision | integer · ≥ 1 | Yeswithin data | Configuration revision. MCP updates must use the currently observed revision. |
data.credentialConfigured | boolean | Yeswithin data | Whether secret or OAuth credentials have been configured; values are not returned. |
data.lastCheck | object · extra fields rejected | Nowithin data | Observed connectivity and tool-discovery result from inside the Environment. |
data.lastCheck.status | string · values: "connected" | "authentication-required" | "unavailable" | Yeswithin data | Current resource state; inspect the allowed values and the operation’s lifecycle notes. |
data.lastCheck.tools | array | Yeswithin data | Tool names associated with this resource or policy. |
data.lastCheck.tools[] | object · extra fields rejected | Yeseach array item | — |
data.lastCheck.tools[].name | string | Yeseach array item | Human-readable name for this resource. |
data.lastCheck.tools[].description | string | Noeach array item | Skill description from SKILL.md frontmatter, used by native discovery. |
data.lastCheck.tools[].inputSchema | object · additional fields allowed | Yeseach array item | JSON Schema accepted by this discovered MCP tool. |
data.lastCheck.checkedAt | string · format: date-time | Yeswithin data | Time of the most recent MCP connection check. |
data.lastCheck.message | string | Nowithin data | Human-readable diagnostic text. |
Example
{
"data": {
"name": "",
"transport": "stdio",
"enabled": false,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": [
"example"
]
},
"id": "",
"environmentId": "",
"revision": 1,
"credentialConfigured": false
}
}Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}Complete an OAuth connection
Start authorization, open the returned URL and complete the callback exchange with its state and code. Remove the local authorization when the Environment should no longer use it.
Start MCP OAuth authorization with PKCE
/v1/environments/{environmentId}/mcp-servers/{serverId}/authorizationMCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
path: serverId | string · min length 1 | Yes | MCP server identifier within this Environment. |
Request example
curl -X POST \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers/$SERVER_ID/authorization" \
-H "Authorization: Bearer $SANDPI_API_TOKEN"No request body.
Responses
200 Successful response.Response body application/json
| Field | Type and constraints | Required | Description |
|---|---|---|---|
data | object · extra fields rejected | Yes | Temporary OAuth authorization URL and one-time state. |
data.state | string | Yeswithin data | One-time OAuth flow state that must match the pending authorization. |
data.authorizationUrl | string · format: uri | Yeswithin data | Upstream OAuth URL to open to authorize the MCP connection. |
data.expiresAt | string · format: date-time | Yeswithin data | Expiration time for this temporary authorization flow. |
Example
{
"data": {
"state": "",
"authorizationUrl": "https://example.com/repository.git",
"expiresAt": "2026-10-12T01:00:00Z"
}
}Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}Complete MCP OAuth authorization
/v1/environments/{environmentId}/mcp-servers/{serverId}/authorizationMCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
path: serverId | string · min length 1 | Yes | MCP server identifier within this Environment. |
Request example
curl -X PUT \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers/$SERVER_ID/authorization" \
-H "Authorization: Bearer $SANDPI_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"state": "example",
"code": "example"
}'Request body · required application/json
State and authorization code used to complete the pending MCP OAuth flow.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
state | string · min length 32; max length 200 | Yes | One-time OAuth flow state that must match the pending authorization. |
code | string · min length 1; max length 4096 | Yes | Authorization code returned by the upstream OAuth callback. |
Example
{
"state": "example",
"code": "example"
}Responses
200 Successful response.Response body application/json
| Field | Type and constraints | Required | Description |
|---|---|---|---|
data | object · extra fields rejected | Yes | Non-secret MCP configuration, revision and observed connection state. |
data.name | stringValidation pattern^[a-z][a-z0-9_-]{0,47}$ | Yeswithin data | Human-readable name for this resource. |
data.transport | string · values: "stdio" | "http" | "sse" | Yeswithin data | MCP transport: sandbox-local stdio, HTTP or legacy SSE. |
data.url | string · format: uri; max length 2048 | Nowithin data | Remote MCP endpoint for HTTP or SSE transport; not used for sandbox-local stdio. |
data.command | string · min length 1; max length 2048 | Nowithin data | Command executable to launch inside the Environment for stdio transport. |
data.args | array · max 64 items | Nowithin data | Arguments passed to the stdio command inside the Environment. |
data.args[] | string · max length 4096 | Yeseach array item | — |
data.enabled | boolean | Yeswithin data | Whether this configuration is enabled for future use. |
data.authentication | string · values: "none" | "headers" | "oauth" | Yeswithin data | Authentication mode used for this MCP connection. |
data.oauth | object · extra fields rejected | Nowithin data | OAuth client configuration for an HTTP or SSE MCP server. |
data.oauth.clientId | string · min length 1; max length 512 | Nowithin data | OAuth client identifier; provide one when the upstream service requires it. |
data.oauth.scopes | array · max 32 items | Nowithin data | OAuth scopes requested from the upstream service. |
data.oauth.scopes[] | string · min length 1; max length 128 | Yeseach array item | — |
data.toolPolicy | object · extra fields rejected | Yeswithin data | Managed MCP policy: all tools, exact-name allow list or exact-name deny list. |
data.toolPolicy.mode | string · values: "all" | "allow" | "deny" | Yeswithin data | Selected behavior variant; use one of the allowed values. |
data.toolPolicy.tools | array · max 256 items | Yeswithin data | Tool names associated with this resource or policy. |
data.toolPolicy.tools[] | string · min length 1; max length 128 | Yeseach array item | — |
data.id | string | Yeswithin data | Resource identifier used to read or manage this resource. |
data.environmentId | string | Yeswithin data | Environment identifier. It must belong to the caller’s account or Project. |
data.revision | integer · ≥ 1 | Yeswithin data | Configuration revision. MCP updates must use the currently observed revision. |
data.credentialConfigured | boolean | Yeswithin data | Whether secret or OAuth credentials have been configured; values are not returned. |
data.lastCheck | object · extra fields rejected | Nowithin data | Observed connectivity and tool-discovery result from inside the Environment. |
data.lastCheck.status | string · values: "connected" | "authentication-required" | "unavailable" | Yeswithin data | Current resource state; inspect the allowed values and the operation’s lifecycle notes. |
data.lastCheck.tools | array | Yeswithin data | Tool names associated with this resource or policy. |
data.lastCheck.tools[] | object · extra fields rejected | Yeseach array item | — |
data.lastCheck.tools[].name | string | Yeseach array item | Human-readable name for this resource. |
data.lastCheck.tools[].description | string | Noeach array item | Skill description from SKILL.md frontmatter, used by native discovery. |
data.lastCheck.tools[].inputSchema | object · additional fields allowed | Yeseach array item | JSON Schema accepted by this discovered MCP tool. |
data.lastCheck.checkedAt | string · format: date-time | Yeswithin data | Time of the most recent MCP connection check. |
data.lastCheck.message | string | Nowithin data | Human-readable diagnostic text. |
Example
{
"data": {
"name": "",
"transport": "stdio",
"enabled": false,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": [
"example"
]
},
"id": "",
"environmentId": "",
"revision": 1,
"credentialConfigured": false
}
}Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}Remove stored MCP credentials and OAuth grants
/v1/environments/{environmentId}/mcp-servers/{serverId}/authorizationMCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
path: serverId | string · min length 1 | Yes | MCP server identifier within this Environment. |
Request example
curl -X DELETE \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers/$SERVER_ID/authorization" \
-H "Authorization: Bearer $SANDPI_API_TOKEN"No request body.
Responses
200 Successful response.Response body application/json
| Field | Type and constraints | Required | Description |
|---|---|---|---|
data | object · extra fields rejected | Yes | Non-secret MCP configuration, revision and observed connection state. |
data.name | stringValidation pattern^[a-z][a-z0-9_-]{0,47}$ | Yeswithin data | Human-readable name for this resource. |
data.transport | string · values: "stdio" | "http" | "sse" | Yeswithin data | MCP transport: sandbox-local stdio, HTTP or legacy SSE. |
data.url | string · format: uri; max length 2048 | Nowithin data | Remote MCP endpoint for HTTP or SSE transport; not used for sandbox-local stdio. |
data.command | string · min length 1; max length 2048 | Nowithin data | Command executable to launch inside the Environment for stdio transport. |
data.args | array · max 64 items | Nowithin data | Arguments passed to the stdio command inside the Environment. |
data.args[] | string · max length 4096 | Yeseach array item | — |
data.enabled | boolean | Yeswithin data | Whether this configuration is enabled for future use. |
data.authentication | string · values: "none" | "headers" | "oauth" | Yeswithin data | Authentication mode used for this MCP connection. |
data.oauth | object · extra fields rejected | Nowithin data | OAuth client configuration for an HTTP or SSE MCP server. |
data.oauth.clientId | string · min length 1; max length 512 | Nowithin data | OAuth client identifier; provide one when the upstream service requires it. |
data.oauth.scopes | array · max 32 items | Nowithin data | OAuth scopes requested from the upstream service. |
data.oauth.scopes[] | string · min length 1; max length 128 | Yeseach array item | — |
data.toolPolicy | object · extra fields rejected | Yeswithin data | Managed MCP policy: all tools, exact-name allow list or exact-name deny list. |
data.toolPolicy.mode | string · values: "all" | "allow" | "deny" | Yeswithin data | Selected behavior variant; use one of the allowed values. |
data.toolPolicy.tools | array · max 256 items | Yeswithin data | Tool names associated with this resource or policy. |
data.toolPolicy.tools[] | string · min length 1; max length 128 | Yeseach array item | — |
data.id | string | Yeswithin data | Resource identifier used to read or manage this resource. |
data.environmentId | string | Yeswithin data | Environment identifier. It must belong to the caller’s account or Project. |
data.revision | integer · ≥ 1 | Yeswithin data | Configuration revision. MCP updates must use the currently observed revision. |
data.credentialConfigured | boolean | Yeswithin data | Whether secret or OAuth credentials have been configured; values are not returned. |
data.lastCheck | object · extra fields rejected | Nowithin data | Observed connectivity and tool-discovery result from inside the Environment. |
data.lastCheck.status | string · values: "connected" | "authentication-required" | "unavailable" | Yeswithin data | Current resource state; inspect the allowed values and the operation’s lifecycle notes. |
data.lastCheck.tools | array | Yeswithin data | Tool names associated with this resource or policy. |
data.lastCheck.tools[] | object · extra fields rejected | Yeseach array item | — |
data.lastCheck.tools[].name | string | Yeseach array item | Human-readable name for this resource. |
data.lastCheck.tools[].description | string | Noeach array item | Skill description from SKILL.md frontmatter, used by native discovery. |
data.lastCheck.tools[].inputSchema | object · additional fields allowed | Yeseach array item | JSON Schema accepted by this discovered MCP tool. |
data.lastCheck.checkedAt | string · format: date-time | Yeswithin data | Time of the most recent MCP connection check. |
data.lastCheck.message | string | Nowithin data | Human-readable diagnostic text. |
Example
{
"data": {
"name": "",
"transport": "stdio",
"enabled": false,
"authentication": "none",
"toolPolicy": {
"mode": "all",
"tools": [
"example"
]
},
"id": "",
"environmentId": "",
"revision": 1,
"credentialConfigured": false
}
}Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}Remove a server
Deleting the definition removes the managed connection. Revoke remote consent separately where required.
Delete an Environment MCP server
/v1/environments/{environmentId}/mcp-servers/{serverId}MCP configuration belongs to the Environment and is shared by its harness Sessions. Secrets are write-only and remain outside RootFS snapshots. Configuration changes apply to subsequent Runs and restarted terminals. Operations require the Environment to be idle; active Runs return 409.
Authentication: Platform API bearer token
Parameters and headers
| Field | Type and constraints | Required | Description |
|---|---|---|---|
path: environmentId | string · min length 1 | Yes | Environment identifier. It must belong to the caller’s account or Project. |
path: serverId | string · min length 1 | Yes | MCP server identifier within this Environment. |
Request example
curl -X DELETE \
"https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/mcp-servers/$SERVER_ID" \
-H "Authorization: Bearer $SANDPI_API_TOKEN"No request body.
Responses
204 Successful response.Empty response body.
Error responses
default Sandpi error.Error body application/json
Standard error envelope containing a stable code, diagnostic message and request identity.
| Field | Type and constraints | Required | Description |
|---|---|---|---|
error | object · extra fields rejected | Yes | Structured failure information. Inspect the stable code and retain the request ID for investigation. |
error.code | string | Yeswithin error | Stable error code used to distinguish failures programmatically. |
error.message | string | Yeswithin error | Human-readable diagnostic text. |
error.requestId | string | Yeswithin error | Request identifier for correlating diagnostics and support investigations. |
error.details | any | Nowithin error | Optional structured error context. Its shape is specific to the service failure. |
error.loginUrl | string | Nowithin error | Authentication URL supplied when a browser login is required. |
error.registrationOpen | boolean | Nowithin error | Whether new account registration is enabled for this deployment. |
Example
{
"error": {
"code": "platform_balance_insufficient",
"message": "Top up Platform credits before submitting a Run.",
"requestId": "req_example"
}
}