Skip to content

Umbrella: MCP + A2A workers overhaul (RBAC delegation, spec completion, client workers) #45

@rohitg00

Description

@rohitg00

Umbrella: MCP + A2A Workers Overhaul

Goal: iii worker add mcp and iii worker add a2a deliver drop-in, spec-compliant protocol surfaces built purely on iii primitives. Users compose apps, harnesses, and agents from narrow workers — no protocol glue.

Why

Current state deviates from that thesis five ways:

  1. RBAC duplicated at handler layer. ALWAYS_HIDDEN_PREFIXES + mcp.expose / a2a.expose metadata + --expose-all + --tier all reinvent access control locally. iii-sdk already has full RBAC at iii-worker-manager (auth_function_id, expose_functions, AuthResult.{allowed,forbidden}_functions). Two policy layers = layered denials, confusing errors, drift risk.
  2. MCP 2025-06-18 gaps. Missing sampling, elicitation, logging, progress, cancellation, completion, pagination, resource subscribe, tool title/annotations/outputSchema, structured content, HTTP-transport authorization.
  3. A2A v0.3 gaps. Missing message/stream, tasks/resubscribe, all four *TaskPushNotificationConfig methods, GetExtendedAgentCard, securitySchemes/security fields, task states Submitted / InputRequired / AuthRequired / Rejected, TaskStatusUpdateEvent, TaskArtifactUpdateEvent.
  4. Concrete bugs. Agent card advertises base_url without /a2a path suffix (spec clients 404). documentation_url points to a dead iii-connect repo. Agent identity (name, description, provider) hardcoded.
  5. No client workers. Neither mcp-client nor a2a-client exists. iii cannot consume external MCP servers or A2A agents as tools. Cross-protocol harness building is structurally blocked.

Constraints:

  • No engine changes. Everything inside iii-hq/workers.
  • Narrow-worker idiom (~2000 LOC per crate).
  • Single breaking migration (Phase 1), additive afterwards.

Outcome: four Rust crates — mcp, a2a, mcp-client (new), a2a-client (new) — fully-spec-compliant server + client halves of both protocols, authorized via iii-sdk RBAC, harness-ready.

Sequence

Phase 0 (bugs) ─────────┐
Phase 1 (RBAC) ─────────┼─→ Phase 2 (MCP spec) ──┐
                        ├─→ Phase 3 (A2A spec) ──┼─→ Phase 5 (harness e2e)
                        └─→ Phase 4 (clients) ───┘

Phase 0 ships as a point release (non-breaking). Phase 1 is the single architectural gate — every subsequent phase reads from the post-RBAC iii.list_functions() worldview. Phases 2, 3, 4 run in parallel after 1 lands.

Tracked sub-issues

  • Phase 0 — Non-breaking bug fixes: serviceEndpoint /a2a suffix, dead iii-connect doc link, configurable agent identity (--agent-name, --agent-description, --provider-org, --provider-url, --docs-url).
  • Phase 1 — RBAC delegation: remove ALWAYS_HIDDEN_PREFIXES (except mcp::/a2a:: structural loop guard), ExposureConfig, mcp.expose/a2a.expose metadata, --expose-all, --tier. Migration README + examples/default-secure-auth.rs.
  • Phase 2 — MCP 2025-06-18 spec completion. Three sub-PRs: (2a) non-streaming methods + annotations + pagination + cancellation + progress; (2b) sampling + elicitation via server-to-client JSON-RPC; (2c) Streamable HTTP SSE via ChannelWriter + RBAC-delegated auth.
  • Phase 3 — A2A v0.3 spec completion: message/stream, tasks/resubscribe, four push-notification methods, GetExtendedAgentCard, full task-state lifecycle, securitySchemes/security agent-card fields.
  • Phase 4 — New crates: mcp-client and a2a-client (consume external servers/agents, register remote tools/skills as local iii functions under namespaced IDs). Shared iii-protocol-common crate.
  • Phase 5 — End-to-end harness validation: Claude Desktop → iii; iii → external MCP server; iii harness → iii harness over A2A streaming.

Key architectural decisions

  • Authorization: forward Authorization header into AuthInput.headers. iii-worker-manager runs deploy-configured auth_function_id. Zero crypto in worker. Example auth_function_id with JWT verification shipped as examples/oauth-passthrough.rs. Not a literal OAuth 2.1 implementation — deploys needing that write a 50-line auth function using jose.
  • Client workers are separate crates, not --mode flags. Server and client semantics are inverted (one-trigger-many-tools vs many-proxies-no-triggers). Separate supervision trees and deps. Matches the narrow-worker convention.
  • SSE primitive: ChannelWriter (reference: iii/sdk/packages/rust/iii/tests/api_triggers.rs:498). Used by MCP Streamable HTTP, MCP progress/logging, A2A message/stream, A2A tasks/resubscribe. Extracted into iii-protocol-common::sse after the first usage lands.
  • introspect::* stays the canonical engine-introspection surface. The old engine::* hard floor is dropped; users who want engine::*-like visibility are pointed at introspect::{functions,workers,triggers,topology,diagram,health,trace_workflow,explain} — already shipped in iii-hq/workers/introspect.

Out of scope

  • Engine changes (constraint).
  • RBAC primitives themselves — already in iii-sdk.
  • introspect::* changes — already correctly shaped.
  • MCP Apps / extensions — niche, deferred.
  • A2A federation protocol layers beyond v0.3.

Issue disposition

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions