github mastra-ai/mastra @mastra/core@1.32.0
May 4, 2026

8 hours ago

Highlights

Fine-Grained Authorization (FGA) across Mastra (core + server adapters + MCP)

Mastra now supports relationship-based, resource-level authorization with centralized enforcement before agent runs (generate()/stream()), tool/workflow execution, and memory thread access via new IFGAProvider/IFGAManager + checkFGA()/FGADeniedError. FGA is also enforced consistently in @mastra/server handlers, all built-in server adapters (Express/Fastify/Hono/Koa), and MCP tool execution.

WorkOS-backed FGA provider (@mastra/auth-workos)

New MastraFGAWorkos implements IFGAManager on top of the WorkOS Authorization API, including check/require/filterAccessible, resource CRUD, role assignments, org scoping, JWT/bearer-token context handling, and permission/resource mappings for multi-tenant setups.

Scheduled Workflows (cron-native) + scheduler + full HTTP/Studio/client support

Workflows can now declare schedule in createWorkflow() to run on cron with automatic promotion to the evented engine, type-checked inputData/initialState/requestContext, and safe multi-instance claiming (CAS) via WorkflowScheduler. End-to-end support includes new schedules storage domains/adapters (PG/LibSQL/MongoDB + in-memory for tests), new @mastra/server routes + @mastra/client-js schedule methods, and new Studio UI for listing schedules, viewing trigger history, and durable pause/resume.

MCP Apps: interactive UI resources over MCP (SEP-1865) + resource listing/reading APIs

MCP servers can now publish ui:// HTML app resources via appResources, with new listResources()/readResource() on MCPServerBase and client/server endpoints (MastraClient.getMcpServerResources() / readMcpServerResource(), plus @mastra/server routes). @mastra/mcp adds proxy helpers (MCPClientServerProxy, toMCPServerProxies()) and stamps serverId into tool metadata to support multi-server UI resolution.

Observability upgrades: nested-run querying + bounded high-cardinality metrics + Datadog bridge

New listBranches/getBranch (plus getSpans and getStructure) let you find and fetch runs even when an entity only appears as a nested span (not root traces), with corresponding HTTP endpoints and store implementations (ClickHouse/DuckDB). Metrics now support count_distinct plus server-side TopK (limit, ordering) for fast dashboards on high-cardinality fields; ClickHouse also adds skip indexes to speed drilldowns, and a new DatadogBridge keeps auto-instrumented spans correctly nested under Mastra spans.

Breaking Changes

  • Schedules storage schema changed (mastra_schedules, mastra_schedule_triggers): adds ownerType/ownerId, renames ScheduleTrigger.statusoutcome, adds trigger id PK plus triggerKind/parentTriggerId/metadata; GET /api/schedules/:id/triggers now returns outcome instead of status (no compat shim; scheduled workflows are alpha).
  • @mastra/client-js Vector return types changed to match runtime:
    • vector.getIndexes()string[] (was { indexes: string[] })
    • vector.upsert(){ ids: string[] } (was string[])
    • vector.query()QueryResult[] (was { results: QueryResult[] })

Changelog

@mastra/core@1.32.0

Minor Changes

  • Added Fine-Grained Authorization (FGA) support for relationship-based, resource-level access control. FGA answers "can this user perform this action on this specific resource?" — enabling multi-tenant isolation and per-resource permissions. (#15410)

    New interfaces: IFGAProvider (read-only checks) and IFGAManager (read + write operations) with types for access checks, resources, and role assignments.

    Enforcement at all execution points: FGA checks are automatically enforced before agent execution (generate(), stream()), tool execution, workflow execution, and memory thread access. When no FGA provider is configured, all checks are skipped (backward compatible).

    New utility: checkFGA() provides centralized FGA enforcement with FGADeniedError for denied checks. MastraMemory.checkThreadFGA() adds thread-level access control.

    Request-aware authorization: Resource ID resolvers receive request context so route-level FGA checks can derive tenant- or request-scoped resource IDs.

    Typed permission constants: Strongly-typed permission identifiers (e.g. 'agents:execute', 'workflows:execute', 'memory:threads:read') for use in authorization config and permissionMapping.

    const mastra = new Mastra({
      server: {
        fga: new MastraFGAWorkos({ apiKey, clientId }),
      },
    });
  • Extend the schedules storage schema to support owned schedules and richer trigger audit. This is a breaking schema change to mastra_schedules and mastra_schedule_triggers; scheduled workflows are still in alpha so no compat shim is provided. (#16166)

    • Schedule gains optional ownerType / ownerId so a schedule row can be attributed to an owning subsystem (e.g. an agent that owns a heartbeat schedule). Workflow schedules leave both fields unset.
    • ScheduleTrigger.status is renamed to outcome and the type is widened to ScheduleTriggerOutcome so future outcome values can be added without another rename.
    • ScheduleTrigger gains a stable id primary key and new triggerKind, parentTriggerId, and metadata fields. triggerKind distinguishes schedule-fire rows from later queue-drain rows (used by upcoming heartbeat work); parentTriggerId links related rows; metadata carries outcome-specific context.
    • The libsql, pg, and mongodb adapters all add the new columns/indexes. Their @mastra/core peer dependency is tightened to >=1.32.0-0 <2.0.0-0 so installing a new storage adapter against an older core (or vice-versa) surfaces a peer-dependency warning at install time instead of silently writing/reading the wrong field.
    • Scheduler producer, server schemas/handler, and client SDK types are updated to use the new fields. The triggers response on GET /api/schedules/:id/triggers now returns outcome instead of status.
    • The bundled Studio (Mastra CLI) is updated to read outcome so the schedule detail page keeps polling and rendering publish-failure rows correctly.
  • Added listResources() and readResource() abstract methods to MCPServerBase, enabling MCP servers to expose app resources. These resources power interactive UI rendering (MCP Apps) in Studio and other consumers. (#16004)

  • Added count_distinct aggregation and server-side TopK to the metrics storage API so dashboards built on high-cardinality fields (like threadId or resourceId) stay fast and bounded. (#16137)

    New aggregation

    getMetricAggregate, getMetricBreakdown, and getMetricTimeSeries accept aggregation: 'count_distinct' with a distinctColumn. Backends pick the most efficient native implementation — uniq on ClickHouse, approx_count_distinct on DuckDB.

    distinctColumn is restricted to a low/medium-cardinality categorical allowlist (entityType, entityName, parentEntityType, parentEntityName, rootEntityType, rootEntityName, name, provider, model, environment, executionSource, serviceName). ID columns are not allowed — distinct counts over near-unique values converge to the row count and are rarely useful.

    await store.getMetricAggregate({
      name: ['mastra_llm_tokens_total'],
      aggregation: 'count_distinct',
      distinctColumn: 'model',
      filters: { timestamp: { start, end } },
    });

    Server-side TopK

    getMetricBreakdown accepts limit and orderDirection, so breakdowns never return the full cardinality of a column from the database. Ordering is always by the aggregated value; orderDirection flips between top-N (DESC, default) and bottom-N (ASC).

    await store.getMetricBreakdown({
      name: ['mastra_agent_duration_ms'],
      aggregation: 'sum',
      groupBy: ['threadId'],
      limit: 20,
      orderDirection: 'DESC',
    });
  • Added RegexFilterProcessor — a zero-cost regex-based content filter for blocking, redacting, or warning on pattern matches in agent messages. Includes built-in presets for PII, secrets, URLs, and prompt injection patterns. Supports input, output, and streaming phases. (#16058)

  • Added scheduled workflows. Declare a schedule on createWorkflow and Mastra fires the workflow on cron with no extra wiring. (#15830)

    import { createWorkflow } from '@mastra/core/workflows';
    
    const dailyReport = createWorkflow({
      id: 'daily-report',
      inputSchema: z.object({ date: z.string() }),
      outputSchema: z.object({ summary: z.string() }),
      schedule: {
        cron: '0 9 * * *',
        timezone: 'America/Los_Angeles',
        inputData: { date: 'today' },
      },
    })
      .then(/* steps */)
      .commit();

    A workflow with a schedule is auto-promoted to the evented engine, so scheduled fires share the same execution path as manual start() calls. inputData, initialState, and requestContext on the schedule are type-checked against the workflow's schemas at definition time. Pass an array of schedules with stable ids to fire one workflow on multiple crons.

    Mastra auto-instantiates a WorkflowScheduler when any registered workflow declares a schedule. The scheduler claims due schedules via compare-and-swap, so multiple instances polling the same storage cannot double-fire. Projects with no scheduled workflows pay zero cost. Configure with new Mastra({ scheduler: { tickIntervalMs, batchSize, enabled, onError } }).

    Requires a storage adapter that implements the new schedules domain (@mastra/libsql and @mastra/pg ship adapters; InMemorySchedulesStorage is included for tests). Adds a croner dependency.

  • Added MCP Apps extension support (SEP-1865). MCPServer now accepts an appResources config to register interactive ui:// HTML resources. MCPClient preserves full tool _meta (including ui.resourceUri) when converting MCP tools to Mastra tools. Both advertise the io.modelcontextprotocol/ui extension capability. (#16004)

    Example — MCPServer with app resources:

    const server = new MCPServer({
      name: 'my-server',
      tools: { myTool },
      appResources: {
        dashboard: {
          name: 'Dashboard',
          description: 'Interactive dashboard UI',
          html: '<html>...</html>',
        },
      },
    });
  • Added CostGuardProcessor, a built-in processor for enforcing monetary cost limits across agent runs. Supports run, resource, and thread scopes with configurable time windows (default 7 days), blocking or warning when limits are reached. Also added onViolation callback to the base Processor interface for generalized violation handling across all processors. (#16057)

    import { Agent } from '@mastra/core/agent';
    import { CostGuardProcessor } from '@mastra/core/processors';
    
    const costGuard = new CostGuardProcessor({
      maxCost: 5.0,
      scope: 'resource',
      window: '24h',
      strategy: 'block',
    });
    
    costGuard.onViolation = ({ processorId, message, detail }) => {
      console.log(`[${processorId}] ${message}`, detail);
    };
    
    const agent = new Agent({
      name: 'my-agent',
      model: 'openai/gpt-5-nano',
      inputProcessors: [costGuard],
    });
  • Added listBranches and getBranch for querying named-entity invocations across traces, including nested ones. listTraces only returns root-rooted traces, so an entity that always runs as a child (e.g., an Observer agent inside a workflow) wasn't queryable before. (#16154)

    // Before: nested-only entities returned nothing
    await store.listTraces({ filters: { entityName: 'Observer' } }); // []
    
    // After: one row per AGENT_RUN, WORKFLOW_RUN, PROCESSOR_RUN, SCORER_RUN,
    // RAG_INGESTION, TOOL_CALL, or MCP_TOOL_CALL span
    await store.listBranches({ filters: { entityName: 'Observer' } });
    
    // Plus: fetch the subtree at any span, with optional depth
    const branch = await store.getBranch({ traceId, spanId, depth: 1 });

    Added getStructure({ traceId }) (canonical name for the lightweight trace skeleton; getTraceLight retained as a deprecated alias) and getSpans({ traceId, spanIds }) (batch-fetch spans by id, used internally by getBranch to avoid pulling whole traces).

Patch Changes

  • Update provider registry and model documentation with latest models and providers (6dcd65f)

  • Fixed Harness token usage so provider-reported totals, reasoning tokens, and cache token fields are preserved. Fixes #16055 (#16072)

  • Fixed supervisor output processors so they can filter streamed chunks from delegated sub-agents. (#16071)

  • Fixed Observational Memory model resolution for user-defined gateways. Models such as cloudflare/google/gemini-2.5-flash-lite now resolve through registered gateways instead of failing with provider-config errors. Closes #13841. (#16083)

  • Fixed model step traces to show the final prompt sent to the model, including memory-injected system messages. (#16029)

  • Fixed tool results dropping provider metadata from the original tool call. (#16078)

  • Fixed workflow request context serialization to skip values that cannot be safely stored as JSON. Fixes #16043. (#16061)

  • Fix buildResumedBlockResult returning suspended instead of failed when a step throws after resume in a parallel or conditional block (#14410)

  • Fixed serializeRequestContext to handle plain Map instances passed as requestContext, restoring backward compatibility broken in #16061 (#16081)

  • Added direct score lookup support to observability storage so score records can be fetched by scoreId without scanning paginated score lists, including DuckDB and ClickHouse vNext observability stores. (#16162)

  • fix(harness): use type 'image' and mimeType for image parts in convertToHarnessMessage to fix Gemini image recognition (#13917)

  • Fixed TokenLimiterProcessor failing silently when no input messages fit the token budget. (#16063)

@mastra/auth-workos@1.2.0

Minor Changes

  • Added MastraFGAWorkos provider for Fine-Grained Authorization using the WorkOS Authorization API. Implements IFGAManager interface with support for: (#15410)

    • Authorization checks (check(), require(), filterAccessible())
    • Resource management (createResource(), getResource(), listResources(), updateResource(), deleteResource())
    • Role assignments (assignRole(), removeRole(), listRoleAssignments())
    • resourceMapping and permissionMapping for translating Mastra resource types and permissions to WorkOS resource type slugs and permission slugs
    • Organization scoping that denies access when the user is not a member of the configured organization
    • Bearer-token / verified JWT support that carries service-token FGA context such as organization membership IDs, while ignoring JWT-derived memberships unless organization claims are trusted
    • Membership caching and batched accessible-resource discovery for lower per-request latency
    • Tenant inference and parent-resource filtering for scoped access checks
    • Paginated organization membership lookup and limited concurrent FGA checks when filtering accessible resources
    • Typed permission constants accepted in permissionMapping
    import { MastraFGAWorkos } from '@mastra/auth-workos';
    
    const fga = new MastraFGAWorkos({
      organizationId: 'org_abc123',
      resourceMapping: {
        agent: { fgaResourceType: 'team', deriveId: ctx => ctx.user.teamId },
      },
      permissionMapping: {
        'agents:execute': 'manage-workflows',
      },
    });
    
    // Check whether a user can execute an agent
    const allowed = await fga.check(user, {
      resource: { type: 'agent', id: 'my-agent' },
      permission: 'agents:execute',
    });

Patch Changes

@mastra/clickhouse@1.7.0

Minor Changes

  • Improved metric drilldown performance with skip indexes on the high-cardinality ID columns of metric_events. Dashboard queries that filter metrics by traceId, threadId, resourceId, userId, organizationId, experimentId, runId, sessionId, or requestId skip data chunks that don't contain the filtered value instead of scanning the full time range. (#16138)

    Equality (=) and IN filters benefit automatically. Aggregations and GROUP BY queries without a filter on these columns are unaffected.

    Migration

    Existing deployments pick up the indexes on next start. The migration is metadata-only and instant — no table lock, no rewrite, no downtime. Insert overhead is negligible and index storage is well under 1% of table size. Existing data is indexed lazily as parts merge under normal retention; no operator action is required.

  • Added count_distinct aggregation and server-side TopK to the metrics storage API so dashboards built on high-cardinality fields (like threadId or resourceId) stay fast and bounded. (#16137)

    New aggregation

    getMetricAggregate, getMetricBreakdown, and getMetricTimeSeries accept aggregation: 'count_distinct' with a distinctColumn. Backends pick the most efficient native implementation — uniq on ClickHouse, approx_count_distinct on DuckDB.

    distinctColumn is restricted to a low/medium-cardinality categorical allowlist (entityType, entityName, parentEntityType, parentEntityName, rootEntityType, rootEntityName, name, provider, model, environment, executionSource, serviceName). ID columns are not allowed — distinct counts over near-unique values converge to the row count and are rarely useful.

    await store.getMetricAggregate({
      name: ['mastra_llm_tokens_total'],
      aggregation: 'count_distinct',
      distinctColumn: 'model',
      filters: { timestamp: { start, end } },
    });

    Server-side TopK

    getMetricBreakdown accepts limit and orderDirection, so breakdowns never return the full cardinality of a column from the database. Ordering is always by the aggregated value; orderDirection flips between top-N (DESC, default) and bottom-N (ASC).

    await store.getMetricBreakdown({
      name: ['mastra_agent_duration_ms'],
      aggregation: 'sum',
      groupBy: ['threadId'],
      limit: 20,
      orderDirection: 'DESC',
    });
    • Added listBranches and getSpans implementations. (#16154)
    • Only spans recorded after this version is deployed are queryable via listBranches; historical traces remain accessible through the existing listTraces / getTrace APIs.

Patch Changes

  • Added direct score lookup support to observability storage so score records can be fetched by scoreId without scanning paginated score lists, including DuckDB and ClickHouse vNext observability stores. (#16162)

@mastra/client-js@1.17.0

Minor Changes

  • Extend the schedules storage schema to support owned schedules and richer trigger audit. This is a breaking schema change to mastra_schedules and mastra_schedule_triggers; scheduled workflows are still in alpha so no compat shim is provided. (#16166)

    • Schedule gains optional ownerType / ownerId so a schedule row can be attributed to an owning subsystem (e.g. an agent that owns a heartbeat schedule). Workflow schedules leave both fields unset.
    • ScheduleTrigger.status is renamed to outcome and the type is widened to ScheduleTriggerOutcome so future outcome values can be added without another rename.
    • ScheduleTrigger gains a stable id primary key and new triggerKind, parentTriggerId, and metadata fields. triggerKind distinguishes schedule-fire rows from later queue-drain rows (used by upcoming heartbeat work); parentTriggerId links related rows; metadata carries outcome-specific context.
    • The libsql, pg, and mongodb adapters all add the new columns/indexes. Their @mastra/core peer dependency is tightened to >=1.32.0-0 <2.0.0-0 so installing a new storage adapter against an older core (or vice-versa) surfaces a peer-dependency warning at install time instead of silently writing/reading the wrong field.
    • Scheduler producer, server schemas/handler, and client SDK types are updated to use the new fields. The triggers response on GET /api/schedules/:id/triggers now returns outcome instead of status.
    • The bundled Studio (Mastra CLI) is updated to read outcome so the schedule detail page keeps polling and rendering publish-failure rows correctly.
  • Added getMcpServerResources() and readMcpServerResource() methods to MastraClient for listing and reading MCP server resources from the client SDK. These methods enable frontend applications to fetch app resource HTML for interactive MCP Apps rendering. (#16004)

    const client = new MastraClient();
    
    // List resources on an MCP server
    const resources = await client.getMcpServerResources('my-server');
    
    // Read a specific app resource
    const resource = await client.readMcpServerResource('my-server', 'ui://calculator/app');
  • Added schedule methods to the client for the new scheduled workflows feature. (#15830)

    import { MastraClient } from '@mastra/client-js';
    
    const client = new MastraClient({ baseUrl: 'http://localhost:4111' });
    
    const schedules = await client.listSchedules({ workflowId: 'daily-report' });
    const schedule = await client.getSchedule('wf_daily-report');
    const triggers = await client.listScheduleTriggers('wf_daily-report', { limit: 50 });
    
    await client.pauseSchedule('wf_daily-report');
    await client.resumeSchedule('wf_daily-report');

    Pause is durable across redeploys. Resume recomputes the next fire time from now so a long-paused schedule does not fire a backlog.

  • Added listBranches and getBranch endpoints. Use these to find specific runs of an agent, workflow, tool, or processor — even when they are nested inside another trace — and to fetch the subtree of spans rooted at any single span. (#16177)

    GET /observability/branches?spanType=agent_run&entityName=Observer
    GET /observability/traces/:traceId/branches/:spanId?depth=1
    

    Each row in listBranches is a single anchor span (one of AGENT_RUN, WORKFLOW_RUN, PROCESSOR_RUN, SCORER_RUN, RAG_INGESTION, TOOL_CALL, MCP_TOOL_CALL), so entities that always run as a child (e.g., an Observer agent inside a workflow) — previously not listable through listTraces — are now queryable via the HTTP API. getBranch accepts an optional depth (0 = anchor only; omitted = full subtree).

    Follow-up to #16154 which added the underlying @mastra/core storage APIs.

  • Fixed Vector resource return types so they match what the server actually returns. Previously the types declared shapes that did not exist at runtime, leading to runtime failures with no TypeScript errors. (#16036)

    What changed

    • vector.getIndexes() now returns string[] (was { indexes: string[] })
    • vector.upsert() now returns { ids: string[] } (was string[])
    • vector.query() now returns QueryResult[] (was { results: QueryResult[] })

    Before

    const response = await client.getVector('docs').getIndexes();
    console.log(response.indexes); // undefined at runtime

    After

    const indexes = await client.getVector('docs').getIndexes();
    console.log(indexes[0]); // 'docs-index'

    Closes #15089.

Patch Changes

  • Fixed client stream handling for step completion and finish chunks that omit step result details. (#9146)

  • Added MCP Apps extension support (SEP-1865). MCPServer now accepts an appResources config to register interactive ui:// HTML resources. MCPClient preserves full tool _meta (including ui.resourceUri) when converting MCP tools to Mastra tools. Both advertise the io.modelcontextprotocol/ui extension capability. (#16004)

    Example — MCPServer with app resources:

    const server = new MCPServer({
      name: 'my-server',
      tools: { myTool },
      appResources: {
        dashboard: {
          name: 'Dashboard',
          description: 'Interactive dashboard UI',
          html: '<html>...</html>',
        },
      },
    });
  • Added server-generated route contract types for the JavaScript client SDK and updated the SDK to use those generated request and response types. (#15519)

@mastra/convex@1.0.10

Patch Changes

  • Fixed @mastra/convex workflow snapshot persistence when snapshots contain $-prefixed JSON Schema keys (for example $schema and $ref). (#16169)
    Snapshots are now stored safely, preventing Convex validation failures during workflow runs. Fixes #16110.

  • Improved Convex bulk insert and delete throughput. (#16149)

@mastra/datadog@1.1.0

Minor Changes

  • Added a new DatadogBridge integration for Mastra tracing so Datadog can keep auto-instrumented HTTP, database, and framework spans nested under the agent, workflow, model, and tool spans that triggered them. (#15716)

    import tracer from 'dd-trace';
    
    tracer.init({
      service: process.env.DD_SERVICE || 'my-mastra-app',
      env: process.env.DD_ENV || 'production',
    });
    
    import { Mastra } from '@mastra/core';
    import { Observability } from '@mastra/observability';
    import { DatadogBridge } from '@mastra/datadog';
    
    const mastra = new Mastra({
      observability: new Observability({
        configs: {
          default: {
            serviceName: 'my-mastra-app',
            bridge: new DatadogBridge({
              mlApp: process.env.DD_LLMOBS_ML_APP!,
            }),
          },
        },
      }),
    });

Patch Changes

@mastra/duckdb@1.3.0

Minor Changes

    • Added listBranches and getSpans implementations. (#16154)
    • Historical span data is queryable immediately; no migration required.
  • Added count_distinct aggregation and server-side TopK to the metrics storage API so dashboards built on high-cardinality fields (like threadId or resourceId) stay fast and bounded. (#16137)

    New aggregation

    getMetricAggregate, getMetricBreakdown, and getMetricTimeSeries accept aggregation: 'count_distinct' with a distinctColumn. Backends pick the most efficient native implementation — uniq on ClickHouse, approx_count_distinct on DuckDB.

    distinctColumn is restricted to a low/medium-cardinality categorical allowlist (entityType, entityName, parentEntityType, parentEntityName, rootEntityType, rootEntityName, name, provider, model, environment, executionSource, serviceName). ID columns are not allowed — distinct counts over near-unique values converge to the row count and are rarely useful.

    await store.getMetricAggregate({
      name: ['mastra_llm_tokens_total'],
      aggregation: 'count_distinct',
      distinctColumn: 'model',
      filters: { timestamp: { start, end } },
    });

    Server-side TopK

    getMetricBreakdown accepts limit and orderDirection, so breakdowns never return the full cardinality of a column from the database. Ordering is always by the aggregated value; orderDirection flips between top-N (DESC, default) and bottom-N (ASC).

    await store.getMetricBreakdown({
      name: ['mastra_agent_duration_ms'],
      aggregation: 'sum',
      groupBy: ['threadId'],
      limit: 20,
      orderDirection: 'DESC',
    });

Patch Changes

  • Improved performance of listTraces and listBranches on DuckDB. The Traces and Branches lists in the observability UI now load noticeably faster, especially on large span tables, because filtering and pagination happen up front and the store only assembles full span data for the rows on the page being viewed. (#16165)

    No API or behavior changes — return shapes and filter semantics are unchanged, and no migration is required.

  • Added direct score lookup support to observability storage so score records can be fetched by scoreId without scanning paginated score lists, including DuckDB and ClickHouse vNext observability stores. (#16162)

@mastra/editor@0.7.23

Patch Changes

  • Added MCP Apps extension support (SEP-1865). MCPServer now accepts an appResources config to register interactive ui:// HTML resources. MCPClient preserves full tool _meta (including ui.resourceUri) when converting MCP tools to Mastra tools. Both advertise the io.modelcontextprotocol/ui extension capability. (#16004)

    Example — MCPServer with app resources:

    const server = new MCPServer({
      name: 'my-server',
      tools: { myTool },
      appResources: {
        dashboard: {
          name: 'Dashboard',
          description: 'Interactive dashboard UI',
          html: '<html>...</html>',
        },
      },
    });

@mastra/express@1.3.17

Patch Changes

  • Added FGA enforcement to server adapter middleware, ensuring authorization checks are applied consistently across all built-in adapters. (#15410)

@mastra/fastify@1.3.17

Patch Changes

  • Added FGA enforcement to server adapter middleware, ensuring authorization checks are applied consistently across all built-in adapters. (#15410)

@mastra/hono@1.4.12

Patch Changes

  • Added FGA enforcement to server adapter middleware, ensuring authorization checks are applied consistently across all built-in adapters. (#15410)

@mastra/koa@1.5.0

Minor Changes

  • Improved the Koa adapter to make request routing more efficient as route counts grow. (#16050)

    Requests now move through a leaner routing path with lower middleware overhead, which helps Koa-based Mastra servers stay faster and produce cleaner request traces without changing the public API.

Patch Changes

  • Added FGA enforcement to server adapter middleware, ensuring authorization checks are applied consistently across all built-in adapters. (#15410)

@mastra/libsql@1.10.0

Minor Changes

  • Extend the schedules storage schema to support owned schedules and richer trigger audit. This is a breaking schema change to mastra_schedules and mastra_schedule_triggers; scheduled workflows are still in alpha so no compat shim is provided. (#16166)

    • Schedule gains optional ownerType / ownerId so a schedule row can be attributed to an owning subsystem (e.g. an agent that owns a heartbeat schedule). Workflow schedules leave both fields unset.
    • ScheduleTrigger.status is renamed to outcome and the type is widened to ScheduleTriggerOutcome so future outcome values can be added without another rename.
    • ScheduleTrigger gains a stable id primary key and new triggerKind, parentTriggerId, and metadata fields. triggerKind distinguishes schedule-fire rows from later queue-drain rows (used by upcoming heartbeat work); parentTriggerId links related rows; metadata carries outcome-specific context.
    • The libsql, pg, and mongodb adapters all add the new columns/indexes. Their @mastra/core peer dependency is tightened to >=1.32.0-0 <2.0.0-0 so installing a new storage adapter against an older core (or vice-versa) surfaces a peer-dependency warning at install time instead of silently writing/reading the wrong field.
    • Scheduler producer, server schemas/handler, and client SDK types are updated to use the new fields. The triggers response on GET /api/schedules/:id/triggers now returns outcome instead of status.
    • The bundled Studio (Mastra CLI) is updated to read outcome so the schedule detail page keeps polling and rendering publish-failure rows correctly.
  • Added the schedules storage domain so LibSQL-backed Mastra apps can use scheduled workflows. Creates mastra_schedules and mastra_schedule_triggers tables on init. (#15830)

Patch Changes

@mastra/mcp@1.7.0

Minor Changes

  • Added MCP Apps support for interactive UI rendering over MCP. (#16004)

    MCPClientServerProxy — a lightweight proxy that delegates resource and tool operations to remote MCP servers via MCPClient, enabling Studio to fetch app resources from any connected server.

    toMCPServerProxies() — new convenience method on MCPClient that creates proxy objects for all configured servers, ready for Mastra-level registration.

    Automatic serverId stamping — tools returned by listTools() now carry _meta.ui.serverId, allowing consumers to resolve ui:// app resources from the correct MCP server in multi-server environments.

    const mcp = new MCPClient({
      servers: {
        myApps: { url: new URL('https://my-mcp-server.example.com/mcp') },
      },
    });
    
    const mastra = new Mastra({
      agents: { myAgent },
      mcpServers: { ...mcp.toMCPServerProxies() },
    });
  • Added MCP Apps extension support (SEP-1865). MCPServer now accepts an appResources config to register interactive ui:// HTML resources. MCPClient preserves full tool _meta (including ui.resourceUri) when converting MCP tools to Mastra tools. Both advertise the io.modelcontextprotocol/ui extension capability. (#16004)

    Example — MCPServer with app resources:

    const server = new MCPServer({
      name: 'my-server',
      tools: { myTool },
      appResources: {
        dashboard: {
          name: 'Dashboard',
          description: 'Interactive dashboard UI',
          html: '<html>...</html>',
        },
      },
    });

Patch Changes

  • Added Fine-Grained Authorization (FGA) enforcement to MCP tool execution. Both transport-driven calls and direct executeTool() calls now run the same authorization checks when a request user is present, and typed FGA permission constants are accepted in MCP server authorization config. (#15410)

  • Fixed trace parenting for long-lived MCP Stream connections. (#15716)

@mastra/memory@1.17.5

Patch Changes

  • Fixed Observational Memory model resolution for user-defined gateways. Models such as cloudflare/google/gemini-2.5-flash-lite now resolve through registered gateways instead of failing with provider-config errors. Closes #13841. (#16083)

  • Fixed async reflection buffering incorrectly triggering during idle timeout and provider-change activations when observation tokens are below the reflection activation threshold (#16076)

@mastra/mongodb@1.8.0

Minor Changes

  • Extend the schedules storage schema to support owned schedules and richer trigger audit. This is a breaking schema change to mastra_schedules and mastra_schedule_triggers; scheduled workflows are still in alpha so no compat shim is provided. (#16166)

    • Schedule gains optional ownerType / ownerId so a schedule row can be attributed to an owning subsystem (e.g. an agent that owns a heartbeat schedule). Workflow schedules leave both fields unset.
    • ScheduleTrigger.status is renamed to outcome and the type is widened to ScheduleTriggerOutcome so future outcome values can be added without another rename.
    • ScheduleTrigger gains a stable id primary key and new triggerKind, parentTriggerId, and metadata fields. triggerKind distinguishes schedule-fire rows from later queue-drain rows (used by upcoming heartbeat work); parentTriggerId links related rows; metadata carries outcome-specific context.
    • The libsql, pg, and mongodb adapters all add the new columns/indexes. Their @mastra/core peer dependency is tightened to >=1.32.0-0 <2.0.0-0 so installing a new storage adapter against an older core (or vice-versa) surfaces a peer-dependency warning at install time instead of silently writing/reading the wrong field.
    • Scheduler producer, server schemas/handler, and client SDK types are updated to use the new fields. The triggers response on GET /api/schedules/:id/triggers now returns outcome instead of status.
    • The bundled Studio (Mastra CLI) is updated to read outcome so the schedule detail page keeps polling and rendering publish-failure rows correctly.
  • Added the schedules storage domain so MongoDB-backed Mastra apps can use scheduled workflows. Creates mastra_schedules and mastra_schedule_triggers collections on init, with default indexes on (status, next_fire_at) for due-schedule polling and (schedule_id, actual_fire_at) for trigger-history queries. (#15830)

Patch Changes

@mastra/observability@1.11.1

Patch Changes

  • Fixed model step traces to show the final prompt sent to the model, including memory-injected system messages. (#16029)

  • Added a new DatadogBridge integration for Mastra tracing so Datadog can keep auto-instrumented HTTP, database, and framework spans nested under the agent, workflow, model, and tool spans that triggered them. (#15716)

    import tracer from 'dd-trace';
    
    tracer.init({
      service: process.env.DD_SERVICE || 'my-mastra-app',
      env: process.env.DD_ENV || 'production',
    });
    
    import { Mastra } from '@mastra/core';
    import { Observability } from '@mastra/observability';
    import { DatadogBridge } from '@mastra/datadog';
    
    const mastra = new Mastra({
      observability: new Observability({
        configs: {
          default: {
            serviceName: 'my-mastra-app',
            bridge: new DatadogBridge({
              mlApp: process.env.DD_LLMOBS_ML_APP!,
            }),
          },
        },
      }),
    });
  • Reduced startup noise: CloudExporter missing-token message is now logged at debug level instead of warn, since being disabled is the expected state for local development (#16070)

@mastra/pg@1.10.0

Minor Changes

  • Extend the schedules storage schema to support owned schedules and richer trigger audit. This is a breaking schema change to mastra_schedules and mastra_schedule_triggers; scheduled workflows are still in alpha so no compat shim is provided. (#16166)

    • Schedule gains optional ownerType / ownerId so a schedule row can be attributed to an owning subsystem (e.g. an agent that owns a heartbeat schedule). Workflow schedules leave both fields unset.
    • ScheduleTrigger.status is renamed to outcome and the type is widened to ScheduleTriggerOutcome so future outcome values can be added without another rename.
    • ScheduleTrigger gains a stable id primary key and new triggerKind, parentTriggerId, and metadata fields. triggerKind distinguishes schedule-fire rows from later queue-drain rows (used by upcoming heartbeat work); parentTriggerId links related rows; metadata carries outcome-specific context.
    • The libsql, pg, and mongodb adapters all add the new columns/indexes. Their @mastra/core peer dependency is tightened to >=1.32.0-0 <2.0.0-0 so installing a new storage adapter against an older core (or vice-versa) surfaces a peer-dependency warning at install time instead of silently writing/reading the wrong field.
    • Scheduler producer, server schemas/handler, and client SDK types are updated to use the new fields. The triggers response on GET /api/schedules/:id/triggers now returns outcome instead of status.
    • The bundled Studio (Mastra CLI) is updated to read outcome so the schedule detail page keeps polling and rendering publish-failure rows correctly.
  • Added the schedules storage domain so Postgres-backed Mastra apps can use scheduled workflows. Creates mastra_schedules and mastra_schedule_triggers tables on init, with default indexes on (status, next_fire_at) for due-schedule polling and (schedule_id, actual_fire_at) for trigger-history queries. (#15830)

Patch Changes

@mastra/playground-ui@26.0.0

Minor Changes

  • Improved the NoLogsInfo empty state. It now accepts optional datePreset, dateFrom, and dateTo props to show why no logs match the active range, suggests lowering the logging level, and links to the docs. Calling <NoLogsInfo /> without props keeps the original copy. (#16139)

  • Removed the deprecated Notification component. Use Notice for inline persistent context (errors, empty states) and toast (from @mastra/playground-ui's sonner wrapper) for transient feedback (success messages, confirmations). (#16033)

    // Before
    <Notification isVisible={true} type="error">Failed to load.</Notification>
    
    // After — inline persistent context
    <Notice variant="destructive">Failed to load.</Notice>
    
    // Before
    <Notification isVisible={true}>Saved successfully!</Notification>
    
    // After — transient feedback
    toast.info('Saved successfully');
  • Added Studio UI for scheduled workflows. (#15830)

    • /workflows/schedules lists every schedule across the project with the most recent run's status. Append ?workflowId=<id> to filter to a single workflow.
    • /workflows/schedules/:scheduleId shows the schedule's metadata, Pause/Resume controls, and paginated trigger history. Each trigger is deep-linked to its workflow run graph. The view polls every five seconds while any fired run is still active.
    • A workflow's detail header shows a Schedules action when it has at least one schedule.
  • Added SectionCard component to design system. Provides card primitive with tinted header strip (title, description, optional action slot), transparent body, and default/danger variants. Composes CardHeading for typography. Suitable for settings pages, dashboard sections, and grouped form layouts. (#16168)

    import { SectionCard } from '@mastra/playground-ui';
    
    <SectionCard title="Theme" description="Customize the appearance.">
      <ThemeSelector />
    </SectionCard>;
  • Redesigned the span token usage panel to show input vs output split with proportional bar and per-side detail breakdowns. DataKeysAndValues gained an optional density='dense' prop. (#16143)

  • Removed the CombinedButtons component. Use ButtonsGroup with spacing="close" for the same segmented-style cluster of toggle buttons. (#16035)

    // Before
    <CombinedButtons>
      <Button>Agent</Button>
      <Button>Model</Button>
    </CombinedButtons>
    
    // After
    <ButtonsGroup spacing="close">
      <Button>Agent</Button>
      <Button>Model</Button>
    </ButtonsGroup>

Patch Changes

  • Added support for icon-and-description layout in Notice by making title optional. When omitted, the notice renders as a single row with icon and description, useful for inline contextual messages. (#16033)

    // Before — title required
    <Notice variant="info" title="Heads up">Some message.</Notice>
    
    // After — title optional, single-row layout
    <Notice variant="info">Some message.</Notice>
  • Improved trace timeline span controls. Added tooltips with row counts to the expand-children, expand-all-descendants, and expand-at-this-level buttons. The expand-children button now collapses only the direct children rather than the entire subtree, and the descendants column gained a matching collapse-all-descendants action. Root spans show a single Expand all / Collapse all button using outward/inward double-chevrons. (#16173)

  • Refreshed toast styling so it aligns with the Notice component and lets sonner own the layout. (#16144)

    What changed for users:

    • Variant toasts (success / error / warning / info) now render with the same notice color tokens as the <Notice> component, including bg, border and text color in both light and dark mode.
    • Sonner's native layout is back in charge — the loader on toast.promise, the close button position, the icon placement and the mobile width all work as documented instead of fighting custom overrides.
    • The native close button has its own polished hover: it blends with the toast at rest and lifts with a tinted bg + stronger border on hover, in every variant and theme.
    • Sticky toasts can be made truly non-dismissible by passing both dismissible: false and closeButton: false.
    • toast.success / error / warning / info now return sonner's toast id (or an array of ids when called with an array of messages) so callers can keep dismissing or updating the toast they created.
  • Added a Scorer span type style on the trace timeline and a colored type dot before each span name so spans are visually flagged in both the name and timing columns. (#16160)

  • Migrated Files/Skills tabs and agent page tabs (Chat/Editor/Evaluate/Review/Traces) to the design-system Tabs component for consistent styling and accessibility (Radix tablist, arrow-key navigation). Also added a cursor-pointer on the Tab trigger and a disabled prop on the DS Tab. (#16148)

  • Added MCP Apps extension support (SEP-1865). MCPServer now accepts an appResources config to register interactive ui:// HTML resources. MCPClient preserves full tool _meta (including ui.resourceUri) when converting MCP tools to Mastra tools. Both advertise the io.modelcontextprotocol/ui extension capability. (#16004)

    Example — MCPServer with app resources:

    const server = new MCPServer({
      name: 'my-server',
      tools: { myTool },
      appResources: {
        dashboard: {
          name: 'Dashboard',
          description: 'Interactive dashboard UI',
          html: '<html>...</html>',
        },
      },
    });
  • Added an informational notice on the trace data panel pointing users to Mastra Studio (local or deployed) when "Evaluate Trace" and "Save as Dataset Item" actions are not available in the current view. (#16157)

  • Fixed pointer cursor on interactive form controls (Button, SelectTrigger, SelectItem) for better affordance. (#16140)

@mastra/react@0.2.34

Patch Changes

  • Fixed custom data stream parts so stable ids are preserved in React UI messages. (#16067)

@mastra/server@1.32.0

Minor Changes

  • Extend the schedules storage schema to support owned schedules and richer trigger audit. This is a breaking schema change to mastra_schedules and mastra_schedule_triggers; scheduled workflows are still in alpha so no compat shim is provided. (#16166)

    • Schedule gains optional ownerType / ownerId so a schedule row can be attributed to an owning subsystem (e.g. an agent that owns a heartbeat schedule). Workflow schedules leave both fields unset.
    • ScheduleTrigger.status is renamed to outcome and the type is widened to ScheduleTriggerOutcome so future outcome values can be added without another rename.
    • ScheduleTrigger gains a stable id primary key and new triggerKind, parentTriggerId, and metadata fields. triggerKind distinguishes schedule-fire rows from later queue-drain rows (used by upcoming heartbeat work); parentTriggerId links related rows; metadata carries outcome-specific context.
    • The libsql, pg, and mongodb adapters all add the new columns/indexes. Their @mastra/core peer dependency is tightened to >=1.32.0-0 <2.0.0-0 so installing a new storage adapter against an older core (or vice-versa) surfaces a peer-dependency warning at install time instead of silently writing/reading the wrong field.
    • Scheduler producer, server schemas/handler, and client SDK types are updated to use the new fields. The triggers response on GET /api/schedules/:id/triggers now returns outcome instead of status.
    • The bundled Studio (Mastra CLI) is updated to read outcome so the schedule detail page keeps polling and rendering publish-failure rows correctly.
  • Added API endpoints for MCP server resources, enabling clients to list and read app resources for interactive UI rendering. (#16004)

    • GET /api/mcp/:serverId/resources — lists available resources on an MCP server
    • POST /api/mcp/:serverId/resources/read — reads a specific resource by URI (e.g. ui://calculator/app)
  • Added HTTP routes for scheduled workflows. (#15830)

    • GET /api/schedules — list schedules across the project, optionally filtered by workflowId.
    • GET /api/schedules/:scheduleId — fetch a schedule with its most recent run summary.
    • GET /api/schedules/:scheduleId/triggers — paginated trigger history joined to the corresponding workflow run.
    • POST /api/schedules/:scheduleId/pause and POST /api/schedules/:scheduleId/resume — durable pause/resume. Both require schedules:write and are idempotent. Resume recomputes nextFireAt from now so a long-paused schedule does not fire a backlog.
  • Added listBranches and getBranch endpoints. Use these to find specific runs of an agent, workflow, tool, or processor — even when they are nested inside another trace — and to fetch the subtree of spans rooted at any single span. (#16177)

    GET /observability/branches?spanType=agent_run&entityName=Observer
    GET /observability/traces/:traceId/branches/:spanId?depth=1
    

    Each row in listBranches is a single anchor span (one of AGENT_RUN, WORKFLOW_RUN, PROCESSOR_RUN, SCORER_RUN, RAG_INGESTION, TOOL_CALL, MCP_TOOL_CALL), so entities that always run as a child (e.g., an Observer agent inside a workflow) — previously not listable through listTraces — are now queryable via the HTTP API. getBranch accepts an optional depth (0 = anchor only; omitted = full subtree).

    Follow-up to #16154 which added the underlying @mastra/core storage APIs.

  • Added Fine-Grained Authorization (FGA) enforcement across server handlers and memory APIs: (#15410)

    • Route-level checks on detail endpoints, custom routes (including request-aware resource ID resolvers and path parameters), and resource-scoped search
    • Thread-level checks on reads, writes, creation, cloning, message saving, and listing — with unviewable threads hidden from totals and pagination
    • Message deletion now denies access when the message's thread cannot be verified
    • Authenticated user context preserved through thread authorization, and the thread's owning resourceId forwarded into the FGA context so providers can derive composite tenant-scoped resource IDs
    • Route permission derivation and memory clone checks now use the correct resource context
    • Typed FGA permission constants accepted in route and thread authorization config

Patch Changes

  • Fixed A2A task resubscribe to return the current task snapshot and continue streaming live artifact and status updates for in-progress tasks. (#15987)

  • Added an observability score lookup endpoint at GET /observability/scores/:scoreId backed by observability storage. (#16162)

  • Added MCP Apps extension support (SEP-1865). MCPServer now accepts an appResources config to register interactive ui:// HTML resources. MCPClient preserves full tool _meta (including ui.resourceUri) when converting MCP tools to Mastra tools. Both advertise the io.modelcontextprotocol/ui extension capability. (#16004)

    Example — MCPServer with app resources:

    const server = new MCPServer({
      name: 'my-server',
      tools: { myTool },
      appResources: {
        dashboard: {
          name: 'Dashboard',
          description: 'Interactive dashboard UI',
          html: '<html>...</html>',
        },
      },
    });
  • Added server-generated route contract types for the JavaScript client SDK and updated the SDK to use those generated request and response types. (#15519)

@mastra/slack@1.1.1

Patch Changes

  • Fixed Slack app creation failing when agent description exceeds 139 characters. The manifest description is now automatically truncated to prevent the Slack API from rejecting the request. (#16093)

@mastra/temporal@0.1.0

Minor Changes

  • Added the new @mastra/temporal package for running Mastra workflows on Temporal. (#15789)

    What changed

    • Added init() to create Temporal-backed Mastra workflows and steps.
    • Added MastraPlugin to bundle workflow code for Temporal workers and load generated activities.
    • Added debug: true support to write transformed workflow modules and emitted bundles to .mastra/temporal.

    Example

    import { init } from '@mastra/temporal';
    import { MastraPlugin } from '@mastra/temporal/worker';
    import { Client, Connection } from '@temporalio/client';
    import { Worker } from '@temporalio/worker';
    
    const connection = await Connection.connect();
    const client = new Client({ connection });
    const { createWorkflow, createStep } = init({ client, taskQueue: 'mastra' });
    
    const step = createStep({ id: 'hello', execute: async () => 'world' });
    export const helloWorkflow = createWorkflow({ id: 'hello-workflow' }).then(step);
    
    await Worker.create({
      connection,
      taskQueue: 'mastra',
      plugins: [new MastraPlugin({ src: import.meta.resolve('./mastra/index.ts') })],
    });

Patch Changes

Other updated packages

The following packages were updated with dependency changes only:

Don't miss a new mastra release

NewReleases is sending notifications on new releases.