{"record":{"id":"82d211852c496b41","repo":"neoclide/coc.nvim","slug":"tool-name-is-required","errorCode":null,"errorMessage":"Tool name is required","messagePattern":"Tool name is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/mcp/index.ts","lineNumber":256,"sourceCode":"      workspace.nvim.setVar('coc_mcp_started', 0, true)\n    }\n    logger.info('MCP server stopped')\n  }\n\n  public dispose(): void {\n    this.stop()\n  }\n\n  /**\n   * Register a custom MCP tool from a coc.nvim extension. The tool becomes\n   * available on the next `tools/list` (immediately when the server is\n   * running, via `notifications/tools/list_changed`). Returns a Disposable\n   * that unregisters the tool.\n   */\n  public registerTool(tool: McpTool): Disposable {\n    let name = tool?.name\n    if (typeof name !== 'string' || name.length === 0) {\n      throw new Error('Tool name is required')\n    }\n    return this.getRegistry().register(tool)\n  }\n\n  private getRegistry(): ToolRegistry {\n    if (!this.registry) {\n      let registry = new ToolRegistry()\n      for (let tool of [...createWorkspaceTools(), ...createDocumentTools(), ...createLspTools(), ...createEditorTools()]) {\n        registry.register(tool)\n      }\n      this.registry = registry\n    }\n    return this.registry\n  }\n\n  private getConfig(): McpConfig {\n    let config = workspace.getConfiguration('mcp')\n    return {","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/mcp/index.ts#L238-L274","documentation":"`McpServer.registerTool` validates that the tool object has a non-empty string `name` before registering it with the tool registry. Registering an unnamed or malformed tool would break MCP tool listing and dispatch, so it is rejected eagerly.","triggerScenarios":"Calling `registerTool(undefined)`, `registerTool({})`, `registerTool({ name: '' })`, or passing a tool whose `name` is not a string (e.g. `name: 42` via untyped JS).","commonSituations":"Hand-writing an McpTool object and forgetting the name field; dynamically constructing tools from config/JSON where the name key is missing or empty after trimming; a factory function returning undefined on an error path that is passed straight to registerTool.","solutions":["Give the tool a non-empty string `name` before calling registerTool","Validate tool objects coming from config/dynamic sources before registering","Log the tool object on failure to find which construction path omitted the name"],"exampleFix":"// before\nserver.registerTool({ handler: async () => ({}) })\n// after\nserver.registerTool({ name: 'my-tool', handler: async () => ({}) })","handlingStrategy":"validation","validationCode":"function isRegisterableTool(tool: unknown): tool is McpTool {\n  return !!tool && typeof tool === 'object' &&\n    typeof (tool as McpTool).name === 'string' && (tool as McpTool).name.length > 0 &&\n    typeof (tool as McpTool).handler === 'function'\n}","typeGuard":"function hasName(t: unknown): t is McpTool & { name: string } {\n  return typeof t === 'object' && t !== null &&\n    typeof (t as { name?: unknown }).name === 'string' &&\n    (t as { name: string }).name.length > 0\n}","tryCatchPattern":"try {\n  disposables.push(server.registerTool(tool))\n} catch (e) {\n  logger.error('registerTool rejected:', JSON.stringify(tool))\n  throw e\n}","preventionTips":["Always define a non-empty string name on McpTool objects","Validate dynamically-generated tool objects before registration","Type tool definitions with the McpTool interface instead of plain literals in JS","Log the full tool object when registration fails"],"tags":["mcp","validation","missing-argument"],"backgroundTag":"missing-required-field","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}