Skip to content

feat(api): wire MCP + A2A protocol endpoints into Nexo.API - #267

Merged
IanFrelinger merged 1 commit into
application/mcp-a2afrom
application/mcp-a2a-endpoints
Aug 13, 2026
Merged

feat(api): wire MCP + A2A protocol endpoints into Nexo.API#267
IanFrelinger merged 1 commit into
application/mcp-a2afrom
application/mcp-a2a-endpoints

Conversation

@IanFrelinger

Copy link
Copy Markdown
Owner

Summary

PR-4 of the MCP/A2A series — the application-layer wiring, targeting the long-lived application/mcp-a2a integration branch (created from the src-side chain #263#266 so the adapter code exists underneath; this PR''s diff touches only application/** per the layer-boundary rules; lands on master via coordinated merge once the src chain is in).

All four protocol directions become available on the API host, feature-flagged off by default.

Changes

  • Program.cs: AddNexoMcpServer().WithHttpTransport() + AddNexoMcpClient + AddNexoA2AServer + AddNexoA2ATransport (before AddNexo() so its scheme registration joins the remote-transport composition); read-only repo tools (repo.fs.read/repo.fs.list) registered for MCP allowlisting — mutating tools deliberately not pre-registered; MapNexoMcpEndpoint() + MapNexoA2AEndpoints() after the security chain with named per-IP rate-limit policies (nexo-mcp/nexo-a2a, off by default). No AllowAnonymous anywhere.
  • NexoApiKeyAuthMiddleware: protocol-path handling — /api/mcp, /api/a2a, and the spec-mandated root /.well-known/agent-card.json are protected on all verbs (the MCP SSE listen channel is a GET that the default mutating-verb scope ignored, and the root card lives outside /api entirely). Card anonymity is an explicit opt-in mirrored from Nexo:A2A:Server:AllowAnonymousAgentCard via the new NexoProtocolIngressOptions, keeping the middleware decoupled from adapter packages.
  • AgentRegistryA2ACatalog: host-side INexoA2AAgentCatalog over IAgentRegistry — the single place the domain persona model meets the A2A descriptor (adapter can''t reference Core.Domain per layering).
  • IngressCapabilitymcp/a2a keys, IngressCatalog operator-inventory rows, NexoMiddlewareIngressOptions rate-limit fields, appsettings.json explicit disabled defaults.
  • Nexo.API.csproj: adapter project references (note in-file: Nexo.API is not packed by any workflow today; if that changes the non-packable A2A refs must be revisited).

Testing

Live smoke on the built host (DOTNET_ROLL_FORWARD=Major, this machine lacks the net8 ASP.NET runtime):

  • Disabled defaults: /health 200 · POST /api/mcp 405 (unmapped) · /.well-known/agent-card.json 404 — surfaces fully dark
  • Enabled + ApiKey auth: POST /api/mcp initialize 401 without key, 200 with key returning a spec-correct result (protocolVersion negotiated down to the client''s 2025-06-18, serverInfo: nexo, tools capability)
  • Nexo.API builds clean with warnings-as-errors

[skip-prod-style] — ProdStyle endpoint tests live in src/Nexo.Tests.Infrastructure which this application-base PR cannot touch; they land in the follow-up src-side PR (ProdStyle suite + mcp-a2a-gate.yml + compose env rows).

Testing strategy (blast radius)

Change typeProof
API host wiring / auth middlewareLive-host smoke above; in-proc ProdStyle suite lands in the src-side follow-up PR
  • make kernel-coverage-gate — n/a (no src/ changes)
  • make kernel-gate — n/a
  • make test-prod-style — deferred to follow-up src PR per layer boundary (see [skip-prod-style])

Checklist

  • Documentation updated (design doc rows landed with the src-side PRs; DEPLOYMENT env examples land with compose changes in the follow-up)
  • No TODO or NotImplementedException left unresolved
  • Breaking changes are documented (none — all surfaces off by default; auth posture only adds protection on new paths)

Release (only when this PR ships a versioned NuGet/GHCR release)

  • Not a versioned release — skip

🤖 Generated with Claude Code

@cursor

cursorBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

All four protocol directions become available on the API host, feature-flagged
off by default (appsettings ships explicit disabled sections):
- Program.cs: AddNexoMcpServer().WithHttpTransport() + AddNexoMcpClient +
AddNexoA2AServer + AddNexoA2ATransport (before AddNexo so its scheme
registration joins the remote-transport composition); read-only repo tools
registered for MCP allowlisting; MapNexoMcpEndpoint + MapNexoA2AEndpoints
after the security chain with named per-IP rate-limit policies (nexo-mcp /
nexo-a2a, off by default via NexoMiddlewareIngressOptions fields).
- NexoApiKeyAuthMiddleware: protocol-path handling - /api/mcp, /api/a2a, and
the /.well-known/agent-card.json discovery path are protected on ALL verbs
(the MCP SSE listen channel is a GET the mutating-verb scope would have
ignored, and the root card lives outside /api entirely). Agent-card
anonymity is an explicit opt-in mirrored from Nexo:A2A:Server via the new
NexoProtocolIngressOptions so the middleware stays decoupled from adapters.
- AgentRegistryA2ACatalog: host-side INexoA2AAgentCatalog over IAgentRegistry
(the one place the domain persona model meets the A2A descriptor).
- IngressCapability mcp/a2a keys + IngressCatalog operator-inventory rows.
Live smoke on the built host: disabled => /health 200, /api/mcp 405, root card
404; enabled+ApiKey => 401 without key, 200 initialize with key (protocol
version negotiated down to the client's 2025-06-18).
[skip-prod-style]: ProdStyle endpoint tests live in src/Nexo.Tests.Infrastructure
(layer boundary forbids src/** changes here); they land in the follow-up
src-side PR together with the mcp-a2a CI gate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@IanFrelinger
IanFrelingerforce-pushed the application/mcp-a2a-endpoints branch from 503c49c to 74d58bcCompareAugust 13, 2026 18:17
@IanFrelinger
IanFrelinger merged commit c69c095 into application/mcp-a2aAug 13, 2026
13 checks passed
@IanFrelinger
IanFrelinger deleted the application/mcp-a2a-endpoints branch August 13, 2026 20:10
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@IanFrelinger@PlzTouchGrass