Elysia adapter
The @mastra/elysia package provides a server adapter for running Mastra with Elysia.
For general adapter concepts, constructor options, and initialization flow, see Server Adapters.
InstallationDirect link to Installation
Install the Elysia adapter and Elysia framework:
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/elysia@latest elysia
pnpm add @mastra/elysia@latest elysia
yarn add @mastra/elysia@latest elysia
bun add @mastra/elysia@latest elysia
Usage exampleDirect link to Usage example
import { Elysia } from 'elysia'
import { MastraServer } from '@mastra/elysia'
import { mastra } from './mastra'
const app = new Elysia()
const server = new MastraServer({ app, mastra })
await server.init()
app.listen(3000)
console.log('Server running on http://localhost:3000')
Constructor parametersDirect link to Constructor parameters
app:
mastra:
prefix?:
/api/v2)openapiPath?:
/openapi.json)bodyLimitOptions?:
streamOptions?:
customRouteAuthConfig?:
METHOD:PATH (e.g., GET:/api/health). Value false makes route public, true requires auth.tools?:
taskStore?:
mcpOptions?:
serverless: true for stateless environments like Vercel Edge.Adding custom routesDirect link to Adding custom routes
Add routes directly to the Elysia app:
import { Elysia } from 'elysia'
import { MastraServer } from '@mastra/elysia'
import { mastra } from './mastra'
const app = new Elysia()
const server = new MastraServer({ app, mastra })
// Before init - runs before Mastra middleware
app.get('/early-health', () => ({ status: 'ok' }))
await server.init()
// After init - has access to Mastra context
app.get('/custom', ({ mastra }) => {
return { agents: Object.keys(mastra.listAgents()) }
})
Routes added before init() run without Mastra context. Add routes after init() to access the Mastra instance and request context.
When you want Mastra-managed auth and route metadata such as requiresAuth, prefer registerApiRoute(). For raw Elysia routes mounted directly on app, use createAuthMiddleware():
import { Elysia } from 'elysia'
import { createAuthMiddleware, MastraServer } from '@mastra/elysia'
import { mastra } from './mastra'
const app = new Elysia()
const server = new MastraServer({ app, mastra })
await server.init()
app.get('/custom/protected', async ctx => {
const authResponse = await createAuthMiddleware({ mastra })(ctx)
if (authResponse) return authResponse
const user = ctx.requestContext.get('user')
return { user }
})
app.get('/custom/public', async ctx => {
const authResponse = await createAuthMiddleware({ mastra, requiresAuth: false })(ctx)
if (authResponse) return authResponse
return { ok: true }
})
Accessing contextDirect link to Accessing context
In Elysia handlers registered after init(), access Mastra context from the handler context:
app.get('/custom', ({ mastra, requestContext, abortSignal }) => {
const agent = mastra.getAgent('myAgent')
const user = requestContext.get('user')
return { agent: agent.name, user, aborted: abortSignal.aborted }
})
Available context keys:
| Key | Description |
|---|---|
mastra | Mastra instance |
requestContext | Request context map |
abortSignal | Request cancellation signal |
registeredTools | Available tools |
taskStore | Task store for A2A operations |
customRouteAuthConfig | Per-route auth overrides |
user | Authenticated user in requestContext when auth is configured |
OpenAPI helpersDirect link to OpenAPI helpers
Use getMastraOpenAPIDoc() when you need to pass Mastra's generated OpenAPI document to Elysia tooling such as @elysiajs/openapi:
import { openapi } from '@elysiajs/openapi'
import { Elysia } from 'elysia'
import { getMastraOpenAPIDoc, MastraServer } from '@mastra/elysia'
import { mastra } from './mastra'
const app = new Elysia()
const server = new MastraServer({ app, mastra })
await server.init()
app.use(
openapi({
documentation: getMastraOpenAPIDoc(server),
}),
)
Call clearMastraOpenAPICache(server) if you need to regenerate the cached document for the same server instance.
MCP supportDirect link to MCP support
The Elysia adapter supports both MCP HTTP and MCP SSE transports.
Manual initializationDirect link to Manual initialization
For custom middleware ordering, call each method separately instead of init(). See manual initialization for details.