#
tokens: 2456/50000 6/6 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── index.ts
├── LICENSE
├── package copy.json
├── package-lock.json
├── package.json
├── README.md
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
node_modules/
build/
.env
*.log
.DS_Store
.idea/
.vscode/
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# @enemyrr/mcp-server-pagespeed

A Model Context Protocol server that provides Google PageSpeed Insights analysis. This server enables AI models to analyze webpage performance through a standardized interface.

<a href="https://glama.ai/mcp/servers/wes81w8il2"><img width="380" height="200" src="https://glama.ai/mcp/servers/wes81w8il2/badge" alt="Server Pagespeed MCP server" /></a>

## Installation & Setup for Cursor IDE

1. Clone and build the project:
```bash
git clone https://github.com/enemyrr/mcp-server-pagespeed.git
cd mcp-server-pagespeed
npm install
npm run build
```

2. Add the server in Cursor IDE settings:
   - Open Command Palette (Cmd/Ctrl + Shift + P)
   - Search for "MCP: Add Server"
   - Fill in the fields:
     - Name: `pagespeed`
     - Type: `command`
     - Command: `node /absolute/path/to/mcp-server-pagespeed/build/index.js`

> **Note**: Replace `/absolute/path/to/` with the actual path where you cloned and built the project.

## Command-line Usage

Just run:

```bash
npx mcp-server-pagespeed
```

## Available Tools

### analyze_pagespeed
Analyze a webpage using Google PageSpeed Insights API.

```typescript
use_mcp_tool({
  server_name: "pagespeed",
  tool_name: "analyze_pagespeed",
  arguments: {
    url: "https://example.com"
  }
});
```

The tool returns:
- Overall performance score (0-100)
- Loading experience metrics
  - First Contentful Paint
  - First Input Delay
- Top 5 improvement suggestions with:
  - Title
  - Description
  - Potential impact
  - Current value

## Features

- Real-time webpage performance analysis
- Detailed loading experience metrics
- Prioritized improvement suggestions
- Comprehensive error handling
- TypeScript support

## Error Handling

The server provides detailed error messages for:
- Invalid URLs
- API request failures
- Connection issues
- Invalid tool calls

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request to https://github.com/enemyrr/mcp-server-pagespeed

## License

MIT 

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "es2020",
    "module": "es2020",
    "moduleResolution": "node",
    "outDir": "./build",
    "rootDir": "./",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": [
    "*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
} 
```

--------------------------------------------------------------------------------
/package copy.json:
--------------------------------------------------------------------------------

```json
{
  "name": "@enemyrr/mcp-mysql-server",
  "version": "0.1.0",
  "description": "A Model Context Protocol server for MySQL database operations",
  "type": "module",
  "bin": {
    "mcp-mysql": "./build/index.js"
  },
  "files": [
    "build"
  ],
  "scripts": {
    "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
    "prepare": "npm run build",
    "watch": "tsc --watch",
    "inspector": "npx @modelcontextprotocol/inspector build/index.js"
  },
  "keywords": [
    "mcp",
    "model-context-protocol",
    "mysql",
    "database",
    "claude",
    "anthropic"
  ],
  "author": "enemyrr",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "0.6.0",
    "dotenv": "^16.4.7",
    "mysql2": "^3.11.5"
  },
  "devDependencies": {
    "@types/node": "^20.11.24",
    "typescript": "^5.3.3"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/enemyrr/mcp-mysql-server"
  },
  "publishConfig": {
    "access": "public"
  }
}

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "mcp-server-pagespeed",
  "version": "1.0.0",
  "description": "A Model Context Protocol server for Google PageSpeed Insights",
  "type": "module",
  "bin": {
    "mcp-pagespeed": "./build/index.js"
  },
  "files": [
    "build"
  ],
  "main": "build/index.js",
  "scripts": {
    "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
    "prepare": "npm run build",
    "watch": "tsc --watch",
    "start": "node build/index.js",
    "dev": "ts-node --esm index.ts",
    "inspector": "npx @modelcontextprotocol/inspector build/index.js"
  },
  "keywords": [
    "mcp",
    "model-context-protocol",
    "pagespeed",
    "google",
    "performance"
  ],
  "author": "@enemyrr",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "0.6.0",
    "axios": "^1.6.7"
  },
  "devDependencies": {
    "@types/node": "^20.11.19",
    "ts-node": "^10.9.2",
    "typescript": "^5.3.3"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/enemyrr/mcp-server-pagespeed"
  },
  "publishConfig": {
    "access": "public"
  }
}

```

--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { ErrorCode, ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import axios from 'axios';

interface PageSpeedInsight {
    score: number;
    title: string;
    description: string;
    displayValue?: string;
}

interface ProcessedPageSpeedResult {
    performanceScore: number;
    insights: PageSpeedInsight[];
    loadingExperience: {
        firstContentfulPaint: {
            category: string;
            percentile: number;
        };
        firstInputDelay: {
            category: string;
            percentile: number;
        };
    };
}

class PageSpeedServer {
    private server: Server;

    constructor() {
        this.server = new Server(
            {
                name: 'pagespeed-server',
                version: '1.0.0',
            },
            {
                capabilities: {
                    tools: {},
                },
            }
        );

        this.setupToolHandlers();
        this.server.onerror = (error) => console.error('[MCP Error]', error);
    }

    private setupToolHandlers() {
        this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
            tools: [
                {
                    name: 'analyze_pagespeed',
                    description: 'Analyzes a webpage using Google PageSpeed Insights API',
                    inputSchema: {
                        type: 'object',
                        properties: {
                            url: {
                                type: 'string',
                                description: 'The URL to analyze'
                            }
                        },
                        required: ['url']
                    }
                }
            ]
        }));

        this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
            if (request.params.name === 'analyze_pagespeed') {
                const { url } = request.params.arguments as { url: string };

                try {
                    const response = await axios.get<any>(
                        `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${encodeURIComponent(url)}`
                    );

                    const result = response.data;
                    const processedResult: ProcessedPageSpeedResult = {
                        performanceScore: Math.round(result.lighthouseResult.categories.performance.score * 100),
                        insights: [],
                        loadingExperience: {
                            firstContentfulPaint: {
                                category: result.loadingExperience?.metrics?.FIRST_CONTENTFUL_PAINT_MS?.category || 'N/A',
                                percentile: result.loadingExperience?.metrics?.FIRST_CONTENTFUL_PAINT_MS?.percentile || 0
                            },
                            firstInputDelay: {
                                category: result.loadingExperience?.metrics?.FIRST_INPUT_DELAY_MS?.category || 'N/A',
                                percentile: result.loadingExperience?.metrics?.FIRST_INPUT_DELAY_MS?.percentile || 0
                            }
                        }
                    };

                    // Process audits and extract insights
                    const audits = result.lighthouseResult.audits;
                    for (const [key, audit] of Object.entries(audits)) {
                        const typedAudit = audit as any;
                        if (typedAudit.score !== null && typedAudit.score < 1) {
                            processedResult.insights.push({
                                score: typedAudit.score,
                                title: typedAudit.title,
                                description: typedAudit.description,
                                displayValue: typedAudit.displayValue
                            });
                        }
                    }

                    // Sort insights by score (lowest first)
                    processedResult.insights.sort((a, b) => a.score - b.score);

                    return {
                        content: [
                            {
                                type: 'text',
                                text: JSON.stringify({
                                    summary: `Your page performance score is ${processedResult.performanceScore}/100`,
                                    loadingExperience: {
                                        firstContentfulPaint: `${processedResult.loadingExperience.firstContentfulPaint.category} (${processedResult.loadingExperience.firstContentfulPaint.percentile}ms)`,
                                        firstInputDelay: `${processedResult.loadingExperience.firstInputDelay.category} (${processedResult.loadingExperience.firstInputDelay.percentile}ms)`
                                    },
                                    topImprovements: processedResult.insights.slice(0, 5).map(insight => ({
                                        title: insight.title,
                                        description: insight.description,
                                        impact: Math.round((1 - insight.score) * 100) + '% improvement possible',
                                        currentValue: insight.displayValue
                                    }))
                                }, null, 2)
                            }
                        ]
                    };
                } catch (error) {
                    console.error('Error analyzing URL:', error);
                    throw {
                        code: ErrorCode.InternalError,
                        message: 'Failed to analyze URL',
                        details: error instanceof Error ? error.message : 'Unknown error'
                    };
                }
            }

            throw {
                code: ErrorCode.MethodNotFound,
                message: `Unknown tool: ${request.params.name}`
            };
        });
    }

    async run() {
        const transport = new StdioServerTransport();
        await this.server.connect(transport);
        console.error('PageSpeed MCP server running on stdio');
    }
}

const server = new PageSpeedServer();
server.run().catch(console.error); 
```