Skip to main content
Glama
GeorgesAdSim

Fetch Crawl MCP

by GeorgesAdSim
README.md
# Fetch Crawl MCP v4.2.0

Serveur MCP (Model Context Protocol) pour fetcher, crawler et analyser des sites web. 29 outils utilisables depuis Claude Code, Claude Desktop, ou tout client MCP compatible.

## Installation

```bash
npm install
npm run build
```

Puppeteer est requis pour les outils `screenshot`, `check_performance`, `check_mobile`, `check_datalayer`, `intercept_tracking_requests`, `audit_tracking` et le fallback anti-bot. Chromium s'installe automatiquement lors du `npm install`.

## Utilisation

### Stdio (défaut)

```bash
npm start
# ou
node build/index.js
```

### HTTP

```bash
npm run start:http
# ou
node build/index.js --http --port 3001
```

### Configuration client MCP

```json
{
  "mcpServers": {
    "fetch-crawl-mcp": {
      "command": "node",
      "args": ["/path/to/fetch-crawl-mcp/build/index.js"]
    }
  }
}
```

## Format de réponse standard

Tous les outils retournent un format `StandardResponse` unifié :

```typescript
{
  url: string;           // URL demandée
  finalUrl: string;      // URL finale (après redirections)
  status: number;        // Code HTTP
  score?: number;        // Score 0-100 (si applicable)
  summary: string;       // Résumé en une phrase
  issues: ToolIssue[];   // Problèmes détectés (severity, element, message, evidence?)
  recommendations: [];   // Recommandations d'amélioration
  meta: {
    fetchedWith: "fetch" | "puppeteer";
    fallbackUsed: boolean;
    partial: boolean;     // true si le contenu a été tronqué (> 5MB)
    durationMs: number;
    timestamp: string;
  };
  data: {};              // Données spécifiques à l'outil
}
```

## Anti-Bot Detection

Le fetcher intègre un système de détection anti-bot avancé :

- **Détection automatique** : Cloudflare, DataDome, Akamai, Sucuri, PerimeterX
- **Stealth Puppeteer** : patches navigator.webdriver, plugins, languages, platform, hardwareConcurrency, deviceMemory, chrome.runtime, Notification permissions, WebGL renderer
- **Fallback propre** : si le site reste bloqué même avec Puppeteer, retour d'un status 403 avec info `antiBot: { blocked, provider, confidence }` au lieu d'un crash
- **Launch args optimisés** : `--disable-blink-features=AutomationControlled`, `--disable-features=IsolateOrigins,site-per-process`, `--window-size=1920,1080`

## Outils (29)

### Fetching & Crawling

#### `fetch_page`

Récupère une page web et retourne son contenu dans le format spécifié.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à fetcher |
| `format` | `"html"` \| `"text"` \| `"markdown"` | `"markdown"` | Format de sortie |
| `headers` | object | — | Headers HTTP personnalisés |

**Retour** : contenu de la page, titre, description, type de contenu.

---

#### `crawl_site`

Crawle un site récursivement en suivant les liens internes.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL de départ |
| `maxDepth` | number (0–10) | `2` | Profondeur max (0 = page de départ uniquement) |
| `maxPages` | number (1–500) | `50` | Nombre max de pages |
| `delay` | number (0–10000) | `300` | Délai en ms entre les requêtes (±30% jitter) |
| `concurrency` | number (1–10) | `3` | Pages fetchées en parallèle |
| `respectRobotsTxt` | boolean | `true` | Respecter robots.txt et Crawl-delay |
| `includePattern` | string | — | Regex : ne crawler que les URLs matchant |
| `excludePattern` | string | — | Regex : exclure les URLs matchant |

**Score** : basé sur le ratio de pages en erreur (status >= 400).

**Timeout** : le crawl s'arrête proprement après 5 minutes (`abortedEarly: true`).

**Retour** : liste des pages crawlées avec titre, status, profondeur, liens trouvés + `crawlStats: { startedAt, finishedAt, durationSeconds, pagesPerSecond, abortedEarly, abortReason }`.

---

#### `screenshot`

Capture une screenshot d'une page web via Puppeteer. Supporte PNG/JPEG, viewport personnalisé, capture pleine page, attente de sélecteur CSS, et fermeture des bannières cookies.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à capturer |
| `width` | number (320–3840) | `1280` | Largeur du viewport |
| `height` | number (240–2160) | `800` | Hauteur du viewport |
| `fullPage` | boolean | `false` | Capturer toute la page scrollable |
| `format` | `"png"` \| `"jpeg"` | `"png"` | Format d'image |
| `quality` | number (1–100) | `80` | Qualité (jpeg uniquement) |
| `waitForSelector` | string | — | Sélecteur CSS à attendre avant capture |
| `dismissCookies` | boolean | `false` | Tenter de fermer les bannières cookies |

**Robustesse** : timeout global Puppeteer, auto-recompression JPEG si fullPage > 900KB, retour d'erreur propre en cas d'échec.

---

### SEO Audit

#### `audit_onpage`

Audit technique on-page complet : title, meta description, canonical, robots, lang, hiérarchie H1-H6, attributs alt des images, Open Graph, Twitter Card, JSON-LD.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |

**Score** : 0-100 basé sur les issues (error = -15pts, warning = -5pts).

**Retour** : données SEO complètes dans `data{}`, issues avec severity, recommandations.

---

#### `check_indexability`

Vérifie si une page est indexable par les moteurs de recherche.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL de la page |

**Analyses** :
- Status HTTP
- Meta robots (noindex, nofollow, none, noarchive, nosnippet)
- X-Robots-Tag HTTP header
- Canonical (auto-référençante ? cross-domain ?)
- Hreflang / rel alternate
- Présence dans le sitemap

**Score** : -40 noindex, -30 status != 200, -20 canonical elsewhere, -10 absent du sitemap.

**Retour** : verdict `indexable: boolean` avec raison détaillée.

---

#### `check_structured_data`

Extrait et valide les données structurées d'une page.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à analyser |

**Extraction** :
- **JSON-LD** (incluant `@graph`) avec validation par type : Product, Organization, LocalBusiness, BreadcrumbList, Article, NewsArticle, BlogPosting
- **Microdata** (itemscope/itemtype/itemprop)
- **Open Graph** (og:*)
- **Twitter Card** (twitter:*)

**Score** : -20 si pas de JSON-LD, -10 si pas d'OG, -10 si pas de Twitter Card, -15 par schema invalide.

---

#### `check_robots_txt`

Analyse le robots.txt d'un site et vérifie la cohérence des sitemaps.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL du site |

**Analyses** :
- Parse complet par User-Agent (Allow + Disallow)
- Crawl-delay
- Sitemaps déclarés vs réellement accessibles
- Détection de sitemaps non déclarés (/sitemap.xml, /1_index_sitemap.xml)

**Score** : -30 si absent, -15 si aucun sitemap déclaré, -10 par sitemap inaccessible ou non déclaré.

---

### Content Extraction

#### `extract_content`

Extrait le contenu structuré d'une page : headings, liens, images, texte brut avec statistiques.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL source |

**Retour** : titre, description, lang, headings, liens (max 100), images (max 50), contenu texte (max 10000 chars), stats.

---

#### `extract_links`

Extrait tous les liens d'une page avec filtrage par type.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL source |
| `type` | `"all"` \| `"internal"` \| `"external"` | `"all"` | Filtrer par type |

**Retour** : liens uniques avec href, texte, rel, isInternal, isNofollow.

---

#### `extract_with_schema`

Extraction structurée basée sur des sélecteurs CSS configurables, avec presets intégrés.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL source |
| `schema` | object | — | Schema d'extraction (voir ci-dessous) |
| `fallbackSelectors` | object | — | Sélecteurs de fallback si le principal échoue |
| `preset` | `"ecommerce-product"` \| `"article"` \| `"local-business"` \| `"recipe"` | — | Preset intégré |

**Schema** : chaque clé est un champ, la valeur est `{ selector, attribute?, multiple?, transform? }`.

```json
{
  "productName": { "selector": "h1.product-title", "transform": "text" },
  "price": { "selector": ".product-price .current", "transform": "number" },
  "images": { "selector": ".product-gallery img", "attribute": "src", "multiple": true },
  "description": { "selector": ".product-description", "transform": "html" }
}
```

**Transforms** : `text` (innerText), `html` (innerHTML), `number` (parseFloat), `trim` (text trimmed), `href` (attribut href).

**Presets intégrés** :
- `ecommerce-product` : productName, price, oldPrice, currency, images, description, sku, brand, availability, breadcrumb, reviewsCount
- `article` : title, author, publishDate, content, categories, tags, readingTime (auto-calculé)
- `local-business` : name, address, phone, email, hours, coordinates, rating, reviewCount
- `recipe` : title, prepTime, cookTime, servings, ingredients, instructions, calories, image

Si `preset` ET `schema` sont fournis, le schema override les champs du preset.

**Score** : `(fieldsFound / fieldsTotal) * 100`.

**Retour** : `data.extracted` (données), `fieldsFound`, `fieldsTotal`, `fieldsMissing`, `usedFallback`, `preset`.

---

#### `parse_sitemap`

Parse un sitemap.xml (ou le détecte automatiquement). Supporte les sitemap index.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL du sitemap ou racine du site |

**Score** : -20 par erreur de parsing, -5 si tronqué.

**Retour** : entrées avec loc, lastmod, changefreq, priority (max 500).

---

### Technical Checks

#### `check_links`

Vérifie tous les liens d'une page pour détecter les liens cassés (404, timeout, erreurs).

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à vérifier |
| `timeout` | number (1000–30000) | `5000` | Timeout par lien |
| `concurrency` | number (1–20) | `3` | Liens vérifiés en parallèle |
| `delay` | number (0–5000) | `200` | Délai entre les batchs (±30% jitter) |

**Score** : basé sur le ratio liens cassés / total.

---

#### `check_redirect_chain`

Suit la chaîne de redirections hop par hop.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à suivre |
| `maxRedirects` | number (1–30) | `10` | Nombre max de redirections |

**Score** : 100 si 0-1 redirect, 80 si 2-3, 60 si > 3, 0 si boucle.

**Détections** : boucles de redirection, chaînes longues (> 3), upgrades HTTP → HTTPS.

---

#### `check_performance`

Mesure les métriques de performance via Puppeteer avec profil mobile ou desktop.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |
| `device` | `"mobile"` \| `"desktop"` | `"mobile"` | Profil (mobile: 375x812 + throttling, desktop: 1280x800) |

**Métriques** : TTFB, FCP, LCP, DOM Content Loaded, Fully Loaded, requêtes réseau, bytes transférés, ressources par type.

**Score (0-100)** : LCP (40%), FCP (35%), TTFB (25%) selon les seuils Web Vitals.

---

#### `check_mobile`

Audit de compatibilité mobile via Puppeteer avec viewport iPhone (375x812).

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à vérifier |

**Vérifications** : meta viewport, scroll horizontal, fonts < 12px, tap targets < 48px.

**Score** : -30 si pas de viewport meta, -10 si scroll horizontal, -5 par tranche de 10 tap targets trop petits.

**Retour** : analyse + screenshot JPEG mobile.

---

### Tracking Audit

#### `check_gtm_snippet`

Vérifie la présence et la configuration des snippets GTM et gtag.js sur une page (analyse HTML statique, pas besoin de Puppeteer).

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à vérifier |

**Détections** :
- Containers GTM (GTM-XXXXX) et IDs GA4 (G-XXXXXXXX)
- Placement du snippet (dans `<head>` ou non)
- Présence du `<noscript>` GTM fallback dans `<body>`
- IDs dupliqués (double-counting)

**Score** : -15 si aucun tracking, -5 par warning (noscript manquant, doublons, mauvais placement).

---

#### `check_datalayer`

Inspecte `window.dataLayer` en runtime via Puppeteer. Vérifie l'existence, le contenu, et détecte les patterns suspects.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à inspecter |
| `wait_ms` | number (0–5000) | `2000` | Délai d'attente après chargement avant lecture du dataLayer |

**Vérifications** :
- `window.dataLayer` existe et contient des events
- `window.google_tag_manager` chargé (runtime GTM)
- `window.gtag` est une function
- Détection de redéfinition de dataLayer après init GTM (pattern suspect)

**Timeout** : 30 secondes (Puppeteer).

---

#### `intercept_tracking_requests`

Intercepte les requêtes réseau de tracking (GA4, GTM, gtag) pendant le chargement de la page via Puppeteer.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à monitorer |
| `wait_ms` | number (0–8000) | `3000` | Délai d'attente après chargement pour capturer les hits différés |

**Requêtes interceptées** :
- `google-analytics.com/g/collect` → hits GA4
- `analytics.google.com/g/collect` → hits GA4 alternatif
- `googletagmanager.com/gtm.js` → chargement GTM
- `googletagmanager.com/gtag/js` → chargement gtag
- `stats.g.doubleclick.net` → hits Universal Analytics (obsolète)

**Parsing GA4** : event name (`en`), measurement ID (`tid`), protocol version (`v`).

**Score** : -15 si aucun hit GA4, -15 si UA détecté, -5 par warning (doublons, multi-IDs).

**Timeout** : 45 secondes (Puppeteer).

---

#### `audit_tracking`

Audit tracking complet : exécute `check_gtm_snippet`, `check_datalayer` et `intercept_tracking_requests` en parallèle, puis produit un rapport unifié.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |

**Rapport** :
- Score global (moyenne pondérée : GTM 30%, dataLayer 30%, intercept 40%)
- `severity_summary` : comptage par niveau (critical, warning, ok)
- `diagnosis` : phrase de diagnostic croisé (ex: "GTM présent mais aucun hit GA4 envoyé → vérifier les triggers")
- Données complètes des 3 sous-outils

---

### Multi-Page & Comparison

#### `compare_pages`

Compare deux pages web côte à côte sur 12 critères SEO.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `urlA` | string | *requis* | Première URL |
| `urlB` | string | *requis* | Deuxième URL |
| `includeScreenshot` | boolean | `false` | Capturer une screenshot de chaque page |

**Critères comparés** : title, meta description, H1, heading structure, word count, internal links, external links, images alt, Open Graph, Twitter Card, JSON-LD, canonical.

**Retour** : score individuel par page (0-100), tableau comparatif avec winner par critère, screenshots optionnels.

---

#### `audit_site_batch`

Audit batch de multiples pages d'un site avec agrégation des résultats.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL du site |
| `source` | `"sitemap"` \| `"crawl"` \| `"urls"` | `"sitemap"` | Source des URLs |
| `urls` | string[] | — | Liste d'URLs (si source = "urls") |
| `limit` | number (1–200) | `30` | Nombre max de pages |
| `concurrency` | number (1–5) | `2` | Pages auditées en parallèle |
| `delay` | number (0–5000) | `500` | Délai entre les batchs |

**Timeout** : le batch s'arrête proprement après 5 minutes avec `meta.partial = true`.

**Fallback sitemap** : si `/sitemap.xml` ne retourne aucune URL, essaie automatiquement `/1_index_sitemap.xml`.

**Agrégation** :
- Score moyen et médiane
- Distribution (excellent / bon / moyen / mauvais)
- Top 10 problèmes triés par fréquence
- Quick wins (pages > 60 pts avec 1-2 fixes faciles)
- Pages critiques (les 10 pires scores)
- `executionStats`: startedAt, finishedAt, durationSeconds, pagesPerSecond, timedOut

---

#### `detect_orphan_pages`

Détecte les pages orphelines en croisant le sitemap, le crawl et le graphe de liens internes.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL du site |
| `maxCrawlPages` | number (1–300) | `100` | Pages crawlées pour le graphe |
| `crawlDepth` | number (1–5) | `3` | Profondeur de crawl |
| `concurrency` | number (1–5) | `3` | Pages en parallèle |
| `delay` | number (0–5000) | `300` | Délai entre batches |

**Classification** (6 catégories) :
- `orphan_in_sitemap` : dans le sitemap, 0 lien interne (critique)
- `orphan_not_in_sitemap` : hors sitemap, 0-1 lien interne (isolée)
- `sitemap_only` : dans le sitemap, non atteinte par le crawl
- `crawl_only` : trouvée par le crawl, absente du sitemap
- `deep_page` : atteinte uniquement à profondeur >= 4
- `well_linked` : sitemap + crawl + >= 2 liens entrants

**Score** : -2/orpheline (max -40), -1/sitemap_only (max -20), -1/crawl_only (max -15), -0.5/deep_page (max -10), -15 si cohérence < 50%.

**Retour** : stats (overlap sitemap/crawl), catégories avec exemples, top 20 pages hub (plus de liens entrants), top 10 orphelines critiques.

---

#### `detect_duplicate_content`

Détecte les contenus dupliqués et quasi-dupliqués sur un site.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL du site |
| `source` | `"sitemap"` \| `"crawl"` \| `"urls"` | `"crawl"` | Source des URLs |
| `urls` | string[] | — | Liste d'URLs (si source = "urls") |
| `limit` | number (1–200) | `50` | Nombre max de pages |
| `concurrency` | number (1–5) | `3` | Pages en parallèle |
| `delay` | number (0–5000) | `300` | Délai entre batches |
| `similarityThreshold` | number (0–1) | `0.8` | Seuil de similarité pour near-duplicates |

**Détection** :
- **Exact duplicates** : titles, descriptions, H1 identiques (groupés par cluster)
- **Near-duplicates** : titles et contenus quasi-identiques (similarité mots communs / mots uniques > seuil)
- Optimisation : regroupement par les 3 premiers mots pour éviter O(n²)

**Score** : -5 par cluster exact (max -40), -2 par cluster near-duplicate (max -30).

**Retour** : `exactDuplicates[]`, `nearDuplicates[]`, `uniquePages`, stats avec `mostDuplicatedValue`.

---

### Security, Accessibility & Compliance (v4.2.0)

#### `check_security_headers`

Audit des HTTP security headers (HSTS, CSP, X-Frame-Options, Referrer-Policy, Permissions-Policy, COOP, CORP, COEP). Score 0-100 avec grade A-F.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |

---

#### `check_hreflang`

Valide les balises hreflang : codes ISO 639-1, liens réciproques, cohérence avec la langue de la page, présence de `x-default`, consistance avec canonical.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |

---

#### `audit_content_quality`

Analyse de la qualité de contenu : lisibilité multilingue (FR/NL/EN/DE/ES/IT), word count, structure des titres, densité de liens, richesse média, signaux d'engagement (TOC, FAQ, CTA).

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |

---

#### `check_accessibility`

Audit WCAG léger sur 9 catégories : alt des images, labels de formulaires, landmarks sémantiques, hiérarchie des titres, qualité du texte des liens (détection multilingue FR/NL/EN/DE du "click here"), ARIA, tableaux, médias, contraste.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |

---

#### `extract_images_audit`

Audit complet des images via Puppeteer : adoption des formats modernes (WebP/AVIF), alt text, responsive (srcset), dimensions optimales, lazy loading, candidat LCP, poids des fichiers.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |

---

#### `check_consent_mode`

Audit Google Consent Mode v2 et conformité cookies RGPD : détection CMP (Cookiebot, OneTrust, Didomi, Axeptio, etc.), IAB TCF API, vérification `gtag('consent', 'default'|'update')`, analyse des signaux `gcs`/`gcd` sur les hits GA4, audit des cookies déposés avant consentement.

| Paramètre | Type | Défaut | Description |
|-----------|------|--------|-------------|
| `url` | string | *requis* | URL à auditer |
| `wait_ms` | number (0–10000) | `5000` | Délai d'attente après chargement pour laisser le CMP s'initialiser |

---

## Architecture

```
src/
├── index.ts                          # Entry point (stdio + HTTP)
├── server.ts                         # MCP server, tool registration
├── tools/
│   ├── fetch-page.ts                 # fetch_page
│   ├── crawl-site.ts                 # crawl_site
│   ├── screenshot.ts                 # screenshot
│   ├── analyze-seo.ts               # audit_onpage
│   ├── check-indexability.ts         # check_indexability
│   ├── check-structured-data.ts     # check_structured_data
│   ├── check-robots-txt.ts          # check_robots_txt
│   ├── extract-content.ts           # extract_content
│   ├── extract-links.ts             # extract_links
│   ├── extract-with-schema.ts       # extract_with_schema
│   ├── parse-sitemap.ts             # parse_sitemap
│   ├── check-links.ts              # check_links
│   ├── check-redirect-chain.ts     # check_redirect_chain
│   ├── check-performance.ts        # check_performance
│   ├── check-mobile.ts             # check_mobile
│   ├── compare-pages.ts            # compare_pages
│   ├── audit-site-batch.ts         # audit_site_batch
│   ├── detect-orphan-pages.ts      # detect_orphan_pages
│   ├── detect-duplicate-content.ts # detect_duplicate_content
│   ├── check-gtm-snippet.ts       # check_gtm_snippet
│   ├── check-datalayer.ts         # check_datalayer
│   ├── intercept-tracking-requests.ts # intercept_tracking_requests
│   └── audit-tracking.ts          # audit_tracking
└── utils/
    ├── fetcher.ts                    # HTTP fetch + stealth Puppeteer + anti-bot detection
    ├── html-parser.ts               # Cheerio-based HTML extraction
    ├── robots-parser.ts             # robots.txt parser
    ├── url-utils.ts                 # URL normalization utilities
    └── response.ts                  # StandardResponse, ToolIssue, ToolMeta, helpers
```

## Stack technique

- **Runtime** : Node.js (ES2022)
- **Langage** : TypeScript (strict)
- **MCP SDK** : @modelcontextprotocol/sdk
- **HTML parsing** : Cheerio
- **Browser automation** : Puppeteer (stealth mode)
- **Validation** : Zod
- **Transport** : stdio (défaut) ou HTTP (Express + StreamableHTTPServerTransport)

## Déploiement Docker

### Quick start

```bash
./deploy.sh
```

### Manuel

```bash
# Build TypeScript
npm run build

# Build image Docker
docker build -t fetch-crawl-mcp:latest .

# Lancer avec docker compose
docker compose up -d

# Vérifier
curl http://localhost:3001/health
```

### Configuration Docker

Le `Dockerfile` utilise `node:22-slim` avec Chromium préinstallé pour Puppeteer. L'image finale ne contient que `build/` et les dépendances de production.

| Variable d'environnement | Défaut | Description |
|--------------------------|--------|-------------|
| `NODE_ENV` | `production` | Environnement Node.js |
| `PUPPETEER_EXECUTABLE_PATH` | `/usr/bin/chromium` | Chemin vers Chromium dans le container |

Ressources par défaut (docker-compose) : 2 Go RAM, 1.5 CPU.

### Configuration client MCP (HTTP distant)

```json
{
  "mcpServers": {
    "fetch-crawl-mcp": {
      "url": "http://YOUR_SERVER:3001/mcp"
    }
  }
}
```

---

## Développement

```bash
npm run dev        # Watch mode avec tsx
npm run build      # Build TypeScript
npm start          # Serveur stdio
npm run start:http # Serveur HTTP (port 3001)
```

## Licence

MIT

TDQS

A3.6/5.0

Scored across 29 tools

Disambiguation3/5

Several tool clusters overlap in purpose, such as fetch_page/extract_content/extract_with_schema, check_gtm_snippet/check_datalayer/intercept_tracking_requests/audit_tracking, and audit_onpage/check_structured_data. The detailed descriptions help an agent distinguish them, but the boundaries are not always obvious and require careful comparison before selecting.

Naming Consistency4/5

Most tools follow a consistent verb_noun pattern, with many check_* and audit_* names plus fetch_page, crawl_site, parse_sitemap, and compare_pages. Minor exceptions like extract_images_audit and screenshot (which lacks an explicit object) prevent a perfect score.

Tool Count2/5

At 29 tools, the set exceeds the 25+ threshold and feels heavy even for a broad SEO/web-analysis domain. Many specialized audit tools could be consolidated into grouped tools or sub-options to reduce the surface area and cognitive load.

Completeness4/5

The toolset covers the web fetching/crawling and SEO auditing lifecycle remarkably well: crawling, sitemaps, robots, redirects, broken links, extraction, on-page audits, performance, mobile, structured data, accessibility, tracking, consent, security headers, content quality, duplicates, and orphan pages. The main gaps are explicitly out-of-scope features like backlinks/keyword rankings and there is no export or persistence tool.

Maintenance

ActivityInactive
ResponsivenessNo issues