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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions