Break the alknet-http architecture spec into atomic, dependency-ordered tasks in tasks/http/, following the taskgraph frontmatter conventions used by the call/core/vault crates. Tasks span 7 phases across 5 module subdirectories (server/, gateway/, client/, adapters/, websocket/): - Phase 0: crate-init (foundation) - Phase 1: gateway-dispatch-spine, error-mapping, shared-http-client (shared infrastructure) - Phase 2: http-adapter, bearer-auth-middleware, gateway-endpoints, healthz-decoy (HTTP server surface) - Phase 3: to-openapi (OpenAPI gateway projection) - Phase 4: from-openapi (OpenAPI adapter, reqwest forwarding) - Phase 5: dispatcher-transport-abstraction, upgrade-handler, connection-overlay (WebSocket browser bidirectional path) - Phase 6: from-mcp, to-mcp (MCP adapters, feature-gated) - Phase 7: review-http, review-websocket, review-mcp, review-http-final (quality checkpoints) The gateway-dispatch-spine task implements the thin shared core recommended by the gateway-factoring research (concrete struct, not a trait). The dispatcher-transport-abstraction task is a cross-crate change to alknet-call (exposes EventEnvelope-level dispatch API for non-QUIC transports) — the highest-risk task. WebTransport/h3 is deferred per ADR-044 and has no tasks; from_wss is out of scope. Validated: 19 tasks, no cycles, 8 parallel generations, critical path length 8 (through the WebSocket strand).
8.2 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | ||
|---|---|---|---|---|---|---|---|---|---|
| http/review-mcp | Review MCP adapters for ADR-037/041 conformance (streamable HTTP, 4-tool gateway, output handling) | pending |
|
moderate | low | phase | review |
Description
Review the MCP adapters (from_mcp, to_mcp) for spec conformance,
pattern consistency, and correctness. This is the quality checkpoint
for the feature-gated MCP work.
Review Checklist
-
from_mcpconformance (http-mcp.md):FromMCPstruct withendpoint,auth_token,namespaceOperationAdapterimpl (async fn import)- Connects via rmcp
StreamableHttpClientTransport::from_uri(endpoint) - Connection failure →
AdapterError::DiscoveryFailed - 401 →
AdapterError::Unauthorized - Calls
tools/list→ MCP tools - For each tool:
HandlerRegistrationwithFromMCPprovenance spec.name= tool name (ornamespace/tool_name)spec.op_type=Mutation(MCP tools are call/response)spec.visibility=Internal(ADR-015)spec.input_schema= tool'sinputSchemaspec.output_schema= declaredoutputSchemaif present, elseContentBlockunionprovenance=FromMCP,composition_authority: None,scoped_env: None(ADR-022)capabilities= bearer token (injected at registration)
-
from_mcpoutput handling (http-mcp.md §"Output handling"):structured_contentpresent → use as result (validated againstoutput_schema)structured_contentabsent → mapcontent: Vec<ContentBlock>toContentBlockunion- No heuristic
JSON.parseof text blocks (carry asContentBlock) isError: true→CallError(not the output handling path)- rmcp client connection maintained for registration lifetime
-
from_mcpno-env-vars (ADR-014):- Handler reads
context.capabilities, neverstd::env::var - Bearer token from
Capabilities, not env vars
- Handler reads
-
to_mcpconformance (http-mcp.md, ADR-041):- Implements rmcp
ServerHandlertrait (call_tool,list_tools) tools/listreturns 4 fixed gateway tools (search,schema,call,batch)tools/listdoes NOT return registry's operations (discovered viasearch)search→ dispatchesservices/listviaGatewayDispatch::invokesearchresults areAccessControl::check(identity)-filteredSubscriptionops filtered out ofsearchresults (ADR-041 §2)schema→ dispatchesservices/schemaviaGatewayDispatch::invokecall→ dispatches viaGatewayDispatch::invoke(shared spine)callresult →CallToolResult::structured(value)forOkcallerror →CallToolResult::structured_error(details)forErr(CallError)batch→ loop overinvoke, returns arrayto_mcpis a pure projection (consumes registry, does not produce entries)
- Implements rmcp
-
to_mcpauth (http-mcp.md, research §4.4):- Bearer auth via shared
bearer_auth_middleware(applied aroundnest_service) Identityread fromRequestContext.extensionsinsidecall_tool- Identity survives rmcp framing (research §6 #2 — confirmed by spike)
- MCP client has no
PeerId(not an alknet peer, ADR-034 §4) AccessControlgatessearchresults andcalldispatch
- Bearer auth via shared
-
to_mcprmcp integration (http-mcp.md, research §4):StreamableHttpServicenested into axumRouterat/mcpServerHandlerimpl is a gateway service (4 fixed tools)- rmcp owns JSON-RPC framing, session management, SSE priming
to_mcpownscall_tool/list_toolsdispatch +CallToolResultmapping
-
Streamable HTTP only (ADR-037):
- stdio transport NOT built (not a dependency, not optional, not behind a feature)
mcpfeature pulls in rmcp with streamable HTTP transport features onlytransport-child-processis not a dependency
-
Feature gate isolation:
from_mcp/to_mcpcompile only withmcpfeaturecargo check -p alknet-http(nomcp) succeeds — MCP code not compiledcargo check -p alknet-http --features mcpsucceeds
-
Shared dispatch spine (research §5.1):
to_mcpcallusesGatewayDispatch::invoke(same spine asto_openapi)ResponseEnvelope→CallToolResultmapping isto_mcp-specific- No
GatewayDispatchtrait (concrete struct) - Identity resolution, context construction, invoke are shared (security axis)
- Wire framing, discovery, streaming are per-gateway (presentation axis)
-
Error fidelity (ADR-023):
from_mcperror_schemas from MCP tool error descriptionsto_mcpcallerror →CallToolResult::structured_errorwith typeddetails- No collision with protocol-level codes
-
Security constraints:
- No-env-vars invariant (from_mcp reads context.capabilities, ADR-014)
- MCP clients are not peers (no PeerId, ADR-034 §4)
- AccessControl gates search results and call dispatch
- No secret material in CallToolResult
-
Test coverage:
- Unit tests for from_mcp (import, outputSchema present/absent, isError)
- Unit tests for to_mcp (tools/list returns 4, search/schema/call/batch)
- Integration test: MCP client → search → schema → call round-trip
- Integration test: Bearer auth gates to_mcp service
- Integration test: no-env-vars (no std::env::var in from_mcp)
- Feature gate: cargo check without mcp succeeds
Acceptance Criteria
- from_mcp matches http-mcp.md (OperationAdapter, tools/list, outputSchema handling)
- from_mcp output handling: structuredContent-preferred, ContentBlock fallback, no JSON.parse
- from_mcp no-env-vars: reads context.capabilities, never std::env::var
- to_mcp matches ADR-041 (4-tool gateway, not one tool per operation)
- to_mcp Subscription excluded from search results
- to_mcp uses GatewayDispatch::invoke (shared spine)
- to_mcp CallToolResult mapping correct (structured/structured_error)
- to_mcp auth: shared middleware, Identity survives rmcp framing
- Streamable HTTP only (ADR-037 — stdio NOT built)
- Feature gate isolation (mcp code not compiled without mcp feature)
- No GatewayDispatch trait (concrete struct, research recommendation)
- Error fidelity (ADR-023 — no collision with protocol codes)
- MCP clients are not peers (no PeerId, ADR-034 §4)
- AccessControl gates search and call
- No secret material in CallToolResult
- Test coverage adequate for all MCP functionality
cargo fmt --check -p alknet-http --features mcppassescargo clippy -p alknet-http --features mcppasses with no warningscargo test -p alknet-http --features mcppassescargo check -p alknet-http(no mcp) succeeds
References
- docs/architecture/crates/http/http-mcp.md — full MCP spec
- docs/research/alknet-http-gateway-factoring/findings.md — §4 (rmcp constraints), §4.4 (auth sharing)
- docs/architecture/decisions/037-mcp-stdio-transport-exclusion.md — ADR-037
- docs/architecture/decisions/041-mcp-tool-gateway-pattern.md — ADR-041
- docs/architecture/decisions/017-call-protocol-client-and-adapter-contract.md — ADR-017 §5
- docs/architecture/decisions/023-operation-error-schemas.md — ADR-023
- docs/architecture/decisions/014-secret-material-flow-and-capability-injection.md — ADR-014
- docs/architecture/decisions/034-outgoing-only-x509-and-three-peer-roles.md — ADR-034 §4
- /workspace/rust-sdk/ — rmcp SDK (ServerHandler, StreamableHttpService, CallToolResult)
Notes
The MCP adapters are feature-gated and the most SDK-coupled part of the crate (rmcp integration). The review should verify: (1) streamable HTTP only (no stdio, ADR-037), (2) the 4-tool gateway pattern (ADR-041, not one tool per operation), (3) the output handling (structuredContent-preferred, ContentBlock fallback, no JSON.parse), (4) the shared dispatch spine is used for to_mcp's call (same spine as to_openapi), (5) the auth middleware is shared (Identity survives rmcp framing — research §6 #2), (6) the no-env-vars invariant holds, (7) feature gate isolation (MCP code not compiled without mcp). If deviations are found, document and fix before considering the MCP adapters complete.
Summary
To be filled on completion