feat: add session-configurable snapshot settings via browser_configure_snapshots
Implements dynamic snapshot configuration that MCP clients can control during sessions without requiring server restarts or CLI changes. New tool: browser_configure_snapshots - Configure includeSnapshots, maxSnapshotTokens, differentialSnapshots at runtime - Changes take effect immediately for subsequent tool calls - Shows current settings when called with no parameters - Provides helpful tips and usage guidance Key improvements: 1. **Runtime Configuration**: Update snapshot behavior during active sessions 2. **Client Control**: MCP clients can adapt to different workflows dynamically 3. **Immediate Effect**: No server restart required - changes apply instantly 4. **State Tracking**: Context maintains current session configuration 5. **User Friendly**: Clear feedback on current settings and changes Updated tool descriptions: - All interactive tools now mention "configurable via browser_configure_snapshots" - Removed references to CLI-only configuration - Enhanced browser_snapshot description for explicit snapshots Benefits for users: 🔄 Dynamic configuration without restarts 🎛️ Client-controlled snapshot behavior 📊 View current settings anytime ⚡ Instant configuration changes 🎯 Adapt settings per workflow/task Example usage: ```json { "includeSnapshots": false, "maxSnapshotTokens": 25000, "differentialSnapshots": true } ``` This transforms snapshot configuration from static CLI options into a flexible session management system that adapts to client needs in real-time. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
574fdc4959
commit
2fe8b9355c
@ -636,4 +636,28 @@ export class Context {
|
||||
this._lastSnapshotFingerprint = undefined;
|
||||
this._lastPageState = undefined;
|
||||
}
|
||||
|
||||
updateSnapshotConfig(updates: {
|
||||
includeSnapshots?: boolean;
|
||||
maxSnapshotTokens?: number;
|
||||
differentialSnapshots?: boolean;
|
||||
}): void {
|
||||
// Update configuration at runtime
|
||||
if (updates.includeSnapshots !== undefined)
|
||||
(this.config as any).includeSnapshots = updates.includeSnapshots;
|
||||
|
||||
|
||||
if (updates.maxSnapshotTokens !== undefined)
|
||||
(this.config as any).maxSnapshotTokens = updates.maxSnapshotTokens;
|
||||
|
||||
|
||||
if (updates.differentialSnapshots !== undefined) {
|
||||
(this.config as any).differentialSnapshots = updates.differentialSnapshots;
|
||||
|
||||
// Reset differential state when toggling
|
||||
if (updates.differentialSnapshots)
|
||||
this.resetDifferentialSnapshot();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +74,12 @@ const installPopularExtensionSchema = z.object({
|
||||
version: z.string().optional().describe('Specific version to install (defaults to latest)')
|
||||
});
|
||||
|
||||
const configureSnapshotsSchema = z.object({
|
||||
includeSnapshots: z.boolean().optional().describe('Enable/disable automatic snapshots after interactive operations. When false, use browser_snapshot for explicit snapshots.'),
|
||||
maxSnapshotTokens: z.number().min(0).optional().describe('Maximum tokens allowed in snapshots before truncation. Use 0 to disable truncation.'),
|
||||
differentialSnapshots: z.boolean().optional().describe('Enable differential snapshots that show only changes since last snapshot instead of full page snapshots.')
|
||||
});
|
||||
|
||||
export default [
|
||||
defineTool({
|
||||
capability: 'core',
|
||||
@ -524,6 +530,78 @@ export default [
|
||||
}
|
||||
},
|
||||
}),
|
||||
defineTool({
|
||||
capability: 'core',
|
||||
schema: {
|
||||
name: 'browser_configure_snapshots',
|
||||
title: 'Configure snapshot behavior',
|
||||
description: 'Configure how page snapshots are handled during the session. Control automatic snapshots, size limits, and differential modes. Changes take effect immediately for subsequent tool calls.',
|
||||
inputSchema: configureSnapshotsSchema,
|
||||
type: 'destructive',
|
||||
},
|
||||
handle: async (context: Context, params: z.output<typeof configureSnapshotsSchema>, response: Response) => {
|
||||
try {
|
||||
const changes: string[] = [];
|
||||
|
||||
// Update snapshot configuration
|
||||
if (params.includeSnapshots !== undefined)
|
||||
changes.push(`📸 Auto-snapshots: ${params.includeSnapshots ? 'enabled' : 'disabled'}`);
|
||||
|
||||
|
||||
if (params.maxSnapshotTokens !== undefined) {
|
||||
if (params.maxSnapshotTokens === 0)
|
||||
changes.push(`📏 Snapshot truncation: disabled (unlimited size)`);
|
||||
else
|
||||
changes.push(`📏 Max snapshot tokens: ${params.maxSnapshotTokens.toLocaleString()}`);
|
||||
|
||||
}
|
||||
|
||||
if (params.differentialSnapshots !== undefined) {
|
||||
changes.push(`🔄 Differential snapshots: ${params.differentialSnapshots ? 'enabled' : 'disabled'}`);
|
||||
|
||||
if (params.differentialSnapshots)
|
||||
changes.push(` ↳ Reset differential state for fresh tracking`);
|
||||
|
||||
}
|
||||
|
||||
// Apply the updated configuration using the context method
|
||||
context.updateSnapshotConfig(params);
|
||||
|
||||
// Provide user feedback
|
||||
if (changes.length === 0) {
|
||||
response.addResult('No snapshot configuration changes specified.\n\n**Current settings:**\n' +
|
||||
`📸 Auto-snapshots: ${context.config.includeSnapshots ? 'enabled' : 'disabled'}\n` +
|
||||
`📏 Max snapshot tokens: ${context.config.maxSnapshotTokens === 0 ? 'unlimited' : context.config.maxSnapshotTokens.toLocaleString()}\n` +
|
||||
`🔄 Differential snapshots: ${context.config.differentialSnapshots ? 'enabled' : 'disabled'}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let result = '✅ **Snapshot configuration updated:**\n\n';
|
||||
result += changes.map(change => `- ${change}`).join('\n');
|
||||
result += '\n\n**💡 Tips:**\n';
|
||||
|
||||
if (!context.config.includeSnapshots)
|
||||
result += '- Use `browser_snapshot` tool when you need explicit page snapshots\n';
|
||||
|
||||
|
||||
if (context.config.differentialSnapshots) {
|
||||
result += '- Differential mode shows only changes between operations\n';
|
||||
result += '- First snapshot after enabling will establish baseline\n';
|
||||
}
|
||||
|
||||
if (context.config.maxSnapshotTokens > 0 && context.config.maxSnapshotTokens < 5000)
|
||||
result += '- Consider increasing token limit if snapshots are frequently truncated\n';
|
||||
|
||||
|
||||
result += '\n**Changes take effect immediately for subsequent tool calls.**';
|
||||
|
||||
response.addResult(result);
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to configure snapshots: ${error}`);
|
||||
}
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
// Helper functions for extension downloading
|
||||
|
||||
@ -27,7 +27,7 @@ const pressKey = defineTabTool({
|
||||
schema: {
|
||||
name: 'browser_press_key',
|
||||
title: 'Press a key',
|
||||
description: 'Press a key on the keyboard. Returns page snapshot after keypress unless disabled with --no-snapshots.',
|
||||
description: 'Press a key on the keyboard. Returns page snapshot after keypress (configurable via browser_configure_snapshots).',
|
||||
inputSchema: z.object({
|
||||
key: z.string().describe('Name of the key to press or a character to generate, such as `ArrowLeft` or `a`'),
|
||||
}),
|
||||
@ -56,7 +56,7 @@ const type = defineTabTool({
|
||||
schema: {
|
||||
name: 'browser_type',
|
||||
title: 'Type text',
|
||||
description: 'Type text into editable element. Returns page snapshot after typing unless disabled with --no-snapshots.',
|
||||
description: 'Type text into editable element. Returns page snapshot after typing (configurable via browser_configure_snapshots).',
|
||||
inputSchema: typeSchema,
|
||||
type: 'destructive',
|
||||
},
|
||||
|
||||
@ -23,7 +23,7 @@ const navigate = defineTool({
|
||||
schema: {
|
||||
name: 'browser_navigate',
|
||||
title: 'Navigate to a URL',
|
||||
description: 'Navigate to a URL. Returns page snapshot after navigation unless disabled with --no-snapshots.',
|
||||
description: 'Navigate to a URL. Returns page snapshot after navigation (configurable via browser_configure_snapshots).',
|
||||
inputSchema: z.object({
|
||||
url: z.string().describe('The URL to navigate to'),
|
||||
}),
|
||||
|
||||
@ -25,7 +25,7 @@ const snapshot = defineTool({
|
||||
schema: {
|
||||
name: 'browser_snapshot',
|
||||
title: 'Page snapshot',
|
||||
description: 'Capture complete accessibility snapshot of the current page. Always returns full snapshot regardless of --no-snapshots or size limits. Better than screenshot for understanding page structure.',
|
||||
description: 'Capture complete accessibility snapshot of the current page. Always returns full snapshot regardless of session snapshot configuration. Better than screenshot for understanding page structure.',
|
||||
inputSchema: z.object({}),
|
||||
type: 'readOnly',
|
||||
},
|
||||
@ -51,7 +51,7 @@ const click = defineTabTool({
|
||||
schema: {
|
||||
name: 'browser_click',
|
||||
title: 'Click',
|
||||
description: 'Perform click on a web page. Returns page snapshot after click unless disabled with --no-snapshots. Large snapshots (>10k tokens) are truncated - use browser_snapshot for full capture.',
|
||||
description: 'Perform click on a web page. Returns page snapshot after click (configurable via browser_configure_snapshots). Use browser_snapshot for explicit full snapshots.',
|
||||
inputSchema: clickSchema,
|
||||
type: 'destructive',
|
||||
},
|
||||
@ -85,7 +85,7 @@ const drag = defineTabTool({
|
||||
schema: {
|
||||
name: 'browser_drag',
|
||||
title: 'Drag mouse',
|
||||
description: 'Perform drag and drop between two elements. Returns page snapshot after drag unless disabled with --no-snapshots.',
|
||||
description: 'Perform drag and drop between two elements. Returns page snapshot after drag (configurable via browser_configure_snapshots).',
|
||||
inputSchema: z.object({
|
||||
startElement: z.string().describe('Human-readable source element description used to obtain the permission to interact with the element'),
|
||||
startRef: z.string().describe('Exact source element reference from the page snapshot'),
|
||||
@ -116,7 +116,7 @@ const hover = defineTabTool({
|
||||
schema: {
|
||||
name: 'browser_hover',
|
||||
title: 'Hover mouse',
|
||||
description: 'Hover over element on page. Returns page snapshot after hover unless disabled with --no-snapshots.',
|
||||
description: 'Hover over element on page. Returns page snapshot after hover (configurable via browser_configure_snapshots).',
|
||||
inputSchema: elementSchema,
|
||||
type: 'readOnly',
|
||||
},
|
||||
@ -142,7 +142,7 @@ const selectOption = defineTabTool({
|
||||
schema: {
|
||||
name: 'browser_select_option',
|
||||
title: 'Select option',
|
||||
description: 'Select an option in a dropdown. Returns page snapshot after selection unless disabled with --no-snapshots.',
|
||||
description: 'Select an option in a dropdown. Returns page snapshot after selection (configurable via browser_configure_snapshots).',
|
||||
inputSchema: selectOptionSchema,
|
||||
type: 'destructive',
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user