Summary
openclaw_chat tool returns 400 Bad Request when called through the MCP bridge. The gateway is healthy, openclaw_instances and openclaw_status work correctly — only openclaw_chat fails.
Environment
| Component |
Version |
| openclaw-mcp |
v1.3.0 (ghcr.io/freema/openclaw-mcp:latest) |
| OpenClaw gateway |
2026.3.24 (cff6dc9) |
| Ollama |
0.18.3 |
| Model |
ollama/qwen2.5:14b (14B, 9.0 GB) |
| Platform |
macOS Darwin x86_64 |
| Client |
Claude Code v2.1.85 (MCP over streamable HTTP) |
Gateway config (openclaw.json)
chatCompletions endpoint is enabled:
{
"gateway": {
"port": 18789,
"mode": "local",
"bind": "loopback",
"auth": { "mode": "token", "token": "REDACTED" },
"http": {
"endpoints": {
"chatCompletions": { "enabled": true }
}
}
}
}
docker-compose.yml
services:
mcp-bridge:
image: ghcr.io/freema/openclaw-mcp:latest
container_name: openclaw-mcp
environment:
- OPENCLAW_URL=http://host.docker.internal:18789
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
- AUTH_ENABLED=true
- MCP_CLIENT_ID=openclaw
- MCP_CLIENT_SECRET=${MCP_CLIENT_SECRET}
- CORS_ORIGINS=https://claude.ai
- DEBUG=true
extra_hosts:
- "host.docker.internal:host-gateway"
Steps to reproduce
- Start OpenClaw gateway with Ollama/Qwen backend and chatCompletions.enabled: true
- Start MCP bridge via Docker (config above)
- Connect Claude Code: claude mcp add --transport http --client-id openclaw --client-secret openclaw http://localhost:3000/mcp
- Call openclaw_chat with any message
What happens
openclaw_chat(message: "What's your opinion on Pokemon?")
-> Error: API request failed: 400 Bad Request
openclaw_chat(instance: "default", message: "...", session_id: "test")
-> Error: API request failed: 400 Bad Request
openclaw_instances and openclaw_status work correctly — only openclaw_chat fails.
What we know
-
Gateway is healthy: /health returns {"ok":true,"status":"live"}
-
MCP bridge connects and can list instances
-
The chat completions endpoint is enabled in gateway config
-
Direct curl to the gateway works fine:
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"model":"openclaw","messages":[{"role":"user","content":"hi"}]}' \
http://localhost:18789/v1/chat/completions
# -> 200 OK, returns valid chat completion response
-
The 400 has no detail in bridge logs even with DEBUG=true
What we don't know
We cannot see the actual request the bridge sends to the gateway, so we don't know what's causing the 400. Possible causes:
- Incorrect model name in the request body (gateway requires "openclaw" or "openclaw/agentId")
- Different endpoint path
- Missing or malformed headers
- Auth token not forwarded correctly
- Request body format mismatch
Request
- Could DEBUG=true log the outgoing request body and the full 400 response body? That would make this trivially diagnosable.
- Any known compatibility requirements between bridge v1.3.0 and specific OpenClaw gateway versions?
- Any additional gateway config needed beyond chatCompletions.enabled: true?
Summary
openclaw_chattool returns400 Bad Requestwhen called through the MCP bridge. The gateway is healthy,openclaw_instancesandopenclaw_statuswork correctly — onlyopenclaw_chatfails.Environment
Gateway config (openclaw.json)
chatCompletions endpoint is enabled:
docker-compose.yml
Steps to reproduce
What happens
openclaw_instances and openclaw_status work correctly — only openclaw_chat fails.
What we know
Gateway is healthy: /health returns {"ok":true,"status":"live"}
MCP bridge connects and can list instances
The chat completions endpoint is enabled in gateway config
Direct curl to the gateway works fine:
The 400 has no detail in bridge logs even with DEBUG=true
What we don't know
We cannot see the actual request the bridge sends to the gateway, so we don't know what's causing the 400. Possible causes:
Request