mastra-ai/mastra · error · HTTPException

Could not derive MCP client ID from name. Please provide an

Error message

Could not derive MCP client ID from name. Please provide an explicit id.

What it means

HTTP 400 thrown when neither an explicit id nor a name that survives slugification is provided, so the handler cannot derive a unique MCP client ID (id = providedId || toSlug(name)). It is a client-input validation failure, returned before any storage writes.

Source

Thrown at packages/server/src/server/handlers/stored-mcp-clients.ts:140

  requiresAuth: true,
  handler: async ({ mastra, id: providedId, authorId, metadata, name, description, servers, requestContext }) => {
    try {
      const storage = mastra.getStorage();

      if (!storage) {
        throw new HTTPException(500, { message: 'Storage is not configured' });
      }

      const mcpClientStore = await storage.getStore('mcpClients');
      if (!mcpClientStore) {
        throw new HTTPException(500, { message: 'MCP clients storage domain is not available' });
      }

      // Derive ID from name if not explicitly provided
      const id = providedId || toSlug(name);

      if (!id) {
        throw new HTTPException(400, {
          message: 'Could not derive MCP client ID from name. Please provide an explicit id.',
        });
      }

      // Check if MCP client with this ID already exists
      const existing = await mcpClientStore.getById(id);
      if (existing) {
        throw new HTTPException(409, { message: `MCP client with id ${id} already exists` });
      }

      await mcpClientStore.create({
        mcpClient: {
          id,
          authorId,
          metadata: scopeStoredResourceMetadata(metadata, await getStoredResourceScope(mastra, requestContext)),
          name,
          description,
          servers,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass an explicit `id` alongside (or instead of) `name` in the create payload.
  2. Ensure `name` contains slug-derivable characters (letters/numbers).
  3. Validate the payload client-side before POSTing.
  4. Trim/normalize the name before sending.

Example fix

// before
await fetch('/api/mcp/clients', { method: 'POST', body: JSON.stringify({ name: '///' }) });
// after
await fetch('/api/mcp/clients', { method: 'POST', body: JSON.stringify({ name: 'My Client', id: 'my-client' }) });
Defensive patterns

Strategy: validation

Validate before calling

function validateClientPayload(p: { id?: string; name?: string }) {
  if (!p.id && !(p.name && p.name.trim().replace(/[^a-zA-Z0-9]/g, '').length > 0)) {
    throw new Error('Provide an explicit id or a slug-derivable name');
  }
}

Type guard

function hasDerivableId(p: { id?: string; name?: string }): boolean {
  return Boolean(p.id && p.id.trim()) || Boolean(p.name && /\w/.test(p.name));
}

Try / catch

try {
  await createMcpClient(payload);
} catch (e) {
  if (String(e).includes('Could not derive MCP client ID')) {
    await createMcpClient({ ...payload, id: crypto.randomUUID() });
  } else throw e;
}

Prevention

When it happens

Trigger: POST create call where `id` is absent and `name` is empty, whitespace-only, or composed solely of characters that toSlug strips (e.g. '---', '///').

Common situations: Frontend form submitting an empty name; programmatic clients sending only metadata; localization edge cases where the name contains only non-ASCII/symbol characters stripped by the slugger.

Related errors


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