mastra-ai/mastra · error · Error

The "extra" key is now nested under "mcp.extra" in tool argu

Error message

The "extra" key is now nested under "mcp.extra" in tool arguments

What it means

Companion to the `elicitation` migration guard: accessing the top-level `extra` key in tool arguments now throws with a pointer to the new location, `mcp.extra`. The throwing getter exists solely to surface the rename to developers instead of silently returning undefined.

Source

Thrown at packages/mcp/src/server/server.ts:1141

        };

        const mcpOptions: MastraToolInvocationOptions = {
          messages: [],
          toolCallId: '',
          requestContext: proxiedContext,
          // Pass MCP-specific context through the mcp property
          mcp: {
            elicitation: sessionElicitation,
            extra,
            log: sessionLog,
            progress: sessionProgress,
          },
          // @ts-expect-error this is to let people know that the elicitation and extra keys are now nested under mcp.elicitation and mcp.extra in tool arguments
          get elicitation() {
            throw new Error(`The "elicitation" key is now nested under "mcp.elicitation" in tool arguments`);
          },
          get extra() {
            throw new Error(`The "extra" key is now nested under "mcp.extra" in tool arguments`);
          },
        };

        await this.enforceToolExecutionFGA(request.params.name, proxiedContext);

        const result = await tool.execute(validation?.value ?? request.params.arguments ?? {}, mcpOptions);

        const duration = Date.now() - startTime;

        // Check if the tool builder returned a validation error (e.g. input failed Zod validation
        // after passing the JSON Schema first-pass validation above)
        if (isValidationError(result)) {
          this.logger.warn(`CallTool: Tool '${request.params.name}' returned a validation error in ${duration}ms.`, {
            error: result.message,
          });
          return {
            content: [{ type: 'text', text: result.message }],
            isError: true,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Access request/session data via `mcp.extra` instead of the top-level `extra` argument.
  2. Update destructured parameters to pull `extra` from the nested `mcp` object.
  3. Grep tools for `extra.` and `extra}` usages and migrate them to `mcp.extra`.

Example fix

// before
execute: async (args, { extra }) => console.log(extra.sessionId)
// after
execute: async (args, mcp) => console.log(mcp.extra.sessionId)
Defensive patterns

Strategy: type-guard

Validate before calling

// static check before deploy
grep -rn "\bextra\b" src/tools/ | grep -v "mcp.extra" && echo 'migrate to mcp.extra'

Type guard

function getExtra(mcp: unknown): McpExtra | undefined { return !!mcp && typeof mcp === 'object' && 'extra' in mcp ? (mcp as any).extra : undefined; }

Try / catch

try { return await tool.execute(args, mcpOptions); } catch (e) { if (String(e?.message).includes('mcp.extra')) { throw new Error('Tool uses deprecated top-level extra; migrate to mcp.extra'); } throw e; }

Prevention

When it happens

Trigger: During a `tools/call`, the tool's execute function accesses `context.extra` (e.g. `extra.requestInfo`, `extra.sessionId`, or request metadata) on the proxied MCP context.

Common situations: Tools that read HTTP request info, auth context, or per-session data via `extra` written before the `mcp.extra` nesting was introduced.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/527642d0be0565ab. Report an issue: GitHub.