MCP Servers
Generated HTTP reference for the 8 operations the published OpenAPI document describes under mcp-servers.
MCP Servers
This page is generated from the published OpenAPI document. It is complete with respect to that document and says nothing about surfaces the document does not describe yet. See what is generated here for what that means.
Base URL: https://api.codespar.dev
Every operation below requires a Bearer token. See Authentication.
GET /v1/mcp-servers
List this project's MCP servers
Responses
| Status | Body | Description |
|---|---|---|
200 | object | OK |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
mcp_servers | array of object | yes | — |
Example response
{
"mcp_servers": [
{
"id": "obj_0000000000000000",
"project_id": "prj_0000000000000000",
"slug": "example",
"name": "Example",
"description": "string",
"overview_md": "string",
"upstream_url": "https://example.com/hook",
"environment": "live",
"payto_kind": "provisioned",
"payto_address": "string",
"platform_fee_bps": 0,
"tool_count": 1,
"active": true,
"gateway_url": "https://example.com/hook",
"tools": [
{
"id": "obj_0000000000000000",
"tool_name": "Example",
"description": "string",
"pricing_model": "string",
"price": "string",
"price_atomic": "string",
"active": true
}
],
"created_at": "2026-01-15T12:00:00.000Z"
}
]
}Example request
curl -X GET https://api.codespar.dev/v1/mcp-servers \
-H "Authorization: Bearer $CODESPAR_API_KEY"POST /v1/mcp-servers
Register a monetized MCP server and price its tools
Request body
| Field | Type | Required | Description |
|---|---|---|---|
category | string | no | — |
consumer_id | string | yes | — |
description | string | no | — |
name | string | yes | — |
overview_md | string | no | — |
platform_fee_bps | integer | no | — |
slug | string | yes | — |
tools | array of object | yes | — |
upstream_auth | object | no | — |
upstream_url | string (uri) | yes | — |
Responses
| Status | Body | Description |
|---|---|---|
201 | object | OK |
400 | object | invalid_body for a body that failed the schema (details.issues) or a tool price that is not a positive six-decimal USDC amount; invalid_upstream_url for a URL refused by the address guard; slug_conflict for a duplicate slug or a repeated tool name. |
403 | object | Forbidden. The operation requires the admin role in the organization, resolved from the acting user forwarded in x-codespar-user. Known values of error: insufficient_role, bearer_admin_role_missing, bearer_admin_user_not_member, bearer_admin_role_unresolved. The same status and body shape also carry the scope gate's refusals, which reach every route in this subtree including the two reads: forbidden when the credential lacks the scope the route is mapped to, and the two alarms scopes_unresolved and route_scope_unresolved. |
503 | object | The receiving CDP address could not be provisioned. The server was not created; retry after connecting Coinbase CDP for this project. |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
active | boolean | yes | — |
category | string,null | yes | — |
consumer_id | string,null | yes | — |
created_at | string (date-time) | yes | — |
description | string | yes | Listing card summary. Empty string when none was supplied. |
environment | "live" | "test" | yes | Taken from the calling credential's environment at create time. There is no body field for it. |
gateway_url | string | yes | https://gw.codespar.dev/mcp/\<slug\>, rebuilt from the slug on every read rather than stored. |
id | string | yes | mcs_ followed by a nanoid. |
name | string | yes | — |
overview_md | string | yes | Listing page body, markdown. Empty string when none was supplied. |
payto_address | string | yes | The address that receives USDC for calls settled through the gateway. |
payto_kind | "provisioned" | "split" | yes | Create always writes provisioned, a CodeSpar-derived CDP wallet. split exists in the column but no operation on this surface produces it, and bring-your-own is not offered. |
platform_fee_bps | integer | yes | Basis points of each settled call accrued as a platform fee, 0 to 10000. Stored at create and applied by settlement, not by this resource. |
project_id | string | yes | — |
slug | string | yes | Lowercase letters, digits, underscore or dash, up to 64 characters. The slug namespace is GLOBAL across all tenants, so a slug another organization already holds is refused. |
tool_count | integer | yes | The number of tools supplied at create time. Nothing recomputes it, so deactivating a tool leaves it unchanged and it is not a count of ACTIVE tools. |
tools | array of object | no | Present on create, on the single read, and on the listing patch. ABSENT from the list response, which returns servers without their tools. |
upstream_url | string | yes | — |
Example response
{
"id": "obj_0000000000000000",
"project_id": "prj_0000000000000000",
"slug": "example",
"name": "Example",
"description": "string",
"overview_md": "string",
"upstream_url": "https://example.com/hook",
"environment": "live",
"payto_kind": "provisioned",
"payto_address": "string",
"platform_fee_bps": 0,
"tool_count": 1,
"active": true,
"gateway_url": "https://example.com/hook",
"tools": [
{
"id": "obj_0000000000000000",
"tool_name": "Example",
"description": "string",
"pricing_model": "string",
"price": "string",
"price_atomic": "string",
"active": true
}
],
"created_at": "2026-01-15T12:00:00.000Z"
}Example request
curl -X POST https://api.codespar.dev/v1/mcp-servers \
-H "Authorization: Bearer $CODESPAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"slug": "example",
"name": "Example",
"description": "string",
"overview_md": "string",
"category": "string",
"upstream_url": "https://example.com/hook",
"consumer_id": "csm_0000000000000000",
"upstream_auth": {
"header": "string",
"value": "string"
},
"platform_fee_bps": 0,
"tools": [
{
"tool_name": "Example",
"description": "string",
"price": "string"
}
]
}'POST /v1/mcp-servers/platform-fees/sweep
Move accrued platform fees to the organization's wallet now
Responses
| Status | Body | Description |
|---|---|---|
200 | object | OK |
403 | object | Forbidden. The operation requires the admin role in the organization, resolved from the acting user forwarded in x-codespar-user. Known values of error: insufficient_role, bearer_admin_role_missing, bearer_admin_user_not_member, bearer_admin_role_unresolved. The same status and body shape also carry the scope gate's refusals, which reach every route in this subtree including the two reads: forbidden when the credential lacks the scope the route is mapped to, and the two alarms scopes_unresolved and route_scope_unresolved. |
409 | object | Another sweep for this organization holds the lock. Nothing was transferred and nothing was marked swept; try again shortly. |
503 | object | The pass failed. Reported for any thrown error, including a platform wallet that could not be provisioned and a database failure mid-sweep. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
partner_wallet | string | no | Absent when there was nothing to sweep, because no address is resolved in that case. |
swept | integer | yes | How many TRANSFERS succeeded. It is not a count of accrual rows or of servers. |
total_atomic | string | yes | The sum of the successful transfers only, in USDC atomic units. It sums across environments, so it is not an amount that moved on any single chain. |
transfers | array of object | yes | — |
Example response
{
"swept": 0,
"total_atomic": "string",
"partner_wallet": "string",
"transfers": [
{
"source": "string",
"amount_atomic": "1000",
"status": "swept"
}
]
}Example request
curl -X POST https://api.codespar.dev/v1/mcp-servers/platform-fees/sweep \
-H "Authorization: Bearer $CODESPAR_API_KEY"POST /v1/mcp-servers/validate
Connect to an upstream MCP server and list its tools
Request body
| Field | Type | Required | Description |
|---|---|---|---|
auth | object | no | — |
upstream_url | string (uri) | yes | — |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | OK |
400 | object | The body did not match the schema (invalid_body, with details.issues carrying the validation issues), or the URL was refused by the address guard (invalid_upstream_url, with details.upstream_url and details.reason). |
403 | object | Forbidden. The operation requires the admin role in the organization, resolved from the acting user forwarded in x-codespar-user. Known values of error: insufficient_role, bearer_admin_role_missing, bearer_admin_user_not_member, bearer_admin_role_unresolved. The same status and body shape also carry the scope gate's refusals, which reach every route in this subtree including the two reads: forbidden when the credential lacks the scope the route is mapped to, and the two alarms scopes_unresolved and route_scope_unresolved. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
count | integer | yes | The length of tools. |
error | string | no | Present only when valid is false. invalid_url, connect_timeout and list_tools_timeout come from the introspection itself; anything else is the upstream error's own message, so treat this as an open string rather than a code enum. |
tools | array of object | yes | Empty when valid is false. |
valid | boolean | yes | — |
Example response
{
"valid": true,
"count": 1,
"tools": [
{
"name": "Example",
"description": "string"
}
],
"error": "string"
}Example request
curl -X POST https://api.codespar.dev/v1/mcp-servers/validate \
-H "Authorization: Bearer $CODESPAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"upstream_url": "https://example.com/hook",
"auth": {
"header": "string",
"value": "string"
}
}'GET /v1/mcp-servers/{id}
Read one MCP server with its priced tools
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | yes | — |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | OK |
404 | object | No such server in this organization and project. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
active | boolean | yes | — |
category | string,null | yes | — |
consumer_id | string,null | yes | — |
created_at | string (date-time) | yes | — |
description | string | yes | Listing card summary. Empty string when none was supplied. |
environment | "live" | "test" | yes | Taken from the calling credential's environment at create time. There is no body field for it. |
gateway_url | string | yes | https://gw.codespar.dev/mcp/\<slug\>, rebuilt from the slug on every read rather than stored. |
id | string | yes | mcs_ followed by a nanoid. |
name | string | yes | — |
overview_md | string | yes | Listing page body, markdown. Empty string when none was supplied. |
payto_address | string | yes | The address that receives USDC for calls settled through the gateway. |
payto_kind | "provisioned" | "split" | yes | Create always writes provisioned, a CodeSpar-derived CDP wallet. split exists in the column but no operation on this surface produces it, and bring-your-own is not offered. |
platform_fee_bps | integer | yes | Basis points of each settled call accrued as a platform fee, 0 to 10000. Stored at create and applied by settlement, not by this resource. |
project_id | string | yes | — |
slug | string | yes | Lowercase letters, digits, underscore or dash, up to 64 characters. The slug namespace is GLOBAL across all tenants, so a slug another organization already holds is refused. |
tool_count | integer | yes | The number of tools supplied at create time. Nothing recomputes it, so deactivating a tool leaves it unchanged and it is not a count of ACTIVE tools. |
tools | array of object | no | Present on create, on the single read, and on the listing patch. ABSENT from the list response, which returns servers without their tools. |
upstream_url | string | yes | — |
Example response
{
"id": "obj_0000000000000000",
"project_id": "prj_0000000000000000",
"slug": "example",
"name": "Example",
"description": "string",
"overview_md": "string",
"upstream_url": "https://example.com/hook",
"environment": "live",
"payto_kind": "provisioned",
"payto_address": "string",
"platform_fee_bps": 0,
"tool_count": 1,
"active": true,
"gateway_url": "https://example.com/hook",
"tools": [
{
"id": "obj_0000000000000000",
"tool_name": "Example",
"description": "string",
"pricing_model": "string",
"price": "string",
"price_atomic": "string",
"active": true
}
],
"created_at": "2026-01-15T12:00:00.000Z"
}Example request
curl -X GET https://api.codespar.dev/v1/mcp-servers/{id} \
-H "Authorization: Bearer $CODESPAR_API_KEY"PATCH /v1/mcp-servers/{id}
Update an MCP server's listing metadata or its active flag
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | yes | — |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
active | boolean | no | — |
category | string | no | — |
description | string | no | — |
name | string | no | — |
overview_md | string | no | — |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | OK |
400 | object | The body failed the schema, or was an empty patch. details.issues carries the issues. |
403 | object | Forbidden. The operation requires the admin role in the organization, resolved from the acting user forwarded in x-codespar-user. Known values of error: insufficient_role, bearer_admin_role_missing, bearer_admin_user_not_member, bearer_admin_role_unresolved. The same status and body shape also carry the scope gate's refusals, which reach every route in this subtree including the two reads: forbidden when the credential lacks the scope the route is mapped to, and the two alarms scopes_unresolved and route_scope_unresolved. |
404 | object | No such server in this organization and project. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
active | boolean | yes | — |
category | string,null | yes | — |
consumer_id | string,null | yes | — |
created_at | string (date-time) | yes | — |
description | string | yes | Listing card summary. Empty string when none was supplied. |
environment | "live" | "test" | yes | Taken from the calling credential's environment at create time. There is no body field for it. |
gateway_url | string | yes | https://gw.codespar.dev/mcp/\<slug\>, rebuilt from the slug on every read rather than stored. |
id | string | yes | mcs_ followed by a nanoid. |
name | string | yes | — |
overview_md | string | yes | Listing page body, markdown. Empty string when none was supplied. |
payto_address | string | yes | The address that receives USDC for calls settled through the gateway. |
payto_kind | "provisioned" | "split" | yes | Create always writes provisioned, a CodeSpar-derived CDP wallet. split exists in the column but no operation on this surface produces it, and bring-your-own is not offered. |
platform_fee_bps | integer | yes | Basis points of each settled call accrued as a platform fee, 0 to 10000. Stored at create and applied by settlement, not by this resource. |
project_id | string | yes | — |
slug | string | yes | Lowercase letters, digits, underscore or dash, up to 64 characters. The slug namespace is GLOBAL across all tenants, so a slug another organization already holds is refused. |
tool_count | integer | yes | The number of tools supplied at create time. Nothing recomputes it, so deactivating a tool leaves it unchanged and it is not a count of ACTIVE tools. |
tools | array of object | no | Present on create, on the single read, and on the listing patch. ABSENT from the list response, which returns servers without their tools. |
upstream_url | string | yes | — |
Example response
{
"id": "obj_0000000000000000",
"project_id": "prj_0000000000000000",
"slug": "example",
"name": "Example",
"description": "string",
"overview_md": "string",
"upstream_url": "https://example.com/hook",
"environment": "live",
"payto_kind": "provisioned",
"payto_address": "string",
"platform_fee_bps": 0,
"tool_count": 1,
"active": true,
"gateway_url": "https://example.com/hook",
"tools": [
{
"id": "obj_0000000000000000",
"tool_name": "Example",
"description": "string",
"pricing_model": "string",
"price": "string",
"price_atomic": "string",
"active": true
}
],
"created_at": "2026-01-15T12:00:00.000Z"
}Example request
curl -X PATCH https://api.codespar.dev/v1/mcp-servers/{id} \
-H "Authorization: Bearer $CODESPAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Example",
"description": "string",
"overview_md": "string",
"category": "string",
"active": true
}'DELETE /v1/mcp-servers/{id}
Delete an MCP server and its priced tools
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | yes | — |
Responses
| Status | Body | Description |
|---|---|---|
204 | — | No Content |
403 | object | Forbidden. The operation requires the admin role in the organization, resolved from the acting user forwarded in x-codespar-user. Known values of error: insufficient_role, bearer_admin_role_missing, bearer_admin_user_not_member, bearer_admin_role_unresolved. The same status and body shape also carry the scope gate's refusals, which reach every route in this subtree including the two reads: forbidden when the credential lacks the scope the route is mapped to, and the two alarms scopes_unresolved and route_scope_unresolved. |
404 | object | No such server in this organization and project. |
Example request
curl -X DELETE https://api.codespar.dev/v1/mcp-servers/{id} \
-H "Authorization: Bearer $CODESPAR_API_KEY"PATCH /v1/mcp-servers/{id}/tools/{tool}
Reprice one tool, or turn it off
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | yes | — |
tool | string | yes | — |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
active | boolean | no | — |
price | string | no | — |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | OK |
400 | object | The body failed the schema, was an empty patch, or carried a price that is not a positive six-decimal USDC amount. |
403 | object | Forbidden. The operation requires the admin role in the organization, resolved from the acting user forwarded in x-codespar-user. Known values of error: insufficient_role, bearer_admin_role_missing, bearer_admin_user_not_member, bearer_admin_role_unresolved. The same status and body shape also carry the scope gate's refusals, which reach every route in this subtree including the two reads: forbidden when the credential lacks the scope the route is mapped to, and the two alarms scopes_unresolved and route_scope_unresolved. |
404 | object | No tool by that name on a server this organization and project owns. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
active | boolean | yes | An inactive tool stays listed and stays priced. |
description | string | yes | Empty string when none was supplied. |
id | string | yes | mct_ followed by a nanoid. |
input_schema | — | no | The tool's argument JSON Schema, stored as it was received from the upstream's tools/list or from the create body. \{\} when none was supplied. |
price | string | yes | The per-call price rendered as a trimmed USDC decimal string, derived from price_atomic. |
price_atomic | string | yes | The authoritative per-call price, in USDC atomic units (six decimals), as an integer string. price is a rendering of this value; charge decisions should read this one. |
pricing_model | string | yes | Only flat is written today. The column is a free string with no CHECK constraint, so read it as open rather than as a closed enum. |
tool_name | string | yes | The MCP tool name. Unique within one server, and the key the tool patch addresses. |
Example response
{
"id": "obj_0000000000000000",
"tool_name": "Example",
"description": "string",
"pricing_model": "string",
"price": "string",
"price_atomic": "string",
"active": true
}Example request
curl -X PATCH https://api.codespar.dev/v1/mcp-servers/{id}/tools/{tool} \
-H "Authorization: Bearer $CODESPAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"price": "string",
"active": true
}'