Json Rpc Routing

Routes JSON-RPC 2.0 requests to different backends based on the “method” field in the JSON request body

Category: Setup-dependent integration
Task: Routes JSON-RPC 2.0 requests to different backends based on the “method” field in the JSON request body

Prerequisites: The external service, credentials, or certificates referenced by this configuration.

Run it: Use ghcr.io/praxis-proxy/ai:0.4.1 and follow the container quickstart to mount and start the configuration.

This configuration comes from the selected release. The example has not been run here; external services are not bundled.

Download the source file.

# JSON-RPC 2.0 Method-Based Routing
#
# Routes JSON-RPC 2.0 requests to different backends based on the
# "method" field in the JSON request body. Uses the json_rpc
# filter to extract the method name into an X-Json-Rpc-Method header,
# then the router matches on that header to select the correct cluster.
#
# Supports both MCP (Model Context Protocol) and A2A (Agent-to-Agent)
# protocol routing by JSON-RPC method name.
#
# Example MCP request:
#
#   curl -X POST http://localhost:8080/mcp/ \
#     -H "Content-Type: application/json" \
#     -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "calculator", "arguments": {"operation": "add", "a": 5, "b": 3}}}'
#
# This request is routed to the mcp-tools cluster. A request with
# "method": "tools/list" goes to the mcp-discovery cluster.
#
# Example A2A request:
#
#   curl -X POST http://localhost:8080/a2a/ \
#     -H "Content-Type: application/json" \
#     -d '{"jsonrpc": "2.0", "id": "msg-123", "method": "SendMessage", "params": {"recipient": "agent-42", "content": "Hello"}}'
#
# This request is routed to the a2a-send cluster.

listeners:
  - name: json-rpc-gateway
    address: "0.0.0.0:8080"
    filter_chains:
      - extract-json-rpc
      - routing

filter_chains:
  - name: extract-json-rpc
    filters:
      - filter: json_rpc
        max_body_bytes: 1048576
        batch_policy: reject
        on_invalid: continue
        headers:
          method: X-Json-Rpc-Method
          id: X-Json-Rpc-Id
          kind: X-Json-Rpc-Kind

  - name: routing
    filters:
      - filter: router
        routes:
          # MCP tool operations
          - path_prefix: "/mcp/"
            headers:
              x-json-rpc-method: "tools/call"
            cluster: mcp-tools
          - path_prefix: "/mcp/"
            headers:
              x-json-rpc-method: "tools/list"
            cluster: mcp-discovery
          - path_prefix: "/mcp/"
            headers:
              x-json-rpc-method: "notifications/tools/list_changed"
            cluster: mcp-discovery

          # A2A messaging operations
          - path_prefix: "/a2a/"
            headers:
              x-json-rpc-method: "SendMessage"
            cluster: a2a-send
          - path_prefix: "/a2a/"
            headers:
              x-json-rpc-method: "SendStreamingMessage"
            cluster: a2a-send
          - path_prefix: "/a2a/"
            headers:
              x-json-rpc-method: "GetTask"
            cluster: a2a-tasks
          - path_prefix: "/a2a/"
            headers:
              x-json-rpc-method: "ListTasks"
            cluster: a2a-tasks
          - path_prefix: "/a2a/"
            headers:
              x-json-rpc-method: "CancelTask"
            cluster: a2a-tasks

          # Default route for unknown methods or non-JSON-RPC traffic
          - path_prefix: "/"
            cluster: default

      - filter: load_balancer
        clusters:
          - name: mcp-tools
            endpoints:
              - "127.0.0.1:9001"
              - "127.0.0.1:9002"
          - name: mcp-discovery
            endpoints:
              - "127.0.0.1:9101"
          - name: a2a-send
            endpoints:
              - "127.0.0.1:9201"
              - "127.0.0.1:9202"
          - name: a2a-tasks
            endpoints:
              - "127.0.0.1:9301"
          - name: default
            endpoints:
              - "127.0.0.1:9000"

insecure_options:
  allow_private_endpoints: true # example proxies to local backends