middleware icon indicating copy to clipboard operation
middleware copied to clipboard

feat: support for auth in hono/mcp

Open MathurAditya724 opened this issue 5 months ago • 9 comments

Which middleware is the feature for?

@hono/mcp

What is the feature you are proposing?

  • [x] Update the HTTP transport based on the latest specs
  • [x] Add support for Auth
  • [x] Added Support for SSE Transport

MathurAditya724 avatar Jun 24 '25 06:06 MathurAditya724

I have started working on the PR

MathurAditya724 avatar Jun 24 '25 06:06 MathurAditya724

@MathurAditya724

Yes! Please!

yusukebe avatar Jun 24 '25 23:06 yusukebe

@MathurAditya724

Or, I've never tried, but can we make an app with auth with a combination of @hono/mcp and current middleware like @hono/oauth-providers without @hono/mcp side implementation?

yusukebe avatar Jun 24 '25 23:06 yusukebe

Yes that is the plan, it also requires rate limiter, so will be using hono-rate-limiter.

Basically, with the auth middleware you will not have to setup a few things and in the background we will be using the ecosystem middleware's

MathurAditya724 avatar Jun 25 '25 01:06 MathurAditya724

@MathurAditya724

It's up to you, but what we need are some examples using @hono/mcp, like stateful and auth.

yusukebe avatar Jun 26 '25 03:06 yusukebe

Working on that too on the side - https://www.muppet.dev/docs/hono-mcp

Still early but will be adding more details soon

MathurAditya724 avatar Jun 26 '25 03:06 MathurAditya724

Working on that too on the side - https://www.muppet.dev/docs/hono-mcp

Cool! This will help many people!

yusukebe avatar Jun 26 '25 06:06 yusukebe

hey in the docs on https://www.muppet.dev/docs/hono-mcp/stateful I have noticed that the transport is not reused. I think it is necessary to use the same transport repeatedly ?

I have done it like this:

.all('/mcp', async (c) => {
      let sessionId = c.req.header('mcp-session-id')

      if (sessionId && c.env.transports.has(sessionId)) {
        const transport = c.env.transports.get(sessionId)!

        return transport.handleRequest(c)
      } else if (!sessionId && isInitializeRequest(await c.req.json())) {
        const transport = new StreamableHTTPTransport({
          sessionIdGenerator: () => ulid(),
          onsessioninitialized: (sessionId) => {
            log('session initialized', sessionId)
            c.env.transports.set(sessionId, transport)
          },
        })

        transport.onclose = () => {
          const sid = transport.sessionId
          if (sid && c.env.transports.has(sid)) {
            c.env.transports.delete(sid)
          }
          console.log('transport closed', sid)
        }
        await c.env.mcpServer.connect(transport)
        return transport.handleRequest(c)
      }
      throw new HTTPException(400, { message: 'Bad Request: No session id' })
    })

I copied the patterns from the typescript-sdk for mcp.

inverted-capital avatar Aug 01 '25 10:08 inverted-capital

@yusukebe The PR is ready for review 🚀

I have also added the SSE transport because some people wanted to use it, so I have added a basic version and marked it experimental. If it doesn't makes sense we can remove it in the later version.

I will update the docs for these new changes

MathurAditya724 avatar Aug 16 '25 00:08 MathurAditya724