JSON-RPC Transport
Plain HTTP alternative to MCP
DataGrout exposes a JSON-RPC 2.0 endpoint alongside MCP. Same tools, same authentication, but over stateless HTTP POST — no handshake, no session. Ideal for scripts, serverless functions, workflow platforms, legacy systems, and anything that can make an HTTP request.
Endpoint
POST https://gateway.datagrout.ai/servers/{server_uuid}/rpc
Replace {server_uuid} with your server’s UUID, found on the server detail page.
Enabling JSON-RPC
A new server has only MCP switched on. Until JSON-RPC is enabled, every request to /rpc is answered — over HTTP 200 — with:
{
"jsonrpc": "2.0",
"error": { "code": -32600, "message": "JSON-RPC not enabled for this server" },
"id": 1
}
Turn it on in the server’s Interaction Settings, or from code:
POST https://gateway.datagrout.ai/servers/{server_uuid}/interaction/enable_protocol
curl -X POST https://gateway.datagrout.ai/servers/YOUR_UUID/interaction/enable_protocol \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"protocol": "jsonrpc"}'
Response:
{ "ok": true, "enabled_protocols": ["mcp", "jsonrpc"] }
- It takes the same authentication as
/rpc. - It is idempotent: enabling a protocol that is already on changes nothing and returns the current list.
- It only adds.
mcpis always enabled; switching a transport off is done in the dashboard. {"protocol": "ws"}enables the WebSocket transport the same way.- A missing
protocolreturns400with{"ok": false, "error": "missing required field: protocol"}; a setting that could not be saved returns422.
A client that meets the -32600 refusal can enable the transport itself and retry the request once.
Authentication
Pass the same credentials you’d use for MCP:
# Bearer token
curl -X POST https://gateway.datagrout.ai/servers/YOUR_UUID/rpc \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "tools.list", "params": {}, "id": 1}'
mTLS and OAuth 2.1 are also supported. See Authentication for details.
Request Format
All requests follow JSON-RPC 2.0:
{
"jsonrpc": "2.0",
"method": "METHOD_NAME",
"params": {},
"id": 1
}
Method names use dots — tools.list, tools.call, tools.get. The MCP spellings with a slash (tools/list, tools/call) are accepted too.
Methods
tools.list
List all available tools on the server:
curl -X POST https://gateway.datagrout.ai/servers/YOUR_UUID/rpc \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "tools.list", "params": {}, "id": 1}'
Response:
{
"jsonrpc": "2.0",
"result": {
"tools": [
{
"name": "salesforce@1/get_leads@1",
"description": "Retrieve leads from Salesforce CRM",
"inputSchema": { ... }
}
]
},
"id": 1
}
tools.call
Execute a specific tool:
curl -X POST https://gateway.datagrout.ai/servers/YOUR_UUID/rpc \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools.call",
"params": {
"name": "salesforce@1/get_leads@1",
"arguments": {"limit": 10}
},
"id": 2
}'
Response:
{
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": "{\"leads\": [...], \"_dg\": {...}}"
}
],
"structuredContent": {
"leads": [{ "Id": "00Q...", "Name": "Jane Doe" }],
"_dg": {
"tool": "salesforce@1/get_leads@1",
"execution_id": "exec_...",
"cache_ref": "rc_...",
"summary": "3 credits charged.",
"credits": { "charged": 3, "estimated": 3, "remaining": 997 }
}
},
"isError": false
},
"id": 2
}
structuredContent is the tool’s result as JSON. content[0].text carries the same result as a string, for clients that only read text.
The _dg receipt. By default DataGrout’s metadata for the call travels inside the result, under _dg: which tool ran, the execution id, a cache_ref for the full result, and the credits charged, estimated and remaining.
The _meta envelope. A server can also carry a fuller receipt in a top-level _meta.datagrout block — the receipt, the credit estimate and any certificate details. It is off by default; turn on Include full _meta.datagrout envelope in the server’s Interaction Settings. Both can be enabled together, and each has its own switch there.
tools.get
Fetch one tool’s definition by name:
curl -X POST https://gateway.datagrout.ai/servers/YOUR_UUID/rpc \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "tools.get", "params": {"name": "data-grout@1/discovery.summary@1"}, "id": 3}'
The result is the tool’s name, title, description, inputSchema and, where it has one, outputSchema.
Calling DataGrout’s own tools
You can call any tool this way, including DataGrout’s own discovery and planning tools:
curl -X POST https://gateway.datagrout.ai/servers/YOUR_UUID/rpc \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools.call",
"params": {
"name": "data-grout@1/discovery.discover@1",
"arguments": {"goal": "get leads from CRM"}
},
"id": 4
}'
Errors
A request that never reaches the JSON-RPC layer is answered with an HTTP status. The body is JSON, except for the 400:
| Status | Body | Meaning |
|---|---|---|
400 |
Bad Request |
The request body is not valid JSON |
401 |
{"error": {"code": 401, "message": "Authentication required"}} |
Credentials are missing or were rejected |
403 |
{"error": {"code": 403, "message": "..."}} |
An account problem that new credentials will not fix, such as an unverified email on the account that owns the server. The message says what to do. |
404 |
{"error": {"code": 404, "message": "Server not found"}} |
No server has that UUID |
Everything else is answered over HTTP 200 with a JSON-RPC error object:
| Code | Meaning |
|---|---|
-32600 |
Invalid request — a malformed envelope, or JSON-RPC is not enabled for this server |
-32601 |
Method not found, or a tool this server does not have or does not allow |
-32602 |
Invalid params — for example, name or arguments missing from tools.call |
-32603 |
The tool ran and failed. message is the tool’s own; data.detail carries its full text. |
-32002 |
Insufficient credits — the account’s balance cannot cover the call |
MCP vs JSON-RPC
| MCP | JSON-RPC (HTTP POST) | |
|---|---|---|
| Endpoint | /servers/{uuid}/mcp |
/servers/{uuid}/rpc |
| Session | Handshake and session | Stateless — one request per call |
| Streaming | Yes | No |
| Client complexity | Medium | Low (any HTTP client) |
| Best for | Interactive agents, long workflows | Scripts, cron, serverless, workflow platforms, legacy apps |
| Enabled on a new server | Always | Opt-in — see Enabling JSON-RPC |
Both endpoints serve the same tools and accept the same authentication. The Conduit SDK supports both transports.
WebSocket
The same JSON-RPC methods are also available over a WebSocket at wss://gateway.datagrout.ai/servers/{uuid}/ws, which adds event subscriptions. It is opt-in like /rpc: enable it with {"protocol": "ws"} (see Enabling JSON-RPC).
Legacy Systems
The JSON-RPC endpoint is the easiest integration path for systems that can’t add MCP. Any language or runtime that can make an HTTP POST can use DataGrout – COBOL, VBA, shell scripts, cron jobs, AWS Lambda, or internal tools.
Conduit SDK
For programmatic use, the Conduit SDK is preferred over raw HTTP. It handles authentication, retries, cost tracking, and transport selection:
from datagrout_conduit import ClientBuilder
client = ClientBuilder() \
.url("https://gateway.datagrout.ai/servers/YOUR_UUID/mcp") \
.auth_bearer("YOUR_TOKEN") \
.build()
tools = client.list_tools()
result = client.call_tool("salesforce@1/get_leads@1", {"limit": 10})
See Conduit SDK for full documentation.
Related
- Authentication – All supported auth methods
- Tools Reference – Available tools
- Quick Start – Get started with your first call