{"record":{"id":"3e74dd946aff9bdc","repo":"microsoft/playwright","slug":"webmcp-tool-params-name-is-not-registered-in-this-frame","errorCode":null,"errorMessage":"WebMCP tool \"${params.name}\" is not registered in this frame","messagePattern":"WebMCP tool \"(.+?)\" is not registered in this frame","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/tools/backend/webmcp.ts","lineNumber":135,"sourceCode":"        consequential: annotations.consequentialHint ?? annotations.consequential,\n      } : undefined,\n      origin: tool.origin,\n    };\n  }));\n}\n\nfunction callToolInPage(params: { name: string, inputJson: string }) {\n  const modelContext = (document as DocumentWithModelContext).modelContext\n      ?? (navigator as NavigatorWithModelContext).modelContext;\n  if (!modelContext)\n    throw new Error('WebMCP is not available on this page');\n  const stringify = (result: unknown) => result === undefined ? 'null' : JSON.stringify(result);\n  if (modelContext.executeTool) {\n    // Chromium: executeTool(registeredTool, inputJsonString) resolves to a JSON string.\n    return Promise.resolve(modelContext.getTools!()).then(tools => {\n      const tool = tools.filter(t => !('window' in t) || t.window === window).find(t => t.name === params.name);\n      if (!tool)\n        throw new Error(`WebMCP tool \"${params.name}\" is not registered in this frame`);\n      return modelContext.executeTool!(tool, params.inputJson);\n    }).then(result => typeof result === 'string' ? result : stringify(result));\n  }\n  // Firefox: invokeTool(name, inputObject) resolves to the value itself.\n  return Promise.resolve(modelContext.invokeTool!(params.name, JSON.parse(params.inputJson))).then(stringify);\n}\n\nconst kTimedOut = Symbol('timedOut');\n\nasync function withTimeout<T>(promise: Promise<T>, timeout: number): Promise<T | typeof kTimedOut> {\n  let timer: NodeJS.Timeout | undefined;\n  const timeoutPromise = new Promise<typeof kTimedOut>(resolve => {\n    timer = setTimeout(() => resolve(kTimedOut), timeout);\n  });\n  try {\n    return await Promise.race([promise, timeoutPromise]);\n  } finally {\n    clearTimeout(timer);","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/microsoft/playwright/blob/f1d33b5029be8bbc1095fe88e559117fa3a6243b/packages/playwright-core/src/tools/backend/webmcp.ts#L117-L153","documentation":"The page exposes a WebMCP modelContext, but no registered tool with the requested name is visible in the target frame. In Chromium the code filters getTools() results by name and by the tool's window scope; if no match is found it throws. The tool name or the frame is wrong.","triggerScenarios":"Calling a WebMCP tool whose name is not registered (typo, tool registered under a different name), or the tool is registered in a different frame/window than the one the call is dispatched to (tools with a 'window' scope are filtered per-frame).","commonSituations":"Tool names changed after a page update; invoking an iframe-registered tool from the main frame context or vice versa; case-sensitivity mistakes in tool names.","solutions":["Run the webmcp-list command (or equivalent) to list the tools actually registered in the target frame and match the exact name.","Target the frame where the tool is registered (iframes register their own modelContext).","Check for typos and casing in the tool name."],"exampleFix":"// before\nawait client.callTool('webmcp-call', { params: { tool: 'getweather', inputJson: '{}' } });\n// after\nconst tools = await client.callTool('webmcp-list', { params: {} });\n// pick the exact registered name, e.g. 'get-weather'\nawait client.callTool('webmcp-call', { params: { tool: 'get-weather', inputJson: '{}' } });","handlingStrategy":"validation","validationCode":"const names = await page.evaluate(() => (navigator.modelContext?.getTools?.() ?? []).map(t => t.name));\nif (!names.includes(toolName)) throw new Error(`Tool ${toolName} not registered. Available: ${names.join(', ')}`);","typeGuard":"null","tryCatchPattern":"try {\n  return await webmcpCall(frame, toolName, inputJson);\n} catch (e) {\n  if (e.message.includes('is not registered')) {\n    // list tools and pick the correct name/frame before retrying once\n  }\n  throw e;\n}","preventionTips":["Always enumerate registered tools (webmcp-list) before invoking.","Match tool names exactly, including casing and dashes.","Dispatch to the frame where the tool was registered, especially for iframe tools."],"tags":["webmcp","tool-not-found","frame"],"backgroundTag":"entity-not-found","analyzedSha":"f1d33b5029be8bbc1095fe88e559117fa3a6243b","analyzedAt":"2026-09-15T07:37:15.003Z","contentChangedAt":"2026-09-15T07:37:15.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}