# 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](https://mastra.ai/docs/server/server-adapters).

## Installation

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

**npm**:

```bash
npm install @mastra/nestjs@latest
```

**pnpm**:

```bash
pnpm add @mastra/nestjs@latest
```

**Yarn**:

```bash
yarn add @mastra/nestjs@latest
```

**Bun**:

```bash
bun add @mastra/nestjs@latest
```

## Usage example

```typescript
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`).

```typescript
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

**mastra** (`Mastra`): Mastra instance

**prefix** (`string`): Route path prefix (e.g., \`/api/v2\`) (Default: `` `/api` ``)

**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 }`): 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. (Default: `` `{ enabled: false }` ``)

## Async registration

```typescript
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

Use the `MASTRA` token or `MastraService` in your services:

```typescript
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

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

Operational endpoints stay unprefixed on purpose for infrastructure compatibility:

- `GET /health`
- `GET /ready`
- `GET /info`

## Related

- [Server Adapters](https://mastra.ai/docs/server/server-adapters)
- [MastraServer Reference](https://mastra.ai/reference/server/mastra-server)