Skip to main content
Glama
lxman

Safari MCP Server

by lxman

safari_get_network_logs

Retrieve network activity logs from Safari for performance analysis and debugging by providing a session identifier.

Instructions

Get network activity logs for performance analysis

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sessionIdYesSession identifier

Implementation Reference

  • Core implementation of network log retrieval: injects JavaScript to capture network activity via PerformanceObserver for resources and fetch interception, then retrieves and formats the logs.
    async getNetworkLogs(sessionId: string): Promise<NetworkLogEntry[]> {
      const session = this.getSession(sessionId);
      if (!session) {
        throw new Error(`Session ${sessionId} not found`);
      }
    
      try {
        // First, inject network monitoring if not already present
        await session.driver.executeScript(`
          if (!window.__safariMCPNetworkLogs) {
            window.__safariMCPNetworkLogs = [];
            
            // Capture existing performance entries
            const existingEntries = performance.getEntriesByType('resource');
            existingEntries.forEach(entry => {
              window.__safariMCPNetworkLogs.push({
                method: 'Network.resourceFinished',
                url: entry.name,
                status: null, // Not available from Resource Timing API
                requestHeaders: null,
                responseHeaders: null,
                timestamp: Date.now() - (performance.now() - entry.startTime),
                duration: entry.duration,
                transferSize: entry.transferSize || null,
                encodedBodySize: entry.encodedBodySize || null,
                decodedBodySize: entry.decodedBodySize || null
              });
            });
            
            // Monitor new resources using PerformanceObserver
            if ('PerformanceObserver' in window) {
              const observer = new PerformanceObserver((list) => {
                for (const entry of list.getEntries()) {
                  if (entry.entryType === 'resource') {
                    window.__safariMCPNetworkLogs.push({
                      method: 'Network.resourceFinished',
                      url: entry.name,
                      status: null,
                      requestHeaders: null,
                      responseHeaders: null,
                      timestamp: Date.now() - (performance.now() - entry.startTime),
                      duration: entry.duration,
                      transferSize: entry.transferSize || null,
                      encodedBodySize: entry.encodedBodySize || null,
                      decodedBodySize: entry.decodedBodySize || null
                    });
                  }
                }
              });
              observer.observe({ entryTypes: ['resource'] });
            }
            
            // Intercept fetch requests for additional data
            const originalFetch = window.fetch;
            window.fetch = function(...args) {
              const url = typeof args[0] === 'string' ? args[0] : args[0].url;
              const startTime = Date.now();
              
              return originalFetch.apply(this, args).then(response => {
                window.__safariMCPNetworkLogs.push({
                  method: 'Network.responseReceived',
                  url: url,
                  status: response.status,
                  requestHeaders: args[1]?.headers || null,
                  responseHeaders: Object.fromEntries(response.headers.entries()),
                  timestamp: startTime,
                  duration: Date.now() - startTime
                });
                return response;
              }).catch(error => {
                window.__safariMCPNetworkLogs.push({
                  method: 'Network.loadingFailed',
                  url: url,
                  status: null,
                  requestHeaders: args[1]?.headers || null,
                  responseHeaders: null,
                  timestamp: startTime,
                  duration: Date.now() - startTime,
                  error: error.message
                });
                throw error;
              });
            };
          }
        `);
    
        // Retrieve captured network logs
        const networkLogs = await session.driver.executeScript(`
          return window.__safariMCPNetworkLogs || [];
        `);
    
        return networkLogs.map((log: any) => ({
          method: log.method,
          url: log.url,
          status: log.status,
          requestHeaders: log.requestHeaders,
          responseHeaders: log.responseHeaders,
          timestamp: log.timestamp,
          ...(log.duration !== undefined && { duration: log.duration }),
          ...(log.transferSize !== undefined && { transferSize: log.transferSize }),
          ...(log.encodedBodySize !== undefined && { encodedBodySize: log.encodedBodySize }),
          ...(log.decodedBodySize !== undefined && { decodedBodySize: log.decodedBodySize }),
          ...(log.error && { error: log.error })
        }));
      } catch (error: unknown) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        throw new Error(`Failed to get network logs: ${errorMessage}`);
      }
    }
  • MCP server handler for the tool: delegates to SafariDriverManager and formats response as JSON text.
    private async getNetworkLogs(args: Record<string, any>): Promise<Array<{ type: string; text: string }>> {
      const { sessionId } = args;
      
      const logs = await this.driverManager.getNetworkLogs(sessionId);
      
      return [
        {
          type: 'text',
          text: `Network Logs (${logs.length} entries):\n\n${JSON.stringify(logs, null, 2)}`
        }
      ];
    }
  • Tool schema definition including input validation (requires sessionId) as registered in listTools response.
    {
      name: 'safari_get_network_logs',
      description: 'Get network activity logs for performance analysis',
      inputSchema: {
        type: 'object',
        properties: {
          sessionId: { type: 'string', description: 'Session identifier' }
        },
        required: ['sessionId']
      }
    },
  • Handler dispatch/registration in the tool call switch statement.
    case 'safari_get_network_logs':
      return await this.getNetworkLogs(args);
  • TypeScript interface defining the structure of network log entries used in the tool's output.
    export interface NetworkLogEntry {
      method: string;
      url: string;
      status?: number;
      requestHeaders?: Record<string, string>;
      responseHeaders?: Record<string, string>;
      timestamp: number;
      duration?: number;
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lxman/safari-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server