Yeachan-Heo/oh-my-codex · warning · Error

Unknown ${descriptor.commandName} tool: ${parsed.toolName} $

Error message

Unknown ${descriptor.commandName} tool: ${parsed.toolName}
${buildDescriptorHelp(descriptor)}

What it means

executeDescriptorCommand resolves the requested tool name (after alias mapping via descriptor.aliases) against the descriptor's registered tool set. If the resolved name is not in descriptor.tools, it throws with the command name, the requested tool name, and the full generated help text listing valid tools.

Source

Thrown at src/cli/mcp-parity.ts:149

  } catch {
    return text;
  }
}

async function executeDescriptorCommand(
  args: string[],
  loadDescriptor: DescriptorLoader,
): Promise<McpParityExecutionResult> {
  const descriptor = await loadDescriptor();
  const parsed = parseMcpCliArgs(args);
  if (parsed.help || !parsed.toolName) {
    return { ok: true, help: buildDescriptorHelp(descriptor) };
  }

  const toolName = descriptor.aliases?.[parsed.toolName] ?? parsed.toolName;
  const allowedTools = new Set(descriptor.tools.map((tool) => tool.name));
  if (!allowedTools.has(toolName)) {
    throw new Error(
      `Unknown ${descriptor.commandName} tool: ${parsed.toolName}\n${buildDescriptorHelp(descriptor)}`,
    );
  }

  const result = await descriptor.handle(
    {
      params: {
        name: toolName,
        arguments: parsed.input,
      },
    },
    descriptor.handleOptions,
  );
  const payload = extractPayload(result);
  return result.isError
    ? { ok: false, error: payload }
    : { ok: true, data: payload };
}

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Read the help text included in the error message — it enumerates every valid tool name
  2. Fix the typo / use the exact tool name from the help output
  3. Verify you're on the version whose tool set you expect (check changelog or --version)
  4. If an alias is expected, confirm it still exists in descriptor.aliases for your version

Example fix

# before
mycli mcp run-tool serach --input '{"q":"x"}'

# after
mycli mcp run-tool search --input '{"q":"x"}'
Defensive patterns

Strategy: try-catch

Validate before calling

const validTools = new Set(['search', 'get', 'list']); // from descriptor help
if (!validTools.has(requestedTool)) {
  console.error(`Unknown tool. Valid: ${[...validTools].join(', ')}`);
  process.exit(2);
}

Type guard

function isKnownTool(name: string, descriptor: { tools: { name: string }[]; aliases?: Record<string, string> }): boolean {
  const resolved = descriptor.aliases?.[name] ?? name;
  return descriptor.tools.some((t) => t.name === resolved);
}

Try / catch

try { await executeDescriptorCommand(descriptor, args); }
catch (e) {
  if (/Unknown \S+ tool:/.test(String(e))) { console.error(e.message); process.exit(2); } // message embeds full help
  throw e;
}

Prevention

When it happens

Trigger: Calling `mcp <command> <toolName>` where toolName is not registered and not an alias — typo'd names, tools from a different/older descriptor, or plugins that failed to load their tools.

Common situations: Typos (serch vs search); upgrading/downgrading versions where tool names changed; docs referencing tools not present in the installed build; alias removed between releases.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/2e28d12c6244d91c. Report an issue: GitHub.