API key on watch tools
POST /mcp
JSON-RPC MCP endpoint for device search and watches. One HTTP request, one JSON response. Not a stdio process.
Endpoint: POST https://udiwatch.com/mcp. JSON-RPC 2.0. Protocol version 2024-11-05. Server name udiwatch, version 1.0.0.
This is one HTTP request and one JSON response. It is not a stdio process, and it does not open an SSE stream or issue an MCP session id. Put the API key on the HTTP request. It is not a tool argument.
{
"mcpServers": {
"udiwatch": {
"type": "http",
"url": "https://udiwatch.com/mcp",
"headers": {"X-API-Key": "uw_…"}
}
}
}
Handshake
curl -sS -X POST "$BASE/mcp" \
-H 'Content-Type: application/json' \
-H "X-API-Key: $UW_KEY" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"example","version":"0"}}}'
Then notifications/initialized and tools/list. ping returns an empty result. An unknown method is -32601. A body that is not an object is -32600. HTTP status is still 200. A batch is an array of at most 20 messages.
Calling a tool
curl -sS -X POST "$BASE/mcp" \
-H 'Content-Type: application/json' \
-H "X-API-Key: $UW_KEY" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_device","arguments":{"udi":"16977660098955"}}}'
The tool payload is a JSON string inside result.content[0].text. Parse it. result.isError is true when that payload has an error field. HTTP 200 does not mean the tool succeeded. HTTP 401 is reserved for the REST routes. HTTP 429 is returned before any tool runs. Limit: 60 calls per IP per minute.
Tools
| Tool | Auth | Arguments | Text payload |
|---|---|---|---|
| search_devices | No | q required, limit optional | Same as GET /v1/search |
| lookup_udi | No | udi required | Same as GET /v1/devices/{udi} |
| get_device | No | udi required | Same record as lookup_udi |
| get_actor | No | srn required | Same as GET /v1/actors/{srn} |
| list_watches | Key or session | none | {"watches":[…]} |
| add_watch | Active account | subject required | {"watch":{…},"error":null} |
| sync_watches | Active account | none | Same as POST /v1/sync |
| list_changes | Active account | none | {"events":[…]}, newest 50 |
Unknown tool name: text {"error":"Unknown tool."} and isError: true. Each tool has its own page.

UdiWatch