mastra/Core Concepts

Server

Deploy Mastra as a standalone server with various adapters and authentication

serverdeploymentadaptersauthentication

Server

Deploy Mastra as a standalone server with various adapters.

Topics

Mastra Server

Mastra Server provides a standalone server for deploying AI agents and workflows.

Quick Start

import { MastraServer } from '@mastra/server';

const server = new MastraServer({
  mastra: myMastra,
  port: 3000,
});

await server.start();

Server Options

const server = new MastraServer({
  mastra: myMastra,
  port: 3000,
  host: '0.0.0.0',
  cors: {
    origin: '*',
  },
  logging: true,
});

Health Check

const health = await fetch('http://localhost:3000/health');
const { status, version, uptime } = await health.json();

Shutdown

await server.stop();

Mastra Client

Client SDK for connecting to a Mastra server.

Installation

npm install @mastra/client

Basic Usage

import { MastraClient } from '@mastra/client';

const client = new MastraClient({
  baseUrl: 'http://localhost:3000',
  apiKey: 'your-api-key',
});

// Get an agent
const agent = client.getAgent('myAgent');

// Generate a response
const response = await agent.generate('Hello, world!');
console.log(response.text);

Client Options

const client = new MastraClient({
  baseUrl: 'http://localhost:3000',
  apiKey: 'your-api-key',
  timeout: 30000,
  headers: {
    'X-Custom-Header': 'value',
  },
});

Streaming

const stream = await agent.stream('Tell me a story');

for await (const chunk of stream) {
  process.stdout.write(chunk.text);
}

Workflows

const workflow = client.getWorkflow('myWorkflow');

const run = await workflow.createRun();
await run.start({ input: 'test' });

Error Handling

try {
  const response = await agent.generate('Hello');
} catch (error) {
  if (error instanceof MastraClientError) {
    console.error('Client error:', error.message);
  } else if (error instanceof MastraServerError) {
    console.error('Server error:', error.status, error.message);
  }
}

Server Adapters

Connect Mastra to different web frameworks.

Available Adapters

  • Express - Express.js adapter
  • Fastify - Fastify adapter
  • Hono - Hono adapter
  • Koa - Koa adapter

Express Adapter

import { createExpressAdapter } from '@mastra/server/express';

const app = express();
const adapter = createExpressAdapter({
  mastra: myMastra,
});

app.use('/api/mastra', adapter);

Fastify Adapter

import { createFastifyAdapter } from '@mastra/server/fastify';

const fastify = Fastify();
const adapter = createFastifyAdapter({
  mastra: myMastra,
});

await fastify.register(adapter, { prefix: '/api/mastra' });

Hono Adapter

import { createHonoAdapter } from '@mastra/server/hono';
import { Hono } from 'hono';

const app = new Hono();
const adapter = createHonoAdapter({
  mastra: myMastra,
});

app.route('/api/mastra', adapter);

Koa Adapter

import { createKoaAdapter } from '@mastra/server/koa';
import Koa from 'koa';

const app = new Koa();
const adapter = createKoaAdapter({
  mastra: myMastra,
});

app.use(adapter.routes());

Custom Adapters

Build your own server adapter for any framework.

Adapter Interface

import { Adapter, AdapterRequest, AdapterResponse } from '@mastra/server';

class MyAdapter implements Adapter {
  async handle(request: AdapterRequest): Promise<AdapterResponse> {
    // Process request
    const result = await this.mastra.handle(request);

    // Return response
    return {
      status: 200,
      body: result,
      headers: {
        'Content-Type': 'application/json',
      },
    };
  }
}

Registering Routes

class MyAdapter implements Adapter {
  registerRoute(method: string, path: string, handler: Function) {
    // Register the route with your framework
  }
}

Error Handling

class MyAdapter implements Adapter {
  async handle(request: AdapterRequest): Promise<AdapterResponse> {
    try {
      const result = await this.mastra.handle(request);
      return { status: 200, body: result };
    } catch (error) {
      return {
        status: error.status || 500,
        body: { error: error.message },
      };
    }
  }
}

Middleware

Add middleware to the Mastra server.

Built-in Middleware

const server = new MastraServer({
  mastra: myMastra,
  middleware: [
    cors(),
    compression(),
    logger(),
  ],
});

Custom Middleware

const server = new MastraServer({
  mastra: myMastra,
  middleware: [
    async (request, next) => {
      const start = Date.now();
      const response = await next(request);
      console.log(`${request.path} - ${Date.now() - start}ms`);
      return response;
    },
  ],
});

Middleware Types

  • Logging - Log requests and responses
  • Authentication - Verify API keys, JWTs
  • Rate Limiting - Prevent abuse
  • CORS - Handle cross-origin requests
  • Compression - Compress responses

Framework Middleware

For Express/Fastify/etc., use the framework's native middleware:

const adapter = createExpressAdapter({
  mastra: myMastra,
});

app.use(cookieParser());
app.use(helmet());
app.use(rateLimit({ max: 100 }));
app.use('/api/mastra', adapter);

Request Context

Access request context in handlers and tools.

Context Object

interface RequestContext {
  request: AdapterRequest;
  mastra: Mastra;
  agent?: Agent;
  user?: User;
  metadata: Record<string, unknown>;
}

Accessing Context

// In a tool
const myTool = createTool({
  name: 'myTool',
  execute: async (input, context) => {
    const userId = context.user?.id;
    const requestId = context.metadata.requestId;
    return { userId, requestId };
  },
});

Setting Context

// Server middleware
const server = new MastraServer({
  mastra: myMastra,
  middleware: [
    async (request, next) => {
      const enhancedRequest = {
        ...request,
        metadata: {
          ...request.metadata,
          requestId: generateId(),
          userId: getUserId(request),
        },
      };
      return next(enhancedRequest);
    },
  ],
});

Context in Workflows

workflow.step('process', async ({ context }) => {
  const userId = context.user?.id;
  // Use userId to personalize processing
});

Custom API Routes

Add custom routes to the Mastra server.

Adding Routes

const server = new MastraServer({
  mastra: myMastra,
  customRoutes: [
    {
      method: 'GET',
      path: '/health',
      handler: () => new Response('OK'),
    },
    {
      method: 'POST',
      path: '/webhook',
      handler: async (request) => {
        const body = await request.json();
        // Process webhook
        return Response.json({ received: true });
      },
    },
  ],
});

Route Handler

const handler = async (request: Request): Promise<Response> => {
  // Access mastra instance
  const agent = mastra.getAgent('myAgent');

  // Process request
  const body = await request.json();
  const result = await agent.generate(body.prompt);

  return Response.json({ result });
};

Dynamic Routes

customRoutes: [
  {
    method: 'GET',
    path: '/users/:id',
    handler: async (request) => {
      const id = request.params.id;
      const user = await getUser(id);
      return Response.json(user);
    },
  },
],

Route Options

{
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
  path: string,
  handler: Function,
  middleware?: Function[],
}

Server Auth

Authentication providers for Mastra Server.

Supported Providers

  • Auth0
  • Better Auth
  • Clerk
  • Firebase
  • JSON Web Token (JWT)
  • Okta
  • Supabase
  • WorkOS
  • Custom Auth Provider
  • Composite Auth
  • Simple Auth

Simple Auth

Simple API key authentication for Mastra Server.

Configuration

import { SimpleAuthProvider } from '@mastra/auth';

const server = new MastraServer({
  auth: {
    provider: new SimpleAuthProvider({
      apiKeys: [
        { key: 'sk_test_123', userId: 'user-1' },
        { key: 'sk_test_456', userId: 'user-2' },
      ],
    }),
  },
});

Adding API Keys

server.auth.addAPIKey({
  key: 'sk_test_789',
  userId: 'user-3',
  metadata: { role: 'admin' },
});

Using API Keys

// Include API key in header
fetch('/api/agent', {
  headers: {
    'Authorization': 'Bearer sk_test_123',
  },
});

Protected Routes

server.route({
  path: '/api/agent',
  auth: { required: true },
  handler: async (request) => {
    const user = request.user;
    return Response.json({ userId: user.id });
  },
});

JSON Web Token (JWT)

Configure custom JWT authentication for Mastra Server.

Configuration

import { JWTProvider } from '@mastra/auth';

const server = new MastraServer({
  auth: {
    provider: new JWTProvider({
      secret: 'your-secret-key',
      issuer: 'mastra',
      audience: 'api',
      expiresIn: '1d',
    }),
  },
});

Generating Tokens

const token = await server.generateToken({
  userId: 'user-123',
  role: 'admin',
});

Verifying Tokens

server.route({
  path: '/api/protected',
  auth: { required: true },
  handler: async (request) => {
    const user = request.user;
    return Response.json({ user });
  },
});

Token Payload

interface JWTPayload {
  userId: string;
  role: string;
  iat: number;
  exp: number;
  iss: string;
  aud: string;
}

Custom Auth Provider

Build your own authentication provider.

Interface

import { AuthProvider, AuthResult } from '@mastra/auth';

class CustomAuthProvider implements AuthProvider {
  async authenticate(request: Request): Promise<AuthResult> {
    // Extract and verify credentials
    const token = request.headers.get('Authorization');

    if (!token) {
      return { authenticated: false };
    }

    // Verify token
    const user = await verifyMyToken(token);

    return {
      authenticated: true,
      user: {
        id: user.id,
        email: user.email,
        metadata: user.metadata,
      },
    };
  }

  async generateToken(user: User): Promise<string> {
    return generateMyToken(user);
  }
}

Usage

const server = new MastraServer({
  auth: {
    provider: new CustomAuthProvider(),
  },
});

Error Handling

class CustomAuthProvider implements AuthProvider {
  async authenticate(request: Request): Promise<AuthResult> {
    try {
      // Authentication logic
    } catch (error) {
      return {
        authenticated: false,
        error: 'Authentication failed',
      };
    }
  }
}