Skip to content

feat(server): add asgi_middleware param to serve()#441

Merged
bokelley merged 3 commits intomainfrom
claude/issue-415-asgi-middleware-callable-factory
May 3, 2026
Merged

feat(server): add asgi_middleware param to serve()#441
bokelley merged 3 commits intomainfrom
claude/issue-415-asgi-middleware-callable-factory

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

@bokelley bokelley commented May 3, 2026

Closes #415

Adds asgi_middleware to serve(), _serve_mcp(), _run_mcp_http(), and _serve_a2a(). The parameter accepts a sequence of entries that are each either a (callable, kwargs) tuple or a bare callable factory f(app) -> app. Both forms compose outermost-first. Applied on HTTP transports (streamable-http, sse, a2a); silently ignored (with a logger.warning) on stdio.

A module-level ASGIMiddlewareEntry type alias is added and exported from adcp.server, mirroring the SkillMiddleware pattern.

What was tested

  • pytest tests/test_serve_asgi_middleware.py — 6 new tests: no-op, outermost-first ordering, kwargs passthrough, callable factory, functools.partial factory, mixed tuple+callable ordering. All pass.
  • Full suite (pytest tests/ --ignore=tests/integration) — 2318 passed, 21 skipped, 1 xfailed (pre-existing network test excluded).
  • ruff check src/adcp/server/serve.py src/adcp/server/__init__.py — clean.
  • mypy src/adcp/server/serve.py — no new errors (pre-existing missing-stub errors for optional deps are unaffected).

Pre-PR review

  • code-reviewer: approved — no blockers; noted stdio silent-drop (fixed with logger.warning) and commit title accuracy (addressed).
  • dx-expert: approved after one blocker fix — widened typeCallable[..., Any] in the tuple annotation so functools.partial as the tuple's first element passes mypy. Also flagged missing ASGIMiddlewareEntry export (fixed).

Remaining nits (surfaced, not fixed):

  • _apply_asgi_middleware has no validation guard for malformed entries (e.g. 3-tuples produce a decontextualized ValueError). Follow-up issue welcome.
  • No test for the size_limit ordering invariant (_wrap_with_size_limit always outermost). Worth a follow-up.
  • create_mcp_server() auth docs reference add_middleware() as an alternative pattern without cross-referencing asgi_middleware=. Docs follow-up.

Triage-managed PR. This bot does not currently iterate on
review comments or PR conversation threads (only on the source
issue). To unblock:

  • Push fixup commits directly: gh pr checkout <num>
    fix → push.
  • Or re-trigger: comment /triage execute on the source
    issue.

See adcp#3121
for context.

Session: https://claude.ai/code/session_01GttQNCHuVSVUyRW5knbitw


Generated by Claude Code

claude added 3 commits May 3, 2026 00:07
…lewareEntry alias

Fixes the tuple form annotation so functools.partial is accepted as the
first element without a mypy error. Adds ASGIMiddlewareEntry type alias
to reduce repetition across five annotation sites. Adds a logger.warning
when asgi_middleware is passed with transport='stdio' (where it is silently
ignored).

https://claude.ai/code/session_01GttQNCHuVSVUyRW5knbitw
Mirrors the SkillMiddleware export pattern so users can annotate
their own asgi_middleware lists with the canonical type alias.

https://claude.ai/code/session_01GttQNCHuVSVUyRW5knbitw
@bokelley bokelley force-pushed the claude/issue-415-asgi-middleware-callable-factory branch from 18c1a7d to a19d64b Compare May 3, 2026 04:09
@bokelley bokelley marked this pull request as ready for review May 3, 2026 04:16
@bokelley bokelley merged commit 69211a3 into main May 3, 2026
11 of 13 checks passed
bokelley added a commit that referenced this pull request May 3, 2026
Bring the branch up to date with main (PRs #441, #444, #445, #446, #447).
Conflicts resolved:

* ``.github/workflows/ci.yml`` — keep main's restructured v3 storyboard
  job (translator-pattern upstream mock + readiness loop) and apply
  the poll-fix pattern (``||`` outside command substitution) to both
  the upstream-mock readiness loop and main's new seller-readiness
  loop.
* ``src/adcp/server/serve.py`` — combine main's strict-by-default
  ``validation=DEFAULT_VALIDATION`` flip with the three transport-
  security kwargs added on this branch (``allowed_hosts``,
  ``allowed_origins``, ``enable_dns_rebinding_protection``).

Auto-merged: ``examples/v3_reference_seller/src/app.py`` (translator
rewrite + this branch's webhook/dispose/DNS-rebinding kwargs),
``examples/v3_reference_seller/tests/test_smoke.py`` (translator
rewrite + this branch's port-stripping regression test),
``src/adcp/server/mcp_tools.py`` (lazy schema gen + this branch's
``setdefault("type", "object")`` for union outputSchemas),
``examples/seller_agent.py`` (channels filter intact).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(server): asgi_middleware accepts Callable[[ASGIApp], ASGIApp] factories

2 participants