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¶
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¶
Response Format (Success)¶
Response Format (Error)¶
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:
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:
Response:
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:
Integrated with Gateway:
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:
- Initialize: Client initiates session and negotiates protocol version
- List Tools: Client discovers available tools with schemas
- Validate Input: Client validates user input against tool schemas (optional)
- Call Tool: Client sends tool execution request
- Execute: MCP server routes to gateway, which executes on appropriate node
- 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
initializebefore 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
inputSchemato 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_idfor debugging and audit trails - Monitor Performance: Track
latency_msfor performance analysis - Verify Security: Check
verifiedflag for signature verification status - Detect Failover: Monitor
degradedflag 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¶
- Transport Security: Use HTTPS in production (deploy behind reverse proxy)
- Input Validation: Server validates all inputs against schemas
- Output Sanitization: Be cautious with tool results containing user data
- Authentication: Consider adding API key authentication for production
- 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
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
Problem: Tools not showing up
Solution: Check that edge nodes are running and discoverable
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