Skip to content

feat(adapters): Hono adapter (#66) - #84

Merged
omkmorendha merged 2 commits into
mainfrom
66-hono-adapter
May 20, 2026
Merged

omkmorendha merged 2 commits into
mainfrom
66-hono-adapter

Conversation

@omkmorendha

@omkmorendha omkmorendha commented May 19, 2026 •

Copy link
Copy Markdown
Owner

Closes #66.

Summary

Adds mcp-authkit-adapter-hono (re-exported under mcp-authkit/adapters/hono),
mirroring the Express adapter. Provides honoMiddleware(authkit, mcp) plus
per-route helpers mcp, metadata, pats, and challenge.

Implementation

  • Private adaptation layer (packages/adapter-hono/src/adapt.ts): builds
    a synthetic IncomingMessage from c.req.raw (Web Request) and a
    synthetic ServerResponse whose writes hit a PassThrough. The first
    head-committing call (writeHead, flushHeaders, write, or end)
    resolves a Response whose body is Readable.toWeb(passthrough) — Hono
    ships that stream as the response body, so the MCP handler is never
    buffered.
  • Host header: Web Request has no Host header (the authority is in
    the URL). The adapter synthesises req.headers.host from URL.host so
    the spec §14 DNS-rebinding check sees the real authority.
  • No workspace cycle: like the Express adapter, this package does not
    depend on mcp-authkit at the package.json level. Core
    (packages/core/src/adapters/hono.ts) re-exports the public API and
    asserts structural compatibility at compile time.
  • Peer dependency: hono ^4.0.0.

Tests

Same handler matrix as adapter-express:

  • mcp forwarding + 401 challenge (no-bearer and invalid-bearer paths)
  • metadata + pats per-route forwarding
  • Response headers (WWW-Authenticate, Cache-Control) flow through
  • challenge() helper with and without reason
  • Error propagation: handler rejection before commit becomes 500 via
    onError

Hono-specific:

  • Streaming response — handler writes a chunk, blocks on a gate the
    test only resolves AFTER reading the chunk, then writes the rest. A
    buffered implementation would deadlock; the test passes because the
    body streams.
  • Request body is forwarded to the raw handler as a Readable.

End-to-end (integration.test.ts) over real @hono/node-server + real
createAuthKit + fetch:

  • Metadata serves the RFC 9728 document.
  • mcp/pats 401 challenges round-trip over the wire.
  • Forged Host returns 403 (DNS-rebinding mitigation, spec §14).
  • Allowlisted Host passes the check (host-only entry, any port).
  • Streaming verified across the HTTP boundary.

Spec sections touched

§5.9 (Hono adapter), §5.10 (import paths), §10 (Hono adapter requirements).

Test plan

  • pnpm lint
  • pnpm typecheck
  • pnpm test (365 passed, +24 new)
  • pnpm build

Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • New Hono adapter enabling MCP AuthKit integration with middleware for MCP, metadata, and PAT routes.
    • Streaming response support without buffering and automatic request/response adaptation.
  • Documentation

    • Added README with usage snippet and adapter behavior notes.
  • Tests

    • Added unit and integration tests validating routing, auth challenges, host validation, and streaming semantics.
  • Chores

    • Package/exports added to publish the Hono adapter and expose it from core.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 19, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@omkmorendha has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d8deb946-5bf3-4e0c-aa6a-35fec549de0b

📥 Commits

Reviewing files that changed from the base of the PR and between ed65653 and b5615d8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • packages/adapter-hono/README.md
  • packages/adapter-hono/package.json
  • packages/adapter-hono/src/adapt.ts
  • packages/adapter-hono/src/index.test.ts
  • packages/adapter-hono/src/index.ts
  • packages/adapter-hono/src/integration.test.ts
  • packages/adapter-hono/tsconfig.json
  • packages/core/package.json
  • packages/core/src/adapters/hono.ts
  • vitest.config.ts
📝 Walkthrough

Walkthrough

Adds a new package packages/adapter-hono that adapts Hono Context to Node-style MCP handlers with streaming responses, exposes honoHandlers/honoMiddleware, includes unit and integration tests, package/tsconfig metadata, README, and core re-exports.

Changes

Hono Adapter for mcp-authkit

Layer / File(s) Summary
Request/Response Adaptation Layer
packages/adapter-hono/src/adapt.ts
toIncomingMessage() converts Web Request to Node IncomingMessage with normalized headers and Readable body; createAdaptedResponse() provides a PassThrough-backed ServerResponse and resolves a Promise<Response> on first commit or error.
Handler Wrapping and Public API
packages/adapter-hono/src/index.ts
Exports RawHandlers, AuthKitLike, and HonoHandlers; wrap() adapts Node-style handlers into Hono middleware (streaming Response) using commit/error detection; honoHandlers() and honoMiddleware() wire handlers and mount routes.
Unit Tests
packages/adapter-hono/src/index.test.ts
Tests forwarding (method, path, Host), error propagation, header preservation, challenge() 401 responses, route mounting, streaming semantics, and request-body streaming to raw handlers.
Integration Tests
packages/adapter-hono/src/integration.test.ts
End-to-end tests via @hono/node-server validating RFC 9728 metadata, MCP/PAT challenges (missing/invalid tokens), host header validation, and non-buffered streaming with real AuthKit + McpServer.
Package Configuration
packages/adapter-hono/package.json, packages/adapter-hono/tsconfig.json, packages/core/package.json, vitest.config.ts
Adds adapter package manifest and tsconfig, new ./adapters/hono export and workspace dependency in core, and a Vitest resolve alias for local test resolution.
Documentation
packages/adapter-hono/README.md
README describing import path, mounted MCP/metadata/PAT handlers, Web-to-Node adaptation, and streaming behavior.
Core Package Integration
packages/core/src/adapters/hono.ts
Re-exports adapter runtime functions and types under core's API and includes compile-time structural type assertions for compatibility.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • omkmorendha/mcp-authkit#47: The Hono adapter's honoHandlers/wrap logic directly consumes the framework-agnostic authkit.handlers(...) implementations for mcp/metadata/pats/challenge endpoints introduced there.

Suggested labels

stage-2, type:feat

Poem

🐰 Hoppy hops through Hono's streams,

Adapting Web to Node, it gleams,
No buffering — chunks flow free,
Bearer challenges, PATs agree,
A rabbit cheers: "Streams, yes please!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(adapters): Hono adapter' clearly and specifically describes the main change: adding a new Hono adapter to the adapters suite.
Linked Issues check ✅ Passed All core objectives from issue #66 are met: packages/adapter-hono created with honoMiddleware and per-route helpers, Web-to-Node adaptation layer implemented, streaming responses enabled, host header synthesis, test coverage matching adapter-express plus Hono-specific streaming and integration tests.
Out of Scope Changes check ✅ Passed All changes directly support the Hono adapter implementation: package structure, adaptation layer, handlers, tests, configuration, and core re-export with type assertions. No out-of-scope modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 66-hono-adapter

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/adapter-hono/package.json`:
- Around line 41-50: Update the vulnerable package versions in package.json:
bump "`@hono/node-server`" from "1.19.0" to at least "1.19.13" (in
devDependencies) and bump "hono" from "4.0.0" to at least "4.12.18" (in both
peerDependencies and devDependencies), then reinstall/update the lockfile
(npm/yarn/pnpm) so the lockfile reflects the upgrades; target the dependency
entries for "`@hono/node-server`" and "hono" when making the changes.

In `@packages/adapter-hono/src/index.test.ts`:
- Line 216: The test uses the Node-22-only API Promise.withResolvers (const gate
= Promise.withResolvers<void>()); replace this with a Node-20-compatible manual
deferred: add a small helper deferred<T>() that constructs a Promise and
captures its resolve/reject (returning { promise, resolve, reject }), then
change the instantiation to const gate = deferred<void>(); update any uses of
the resolver to use gate.promise where the Promise was expected and call
gate.resolve()/gate.reject() where the test previously used the withResolvers
resolvers; reference symbols: Promise.withResolvers, gate, deferred, and replace
usages throughout the test.

In `@packages/adapter-hono/src/integration.test.ts`:
- Line 210: Replace the use of Promise.withResolvers for the test-level gate by
creating a manual promise with externally-captured resolve/reject functions:
instead of calling Promise.withResolvers() for the variable gate, create a new
Promise that assigns its resolve and reject to outer variables (or a small
helper createResolvable) and expose those functions alongside the promise so
existing test code that awaits gate or calls gate.resolve()/gate.reject()
continues to work; update any references to gate to use the promise object and
its captured resolve/reject functions (referencing the symbol gate and the
original Promise.withResolvers usage).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c128d233-db4f-4964-a5e6-4819dddcd948

📥 Commits

Reviewing files that changed from the base of the PR and between b53d7ba and 7819b6c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • packages/adapter-hono/README.md
  • packages/adapter-hono/package.json
  • packages/adapter-hono/src/adapt.ts
  • packages/adapter-hono/src/index.test.ts
  • packages/adapter-hono/src/index.ts
  • packages/adapter-hono/src/integration.test.ts
  • packages/adapter-hono/tsconfig.json
  • packages/core/package.json
  • packages/core/src/adapters/hono.ts
  • vitest.config.ts

Comment thread packages/adapter-hono/package.json
Comment thread packages/adapter-hono/src/index.test.ts Outdated
Comment thread packages/adapter-hono/src/integration.test.ts Outdated
claude added 2 commits May 20, 2026 09:06
Adds `mcp-authkit-adapter-hono`, exposed via `mcp-authkit/adapters/hono`,
mirroring the Express adapter. Provides `honoMiddleware(authkit, mcp)`
plus per-route helpers `mcp`, `metadata`, `pats`, and `challenge`.

The adapter privately bridges Hono's Web Fetch `Context` to Node-style
`IncomingMessage`/`ServerResponse` so the framework-agnostic v0.1
`Handlers` run unchanged. Responses stream through a `PassThrough` —
the `mcp` handler is never buffered, which matters for large MCP
payloads. The Host header is synthesised from the Web Request URL so
the DNS-rebinding check (spec §14) sees the real authority.

Tests cover the same handler matrix as `adapter-express` (mcp /
metadata / pats / 401 challenge), plus Hono-specific streaming
verification and end-to-end host-header validation against a real
`@hono/node-server`.

Closes #66.
- Replace Promise.withResolvers (Node 22+) with a manual deferred
  helper so the streaming tests run on Node 20.
- Bump @hono/node-server from ^1.19.0 to ^1.19.13 (security: GHSA-9hgr-4rmp-vgxw,
  GHSA-4r7q-rh3h-r9gq for authorization bypass and middleware bypass) and
  hono from ^4.0.0 to ^4.12.18 (advisories resolved by ^4.12.18).
@omkmorendha
omkmorendha merged commit c1d5045 into main May 20, 2026
5 checks passed
@omkmorendha
omkmorendha deleted the 66-hono-adapter branch May 20, 2026 03:37
Sign up for free to 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.

feat(adapters): Hono adapter

2 participants