playwright-mcp/src/tools/network.ts
Ryan Malloy 9257404ba3 feat: fix video recording session persistence and add HTTP request monitoring
Video Recording Fixes:
- Fix session persistence issues where recording state was lost between tool calls
- Improve page video object handling by triggering navigation when needed
- Add browser_reveal_artifact_paths tool to show exact file locations
- Enhance browser_recording_status with detailed debugging info and file listings
- Add clearVideoRecordingState() method for proper state management
- Keep recording config available for debugging until new session starts

Request Monitoring System:
- Add comprehensive RequestInterceptor class for HTTP traffic capture
- Implement 5 new MCP tools for request monitoring and analysis
- Support multiple export formats: JSON, HAR, CSV, and summary reports
- Add filtering by domain, method, status codes, and response timing
- Integrate with artifact storage for organized session-based file management
- Enhance browser_network_requests with rich intercepted data

Additional Improvements:
- Add getBaseDirectory/getSessionDirectory methods to ArtifactManager
- Fix floating promise in tab.ts extension console message polling
- Add debug script for comprehensive video recording workflow testing
- Update README with new tool documentation

Resolves video recording workflow issues and adds powerful HTTP traffic
analysis capabilities for web application debugging and security testing.
2025-09-05 07:17:11 -06:00

112 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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 { z } from 'zod';
import { defineTabTool } from './tool.js';
import type * as playwright from 'playwright';
const requests = defineTabTool({
capability: 'core',
schema: {
name: 'browser_network_requests',
title: 'List network requests',
description: 'Returns all network requests since loading the page. For more detailed analysis including timing, headers, and bodies, use the advanced request monitoring tools (browser_start_request_monitoring, browser_get_requests).',
inputSchema: z.object({
detailed: z.boolean().optional().default(false).describe('Show detailed request information if request monitoring is active')
}),
type: 'readOnly',
},
handle: async (tab, params, response) => {
// Check if request interceptor is active and can provide richer data
const interceptor = tab.context.getRequestInterceptor();
if (params.detailed && interceptor) {
// Use rich intercepted data
const interceptedRequests = interceptor.getData();
if (interceptedRequests.length > 0) {
response.addResult('📊 **Network Requests (Enhanced)**');
response.addResult('');
interceptedRequests.forEach((req, index) => {
const duration = req.duration ? ` (${req.duration}ms)` : '';
const status = req.failed ? 'FAILED' : req.response?.status || 'pending';
const size = req.response?.bodySize ? ` - ${(req.response.bodySize / 1024).toFixed(1)}KB` : '';
response.addResult(`${index + 1}. **${req.method} ${status}**${duration}`);
response.addResult(` ${req.url}${size}`);
if (req.response) {
const contentType = req.response.headers['content-type'];
if (contentType)
response.addResult(` 📄 ${contentType}`);
}
if (req.failed && req.failure)
response.addResult(`${req.failure.errorText}`);
response.addResult('');
});
const stats = interceptor.getStats();
response.addResult('📈 **Summary:**');
response.addResult(`• Total: ${stats.totalRequests} | Success: ${stats.successfulRequests} | Failed: ${stats.failedRequests}`);
response.addResult(`• Average Response Time: ${stats.averageResponseTime}ms`);
return;
}
}
// Fall back to basic playwright request data
const basicRequests = tab.requests();
if (basicRequests.size === 0) {
response.addResult(' **No network requests found**');
response.addResult('');
response.addResult('💡 For comprehensive request monitoring, use:');
response.addResult(' • `browser_start_request_monitoring` - Enable detailed capture');
response.addResult(' • `browser_get_requests` - View captured data with analysis');
return;
}
response.addResult('📋 **Network Requests (Basic)**');
response.addResult('');
[...basicRequests.entries()].forEach(([req, res], index) => {
response.addResult(`${index + 1}. ${renderRequest(req, res)}`);
});
response.addResult('');
response.addResult('💡 **For detailed analysis** including timing, headers, and bodies:');
response.addResult(' • Use `browser_start_request_monitoring` to enable advanced capture');
response.addResult(' • Then use `browser_get_requests` for comprehensive analysis');
},
});
function renderRequest(request: playwright.Request, response: playwright.Response | null) {
const result: string[] = [];
result.push(`[${request.method().toUpperCase()}] ${request.url()}`);
if (response)
result.push(`=> [${response.status()}] ${response.statusText()}`);
return result.join(' ');
}
export default [
requests,
];