Docs Guides

Call it from code

Use the endpoint from a script: plain HTTP, or an MCP SDK in TypeScript or Python.

The endpoint is ordinary HTTPS. It speaks JSON-RPC 2.0 as MCP defines it, over the Streamable HTTP transport, and keeps no session: every POST stands on its own and carries your API key. You can use an MCP SDK, or send the requests yourself.

The request

  • POST https://app.soontra.com/api/mcp. Other methods get 405.
  • Authorization: Bearer <your key>
  • Content-Type: application/json
  • Accept: application/json, text/event-stream. The transport lets a server answer either way, so a client must accept both.

List the tools

Terminal
curl -s https://app.soontra.com/api/mcp \
  -H "Authorization: Bearer $SOONTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
  | sed -n 's/^data: //p'

Call a tool

Terminal
curl -s https://app.soontra.com/api/mcp \
  -H "Authorization: Bearer $SOONTRA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "soontra_projects_list",
      "arguments": { "limit": 5 }
    }
  }' \
  | sed -n 's/^data: //p'

Reading the answer

A tool’s result is an MCP result whose first content item is text holding JSON. Parse that text to get the data.

Response
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"projects\":[...],\"count\":5,\"_notice\":\"...\"}"
      }
    ]
  }
}
  • If result.isError is true, the text holds {"error": "..."} instead. See Errors.
  • Soontra answers as an event stream (text/event-stream) with one message event: the JSON-RPC message is its data: line, which is what the sed in the curl examples prints. The SDKs read it for you.
  • Ignore _notice in your own code. It is there for language models.

Good habits

  • Call soontra_workspace_getContext once at the start to confirm which workspace and scopes the key has.
  • Send an idempotency_key with every write, so a retry after a timeout cannot write twice.
  • On a rate-limit error, wait the retry_after_seconds it gives. See Limits.
  • Keep the key in an environment variable or a secret store, never in the script.
  • To follow what changes in a workspace, poll soontra_workspace_changes with the next_cursor from the last call. There are no webhooks.