Skip to main content

Hono Adapter

The @mastra/hono package provides a server adapter for running Mastra with Hono.

info

For general adapter concepts (constructor options, initialization flow, etc.), see Server Adapters.

Installation
Direct link to Installation

  1. Install the Hono adapter and Hono framework:

    npm install @mastra/hono hono
  2. Create your server file:

    server.ts
    import { Hono } from 'hono';
    import { HonoBindings, HonoVariables, MastraServer } from '@mastra/hono';
    import { mastra } from './mastra';

    const app = new Hono<{ Bindings: HonoBindings; Variables: HonoVariables }>();
    const server = new MastraServer({ app, mastra });

    await server.init();

    export default app;

Full example
Direct link to Full example

server.ts
import { Hono } from 'hono';
import { HonoBindings, HonoVariables, MastraServer } from '@mastra/hono';
import { mastra } from './mastra';

const app = new Hono<{ Bindings: HonoBindings; Variables: HonoVariables }>();

const server = new MastraServer({
app,
mastra,
prefix: '/api/v2',
openapiPath: '/openapi.json',
bodyLimitOptions: {
maxSize: 10 * 1024 * 1024, // 10MB
onError: (err) => ({ error: 'Payload too large', maxSize: '10MB' }),
},
streamOptions: { redact: true },
});

await server.init();

export default app;

Constructor parameters
Direct link to Constructor parameters

app:

Hono
Hono app instance

mastra:

Mastra
Mastra instance

prefix?:

string
= ''
Route path prefix (e.g., `/api/v2`)

openapiPath?:

string
= ''
Path to serve OpenAPI spec (e.g., `/openapi.json`)

bodyLimitOptions?:

{ maxSize: number, onError: (err) => unknown }
Request body size limits

streamOptions?:

{ redact?: boolean }
= { redact: true }
Stream redaction config. When true, redacts sensitive data from streams.

customRouteAuthConfig?:

Map<string, boolean>
Per-route auth overrides. Keys are `METHOD:PATH` (e.g., `GET:/api/health`). Value `false` makes route public, `true` requires auth.

tools?:

Record<string, Tool>
Available tools for the server

taskStore?:

InMemoryTaskStore
Task store for A2A (Agent-to-Agent) operations

Adding custom routes
Direct link to Adding custom routes

Add routes directly to the Hono app:

server.ts
import { Hono } from 'hono';
import { HonoBindings, HonoVariables, MastraServer } from '@mastra/hono';

const app = new Hono<{ Bindings: HonoBindings; Variables: HonoVariables }>();
const server = new MastraServer({ app, mastra });

// Before init - runs before Mastra middleware
app.get('/early-health', (c) => c.json({ status: 'ok' }));

await server.init();

// After init - has access to Mastra context
app.get('/custom', (c) => {
const mastraInstance = c.get('mastra');
return c.json({ agents: Object.keys(mastraInstance.listAgents()) });
});
tip

Routes added before init() run without Mastra context. Add routes after init() to access the Mastra instance and request context.

Accessing context
Direct link to Accessing context

In Hono middleware and route handlers, access Mastra context via c.get():

app.get('/custom', async (c) => {
const mastra = c.get('mastra');
const requestContext = c.get('requestContext');
const abortSignal = c.get('abortSignal');

const agent = mastra.getAgent('myAgent');
return c.json({ agent: agent.name });
});

Available context keys:

KeyDescription
mastraMastra instance
requestContextRequest context map
abortSignalRequest cancellation signal
toolsAvailable tools
taskStoreTask store for A2A operations
customRouteAuthConfigPer-route auth overrides
userAuthenticated user (if auth configured)

Adding middleware
Direct link to Adding middleware

Add Hono middleware before or after init():

server.ts
import { Hono } from 'hono';
import { HonoBindings, HonoVariables, MastraServer } from '@mastra/hono';

const app = new Hono<{ Bindings: HonoBindings; Variables: HonoVariables }>();

// Middleware before init
app.use('*', async (c, next) => {
console.log(`${c.req.method} ${c.req.url}`);
await next();
});

const server = new MastraServer({ app, mastra });
await server.init();

// Middleware after init has access to Mastra context
app.use('*', async (c, next) => {
const mastra = c.get('mastra');
// ...
await next();
});

Manual initialization
Direct link to Manual initialization

For custom middleware ordering, call each method separately instead of init(). See Server Adapters: Manual initialization for details.

Examples
Direct link to Examples