microsoft/playwright-mcp · error · Error
Unknown tool capabilities: ${unknownCapabilities.join(', ')}
Error message
Unknown tool capabilities: ${unknownCapabilities.join(', ')}. Please update the capabilities map in ${path.basename(__filename)}. What it means
This error is thrown by utils/update-readme.js, the maintenance script that regenerates the README's tool tables from the manifest produced by the MCP server. Every browser tool declares a `capability` field, and the script keeps a hardcoded `capabilities` map (e.g. 'core', 'testing') that must enumerate every possible capability value. When a tool reports a capability not present in that map, the script aborts because it would otherwise silently drop that tool from the generated README.
Source
Thrown at update-readme.js:43
const capabilities = /** @type {Record<string, string>} */ ({
'core-navigation': 'Core automation',
'core': 'Core automation',
'core-tabs': 'Tab management',
'core-input': 'Core automation',
'core-install': 'Browser installation',
'config': 'Configuration',
'network': 'Network',
'storage': 'Storage',
'devtools': 'DevTools',
'vision': 'Coordinate-based',
'pdf': 'PDF generation',
'testing': 'Test assertions',
});
const knownCapabilities = new Set(Object.keys(capabilities));
const unknownCapabilities = [...new Set(tools.browserTools.map(tool => tool.capability))].filter(cap => !knownCapabilities.has(cap));
if (unknownCapabilities.length)
throw new Error(`Unknown tool capabilities: ${unknownCapabilities.join(', ')}. Please update the capabilities map in ${path.basename(__filename)}.`);
/** @type {Record<string, any[]>} */
const toolsByCapability = {};
for (const capability of Object.keys(capabilities)) {
const title = capabilityTitle(capability);
let filteredTools = tools.browserTools.filter(tool => tool.capability === capability && !tool.skillOnly);
filteredTools = (toolsByCapability[title] || []).concat(filteredTools);
toolsByCapability[title] = filteredTools;
}
for (const [, tools] of Object.entries(toolsByCapability))
tools.sort((a, b) => a.schema.name.localeCompare(b.schema.name));
/**
* @param {string} capability
* @returns {string}
*/
function capabilityTitle(capability) {
const title = capabilities[capability];View on GitHub (pinned to 16cf228d7b)
Solutions
- Add the new capability as a key in the `capabilities` map in utils/update-readme.js with a short description, and add a matching entry via `capabilityTitle()` if one is required.
- Fix the tool definition: check the `capability` value on the tool named in the manifest and correct typos or casing so it matches an existing key such as 'core' or 'testing'.
- If a capability was renamed intentionally, update both the tools and the capabilities map in the same commit, then rerun `node utils/update-readme.js` to confirm it passes.
Example fix
// before (utils/update-readme.js)
const capabilities = {
'core': 'Core tools',
'testing': 'Test assertions',
};
// after — new tool declares capability: 'network'
const capabilities = {
'core': 'Core tools',
'testing': 'Test assertions',
'network': 'Network interception',
}; Defensive patterns
Strategy: validation
Validate before calling
// Before running the generator, verify every tool capability is known:
import { createServer } from '../src/index.js';
import fs from 'fs';
const script = fs.readFileSync('utils/update-readme.js', 'utf-8');
const known = [...script.matchAll(/^\s*'([a-z-]+)':/gm)].map(m => m[1]);
const { tools } = await createServer(/* minimal config */).listTools();
const unknown = [...new Set(tools.map(t => t.capability))].filter(c => !known.includes(c));
if (unknown.length) {
console.error('Update capabilities map first:', unknown.join(', '));
process.exit(1);
} Try / catch
try {
execSync('node utils/update-readme.js', { stdio: 'inherit' });
} catch (e) {
if (/Unknown tool capabilities/.test(e.message ?? String(e))) {
// parse the capability list, add them to the capabilities map, rerun
throw new Error('README generator out of date: add missing capabilities to update-readme.js');
}
throw e;
} Prevention
- When adding a tool or capability, update the capabilities map in update-readme.js in the same commit.
- Keep capability strings as a single shared const/enum in src so tools and the script cannot drift.
- Run `npm run update-readme` in CI to catch drift immediately rather than at release time.
When it happens
Trigger: Running `node utils/update-readme.js` (or `npm run update-readme`) after adding a new tool to src/tools/*.ts whose `capability` string (e.g. capability: 'network') is not a key in the `capabilities` map at the top of update-readme.js. It also fires if an existing capability is renamed in the tool definition without updating the script, or if a tool's capability has a typo/case mismatch ('Core' vs 'core').
Common situations: Contributing a new browser tool or intercept tool to playwright-mcp; refactoring capability groupings (e.g. splitting 'core' into finer categories); copy-pasting a tool file and editing its capability field. Typically hit in CI or locally right after `npm run build` when regenerating docs.
Related errors
AI-assisted analysis of microsoft/playwright-mcp@16cf228d7b (2026-08-27).
Data as JSON: /api/errors/ff61f152fb90c771.
Report an issue: GitHub.