Speak MCP to Pixel's tools
const url = 'https://api.pixonaut.app/v1/mcp';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"id":1,"jsonrpc":"2.0","method":"tools/list"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.pixonaut.app/v1/mcp \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "id": 1, "jsonrpc": "2.0", "method": "tools/list" }'Operation ID: mcp.request
A stateless JSON-RPC MCP server (protocol versions 2025-11-25, 2025-06-18 and 2025-03-26) over POST alone: initialize, ping, tools/list, tools/call and notifications/cancelled. A connected store’s member key acts as the member its user linked, exactly as an MCP key acts as the member who minted it: tools/list is the tools that member’s MCP key would get, and each tools/call runs the tool’s route as the member, judged by their grants, the workspace’s features and its plan. A tool the member may not use answers result.isError: true with the route’s reason; an unknown tool is JSON-RPC error -32602. There are no confirm cards: a destructive tool says so in annotations.destructiveHint, and a template change that needs an author’s confirmation is refused in isError. The workspace must have mcp. The store’s own integration key is refused member_link_required.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”Responses
Section titled “Responses”The JSON-RPC answer to one request
object
Examples
Example
{ "id": 1, "jsonrpc": "2.0", "result": { "tools": [ { "annotations": { "destructiveHint": false, "readOnlyHint": true }, "description": "List the workspace's inks.", "inputSchema": { "properties": {}, "type": "object" }, "name": "list_inks" } ] }}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
A notification, acknowledged
Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
A body that is not JSON, or a protocol version this server does not speak, answered as a JSON-RPC error object
Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: unauthorized, member_link_required, member_link_revoked
object
Examples
member_link_required
{ "error": "member_link_required"}member_link_revoked
{ "error": "member_link_revoked"}unauthorized
{ "error": "unauthorized"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: origin_forbidden, forbidden, feature_disabled, workspace_suspended
object
The feature the tenant does not have. Always sent with feature_disabled.
Examples
feature_disabled
{ "error": "feature_disabled", "feature": "api"}forbidden
{ "error": "forbidden"}origin_forbidden
{ "error": "origin_forbidden"}workspace_suspended
{ "error": "workspace_suspended"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: payload_too_large
object
Always sent with payload_too_large.
Examples
payload_too_large
{ "error": "payload_too_large", "maxBytes": 0}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: rate_limited
object
Examples
rate_limited
{ "error": "rate_limited"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Refused: db_error. A request that failed unexpectedly answers as text instead.
object
Examples
db_error
{ "error": "db_error"}Headers
Section titled “Headers”Every response names the request it answers in X-Request-Id: the id the request was sent with in that header, when it is well formed, else one the API gave it. Quote it when reporting a refusal or a failure: the API’s log lines for that request carry it.
Questions? Write to [email protected].