Files
operations/tasks/envelope-directionality-serving.md

2.7 KiB

Task: Envelope Directionality — Serving Operations via MCP and HTTP

Priority: Medium (blocks hub serving operations to spokes)

Dependencies: ADR-005 (response envelopes implemented), ADR-006 (unified invocation path)

Architecture docs: response-envelopes.md § Open Questions #4

Problem

The current design covers consuming remote operations (MCP, OpenAPI) and wrapping their results in ResponseEnvelope. The reverse direction — serving local operations via MCP or OpenAPI — is not yet addressed.

When the hub exposes operations as an MCP server, results must be wrapped in MCP's CallToolResult format (structuredContent + content). When exposing as OpenAPI, results must be serialized as HTTP response bodies. How ResponseEnvelope results get converted to these protocol-specific formats is an open design question.

Design Questions to Answer

  1. Where does the conversion happen? Does the hub call registry.execute(), get a ResponseEnvelope, and then convert it? Or does a serving adapter register as a handler that wraps and returns protocol-native types?

  2. What happens to envelope metadata when serving? A local operation's ResponseEnvelope has meta: { source: "local", operationId, timestamp }. When served as MCP, should this become _meta on the CallToolResult? When served as HTTP, should the timestamp become a X-Operation-Timestamp header?

  3. Access control direction for serving: When serving operations, access control is "what operations does this connected spoke have access to?" vs the consuming direction which is "does the caller have scopes for this operation?"

  4. How do subscription (SUBSCRIPTION) operations work in the serving direction? When a spoke calls an MCP tool that maps to a SUBSCRIPTION operation on the hub, the result is a stream. How does this map to MCP's response model? MCP doesn't natively have streaming tool results.

  5. Relationship to existing adapters: from_mcp and from_openapi are currently one-directional (consume external → register operations). Would "to" variants (to_mcp, to_openapi) be separate modules, or would the existing adapters gain serving capabilities?

Scope

Design-only task. Produce:

  1. A decision document (ADR or architecture section) answering the questions above
  2. An API sketch showing the serving adapter interfaces
  3. Identification of implementation work needed

Constraints

  • Must work with the existing ResponseEnvelope model — don't change the envelope to accommodate serving
  • Must handle all three operation types (QUERY, MUTATION, SUBSCRIPTION)
  • Runtime-agnostic (same as rest of package)
  • Coherent with ADR-005 and ADR-006