tools/call
Invoke one namespaced CoreSpeed tool and read its result or isError payload.
https://api.corespeed.io/mcptools/callHolds, suspensions, and API-key spend caps are checked before a metered tool
executes. Those refusals arrive as tool-level errors inside HTTP 200, not as
HTTP failures — see Errors.
Authorizations
AuthorizationstringheaderrequiredBearer <token>— an MCP OAuth token, ask-cs-…API key, or a user session JWT.x-api-key: <sk-cs-…>is accepted in its place.Acceptstringheaderrequiredapplication/json, text/event-stream— the Streamable HTTP transport requires both media types even though CoreSpeed answers with JSON.Content-Typestringheaderrequiredapplication/json. The transport rejects anything else with415.
Request
params.namestringrequiredA name returned by
tools/list, e.g.memory__remember. An unknown or disabled name is not a transport error: it comes back as HTTP200withresult.isError: trueand the textTool <name> not found. Nothing about a misspelled tool name shows up in the HTTP status.params.argumentsobjectoptionalArguments matching that tool's
inputSchema. Optional in the MCP request schema — omit it for a tool that takes none, rather than sending{}— but required in practice for every tool whoseinputSchemahas required properties. Schema violations come back as a tool-level error, not a transport error.
Response fields
result.contentarrayrequiredContent blocks. Text tools return
{ "type": "text", "text": "…" }; media tools return signed artifact URLs.result.isErrorbooleanoptionaltruewhen the tool refused or failed. The HTTP status is still200, so branch on this field before treating a call as successful.
Most manage__* tools (API keys, connected accounts, whoami) require a
human session. Called with an API key through /mcp they return HTTP 200
with isError: true and code jwt_session_required. The remote-connector
lifecycle tools (manage__remote_add, manage__remote_list,
manage__remote_refresh, manage__remote_remove) accept API keys, subject to
their own role checks.
curl https://api.corespeed.io/mcp \
-H "Authorization: Bearer $CORESPEED_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "memory__remember",
"arguments": {
"memory": "Rollout changes require a two-day review window.",
"scope": "shared"
}
}
}'const res = await fetch("https://api.corespeed.io/mcp", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CORESPEED_API_KEY}`,
"Content-Type": "application/json",
Accept: "application/json, text/event-stream",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 3,
method: "tools/call",
params: {
name: "memory__remember",
arguments: {
memory: "Rollout changes require a two-day review window.",
scope: "shared",
},
},
}),
});
const { result } = await res.json();
if (result.isError) throw new Error(result.content[0].text);import os
import httpx
res = httpx.post(
"https://api.corespeed.io/mcp",
headers={
"Authorization": f"Bearer {os.environ['CORESPEED_API_KEY']}",
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream",
},
json={
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "memory__remember",
"arguments": {
"memory": "Rollout changes require a two-day review window.",
"scope": "shared",
},
},
},
)
result = res.json()["result"]
if result.get("isError"):
raise RuntimeError(result["content"][0]["text"])package main
import (
"bytes"
"encoding/json"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]any{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": map[string]any{
"name": "memory__remember",
"arguments": map[string]any{
"memory": "Rollout changes require a two-day review window.",
"scope": "shared",
},
},
})
req, _ := http.NewRequest("POST", "https://api.corespeed.io/mcp", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("CORESPEED_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json, text/event-stream")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var out struct {
Result struct {
Content []struct {
Text string `json:"text"`
} `json:"content"`
IsError bool `json:"isError"`
} `json:"result"`
}
json.NewDecoder(res.Body).Decode(&out)
if out.Result.IsError {
panic(out.Result.Content[0].Text)
}
}{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Memory saved."
}
],
"structuredContent": {
"id": "mem_01J…",
"memory": "Rollout changes require a two-day review window."
}
}
}{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "{\"error\":{\"type\":\"forbidden\",\"message\":\"This operation requires a human session, not an API key.\",\"code\":\"jwt_session_required\"}}"
}
],
"isError": true
}
}