API and MCP
The gateway is https://casefork-gateway.samudrala153.workers.dev. The Salesforce package calls callout:Casefork_Gateway/v1/decide. A headless caller can use the same decide path over MCP. Both use the Casefork token for that org. A missing or unknown token is HTTP 401.
The response keys are choice, confidence, probabilities, request_id, and other_label. Provider and cost are not in the response. Any other top-level field on the request is rejected.
POST /v1/decide
Section titled “POST /v1/decide”Send Authorization: Bearer with the Casefork token, and header X-Casefork-Org-Id with the 18-character org id. The org id on the header must be the org stored for that token.
Authorization: Bearer <Casefork token>X-Casefork-Org-Id: <18-character org id>Example request:
{ "subject": "Invoice", "description": "Charged twice", "queues": [{ "api_name": "Billing", "description": "Invoices and payments" }], "other_label": "None of the named queues."}exemplars is optional. Each exemplar has subject, description, and choice. Lines after a prior-examples block in description must be exemplar lines (- queue=).
Example response:
{ "choice": "Billing", "confidence": 0.91, "probabilities": { "Billing": 0.91 }, "request_id": "6f1c0b3e-1a2b-4c5d-8e9f-0123456789ab", "other_label": "None of the named queues."}When the call cannot be completed, the HTTP body is fail_closed and a request id, and the status is not 200. Salesforce then holds the Case for review.
{ "error": "fail_closed", "request_id": "6f1c0b3e-1a2b-4c5d-8e9f-0123456789ab" }POST /mcp
Section titled “POST /mcp”POST https://casefork-gateway.samudrala153.workers.dev/mcp speaks MCP over Streamable HTTP. Each body is one JSON-RPC 2.0 request. The response is application/json. There is no SSE stream and no session.
The auth header is the Casefork token already used by POST /v1/decide:
Authorization: Bearer <Casefork token>The org id is the org stored for that token. Do not put an org id in the tool arguments. A missing or unknown token is HTTP 401, before any JSON-RPC handling. The only tool is casefork.decide. tools/call runs the same decide path as POST /v1/decide. A JSON-RPC array is rejected.
Example tools/call:
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "casefork.decide", "arguments": { "subject": "Invoice", "description": "Charged twice", "queues": [{ "api_name": "Billing", "description": "Invoices and payments" }], "other_label": "None of the named queues." } }}Example response:
{ "jsonrpc": "2.0", "id": 1, "result": { "content": [ { "type": "text", "text": "{\"choice\":\"Billing\",\"confidence\":0.91,\"probabilities\":{\"Billing\":0.91},\"request_id\":\"6f1c0b3e-1a2b-4c5d-8e9f-0123456789ab\",\"other_label\":\"None of the named queues.\"}" } ], "structuredContent": { "choice": "Billing", "confidence": 0.91, "probabilities": { "Billing": 0.91 }, "request_id": "6f1c0b3e-1a2b-4c5d-8e9f-0123456789ab", "other_label": "None of the named queues." }, "isError": false }}The text item and structuredContent carry the same five keys as POST /v1/decide.
When the decide path fails closed, the tool result has choice fail_closed and is not a JSON-RPC error. isError stays false.
{ "choice": "fail_closed", "confidence": 0, "probabilities": {}, "request_id": "6f1c0b3e-1a2b-4c5d-8e9f-0123456789ab", "other_label": "None of the named queues."}What is stored from either call is in Security and data.