Skip to main content

NestJS Adapter

The @mastra/nestjs package provides a NestJS module for running Mastra with the Express-based NestJS platform.

It's intentionally Express-only for v1. If Nest is bootstrapped with a different HTTP adapter, MastraModule throws during startup instead of attempting a partial integration. For general adapter concepts, see Server Adapters.

Installation
Direct link to Installation

Install the NestJS adapter and ensure your app uses the Express platform:

npm install @mastra/nestjs@latest

Usage example
Direct link to Usage example

src/app.module.ts
import { Module } from '@nestjs/common'
import { MastraModule } from '@mastra/nestjs'
import { mastra } from './mastra'

@Module({
imports: [
MastraModule.register({
mastra,
}),
],
})
export class AppModule {}
note

MastraModule registers a catch-all controller (@All('*')). If it's imported before your app modules, it can intercept unrelated routes and return 404s. To avoid conflicts, import MastraModule last or mount it under a dedicated prefix (e.g., /api/v1/mastra).

src/main.ts
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'

async function bootstrap() {
const app = await NestFactory.create(AppModule)
await app.listen(3000)
}

bootstrap()

By default, Mastra routes mount under /api. Use prefix to change it.

Module options
Direct link to Module options

mastra:

Mastra
Mastra instance

prefix?:

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

rateLimitOptions?:

{ enabled?: boolean; defaultLimit?: number; windowMs?: number; generateLimit?: number }
Rate limiting config (enabled by default)

shutdownOptions?:

{ timeoutMs?: number; notifyClients?: boolean }
Graceful shutdown configuration

bodyLimitOptions?:

{ maxSize?: number; maxFileSize?: number; tempDir?: string; allowedMimeTypes?: string[] }
Request body size limits

streamOptions?:

{ redact?: boolean; heartbeatMs?: number }
Streaming configuration

tracingOptions?:

{ enabled?: boolean; serviceName?: string }
OpenTelemetry tracing configuration

contextOptions?:

{ strict?: boolean; logWarnings?: boolean }
Request context parsing config

customRouteAuthConfig?:

Map<string, boolean>
Per-route auth overrides. Keys are METHOD:PATH. Custom routes from server.apiRoutes (registerApiRoute()) are added automatically based on their requiresAuth setting.

tools?:

Record<string, Tool>
Registered tools for the server

taskStore?:

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

mcpOptions?:

{ serverless?: boolean; sessionIdGenerator?: () => string }
MCP transport options

auth?:

{ enabled?: boolean; allowQueryApiKey?: boolean }
Controls Mastra auth for Mastra routes. When server.auth is configured on your Mastra instance, it runs automatically (the same pipeline as other adapters: bearer tokens, cookie sessions, session refresh, and mapUserToResourceId). Set enabled: false to rely only on your own NestJS guards. Query-string apiKey auth is opt-in for backward compatibility.

Async registration
Direct link to Async registration

src/app.module.ts
import { Module } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { MastraModule } from '@mastra/nestjs'
import { Mastra } from '@mastra/core/mastra'

@Module({
imports: [
ConfigModule.forRoot(),
MastraModule.registerAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => ({
mastra: new Mastra({
agents: {
greeter: {
name: 'greeter',
description: 'Greets the user',
model: config.get('MASTRA_MODEL', 'openai/gpt-5-mini'),
},
},
}),
prefix: config.get('MASTRA_PREFIX', '/api'),
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}

Accessing Mastra
Direct link to Accessing Mastra

Use the MASTRA token or MastraService in your services:

import { Injectable, Inject } from '@nestjs/common'
import { MASTRA, MastraService } from '@mastra/nestjs'
import type { Mastra } from '@mastra/core/mastra'

@Injectable()
export class AgentService {
constructor(@Inject(MASTRA) private readonly mastra: Mastra) {}
}

@Injectable()
export class WorkflowService {
constructor(private readonly mastraService: MastraService) {}
}

Start background workers
Direct link to Start background workers

MastraModule doesn't start Mastra's background workers. Without them, scheduled workflows, agent schedules, and event listeners never run. Call mastra.startWorkers() after the app starts listening:

src/main.ts
import { NestFactory } from '@nestjs/core'
import { MASTRA } from '@mastra/nestjs'
import type { Mastra } from '@mastra/core/mastra'
import { AppModule } from './app.module'

async function bootstrap() {
const app = await NestFactory.create(AppModule)
app.enableShutdownHooks()
await app.listen(3000)

try {
await app.get<Mastra>(MASTRA).startWorkers()
} catch (error) {
console.error('Failed to start background workers', error)
await app.close()
process.exit(1)
}
}

bootstrap()

The module's shutdown handling drains in-flight requests but doesn't stop Mastra. To stop workers and drain in-flight workflow runs, call mastra.shutdown() from a shutdown hook. The drain is bounded by drainTimeout (default 5 seconds), and runs that don't settle within it are abandoned with a warning:

src/mastra-lifecycle.service.ts
import { Inject, Injectable, type OnApplicationShutdown } from '@nestjs/common'
import { MASTRA } from '@mastra/nestjs'
import type { Mastra } from '@mastra/core/mastra'

@Injectable()
export class MastraLifecycleService implements OnApplicationShutdown {
constructor(@Inject(MASTRA) private readonly mastra: Mastra) {}

async onApplicationShutdown() {
await this.mastra.shutdown()
}
}

Add MastraLifecycleService to the providers of a module that imports MastraModule. Shutdown hooks only run when app.enableShutdownHooks() is called.

See Start background workers for more details.

MCP routes
Direct link to MCP routes

MCP endpoints are exposed under the API prefix:

  • POST /api/mcp/:serverId/mcp

Health routes
Direct link to Health routes

Operational endpoints stay unprefixed on purpose for infrastructure compatibility:

  • GET /health
  • GET /ready
  • GET /info