# Express Adapter The `@mastra/express` package provides a server adapter for running Mastra with [Express](https://expressjs.com). > **Info:** For general adapter concepts (constructor options, initialization flow, etc.), see [Server Adapters](https://mastra.ai/docs/server/server-adapters). ## Installation Install the Express adapter and Express framework: **npm**: ```bash npm install @mastra/express@latest express ``` **pnpm**: ```bash pnpm add @mastra/express@latest express ``` **Yarn**: ```bash yarn add @mastra/express@latest express ``` **Bun**: ```bash bun add @mastra/express@latest express ``` ## Usage example ```typescript import express from 'express'; import { MastraServer } from '@mastra/express'; import { mastra } from './mastra'; const app = express(); app.use(express.json()); // Required for body parsing const server = new MastraServer({ app, mastra }); await server.init(); app.listen(4111, () => { console.log('Server running on port 4111'); }); ``` > **Note:** Express requires `express.json()` middleware for JSON body parsing. Add it before creating the `MastraServer`. ## Constructor parameters **app:** (`Application`): Express app instance **mastra:** (`Mastra`): Mastra instance **prefix?:** (`string`): Route path prefix (e.g., \`/api/v2\`) (Default: `''`) **openapiPath?:** (`string`): Path to serve OpenAPI spec (e.g., \`/openapi.json\`) (Default: `''`) **bodyLimitOptions?:** (`{ maxSize: number, onError: (err) => unknown }`): Request body size limits **streamOptions?:** (`{ redact?: boolean }`): Stream redaction config. When true, redacts sensitive data from streams. (Default: `{ redact: true }`) **customRouteAuthConfig?:** (`Map`): Per-route auth overrides. Keys are \`METHOD:PATH\` (e.g., \`GET:/api/health\`). Value \`false\` makes route public, \`true\` requires auth. **tools?:** (`Record`): Available tools for the server **taskStore?:** (`InMemoryTaskStore`): Task store for A2A (Agent-to-Agent) operations **mcpOptions?:** (`MCPOptions`): MCP transport options. Set \`serverless: true\` for stateless environments like Cloudflare Workers or Vercel Edge. ## Differences from Hono | Aspect | Express | Hono | | -------------------- | ------------------------------ | --------------------- | | Body parsing | Requires `express.json()` | Handled by framework | | Context storage | `res.locals` | `c.get()` / `c.set()` | | Middleware signature | `(req, res, next)` | `(c, next)` | | Streaming | `res.write()` / `res.end()` | `stream()` helper | | AbortSignal | Created from `req.on('close')` | `c.req.raw.signal` | ## Adding custom routes Add routes directly to the Express app: ```typescript const app = express(); app.use(express.json()); const server = new MastraServer({ app, mastra }); // Before init - runs before Mastra middleware app.get('/early-health', (req, res) => res.json({ status: 'ok' })); await server.init(); // After init - has access to Mastra context app.get('/custom', (req, res) => { const mastraInstance = res.locals.mastra; res.json({ agents: Object.keys(mastraInstance.listAgents()) }); }); app.listen(4111); ``` > **Tip:** Routes added before `init()` run without Mastra context. Add routes after `init()` to access the Mastra instance and request context. ## Accessing context In Express middleware and routes, access Mastra context via `res.locals`: ```typescript app.get('/custom', (req, res) => { const mastra = res.locals.mastra; const requestContext = res.locals.requestContext; const abortSignal = res.locals.abortSignal; const agent = mastra.getAgent('myAgent'); res.json({ agent: agent.name }); }); ``` Available properties on `res.locals`: | Key | Description | | ----------------------- | --------------------------------------- | | `mastra` | Mastra instance | | `requestContext` | Request context map | | `abortSignal` | Request cancellation signal | | `tools` | Available tools | | `taskStore` | Task store for A2A operations | | `customRouteAuthConfig` | Per-route auth overrides | | `user` | Authenticated user (if auth configured) | ## Adding middleware Add Express middleware before or after `init()`: ```typescript const app = express(); app.use(express.json()); // Middleware before init app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); }); const server = new MastraServer({ app, mastra }); await server.init(); // Middleware after init has access to Mastra context app.use((req, res, next) => { const mastra = res.locals.mastra; next(); }); ``` ## Manual initialization For custom middleware ordering, call each method separately instead of `init()`. See [manual initialization](https://mastra.ai/docs/server/server-adapters) for details. ## Examples - [Express Adapter](https://github.com/mastra-ai/mastra/tree/main/examples/server-express-adapter) - Basic Express server setup ## Related - [Server Adapters](https://mastra.ai/docs/server/server-adapters) - Shared adapter concepts - [MastraServer Reference](https://mastra.ai/reference/server/mastra-server) - Full API reference - [createRoute() Reference](https://mastra.ai/reference/server/create-route) - Creating type-safe custom routes