MCP server
wickworks serves a Model Context Protocol server in the same process as the REST API, at /mcp on the same port. An agent can compute indicators over JSON-RPC without a REST client. There is nothing to enable; the endpoint is always there.
The server uses the streamable HTTP transport in stateless mode with JSON responses. Every call stands alone: no initialize handshake is required, no session is kept, and responses are plain JSON instead of an SSE stream. Both /mcp and /mcp/ work.
Tools
| Tool | Arguments | Returns |
|---|---|---|
health | none | { ok, version }, the same as GET /health |
list_indicators | none | { indicators: [...] }, every type compute accepts, sorted |
metadata | none | The output catalog, the same as GET /metadata |
compute | bars, indicators, timeframe (optional), symbol (optional) | The same envelope as POST / |
compute validates its arguments with the same model as the REST endpoint, so the request rules and the indicator specs are identical. The result is the same camelCase JSON the REST API returns for the same input.
Connect a client
Clients that support remote streamable-HTTP servers connect straight to the endpoint. Claude Code:
claude mcp add --transport http wickworks http://localhost:8000/mcp
For a client that only starts local stdio servers, the @psyb0t/wickworks plugin bridges stdio to /mcp/.
Raw JSON-RPC
Because the server is stateless, you can call a tool with a single POST:
curl -s http://localhost:8000/mcp/ \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "health",
"arguments": {}
}
}'
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\n \"ok\": true,\n \"version\": \"0.7.1\"\n}"
}
],
"structuredContent": {
"ok": true,
"version": "0.7.1"
},
"isError": false
}
}
The Accept header above is what the streamable HTTP specification asks clients to send. The server answers with JSON either way. A compute call carries the bars and indicators in arguments:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "compute",
"arguments": {
"symbol": "EURUSD",
"timeframe": "H1",
"bars": [
{
"time": 1700000000,
"open": 1.0832,
"high": 1.0851,
"low": 1.0828,
"close": 1.0844,
"volume": 1247
}
],
"indicators": {
"rsi": true
}
}
}
}
Errors
Tool failures do not use HTTP status codes. The JSON-RPC call succeeds and the result has isError: true with the message as text:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Error executing tool compute: insufficient_bars: insufficient bars: have 1, but: rsi (type=rsi) needs 15 (available=1, deficits=[{'outputKey': 'rsi', 'type': 'rsi', 'required': 15, 'available': 1}])"
}
],
"isError": true
}
}
The messages match the REST errors: empty bars or indicators, too many bars (too many bars: N > MAX_BARS=5000), invalid request: ... with the validation details where REST would answer 422, unknown indicator types and parameters, and insufficient bars. The troubleshooting page lists them.
Access control
The MCP endpoint has no authentication, like the rest of wickworks. The MCP SDK’s DNS-rebinding protection, which only accepts an allowlist of Host headers, is turned off so the endpoint works behind any hostname or reverse proxy. Put access control in the proxy; see Security.