MCP + ADK + Spine Cache — Universal Communication Architecture
Tier C — Historical. This document is a point-in-time snapshot preserved for reference. For current architecture, see CANONICAL_PLATFORM_ARCHITECTURE.md.
Executive Summary
IntegrateWise provides three distinct connectivity paths all converging on the Spine (Cloudflare D1 + KV + R2 + Vectorize), enabling universal agent-to-agent communication regardless of runtime location or protocol:
- Connector Path — External tools (HubSpot, Jira, Slack, etc.) through standardized Loader/Normalizer/Spine ingestion
- MCP-to-MCP Path — Direct protocol communication between MCP-capable systems (AI clients, agents, tools)
- ADK Agent Path — Agent-to-agent communication via shared Spine Cache + Registry + Log Table
All three paths enforce the same governance principles: truth in the Spine, proposals before execution, audit everywhere.
Architecture Overview
┌─────────────────────────────────────────────────────────────────────────┐
│ CONNECTIVITY LAYER │
├──────────────────────────┬──────────────────────┬─────────────────────────┤
│ Connector Path │ MCP-to-MCP Path │ ADK Agent Path │
│ (External Tools) │ (Direct Protocol) │ (Spine-based Comms) │
├──────────────────────────┼──────────────────────┼─────────────────────────┤
│ • HubSpot (Nango) │ • Notion (native MCP)│ • Notion Agent │
│ • Jira (Nango) │ • Claude (MCP client)│ • Cloudflare Agent │
│ • Slack (Nango) │ • ChatGPT (MCP) │ • Hostinger Agent │
│ • Coda, Mintlify, etc. │ • Direct MCP calls │ • Custom agents (ADK) │
│ • 26+ providers │ (no transform) │ • Any runtime + MCP │
└────────┬─────────────────┴──────────┬───────────┴────────────┬───────────┘
│ │ │
│ Loader │ MCP Protocol │ Spine Cache
↓ Normalizer ↓ (register in ↓ Registry (D1)
│ Spine Write │ Registry) │ Log Table (D1)
│ │ │
└──────────────┬───────────┴────────────┬───────────┘
▼
┌────────────────────────────────────┐
│ SPINE (Universal Truth) │
├────────────────────────────────────┤
│ D1: Canonical entities, audit logs │
│ KV: Spine Cache (shared context) │
│ KV: SIGNAL_CACHE, METRICS │
│ R2: Raw events, artifacts │
│ Vectorize: Semantic search index │
└────────────────────────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
Entity 360 Memory Hydration ADK Agent Comms
(Entity views) (conversational, (agent-to-agent
org, personal) message passing)
Path 1: Connector Path (Nango + API Wrappers)
Flow
External Tool → Nango Connector (OAuth) → API Wrapper → Loader
↓
Normalizer (8-stage LLM pipeline)
↓ Strip tool-specific schema
↓ Map to canonical business entities
↓
Entity Resolution (dedup, merge, link)
↓
Spine Writer (D1 + R2 lineage + KV cache update)
↓
Spine (canonical truth for that entity)
Guarantee: "No Bypass"
- ALL connectors (Nango providers AND custom API wrappers) MUST route through Loader/Normalizer/Spine
- Direct writes to Spine bypassing normalization are strictly forbidden
- Example: HubSpot deal → normalized to "Opportunity" entity with source lineage preserved
Supported Connectors (26+ providers via Nango)
| Provider | Type | Status |
|---|---|---|
| HubSpot | Nango | ✓ Active |
| Jira | Nango | ✓ Active |
| Slack | Nango | ✓ Active |
| Coda | Nango | ✓ Active |
| Mintlify | Nango | ✓ Active |
| Salesforce | Nango | ✓ Active |
| Notion | Nango + MCP | ✓ Active (dual support) |
| Linear | Nango | ✓ Active |
| GitHub | Nango | ✓ Active |
| Asana | Nango | ✓ Active |
| Monday.com | Nango | ✓ Active |
| Stripe | API Wrapper | ✓ Active |
| Airtable | API Wrapper | ✓ Active |
| [21+ others] | Mixed | ✓ Active |
Normalization Pipeline (8 stages)
Stage 1: Parse — Extract raw event schema
Stage 2: Validate — Check against provider signature
Stage 3: Transform — Apply provider-specific mappings
Stage 4: Denormalize — Convert to canonical schema
Stage 5: Enrich — Add computed fields, infer relationships
Stage 6: Validate — Verify canonical schema compliance
Stage 7: Dedup — Check for duplicates in Spine
Stage 8: Promote — Write to D1 with full lineage
Lineage Tracking
Every entity preserves its origin:
{
"entity_id": "opp_abc123",
"entity_type": "Opportunity",
"canonical_value": { "name": "Acme Deal", "value": 50000 },
"source": {
"provider": "hubspot",
"event_id": "deal_xyz789",
"connection_id": "conn_hubspot_1",
"timestamp": "2026-06-19T14:30:00Z",
"raw_payload_ref": "s3://bucket/raw/hubspot/deal_xyz789.json"
}
}
Path 2: MCP-to-MCP Path (Direct Protocol Communication)
What is MCP?
Model Context Protocol — Standard protocol for AI systems and tools to communicate structured data and function calls.
- Standardized by Anthropic (open standard)
- Supported by: Claude, ChatGPT (native), Notion, custom integrations
- Enables: structured tool discovery, typed schemas, async function calls
MCP Endpoint in IntegrateWise
Deployed endpoint: https://mcp.integratewise.ai (live June 9, 2026)
Authentication: OAuth 2.0 RS256 JWT (scope-bound)
18 Exposed Tools:
| Tool Group | Tools | Access Level |
|---|---|---|
kb.* | kb.search, kb.list, kb.get_context | Read-only |
memory.* | memory.propose, memory.list, memory.get | Propose-only (write restricted) |
spine.* | spine.query, spine.entity_360, spine.timeline | Read-only |
signal.* | signal.emit, signal.list, signal.correlate | Propose-only |
proposal.* | proposal.create, proposal.list, proposal.get_status | Propose-only (handoff) |
search.* | search.semantic, search.fulltext, search.entity | Read-only |
MCP Communication Flow
AI Client (Notion / Claude)
│
├─ Discover MCP tools at mcp.integratewise.ai
├─ Authenticate with OAuth JWT
└─ Call tool (e.g., kb.search)
│
▼
IntegrateWise MCP-CONNECTOR Worker
│
├─ Verify scope (e.g., "kb:read")
├─ Authorize based on tenant + principal
└─ Delegate to backend service
│
├─ kb.search → KNOWLEDGE service (Vectorize semantic search)
├─ memory.propose → CONTINUITY service (memory write)
├─ spine.query → D1 query (authorized subset)
└─ [... route to appropriate service ...]
│
▼
Return typed response to AI client
│
└─ MCP-CONNECTOR logs call to Spine Log Table (comms audit)
Key Property: Direct MCP-to-MCP Calls Bypass Normalizer
When both endpoints support MCP natively:
- ✅ No Loader/Normalizer transformation overhead
- ✅ Direct protocol call (preserves fidelity)
- ✅ Still logged in Spine Log Table (for audit + replay)
- ✅ Still enforces authentication (OAuth JWT)
- ✅ Still registered in agent Registry (for discovery)
Example: Notion Agent calling Claude via MCP
Notion Agent
├─ Reads Spine Cache (agent registry)
├─ Discovers: "Claude endpoint available, MCP-capable"
└─ Direct MCP call → Claude
│ (no Loader/Normalizer)
│
└─ Claude responds with structured tool result
│
└─ Notion Agent writes outcome to Spine Cache + Log
Path 3: ADK Agent Communication (via Spine)
What is ADK?
Agent Development Kit — Framework for building, deploying, and scaling multi-agent systems on Cloudflare Durable Objects.
Core components:
- Agent Registry (D1 table mapping agents to capabilities)
- Spine Cache (KV shared context for agent communication)
- Log Table (D1 communication history for sequencing + replay)
- Agent Runtime (Cloudflare DO-based agent runtime with memory + tools + policies)
Agent-to-Agent Communication Substrate
Three agents (Notion, Cloudflare, Hostinger) can coordinate via Spine:
Agent A (Notion)
│
├─ Read Spine Cache (shared state)
├─ Query Registry: "Who handles coda_write?"
├─ Discover: "Cloudflare Agent (id: agent_cf_1) handles coda_write"
│
├─ Write to Spine Cache: {"request_id": "req_123", "type": "coda_write", "target": "agent_cf_1"}
├─ Write to Log Table: {sender_id, receiver_id, message_type, payload_ref, status: "pending"}
│
└─ Poll Log Table or subscribe to changes
│
▼
Agent B (Cloudflare)
│
├─ Monitor Spine Cache (watch pattern)
├─ Detect: "New coda_write request in cache"
│
├─ Read full request from Spine Cache
├─ Process (execute coda_write action)
│
├─ Write result to Spine Cache: {"request_id": "req_123", "result": {...}, "status": "completed"}
├─ Update Log Table: {status: "completed", result_ref}
│
└─ Notify Agent A (via cache watcher subscription)
│
▼
Agent A receives result from Spine Cache
Spine Cache (KV): Shared Operational Context
What it stores:
- Agent state snapshots
- In-flight request state
- Shared signals and metrics
- Capability registrations
TTL: Configurable per use case (default: 24 hours)
Schema:
// Key pattern: agent:{agent_id}:state
{
"agent:notion_1:state": {
"status": "idle",
"last_heartbeat": "2026-06-19T14:35:00Z",
"capabilities": ["notion_read", "memory_propose"],
"current_task": null
},
// Key pattern: request:{request_id}
"request:req_123": {
"sender_id": "agent_notion_1",
"receiver_id": "agent_cf_1",
"type": "coda_write",
"payload": { "page_id": "...", "content": "..." },
"status": "pending",
"created_at": "2026-06-19T14:30:00Z",
"result": null
}
}
Registry (D1): Agent Routing Table
Table: agent_registry
{
agent_id: "agent_cf_1",
agent_name: "Cloudflare Intelligence Agent",
runtime: "cloudflare_do",
capabilities: ["coda_write", "hubspot_update", "memory_propose"],
endpoint: "https://cf-agent.integratewise.ai/invoke",
status: "active",
tenant_id: "tenant_acme",
updated_at: "2026-06-19T14:35:00Z",
health_check_interval: 60,
last_health_check: "2026-06-19T14:34:00Z"
}
Query patterns:
-- Agent discovery: find all agents handling "coda_write"
SELECT * FROM agent_registry
WHERE tenant_id = ?
AND capabilities @> '["coda_write"]'
AND status = 'active'
-- Agent health: mark offline
UPDATE agent_registry
SET status = 'offline'
WHERE agent_id = ? AND last_health_check < NOW() - INTERVAL 2 MINUTE
-- Agent capability lookup
SELECT capabilities FROM agent_registry
WHERE agent_id = ? AND tenant_id = ?
Log Table (D1): Communication History
Table: agent_communication_log
{
log_id: "log_abc123",
sender_agent_id: "agent_notion_1",
receiver_agent_id: "agent_cf_1",
message_type: "coda_write",
request_id: "req_123",
payload_ref: "s3://bucket/comms/req_123.json",
status: "completed", // pending | completed | failed | timeout
result_status: "success",
tenant_id: "tenant_acme",
created_at: "2026-06-19T14:30:00Z",
completed_at: "2026-06-19T14:30:15Z",
duration_ms: 150,
error_message: null,
audit_id: "audit_xyz789"
}
Guarantees:
- ✓ Every agent-to-agent message is logged
- ✓ Enables replay and debugging
- ✓ Enables sequencing for eventual consistency
- ✓ Enables SLA tracking (duration_ms)
Communication Patterns
1. Synchronous (Request-Response via Log Table)
Agent A: Write request to Log Table → status: "pending"
Agent A: Poll Log Table for completion
Agent B: Read log entry, process request
Agent B: Update Log Table → status: "completed", result
Agent A: Read updated log entry, get result
Latency: <500ms for local agents, <5s for distributed agents
2. Asynchronous (Fire-and-Forget via Spine Cache)
Agent A: Write signal to Spine Cache
Agent A: Return immediately (no waiting)
Agent B: Subscribe to Spine Cache pattern
Agent B: Receive signal, process
Agent B: Update Spine Cache with result (Agent A can check later)
Use case: Non-critical signals, batch processing
3. Pub/Sub (Broadcast via Spine Cache)
Agent A: Publish signal to Spine Cache pattern: "signals:*"
Agent B, C, D: Subscribe to "signals:*"
All agents: Receive signal simultaneously
Each agent: Process independently, write result to own state
Use case: System-wide signals, multi-agent coordination
MCP Layer Deep Dive
Endpoint Architecture
External AI Client (Claude, ChatGPT, Notion)
│
└─ Connect to mcp.integratewise.ai
│
├─ WebSocket (real-time streaming) OR
└─ HTTP/SSE (request-response)
│
▼
MCP-CONNECTOR Worker (Cloudflare)
│
├─ Parse MCP message
├─ Extract tool call (kb.search, memory.propose, etc.)
├─ Verify OAuth JWT token
├─ Check tenant + scopes (authorization)
│
├─ Route to appropriate backend service
│ ├─ kb.search → KNOWLEDGE (Vectorize semantic)
│ ├─ memory.propose → CONTINUITY (write to memory)
│ ├─ spine.query → D1 direct query
│ ├─ signal.emit → INTELLIGENCE (signal processing)
│ ├─ proposal.* → GOVERN (approval gate)
│ └─ search.* → KNOWLEDGE (hybrid search)
│
├─ Collect response
├─ Log to Spine Log Table (for audit)
└─ Return MCP-formatted response
│
└─ Back to AI Client
Tool Categories
Read-Only Tools (kb., spine., search.*)
- No side effects
- Can be called freely (within rate limits)
- Example:
kb.search("How do we handle SaaS pricing?")→ returns context
Propose-Only Tools (memory., signal., proposal.*)
- Write side effects but non-executable
- Create artifacts in Spine (memory records, signals, proposals)
- Require human-in-loop for execution
- Example:
memory.propose({"type": "decision", "content": "..."})
Governance-Gated Tools (proposal.create via handoff)
- Require approval before execution
- Never execute directly; handoff to customer infrastructure
- Example:
proposal.create({"action": "update_hubspot_deal"})→ returns approval_url
ADK Layer Deep Dive
Agent Builder Framework
// ADK Agent definition
class MyAgent extends ADKAgent {
capabilities = ["notion_read", "memory_propose", "signal_emit"]
async initialize(context: AgentContext) {
this.registry = context.registry
this.spine_cache = context.spine_cache
this.memory = context.memory
}
async execute(request: AgentRequest) {
// Read shared context from Spine Cache
const sharedState = await this.spine_cache.get("shared:state")
// Discover other agents
const agents = await this.registry.query({
tenant_id: this.tenant_id,
capabilities: ["coda_write"]
})
// Invoke another agent via Log Table + Spine Cache
const result = await this.invoke_agent(agents[0].agent_id, {
type: "coda_write",
payload: { ... }
})
// Propose memory (no execution)
await this.memory.propose({
type: "decision",
content: "Selected Cloudflare agent for coda_write"
})
// Return proposal (never execute directly)
return {
action: "...",
explanation: "...",
confidence: 0.87
}
}
}
ADK Runtime (Cloudflare DO)
Lifecycle:
1. Initialization
- Agent reads Registry (discover peers)
- Agent reads Spine Cache (load shared state)
- Agent registers itself in Registry
2. Idle Loop
- Poll Log Table for new messages
- Monitor Spine Cache for signals
- Health check peer agents (mark offline if no heartbeat)
3. Request Processing
- Receive message from Log Table or Spine Cache
- Execute agent logic (propose, don't execute)
- Write result back to Log Table / Spine Cache
4. Shutdown
- Unregister from Registry
- Close Spine Cache subscriptions
Agent Policies
Before execution, agents evaluate policies:
Policy: "Cloudflare Agent can only invoke Notion Agent for read-only tasks"
Policy: "Memory proposals require confidence > 0.8"
Policy: "Signal emission limited to 100 per minute"
Policy: "Tenant isolation: agent_acme_1 can only access tenant_acme data"
Enforcement: Built into ADK runtime (fail-safe deny by default)
Governance & Execution Flow
The Hard Gate: "Propose, Don't Execute"
All three communication paths converge on governance before execution:
Agent Proposal
│
├─ Routing through GOVERN worker
│
├─ Evaluation:
│ ├─ Risk score calculation
│ ├─ Policy matching
│ ├─ Scope validation
│ └─ Tenant isolation check
│
├─ Decision:
│ ├─ Auto-approve (low-risk, policy match)
│ ├─ HITL (human-in-the-loop required)
│ └─ Reject (high-risk, policy violation)
│
└─ If approved:
│
└─ Handoff Layer
│
├─ Package proposal in canonical contract
├─ Select target adapter (MCP, JSON, Zapier, etc.)
└─ Dispatch to customer execution environment
│ (customer infrastructure, not IntegrateWise)
│
└─ Customer executes (they own execution)
Non-negotiable: No agent can bypass this gate. TenantBrainDO (per-tenant brain) enforces with 15-min alarm timeout.
Scalability & Performance
Spine Cache Performance
| Operation | Latency | Scale |
|---|---|---|
| Cache read (KV) | <10ms | 100K+ requests/sec |
| Cache write (KV) | <10ms | 100K+ requests/sec |
| Registry query (D1) | <50ms | millions of agents |
| Log table insert (D1) | <20ms | millions of messages |
| Semantic search (Vectorize) | <100ms | billions of embeddings |
Agent Communication SLA
| Pattern | P50 Latency | P99 Latency | Notes |
|---|---|---|---|
| Local agents (same CF region) | <50ms | <200ms | via Spine Cache |
| Distributed agents (cross-region) | <500ms | <2s | via Log Table + polling |
| MCP direct call | <100ms | <500ms | no normalizer overhead |
| Connector path (with normalizer) | <2s | <10s | 8-stage pipeline |
Security & Multi-Tenancy
Tenant Isolation
Every query includes tenant_id scoping:
// Registry lookup (tenant-scoped)
SELECT * FROM agent_registry
WHERE tenant_id = ? AND agent_id = ?
// Cache key (tenant-scoped)
Key: "{tenant_id}:agent:{agent_id}:state"
// Log table (tenant-scoped)
SELECT * FROM agent_communication_log
WHERE tenant_id = ? AND created_at > ?
// Memory access (RLS in Supabase)
SELECT * FROM org_memory
WHERE tenant_id = ? AND org_id = ? -- RLS enforces
Authentication & Authorization
OAuth 2.0 RS256 JWT on all MCP calls:
Token payload:
{
"sub": "user_abc123",
"aud": "mcp.integratewise.ai",
"scope": ["kb:read", "memory:propose"],
"tenant_id": "tenant_acme",
"iat": 1718819400,
"exp": 1718823000
}
Scope binding:
kb:read— Can call kb.search, kb.list, kb.get_contextmemory:propose— Can call memory.propose (write to memory)spine:read— Can call spine.query (subset of entities)signal:emit— Can call signal.emit (emit signals)
Audit Trail
100% cloud-based logging (no local agent state):
1. Agent communication logged to Log Table (D1)
2. All MCP calls logged to MCP audit trail
3. All governance decisions logged with reasoning
4. All memory writes logged with source + principal
5. Retention: 2 years (compliant with SOC2)
Deployment & Operations
Environments
| Environment | Agents | Spine | MCP | Governance |
|---|---|---|---|---|
| dev | Local + Cloudflare | D1 dev DB | localhost MCP | Auto-approve |
| test | Cloudflare staging | D1 test DB | test.mcp.integratewise.ai | HITL simulated |
| prod | Cloudflare prod | D1 prod DB | mcp.integratewise.ai | HITL real |
Monitoring & Observability
Metrics tracked:
Agent metrics:
- Registry query latency (p50, p99)
- Spine Cache hit rate (%)
- Log table write latency (p50, p99)
- Agent health (active/offline/error)
- Communication success rate (%)
MCP metrics:
- Tool call latency per tool (ms)
- Authentication failures (count)
- Scope violations (count)
- Rate limit hits (count)
Governance metrics:
- Proposal approval rate (%)
- Average approval time (minutes)
- Policy violations (count)
- Execution success rate (%)
Example: Multi-Agent Workflow
Scenario: "Automatically update HubSpot based on Coda document changes"
Agents involved:
- Notion Agent (reads document changes)
- Cloudflare Agent (handles HubSpot integration)
- Hostinger Agent (executes on customer infrastructure)
Flow:
1. Notion Agent
├─ Receives webhook: Coda document updated
├─ Reads Spine Cache for current opportunities
├─ Queries Registry: "Who handles hubspot_update?"
└─ Discovers: Cloudflare Agent (agent_cf_1)
2. Notion Agent → Cloudflare Agent (via Log Table)
├─ Write to Log Table: {type: "hubspot_update", target_id: "opp_123", data: {...}}
├─ Poll Log Table for completion
3. Cloudflare Agent
├─ Monitor Log Table (watch pattern for messages to agent_cf_1)
├─ Read message from Log Table
├─ Prepare HubSpot API call
├─ Create PROPOSAL (not execute yet)
└─ Write to Spine Cache: {request_id, proposal, status: "pending_approval"}
4. Governance Gate (GOVERN worker)
├─ Evaluate proposal
├─ Decision: HITL (needs human approval)
└─ Return approval_url
5. Human in L7 Approval Center
├─ Review proposal with evidence
├─ Click "Approve"
└─ Governance marks as approved
6. Handoff Layer
├─ Package approved proposal in canonical contract
├─ Select adapter: MCP (Hostinger supports MCP)
└─ Dispatch to Hostinger Agent
7. Hostinger Agent (customer infrastructure)
├─ Receive handoff package
├─ Execute HubSpot API call (in their environment)
├─ Capture outcome
└─ Send outcome back to IntegrateWise
8. Outcome Ingestion (Return Loop)
├─ Receive: {status: "success", hubspot_id: "deal_456"}
├─ Update Spine: Mark opportunity as synchronized
├─ Update Memory: Log successful action
├─ Update Graph: Record entity relationship
└─ Notify all agents via Spine Cache (broadcast signal)
9. All agents
├─ Subscribe to Spine Cache for outcome signal
├─ Read final state from Spine
├─ Update their models based on new ground truth
└─ Ready for next workflow
Result: Universal agent coordination with no vendor lock-in, full governance, complete audit trail.
Key Invariants (MCP + ADK + Spine Cache)
- One Spine, Many Agents — All agents share same D1 source of truth
- Registry is the Discovery Mechanism — Agents find each other via Registry, not hardcoded
- Log Table is the Communication Bus — Every agent-to-agent message recorded for audit + replay
- Spine Cache is Shared State — Agents read/write operational state, not private memory
- No Bypass, No Exception — All proposals flow through governance gate (fail-safe deny)
- Tenant Isolation on Every Query — Every D1/KV access scoped by tenant_id (no data leakage)
- Audit Everything — All MCP calls, registry lookups, cache reads/writes logged
- Eventual Consistency — Agent state converges through polling Log Table + Spine Cache subscriptions
Conclusion
MCP + ADK + Spine Cache together enable:
✓ Universal Communication — Any agent (Notion, Cloudflare, Hostinger, custom) can communicate with any other
✓ Zero Vendor Lock-in — Standard protocols (MCP, OAuth) + Spine as neutral ground truth
✓ Full Governance — All execution gated through HITL approval before reaching customer infrastructure
✓ Complete Observability — 100% audit trail (no local agent state, everything in cloud)
✓ Scalable Architecture — Millions of agents, billions of messages, no single point of failure
The Spine is the universal substrate. MCP + ADK are the connective tissues. Governance is the hard gate. Together, they enable an open, auditable, secure multi-agent operating system.