playwright-mcp/src/tools.ts
Ryan Malloy b7ec4faf60 feat: add MCP client identification system with debug toolbar and custom code injection
- Implement comprehensive debug toolbar showing project name, session ID, client info, and uptime
- Add Django-style draggable toolbar with terminal aesthetics for multi-client identification
- Support custom JavaScript/CSS injection into all pages with session persistence
- Auto-injection system hooks into page creation lifecycle for seamless operation
- LLM-safe HTML comment wrapping prevents confusion during automated testing
- 5 new MCP tools: enable_debug_toolbar, inject_custom_code, list_injections, disable_debug_toolbar, clear_injections
- Session-based configuration storage with auto-injection on new pages
- Solves multi-parallel MCP client identification problem for development workflows

Tools added:
- browser_enable_debug_toolbar: Configure project identification overlay
- browser_inject_custom_code: Add custom JS/CSS to all session pages
- browser_list_injections: View active injection configuration
- browser_disable_debug_toolbar: Remove debug toolbar
- browser_clear_injections: Clean up custom injections

Files modified:
- src/tools/codeInjection.ts: Complete injection system (547 lines)
- src/context.ts: Added injection config and auto-injection hooks
- src/tools.ts: Registered new tools in main array
- test-code-injection-simple.cjs: Validation test suite

Addresses issue: "I'm running many different 'mcp clients' in parallel on the same machine.
It's sometimes hard to figure out what client a playwright window belongs to."
2025-09-09 06:25:38 -06:00

67 lines
2.0 KiB
TypeScript

/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import artifacts from './tools/artifacts.js';
import common from './tools/common.js';
import codeInjection from './tools/codeInjection.js';
import configure from './tools/configure.js';
import console from './tools/console.js';
import dialogs from './tools/dialogs.js';
import evaluate from './tools/evaluate.js';
import files from './tools/files.js';
import install from './tools/install.js';
import keyboard from './tools/keyboard.js';
import navigate from './tools/navigate.js';
import network from './tools/network.js';
import pdf from './tools/pdf.js';
import requests from './tools/requests.js';
import snapshot from './tools/snapshot.js';
import tabs from './tools/tabs.js';
import screenshot from './tools/screenshot.js';
import video from './tools/video.js';
import wait from './tools/wait.js';
import mouse from './tools/mouse.js';
import type { Tool } from './tools/tool.js';
import type { FullConfig } from './config.js';
export const allTools: Tool<any>[] = [
...artifacts,
...codeInjection,
...common,
...configure,
...console,
...dialogs,
...evaluate,
...files,
...install,
...keyboard,
...navigate,
...network,
...mouse,
...pdf,
...requests,
...screenshot,
...snapshot,
...tabs,
...video,
...wait,
];
export function filteredTools(config: FullConfig) {
return allTools.filter(tool => tool.capability.startsWith('core') || config.capabilities?.includes(tool.capability));
}