Protocol Specification
NDP has four conceptual layers. They are loosely coupled, so changes to one layer do not require changes to the layers above it.
Protocol Layers
MCP Protocol
Layer 4JSON-RPC 2.0 -- initialize, tools/list, tools/call
NDP Auth
Layer 3HMAC-SHA256 challenge-response handshake
NDP Discovery
Layer 2UDP broadcast (Node.js) or mDNS/Zeroconf (Python)
Transport
Layer 1TCP with ndjson framing
Discovery Manifest
Node.js providers broadcast this JSON payload via UDP every 10 seconds. Python providers register via mDNS/Zeroconf. Both approaches are interoperable. The Python caller listens for both UDP broadcasts and mDNS services.
{
"protocol": "ndp",
"version": "0.1.0",
"agentId": "mcp-math-server",
"role": "provider",
"dataPort": 41235,
"ip": "192.168.1.100",
"mcp_url": "http://192.168.1.100:41235",
"tools": [
{
"name": "add",
"description": "Sums two numbers",
"args": ["a", "b"]
}
],
"timestamp": 1711843200000,
"signature": "hmac-sha256 (optional, if manifestSecret is set)"
}Authentication Handshake
Three-step HMAC-SHA256 challenge-response. Each connection authenticates independently. Servers can use a shared secret or per-agent capability tokens for scoped access.
auth-challenge { nonce: "a7f3..." }auth-response { proof: HMAC(nonce, secret) }auth-okMCP Messages (JSON-RPC 2.0)
Standard MCP JSON-RPC 2.0 messages. NDP does not modify or wrap these. The same protocol that runs over stdio or HTTP runs over NDP connections. Agents need the NDP client library for discovery and auth, but the MCP calls themselves are standard.
initialize
{
"jsonrpc": "2.0",
"id": "uuid",
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"clientInfo": { "name": "claude-agent-01" },
"capabilities": {}
}
}{
"jsonrpc": "2.0",
"id": "uuid",
"result": {
"protocolVersion": "2025-03-26",
"serverInfo": { "name": "mcp-math-server", "version": "0.1.0" },
"capabilities": { "tools": { "listChanged": false } }
}
}tools/list
{
"jsonrpc": "2.0",
"id": "uuid",
"result": {
"tools": [
{
"name": "add",
"description": "Sums two numbers",
"inputSchema": {
"type": "object",
"properties": {
"a": { "type": "number" },
"b": { "type": "number" }
},
"required": ["a", "b"]
}
}
]
}
}tools/call
{
"jsonrpc": "2.0",
"id": "uuid",
"method": "tools/call",
"params": {
"name": "add",
"arguments": { "a": 15, "b": 27 }
}
}{
"jsonrpc": "2.0",
"id": "uuid",
"result": {
"content": [{ "type": "text", "text": "42" }]
}
}