CRUMB a card from devarno-cloud

MCP Bridge — 4 Tools (Tier 2)

iris intermediate 5 min read

ELI5

MCP (Model Context Protocol) is like a universal remote control for AI assistants. The IRIS MCP server is a small adapter that lets Claude (or any MCP-compatible client) create sprites, validate them, form councils, and run chains — all by speaking a standard language that the client already understands.

Technical Deep Dive

MCP Architecture

flowchart TB
subgraph client["MCP Client"]
claude["Claude Desktop or MCP Client"]
end
subgraph bridge["Tier 2 — Bridge"]
mcp["iris-mcp-server<br/>stdio / SSE transport"]
end
subgraph core["Tier 1 — Core"]
iris["iris-service FastAPI"]
end
claude --> mcp
mcp --> iris

Transport: MCP uses stdio (for local clients like Claude Desktop) or SSE (Server-Sent Events) for remote connections. The iris-mcp-server currently implements stdio transport.

Deployment: The server is built for Cloudflare Workers using Wrangler (wrangler.toml). It can also run locally with Node.js.

The 4 MCP Tools

flowchart TB
subgraph Tools["MCP Tools"]
A["create_sprite_in_iris"]
B["validate_sprite"]
C["create_council"]
D["run_chain"]
end
subgraph Delegation["Delegates to iris-service"]
E["POST /v1/sprites"]
F["Client-side validation"]
G["POST /v1/councils"]
H["POST /v1/chains/execute"]
end
A --> E
B --> F
C --> G
D --> H

Tool 1: create_sprite_in_iris

Purpose: Create a sprite in the IRIS registry, optionally documenting it in Choco.

Input schema (JSON Schema):

{
"name": "SOL-FORGE-01",
"version": "1.0.0",
"role": "architect",
"capabilities": [{"name": "generate_code", "description": "..."}],
"system_prompt": "You are a senior software architect...",
"protected": false,
"gate_authority": false,
"metadata": {"author": "dev", "tags": ["core"]},
"document_in_choco": false,
"choco_workspace": null
}

Output:

{
"sprite": { /* full Sprite object with id + fingerprint */ },
"documented": false,
"choco_page_url": null
}

Key design: Sprite creation always happens in IRIS. Choco documentation is optional and currently a stub (always returns documented: false).

Tool 2: validate_sprite

Purpose: Dry-run validation against iris.schema.json without persisting.

Input: sprite_definition (object), optional format (json or yaml)

Output:

{
"valid": true,
"errors": [],
"schema_version": "1.0.0",
"fingerprint_preview": "a1b2c3d4..."
}

Validation checks:

  • Name matches SOL-[A-Z]+-\d+ pattern
  • Version is valid semver
  • Role is one of 6 valid roles
  • Capabilities array has ≥1 item with name and description
  • System prompt is non-empty string

Note: YAML format is not yet supported in the MCP server (returns an error). The fingerprint preview is a placeholder hash, not real Blake3.

Tool 3: create_council

Purpose: Group existing sprites under a domain with governance.

Input:

{
"domain": "engineering",
"sprite_ids": ["uuid1", "uuid2"],
"gate_agent_ids": ["uuid1"],
"chains": [ /* optional Chain definitions */ ],
"rules": [ /* optional Rules */ ]
}

Field name translation: The MCP client uses descriptive names (sprite_ids, gate_agent_ids) while the REST API uses concise names (sprites, gate_agents). The MCP server translates between them.

Output: Full council object with server-generated id and timestamps.

Tool 4: run_chain

Purpose: Synchronous chain execution per DEC-002.

Input:

{
"council_id": "uuid",
"chain_id": "uuid",
"input": {
"task": "Generate a REST API for user management",
"context": {"language": "python", "framework": "fastapi"}
}
}

Output: Full ChainExecutionResult including execution_id, status, steps, gates, and timing.

Error Handling

flowchart TD
A["MCP Tool Call"] --> B{"IrisServiceError?"}
B -->|Yes| C["Return {isError: true, content: [{type: text, text: error_json}]}"]
B -->|No| D["Return {content: [{type: text, text: result_json}]}"]
D --> E{"Generic error?"}
E -->|Yes| C
E -->|No| F["Success ✓"]

All errors are returned as MCP text content with isError: true, containing the full JSON error response from iris-service.

Key Terms

  • MCP → Model Context Protocol; a standard protocol for AI assistants to discover and call tools
  • stdio transport → MCP over standard input/output streams (used by Claude Desktop)
  • Tool schema → JSON Schema defining each tool’s inputs, used by MCP clients for auto-discovery
  • Field name translation → MCP uses descriptive names (sprite_ids) while REST uses concise names (sprites)
  • Choco integration → Optional documentation sync; currently a stub in the MCP server
  • Dry-run validationvalidate_sprite checks constraints without persisting to the registry

Q&A

Q: Do I need Choco to use the MCP server? A: No. The MCP server works standalone. Choco documentation is optional. Sprite creation, validation, council creation, and chain execution all work without Choco.

Q: Can the MCP server run outside Cloudflare Workers? A: Yes. While wrangler.toml configures it for Workers, the server is standard TypeScript/Node.js and can run anywhere Node 18+ is available.

Q: How does Claude discover the available tools? A: The MCP server implements ListToolsRequestSchema, returning the JSON Schema for all 4 tools. Claude (or any MCP client) calls this on connection to learn what tools are available.

Q: Why does validate_sprite not use real Blake3? A: The MCP server is designed to be lightweight with zero heavy dependencies. Real fingerprinting requires the blake3 Python library or WebAssembly module. The preview hash is a deterministic placeholder for quick validation feedback.

Q: Can I use the MCP server with clients other than Claude? A: Yes. Any MCP-compatible client can connect. The protocol is transport-agnostic (stdio, SSE, HTTP).

Examples

The MCP bridge is like a restaurant’s phone ordering system:

  • create_sprite_in_iris = “I’d like to place a new item on the menu” (the kitchen always receives the order; optionally the PR team writes a press release)
  • validate_sprite = “Can you check if my recipe will work before I cook it?” (tastes the sauce, doesn’t serve it to customers)
  • create_council = “I’d like to book a private dining room for my team with one designated person who can cancel the reservation”
  • run_chain = “Start the tasting menu course by course” (each course comes out sequentially; if the designated taster says “this is bad,” the kitchen stops immediately)

neighbors on the map