Skip to content

MCP Server API Reference

The MCP (Model Context Protocol) Server provides a JSON-RPC 2.0 interface for AI assistants and development tools to discover and execute Adaptive Sentience tools. It follows the Model Context Protocol specification.

Overview

The MCP Server enables:

  • Tool Discovery: AI assistants can query available tools with schemas
  • Tool Execution: Execute tools with automatic input validation
  • Execution Metadata: Track which nodes executed tools and verification status
  • Claude Desktop Integration: Direct integration with Claude Desktop and other MCP clients

Base URL

http://127.0.0.1:8787/mcp

The MCP endpoint is hosted on the same port as the HTTP Gateway (default: 8787).

Protocol

The MCP Server implements JSON-RPC 2.0 over HTTP POST. All requests and responses follow the JSON-RPC 2.0 specification.

Request Format

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "method_name",
  "params": {
    "param1": "value1"
  }
}

Response Format (Success)

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "data": "response_data"
  }
}

Response Format (Error)

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32600,
    "message": "Invalid Request"
  }
}

Error Codes

Standard JSON-RPC 2.0 error codes:

Code Message Meaning
-32700 Parse error Invalid JSON received
-32600 Invalid Request Request doesn't match JSON-RPC 2.0 spec
-32601 Method not found Requested method doesn't exist
-32602 Invalid params Invalid method parameters
-32603 Internal error Server-side error during execution

MCP Methods

1. Initialize

Initialize the MCP session and negotiate capabilities.

Method: initialize

Request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "clientInfo": {
      "name": "claude-desktop",
      "version": "1.0.0"
    },
    "capabilities": {}
  }
}

Parameters:

Field Type Required Description
protocolVersion string Yes MCP protocol version
clientInfo object Yes Client identification
clientInfo.name string Yes Client name
clientInfo.version string Yes Client version
capabilities object No Client capabilities

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": {
      "name": "dwo-gateway",
      "version": "1.0.0"
    },
    "capabilities": {
      "tools": {}
    }
  }
}

Result Fields:

Field Type Description
protocolVersion string Negotiated protocol version
serverInfo object Server identification
serverInfo.name string Server name ("dwo-gateway")
serverInfo.version string Server version
capabilities object Server capabilities
capabilities.tools object Tool execution capability (always present)

cURL Example:

curl -X POST http://127.0.0.1:8787/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2024-11-05",
      "clientInfo": {
        "name": "test-client",
        "version": "1.0.0"
      }
    }
  }'

Python Example:

import requests

response = requests.post(
    "http://127.0.0.1:8787/mcp",
    json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "initialize",
        "params": {
            "protocolVersion": "2024-11-05",
            "clientInfo": {
                "name": "python-client",
                "version": "1.0.0"
            }
        }
    }
)

result = response.json()
print(f"Server: {result['result']['serverInfo']['name']}")
print(f"Protocol: {result['result']['protocolVersion']}")

2. List Tools

Discover available tools with their schemas.

Method: tools/list

Request:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

Parameters:

No parameters required.

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "dwo.unit_convert",
        "description": "Convert between units (length, temperature, mass). Supports meters, feet, kilometers, miles, Celsius, Fahrenheit, kilograms, pounds.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "value": {
              "type": "number",
              "description": "Numeric value to convert"
            },
            "from_unit": {
              "type": "string",
              "description": "Source unit (e.g., 'km', 'mi', 'c', 'f', 'kg', 'lb')"
            },
            "to_unit": {
              "type": "string",
              "description": "Target unit (e.g., 'km', 'mi', 'c', 'f', 'kg', 'lb')"
            }
          },
          "required": ["value", "from_unit", "to_unit"],
          "additionalProperties": false
        }
      },
      {
        "name": "dwo.pii_redact",
        "description": "Redact PII (emails, phone numbers) from text using regex patterns. WARNING: Heuristic-based, not ML-grade detection.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "text": {
              "type": "string",
              "description": "Text to redact PII from"
            },
            "redact_emails": {
              "type": "boolean",
              "description": "Whether to redact email addresses",
              "default": true
            },
            "redact_phones": {
              "type": "boolean",
              "description": "Whether to redact phone numbers",
              "default": true
            },
            "replacement": {
              "type": "string",
              "description": "Replacement text for redacted content",
              "default": "[REDACTED]"
            }
          },
          "required": ["text"],
          "additionalProperties": false
        }
      },
      {
        "name": "dwo.jsonschema_validate",
        "description": "Validate data against a JSON Schema. Returns validation results with detailed error messages.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "schema": {
              "type": "object",
              "description": "JSON Schema to validate against"
            },
            "data": {
              "description": "Data to validate (any type)"
            }
          },
          "required": ["schema", "data"],
          "additionalProperties": false
        }
      },
      {
        "name": "dwo.doc_summarize",
        "description": "Create extractive summary of text using frequency-based sentence scoring. Simple heuristic approach.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "text": {
              "type": "string",
              "description": "Text to summarize"
            },
            "max_sentences": {
              "type": "integer",
              "description": "Maximum number of sentences in summary",
              "default": 3,
              "minimum": 1
            }
          },
          "required": ["text"],
          "additionalProperties": false
        }
      }
    ]
  }
}

Result Fields:

Field Type Description
tools array Array of tool definitions
tools[].name string Tool name (prefixed with "dwo.")
tools[].description string Human-readable description
tools[].inputSchema object JSON Schema for input validation

cURL Example:

curl -X POST http://127.0.0.1:8787/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/list",
    "params": {}
  }'

Python Example:

import requests

response = requests.post(
    "http://127.0.0.1:8787/mcp",
    json={
        "jsonrpc": "2.0",
        "id": 2,
        "method": "tools/list",
        "params": {}
    }
)

result = response.json()
tools = result["result"]["tools"]

print(f"Available tools: {len(tools)}")
for tool in tools:
    print(f"  - {tool['name']}: {tool['description']}")

3. Call Tool

Execute a tool with automatic input validation.

Method: tools/call

Request:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "dwo.unit_convert",
    "arguments": {
      "value": 100,
      "from_unit": "celsius",
      "to_unit": "fahrenheit"
    }
  }
}

Parameters:

Field Type Required Description
name string Yes Tool name (with or without "dwo." prefix)
arguments object Yes Tool-specific arguments (validated against inputSchema)

Response (Success):

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"value\": 212.0,\n  \"from_unit\": \"celsius\",\n  \"to_unit\": \"fahrenheit\"\n}"
      }
    ],
    "isError": false,
    "_meta": {
      "trace_id": "trace_abc123",
      "tool_name": "unit_convert",
      "tool_version": "1.0.0",
      "execution_path": ["local"],
      "verified": false,
      "degraded": false,
      "node_id": "gateway_local",
      "latency_ms": 5,
      "timestamp": "2026-01-24T12:00:00Z"
    }
  }
}

Result Fields:

Field Type Description
content array Array of content items (MCP standard)
content[].type string Content type (always "text")
content[].text string JSON-formatted tool result
isError boolean Whether execution failed
_meta object Execution metadata (Adaptive Sentience extension)
_meta.trace_id string Unique trace ID for request
_meta.tool_name string Tool name executed
_meta.tool_version string Tool version
_meta.execution_path array Execution path (nodes involved)
_meta.verified boolean Whether response signature was verified
_meta.degraded boolean Whether failover occurred
_meta.node_id string Node that executed the tool
_meta.latency_ms integer Execution latency in milliseconds
_meta.timestamp string ISO 8601 timestamp

Response (Error):

{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32602,
    "message": "Invalid input: Field 'value' must be a number"
  }
}

cURL Example (unit_convert):

curl -X POST http://127.0.0.1:8787/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "dwo.unit_convert",
      "arguments": {
        "value": 10,
        "from_unit": "miles",
        "to_unit": "km"
      }
    }
  }'

cURL Example (pii_redact):

curl -X POST http://127.0.0.1:8787/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "tools/call",
    "params": {
      "name": "dwo.pii_redact",
      "arguments": {
        "text": "Contact me at john@example.com or 555-123-4567"
      }
    }
  }'

cURL Example (jsonschema_validate):

curl -X POST http://127.0.0.1:8787/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 5,
    "method": "tools/call",
    "params": {
      "name": "dwo.jsonschema_validate",
      "arguments": {
        "schema": {
          "type": "object",
          "properties": {
            "name": {"type": "string"},
            "age": {"type": "number"}
          },
          "required": ["name"]
        },
        "data": {
          "name": "Alice",
          "age": 30
        }
      }
    }
  }'

Python Example:

import requests
import json

def call_tool(tool_name: str, arguments: dict):
    """Call an MCP tool and return the result."""
    response = requests.post(
        "http://127.0.0.1:8787/mcp",
        json={
            "jsonrpc": "2.0",
            "id": 100,
            "method": "tools/call",
            "params": {
                "name": tool_name,
                "arguments": arguments
            }
        }
    )

    result = response.json()

    if "error" in result:
        print(f"Error: {result['error']['message']}")
        return None

    # Parse tool result from content
    content_text = result["result"]["content"][0]["text"]
    tool_result = json.loads(content_text)

    # Print metadata
    meta = result["result"]["_meta"]
    print(f"Executed on: {meta['node_id']}")
    print(f"Latency: {meta['latency_ms']}ms")
    print(f"Verified: {meta['verified']}")

    return tool_result


# Example 1: Unit conversion
result = call_tool(
    "dwo.unit_convert",
    {
        "value": 100,
        "from_unit": "celsius",
        "to_unit": "fahrenheit"
    }
)
print(f"100°C = {result['value']}°F")

# Example 2: PII redaction
result = call_tool(
    "dwo.pii_redact",
    {
        "text": "Contact support@company.com for help"
    }
)
print(f"Redacted: {result['redacted_text']}")
print(f"Redactions: {result['redactions']}")

# Example 3: JSON Schema validation
result = call_tool(
    "dwo.jsonschema_validate",
    {
        "schema": {
            "type": "object",
            "properties": {
                "email": {"type": "string", "format": "email"}
            },
            "required": ["email"]
        },
        "data": {"email": "invalid-email"}
    }
)
print(f"Valid: {result['valid']}")
print(f"Errors: {result['errors']}")

4. Ping

Health check for MCP server.

Method: ping

Request:

{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "ping",
  "params": {}
}

Response:

{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "status": "ok"
  }
}

cURL Example:

curl -X POST http://127.0.0.1:8787/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 6,
    "method": "ping",
    "params": {}
  }'

Python Example:

import requests

response = requests.post(
    "http://127.0.0.1:8787/mcp",
    json={
        "jsonrpc": "2.0",
        "id": 6,
        "method": "ping",
        "params": {}
    }
)

result = response.json()
print(f"Status: {result['result']['status']}")

Claude Desktop Integration

Configuration

To integrate with Claude Desktop, add the MCP server to your Claude Desktop configuration:

macOS/Linux: ~/Library/Application Support/Claude/claude_desktop_config.json

Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "adaptive-sentience": {
      "command": "python",
      "args": ["-m", "gateway.mcp_server_cli", "--port", "8787"],
      "env": {
        "DWO_NODE_TYPE": "gateway"
      }
    }
  }
}

Alternative: HTTP Transport

For HTTP-based integration (without stdio):

{
  "mcpServers": {
    "adaptive-sentience": {
      "url": "http://127.0.0.1:8787/mcp",
      "transport": "http"
    }
  }
}

Starting the MCP Server

Standalone Mode:

python -m gateway.mcp_server_cli --port 8787

Integrated with Gateway:

python -m gateway.http_gateway --port 8787 --dev-token

The MCP endpoint is automatically available at /mcp when the HTTP Gateway is running.


Tool Discovery Flow

Here's a typical flow for an MCP client to discover and execute tools:

sequenceDiagram
    participant Client
    participant MCP Server
    participant Gateway
    participant Edge Node

    Client->>MCP Server: initialize
    MCP Server-->>Client: server info + capabilities

    Client->>MCP Server: tools/list
    MCP Server-->>Client: tool catalog with schemas

    Client->>MCP Server: tools/call (pii_redact)
    MCP Server->>Gateway: Execute tool
    Gateway->>Edge Node: HTTP tool call
    Edge Node-->>Gateway: Tool result
    Gateway-->>MCP Server: Result + metadata
    MCP Server-->>Client: Content + _meta

Step-by-step:

  1. Initialize: Client initiates session and negotiates protocol version
  2. List Tools: Client discovers available tools with schemas
  3. Validate Input: Client validates user input against tool schemas (optional)
  4. Call Tool: Client sends tool execution request
  5. Execute: MCP server routes to gateway, which executes on appropriate node
  6. Return Result: Tool result returned with execution metadata

Complete Python MCP Client Example

import requests
import json
from typing import Dict, Any, List, Optional


class AdaptiveSentienceMCPClient:
    """MCP client for Adaptive Sentience."""

    def __init__(self, base_url: str = "http://127.0.0.1:8787"):
        self.base_url = base_url.rstrip("/")
        self.mcp_url = f"{self.base_url}/mcp"
        self.request_id = 0
        self.session_id = None
        self.tools_cache = None

    def _next_id(self) -> int:
        """Get next request ID."""
        self.request_id += 1
        return self.request_id

    def _rpc_call(self, method: str, params: Dict = None) -> Dict[str, Any]:
        """Make JSON-RPC 2.0 call."""
        request = {
            "jsonrpc": "2.0",
            "id": self._next_id(),
            "method": method,
            "params": params or {}
        }

        response = requests.post(self.mcp_url, json=request)
        response.raise_for_status()
        result = response.json()

        if "error" in result:
            raise Exception(f"RPC Error: {result['error']['message']}")

        return result["result"]

    def initialize(self, client_name: str = "python-client", client_version: str = "1.0.0") -> Dict[str, Any]:
        """Initialize MCP session."""
        result = self._rpc_call("initialize", {
            "protocolVersion": "2024-11-05",
            "clientInfo": {
                "name": client_name,
                "version": client_version
            }
        })
        self.session_id = result.get("sessionId")
        return result

    def list_tools(self, force_refresh: bool = False) -> List[Dict[str, Any]]:
        """List available tools (with caching)."""
        if self.tools_cache is None or force_refresh:
            result = self._rpc_call("tools/list")
            self.tools_cache = result["tools"]
        return self.tools_cache

    def get_tool_schema(self, tool_name: str) -> Optional[Dict[str, Any]]:
        """Get schema for a specific tool."""
        tools = self.list_tools()

        # Normalize tool name
        if not tool_name.startswith("dwo."):
            tool_name = f"dwo.{tool_name}"

        for tool in tools:
            if tool["name"] == tool_name:
                return tool["inputSchema"]

        return None

    def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> tuple[Any, Dict[str, Any]]:
        """Call a tool and return (result, metadata)."""
        # Normalize tool name
        if not tool_name.startswith("dwo."):
            tool_name = f"dwo.{tool_name}"

        result = self._rpc_call("tools/call", {
            "name": tool_name,
            "arguments": arguments
        })

        # Parse result from content
        content_text = result["content"][0]["text"]
        tool_result = json.loads(content_text)

        # Extract metadata
        metadata = result.get("_meta", {})

        return tool_result, metadata

    def ping(self) -> bool:
        """Ping server to check health."""
        result = self._rpc_call("ping")
        return result.get("status") == "ok"


# Example usage
if __name__ == "__main__":
    client = AdaptiveSentienceMCPClient()

    # Initialize
    server_info = client.initialize(client_name="demo-client")
    print(f"Connected to: {server_info['serverInfo']['name']}")

    # List tools
    tools = client.list_tools()
    print(f"\nAvailable tools: {len(tools)}")
    for tool in tools:
        print(f"  - {tool['name']}: {tool['description'][:60]}...")

    # Get schema for specific tool
    schema = client.get_tool_schema("unit_convert")
    print(f"\nunit_convert schema: {json.dumps(schema, indent=2)}")

    # Call tool: unit conversion
    result, meta = client.call_tool("unit_convert", {
        "value": 10,
        "from_unit": "miles",
        "to_unit": "km"
    })
    print(f"\n10 miles = {result['value']} km")
    print(f"Executed on: {meta['node_id']} in {meta['latency_ms']}ms")

    # Call tool: PII redaction
    result, meta = client.call_tool("pii_redact", {
        "text": "Contact support@company.com or call 555-123-4567"
    })
    print(f"\nOriginal: Contact support@company.com or call 555-123-4567")
    print(f"Redacted: {result['redacted_text']}")
    print(f"Redactions: {result['redactions']}")

    # Call tool: JSON Schema validation
    result, meta = client.call_tool("jsonschema_validate", {
        "schema": {
            "type": "object",
            "properties": {
                "name": {"type": "string"},
                "age": {"type": "number", "minimum": 0}
            },
            "required": ["name", "age"]
        },
        "data": {
            "name": "Alice",
            "age": 30
        }
    })
    print(f"\nValidation result: {result['valid']}")
    if not result['valid']:
        print(f"Errors: {result['errors']}")

    # Call tool: Document summarization
    result, meta = client.call_tool("doc_summarize", {
        "text": """
        Artificial intelligence is transforming how we work and live.
        Machine learning models can now perform complex tasks with high accuracy.
        However, concerns about AI safety and ethics remain important.
        Organizations must balance innovation with responsible AI practices.
        The future of AI depends on thoughtful development and deployment.
        """,
        "max_sentences": 2
    })
    print(f"\nSummary ({result['summary_sentences']} sentences):")
    print(result['summary'])

    # Ping
    if client.ping():
        print("\nServer is healthy!")

TypeScript/JavaScript Example

interface RPCRequest {
  jsonrpc: "2.0";
  id: number;
  method: string;
  params?: any;
}

interface RPCResponse {
  jsonrpc: "2.0";
  id: number;
  result?: any;
  error?: {
    code: number;
    message: string;
  };
}

class AdaptiveSentienceMCPClient {
  private baseUrl: string;
  private requestId: number = 0;

  constructor(baseUrl: string = "http://127.0.0.1:8787") {
    this.baseUrl = baseUrl;
  }

  private async rpcCall(method: string, params: any = {}): Promise<any> {
    const request: RPCRequest = {
      jsonrpc: "2.0",
      id: ++this.requestId,
      method,
      params,
    };

    const response = await fetch(`${this.baseUrl}/mcp`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(request),
    });

    const result: RPCResponse = await response.json();

    if (result.error) {
      throw new Error(`RPC Error: ${result.error.message}`);
    }

    return result.result;
  }

  async initialize(clientName: string = "js-client"): Promise<any> {
    return this.rpcCall("initialize", {
      protocolVersion: "2024-11-05",
      clientInfo: {
        name: clientName,
        version: "1.0.0",
      },
    });
  }

  async listTools(): Promise<any[]> {
    const result = await this.rpcCall("tools/list");
    return result.tools;
  }

  async callTool(toolName: string, arguments: any): Promise<[any, any]> {
    if (!toolName.startsWith("dwo.")) {
      toolName = `dwo.${toolName}`;
    }

    const result = await this.rpcCall("tools/call", {
      name: toolName,
      arguments,
    });

    const contentText = result.content[0].text;
    const toolResult = JSON.parse(contentText);
    const metadata = result._meta;

    return [toolResult, metadata];
  }

  async ping(): Promise<boolean> {
    const result = await this.rpcCall("ping");
    return result.status === "ok";
  }
}

// Example usage
async function demo() {
  const client = new AdaptiveSentienceMCPClient();

  // Initialize
  const serverInfo = await client.initialize("demo-client");
  console.log(`Connected to: ${serverInfo.serverInfo.name}`);

  // List tools
  const tools = await client.listTools();
  console.log(`\nAvailable tools: ${tools.length}`);

  // Call unit_convert
  const [result, meta] = await client.callTool("unit_convert", {
    value: 100,
    from_unit: "celsius",
    to_unit: "fahrenheit",
  });
  console.log(`\n100°C = ${result.value}°F`);
  console.log(`Latency: ${meta.latency_ms}ms`);
}

demo();

Best Practices

1. Connection Management

  • Session Initialization: Always call initialize before other methods
  • Connection Pooling: Reuse HTTP connections for multiple requests
  • Error Handling: Handle JSON-RPC errors gracefully

2. Tool Schema Validation

  • Pre-validate Inputs: Use inputSchema to validate before calling tools
  • Type Checking: Ensure arguments match expected types
  • Required Fields: Check for required fields before submission

3. Metadata Utilization

  • Track Execution: Use trace_id for debugging and audit trails
  • Monitor Performance: Track latency_ms for performance analysis
  • Verify Security: Check verified flag for signature verification status
  • Detect Failover: Monitor degraded flag for failover events

4. Caching

  • Cache Tool List: Tools don't change frequently; cache for 5-10 minutes
  • Schema Caching: Cache inputSchema for each tool

5. Error Recovery

  • Retry Logic: Implement exponential backoff for transient errors
  • Timeout Handling: Set appropriate timeouts (recommend 30s)
  • Graceful Degradation: Handle tool unavailability gracefully

Security Considerations

  1. Transport Security: Use HTTPS in production (deploy behind reverse proxy)
  2. Input Validation: Server validates all inputs against schemas
  3. Output Sanitization: Be cautious with tool results containing user data
  4. Authentication: Consider adding API key authentication for production
  5. Rate Limiting: Implement rate limiting for production deployments

Troubleshooting

Common Issues

Problem: "Method not found" error

Solution: Check method name spelling and ensure server is initialized

# Verify server is running
curl http://127.0.0.1:8787/health

Problem: "Invalid params" error

Solution: Validate arguments against tool's inputSchema

# Get schema first
schema = client.get_tool_schema("unit_convert")
print(json.dumps(schema, indent=2))

# Validate your arguments match the schema

Problem: Connection refused

Solution: Ensure gateway is running on correct port

# Start gateway
python -m gateway.http_gateway --port 8787 --dev-token

Problem: Tools not showing up

Solution: Check that edge nodes are running and discoverable

# Scan for nodes
curl http://127.0.0.1:8787/v1/mesh_scan

Changelog

  • v1.0.0 (2026-01-24): Initial MCP integration
  • JSON-RPC 2.0 implementation
  • Tool discovery and execution
  • Claude Desktop support
  • Execution metadata tracking