Skip to main content

NestJS Adapter

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

It is intentionally Express-only for v1. If Nest is bootstrapped with a different HTTP adapter, MastraModule throws during startup instead of attempting a partial integration.

info

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 is 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`.

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 }
= `{ enabled: false }`
Enable Mastra token auth. Disabled by default — most NestJS apps use their own auth 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-4o-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) {}
}

MCP routes
Direct link to MCP routes

MCP endpoints are exposed under the API prefix:

  • POST /api/mcp/:serverId/mcp
  • GET /api/mcp/:serverId/sse
  • POST /api/mcp/:serverId/messages

Health routes
Direct link to Health routes

Operational endpoints stay unprefixed on purpose for infrastructure compatibility:

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