MCP server in TestO
TestO can expose its ECU/diagnostic functionality over the Model Context Protocol (MCP) so external AI clients (Claude Desktop, Cursor, mcp-cli, custom scripts) can drive TestO using your own AI subscription. Unlike the built-in AI chat, MCP doesn't require an API key — the user's MCP client uses their existing Claude Pro / ChatGPT Plus / local model.
Enabling the server
Edit testo.ini (next to testo.exe) and add:
[mcp]
enabled=true
bindHost=127.0.0.1
httpPort=13721
endpointPath=/mcp
bearerToken=
Restart TestO. On startup you'll see in the log:
[McpHttpTransport] listening at http://127.0.0.1:13721/mcp
Defaults are safe: bound to localhost, no auth required because nothing
off-machine can reach it. If you need LAN access set bindHost=0.0.0.0
and put a non-empty bearerToken in (otherwise any host on the network
could drive your car).
Quick health probe:
curl http://127.0.0.1:13721/health
# -> ok
Connecting Claude Desktop
Edit %APPDATA%\Claude\claude_desktop_config.json (Windows) or the equivalent
on your platform. Add:
{
"mcpServers": {
"testo": {
"transport": {
"type": "http",
"url": "http://127.0.0.1:13721/mcp"
}
}
}
}
Restart Claude Desktop. TestO's tools appear under the tools menu (the small
hammer icon). Tools prefixed testo_* come from this server.
Connecting Cursor
~/.cursor/mcp.json:
{
"mcpServers": {
"testo": {
"url": "http://127.0.0.1:13721/mcp"
}
}
}
Connecting from a script (mcp-cli, custom Python, etc.)
The endpoint accepts standard JSON-RPC 2.0 POSTs. Example with curl:
# 1. initialize handshake
curl -s -X POST http://127.0.0.1:13721/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
# 2. list tools
curl -s -X POST http://127.0.0.1:13721/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
# 3. call one
curl -s -X POST http://127.0.0.1:13721/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"testo_list_jobs","arguments":{"ecu":"MSD80"}}}'
Available tools
The current toolset:
| Tool | Safety | Description |
|---|---|---|
testo_get_loaded_dll |
read | Inspect the loaded EDIABAS api64.dll (path, version, implementation) |
testo_get_ediabas_config |
read | Full EDIABAS config: DLL identity + active Interface, port, ECU path, ini file paths |
testo_api_state |
read | EDIABAS API state and last error |
testo_list_ecus |
read | List all ECU (.prg) files available; optional name filter |
testo_list_jobs |
read | All jobs on an ECU |
testo_describe_job |
read | Arguments, result fields, description for one job |
testo_search_jobs |
read | Fuzzy search across an ECU's jobs |
testo_list_sessions |
read | List logged sessions for an ECU/job |
testo_get_session |
read | Time-series samples from a session |
testo_run_job |
vehicle | Execute one job (talks to vehicle) |
testo_read_fault_codes |
vehicle | Read DTCs |
testo_clear_fault_codes |
dangerous | Clear DTCs (modifies ECU state) |
testo_run_script |
write | Execute arbitrary JS in TestO's scripting context |
Each tool advertises its safety and readOnlyHint / destructiveHint
annotations. Well-behaved MCP clients (Claude Desktop) prompt the user before
invoking vehicle or dangerous tools.
Example conversation
In Claude Desktop with the TestO MCP server connected:
User: My MSD80 is throwing a P0420. Pull recent O2 sensor data and tell me what's wrong.
Claude: [calls testo_search_jobs ecu=MSD80 keyword=lambda] [calls testo_run_job ecu=MSD80 job=STATUS_MESSWERTBLOCK_LESEN params={MESSWERTBLOCK:"LAMBDA"}] [calls testo_get_session ecu=MSD80 job=LAMBDA_VOR_KAT limit=200]
Looking at the last 200 samples, your pre-cat lambda is swinging normally around 1.0 (0.95–1.05) but the post-cat sensor is also swinging — it should be stable around 0.8–0.9 if the cat is healthy. Combined with the P0420, this points to a degraded catalyst rather than an O2-sensor issue.
The model used your Claude Pro subscription; TestO billed nothing.
Security notes
- Localhost-only by default. Don't change
bindHostunless you understand the implication. - No auth by default. Fine on localhost (only processes you ran can talk to it). Required if you bind to LAN.
- MCP tool calls run synchronously on the GUI thread. A long-running tool will freeze the UI until it returns. This is intentional for v1 — async streaming via SSE is a future feature.
- No rate limiting. A misbehaving client can spam the server. Not a problem in practice for the localhost-only setup; would matter for LAN/internet exposure.