capture_traffic
Capture live HTTP(S) traffic from intercepted browsers, apps, or containers. Creates a temporary session to collect requests and responses for analysis and debugging.
Instructions
Capture live HTTP(S) traffic being intercepted by HTTP Toolkit. Creates a temporary session, subscribes to traffic events via WebSocket, collects requests and responses for the specified duration, then returns all captured exchanges. Use this to see what HTTP requests are being made by intercepted browsers, apps, or containers.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| duration | No | Duration in seconds to capture traffic (default: 5, max: 30) |
Implementation Reference
- src/index.ts:390-408 (handler)Registration and MCP handler for the 'capture_traffic' tool.
server.registerTool( 'capture_traffic', { title: 'Capture Live Intercepted Traffic', description: 'Capture live HTTP(S) traffic being intercepted by HTTP Toolkit. Creates a temporary session, subscribes to traffic events via WebSocket, collects requests and responses for the specified duration, then returns all captured exchanges. Use this to see what HTTP requests are being made by intercepted browsers, apps, or containers.', inputSchema: z.object({ duration: z.number().optional().describe('Duration in seconds to capture traffic (default: 5, max: 30)'), }), }, async ({ duration }) => { const durationMs = Math.min((duration || 5), 30) * 1000; const exchanges = await trafficCapture.captureLive(durationMs); return jsonResult({ capturedExchanges: exchanges.length, exchanges, }); } ); - src/traffic-capture.ts:134-247 (helper)The implementation of the traffic capturing logic using WebSockets and the Mockttp API.
async captureLive(durationMs: number = 5000): Promise<CapturedExchange[]> { const sessionId = await this.createSession(); const wsUrl = this.adminUrl.replace(/^http/, 'ws') + `/session/${sessionId}/subscription`; const exchanges = new Map<string, CapturedExchange>(); return new Promise<CapturedExchange[]>((resolve, reject) => { const ws = new WebSocket(wsUrl, 'graphql-ws', { headers: { 'Origin': 'http://localhost' }, }); const cleanup = () => { try { ws.close(); } catch {} this.stopSession(sessionId).catch(() => {}); }; const timeout = setTimeout(() => { cleanup(); resolve(Array.from(exchanges.values())); }, durationMs); ws.on('open', () => { // Init connection ws.send(JSON.stringify({ type: 'connection_init' })); }); ws.on('message', (data: WebSocket.Data) => { const msg = JSON.parse(data.toString()); if (msg.type === 'connection_ack') { // Subscribe to request initiated ws.send(JSON.stringify({ id: '1', type: 'start', payload: { query: `subscription { requestInitiated { id protocol httpVersion method url path headers remoteIpAddress remotePort tags } }`, }, })); // Subscribe to response completed ws.send(JSON.stringify({ id: '2', type: 'start', payload: { query: `subscription { responseCompleted { id statusCode statusMessage headers tags } }`, }, })); } if (msg.type === 'data' && msg.id === '1' && msg.payload?.data?.requestInitiated) { const req = msg.payload.data.requestInitiated; exchanges.set(req.id, { request: { id: req.id, method: req.method, url: req.url, protocol: req.protocol, headers: req.headers, remoteIpAddress: req.remoteIpAddress, tags: req.tags, }, }); } if (msg.type === 'data' && msg.id === '2' && msg.payload?.data?.responseCompleted) { const resp = msg.payload.data.responseCompleted; const exchange = exchanges.get(resp.id); if (exchange) { exchange.response = { id: resp.id, statusCode: resp.statusCode, statusMessage: resp.statusMessage, headers: resp.headers, tags: resp.tags, }; } } }); ws.on('error', (err) => { clearTimeout(timeout); cleanup(); reject(new Error(`WebSocket error: ${err.message}`)); }); ws.on('close', () => { clearTimeout(timeout); resolve(Array.from(exchanges.values())); }); }); } }