Vai al contenuto

Server MCP ​

Il server MCP di Rankbeam permette a un assistente AI di leggere e, facoltativamente, modificare i metadati SEO del sito tramite il Model Context Protocol. Collega un client MCP, come Claude Code, Claude Desktop, Cursor o Codex, alla tua app Laravel: potrà risolvere i metadati, eseguire un audit, leggere il punteggio Pro e le regole per i crawler AI e, se lo abiliti, salvare modifiche.

È un server stdio autonomo, senza SDK o pacchetti aggiuntivi, compatibile con le combinazioni supportate di PHP 8.2–8.4 (Laravel 11), PHP 8.2–8.5 (Laravel 12), PHP 8.3–8.5 (Laravel 13).

Funzione Pro

Il server è incluso in rankbeam/laravel-seo-pro. Per impostazione predefinita è in sola lettura; le modifiche richiedono l'attivazione esplicita e rispettano l'elenco dei modelli consentiti.

Cosa può fare l'assistente ​

Strumenti di analisi, sempre disponibili ​

StrumentoFunzione
seo_resolveMetadati risolti di un record: titolo, descrizione, canonical, robots, Open Graph e JSON-LD, inclusi i fallback del resolver.
seo_auditAudit dei metadati nel processo per un record o i primi N: stessi controlli di seo:audit, senza coda.
seo_scoreUltimo punteggio SEO Pro salvato per un record, da 0 a 100 con fascia.
seo_robots_directivesDirettive robots.txt per i crawler AI gestite dal pacchetto e regole risolte per bot.
validate_schemaValida un oggetto JSON-LD o il grafo risolto di un modello consentito tramite il validatore core, che include controlli per tipo sui requisiti dei risultati avanzati. Non è un test live di Google.
analyze_robotsRegola allow/disallow risolta per crawler AI noto e sua origine: override del bot, regola per finalità o predefinito. La configurazione è globale per il sito.
debug_social_shareDati Open Graph e Twitter risolti del record, dopo i fallback, con osservazioni sulla scheda. Non effettua una richiesta al crawler social.
check_metaTitolo, descrizione, canonical, robots e og:image risolti, lunghezze, presenza e risultati dell'audit per un record.

Strumenti sui contenuti, sempre disponibili ​

Permettono all'assistente di elencare e cercare le pagine del sito:

StrumentoFunzione
list_pagesElenca i record SEO di un modello consentito, con URL e titolo effettivo. Paginazione tramite limit e offset.
search_pagesCerca nei record di un modello consentito tramite Laravel Scout, se configurato, oppure una query SQL LIKE sui campi title/name/headline e sui metadati SEO associati. Restituisce URL, titolo ed estratto.

Strumenti operativi, da abilitare ​

Leggono lo stato delle scansioni o modificano la configurazione del sito. Come lo strumento di modifica, richiedono allow_edits: nel server in sola lettura non vengono esposti né eseguiti.

StrumentoFunzione
list_issuesProblemi SEO attualmente aperti, conservati tra esecuzioni, e intestazione dell'ultima scansione. Filtri severity e type.
trigger_scanAvvia una scansione di un record consentito o di tutti i target: in coda per impostazione predefinita, nel processo con sync: true.
create_redirectCrea una regola di redirect, da percorso o regex a destinazione, con stato 301, 302, 307, 308 o 410, usando i validatori del modello redirect.

Strumento di modifica, da abilitare ​

StrumentoFunzione
seo_save_metaSalva titolo, descrizione, canonical, robots, OG, Twitter e JSON-LD su un record consentito, tramite saveSEO().

Gli strumenti operativi e seo_save_meta non compaiono in tools/list e non sono eseguibili finché non abiliti le modifiche. Vedi Sicurezza.

Collegare un client AI ​

Il server usa JSON-RPC su stdio. Il client avvia un comando Artisan e comunica tramite le pipe del processo. Lo stesso comando funziona con i diversi client MCP.

Un comando per tutti i client

Tutti gli esempi avviano php artisan seo-pro:mcp dalla radice dell'app, così Artisan può inizializzarla. Se php non è nel PATH del client, situazione comune su Windows o nelle app grafiche, usa percorsi assoluti sia per PHP sia per artisan. Artisan inizializza l'app dalla directory del proprio script, senza richiedere cwd.

Claude Code, CLI ​

Esegui questo comando dalla radice dell'app per registrare il server:

bash
claude mcp add rankbeam-seo -- php artisan seo-pro:mcp

Verifica la connessione:

bash
claude mcp list
# rankbeam-seo: php artisan seo-pro:mcp - ✔ Connected

Su Windows con Laravel Herd, indica percorsi assoluti per non dipendere dalla directory di avvio:

bash
claude mcp add rankbeam-seo -- "C:\Users\you\.config\herd\bin\php84\php.exe" "C:\path\to\app\artisan" seo-pro:mcp

Claude Desktop ​

Apri la configurazione da Settings → Developer → Edit Config, oppure direttamente:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
json
{
  "mcpServers": {
    "rankbeam-seo": {
      "command": "php",
      "args": ["/absolute/path/to/your/app/artisan", "seo-pro:mcp"]
    }
  }
}

Su Windows, usa il percorso assoluto di php.exe e raddoppia ogni backslash nel JSON:

json
{
  "mcpServers": {
    "rankbeam-seo": {
      "command": "C:\\Users\\you\\.config\\herd\\bin\\php84\\php.exe",
      "args": ["C:\\path\\to\\app\\artisan", "seo-pro:mcp"]
    }
  }
}

Chiudi completamente e riapri Claude Desktop. Gli strumenti sono disponibili nei controlli degli strumenti o dei connettori del client; nomi e posizione possono variare con la versione.

Cursor ​

Crea .cursor/mcp.json nel progetto, oppure ~/.cursor/mcp.json per tutti i progetti. Usa il percorso assoluto di artisan:

json
{
  "mcpServers": {
    "rankbeam-seo": {
      "command": "php",
      "args": ["/absolute/path/to/your/app/artisan", "seo-pro:mcp"]
    }
  }
}

Su Windows, usa il percorso assoluto di php.exe e backslash raddoppiati come nell'esempio Claude Desktop. Abilita il server nelle impostazioni MCP di Cursor.

Codex CLI ​

bash
codex mcp add rankbeam-seo -- php artisan seo-pro:mcp
codex mcp get rankbeam-seo   # transport: stdio, enabled

Come per Claude Code, su Windows o Herd usa percorsi assoluti per PHP e artisan.

Una volta collegato, l'assistente può chiamare gli strumenti esposti.

Esempio di conversazione ​

L'esempio pubblicato usa un'app dimostrativa di un istituto medico con circa 900 pagine; gli output sono abbreviati. L'elenco dei modelli consentiti contiene App\Models\Page e App\Models\PublicPage, con allow_edits attivo.

Tu: Come sono i metadati SEO della pagina “Accoglienza”, Page id 1? Correggi i problemi evidenti.

L'assistente esegue prima l'audit con seo_audit { model: "App\\Models\\Page", id: 1 }:

json
[
  {
    "id": 1,
    "url": "http://localhost/accoglienza",
    "issue_count": 2,
    "issues": [
      { "code": "title_too_short", "severity": "notice", "field": "title", "message": "Title is only 17 characters (recommended min 30).", "context": { "length": 17, "min": 30 } },
      { "code": "description_too_short", "severity": "notice", "field": "description", "message": "Description is only 11 characters (recommended min 70).", "context": { "length": 11, "min": 70 } }
    ]
  }
]

Poi risolve i metadati con seo_resolve { model: "App\\Models\\Page", id: 1 }: trova un titolo di 17 caratteri e una descrizione di 11, sotto le soglie consigliate. Salva la correzione tramite seo_save_meta:

json
{
  "model": "App\\Models\\Page",
  "id": 1,
  "title": "Accoglienza IDI | Istituto Dermopatico dell'Immacolata",
  "description": "Il reparto Accoglienza dell'IDI di Roma: accessi, orari di visita e servizi di supporto ai pazienti."
}

Lo strumento conferma il salvataggio e restituisce il record nuovamente risolto:

json
{ "saved": true, "fields": ["title", "description"], "resolved": { "title": "Accoglienza IDI | Istituto Dermopatico dell'Immacolata - IDI", "...": "…" } }

Infine ripete l'audit: issue_count è ora 0:

json
[ { "id": 1, "url": "http://localhost/accoglienza", "issue_count": 0, "issues": [] } ]

Assistente: Fatto. Titolo e descrizione erano di 17 e 11 caratteri, sotto le soglie consigliate. Ho salvato valori più descrittivi; il nuovo audit non rileva problemi nei controlli eseguiti.

Il salvataggio usa saveSEO(), con campi fillable e cast del modello, come una modifica da codice. Non passa dai validatori di lunghezza del form Filament. Ripetere l'audit verifica i controlli automatici sul nuovo valore; resta necessario valutare l'accuratezza editoriale del testo. Un audit senza problemi non certifica la qualità complessiva della pagina.

Interrogare i contenuti del sito ​

Gli strumenti sui contenuti permettono domande sul sito nel suo insieme, senza conoscere in anticipo l'ID di un record.

Tu: Quali pagine parlano di “immunoterapia” e hanno titoli adeguati?

L'assistente cerca con search_pages { model: "App\\Models\\Page", query: "immunoterapia" }:

json
{
  "model": "App\\Models\\Page",
  "query": "immunoterapia",
  "driver": "like",
  "count": 3,
  "results": [
    { "id": 42, "url": "http://localhost/ricerca/immunoterapia-oncologica", "title": "Immunoterapia oncologica", "snippet": "Il programma di immunoterapia dell'IDI: terapie, sperimentazioni e accesso…" },
    { "id": 87, "url": "http://localhost/reparti/dermatologia-oncologica", "title": "Dermatologia oncologica", "snippet": "…include protocolli di immunoterapia per i tumori cutanei avanzati…" },
    { "id": 91, "url": "http://localhost/news/nuova-immunoterapia-2026", "title": "Nuova", "snippet": "Al via una nuova immunoterapia…" }
  ]
}

Il terzo titolo è solo “Nuova”. L'assistente controlla i metadati con check_meta { model: "App\\Models\\Page", id: 91 }:

json
{
  "url": "http://localhost/news/nuova-immunoterapia-2026",
  "title": { "value": "Nuova", "length": 5, "present": true },
  "description": { "value": null, "length": 0, "present": false },
  "og_image": { "value": null, "present": false },
  "issue_count": 2,
  "issues": [
    { "code": "title_too_short", "severity": "notice", "field": "title", "message": "Title is only 5 characters (recommended min 30)." },
    { "code": "missing_description", "severity": "warning", "field": "description", "message": "No meta description is set." }
  ]
}

Assistente: Tre pagine citano “immunoterapia”. Nei controlli mostrati, due non presentano problemi, mentre /news/nuova-immunoterapia-2026 ha il titolo “Nuova”, di 5 caratteri, e nessuna meta description. Posso proporre valori più descrittivi.

Con allow_edits attivo può salvarli tramite seo_save_meta; in sola lettura può solo suggerirli. Qui search_pages usa il fallback SQL LIKE, indicato da "driver": "like", perché il modello non è indicizzato con Scout. Configurando Laravel Scout, lo stesso strumento usa il motore di ricerca del modello.

Sicurezza ​

Tre controlli definiscono il comportamento predefinito. Amplia i permessi solo in base all'uso previsto.

1. Modifiche disattivate per impostazione predefinita ​

Lo strumento di scrittura non è esposto né eseguibile finché non attivi:

php
// config/seo-pro.php
'mcp' => [
    'allow_edits' => true,   // default: false
],

Con allow_edits disattivato, seo_save_meta non compare in tools/list e una sua chiamata fallisce con JSON-RPC -32602. Abilitalo solo per un client e un database su cui intendi consentire modifiche.

2. Elenco dei modelli consentiti ​

Ogni strumento riferito a modelli, in lettura o scrittura, accede solo a modelli HasSEO consentiti. Il client non può scegliere una classe arbitraria:

php
'mcp' => [
    'models' => [
        \App\Models\Post::class,
        \App\Models\Page::class,
    ],
],

Una classe non consentita produce un errore, come Model [App\Models\User] is not in the MCP allowlist, senza essere usata. Se models è vuoto, l'elenco deriva da seo.audit.models e seo.sitemap.models: controlla anche queste configurazioni per sapere quali record il client può leggere.

3. Solo stdio, senza listener di rete ​

Il client avvia il processo e scambia JSON-RPC tramite stdio. Il server MCP non apre listener HTTP, porte o socket di rete. L'accesso dipende quindi dal client e dai permessi del processo locale. STDOUT è riservato al protocollo; la diagnostica del server va a STDERR, raccolto nei log del client, per esempio %APPDATA%\Claude\logs\mcp-server-rankbeam-seo.log.

Abilitare le modifiche significa consentire scritture sul database

Con allow_edits, l'assistente collegato può modificare le righe SEO del database usato dal comando. Per le prove usa locale o staging, limita i modelli consentiti e disattiva le modifiche quando non servono più. 'enabled' => false impedisce l'avvio del comando. Il trasporto locale non impedisce al client AI di inviare i risultati al proprio provider: considera anche la sua configurazione dei dati.

Configurazione ​

php
// config/seo-pro.php
'mcp' => [
    'enabled'     => true,           // master switch; the command refuses to run when false
    'allow_edits' => false,          // expose + permit the ops tools + seo_save_meta
    'models'      => [],             // allowlist; [] = fall back to audit/sitemap models
    'server_name' => 'rankbeam-seo', // reported in the MCP initialize handshake

    // Optional Server Card discovery route (off by default) — see below.
    'server_card' => [
        'enabled'     => false,      // serve GET {path} with the discovery card
        'path'        => '.well-known/mcp/server-card.json',
        'name'        => null,       // reverse-DNS server name (null = derived from app.url)
        'schema_url'  => 'https://modelcontextprotocol.io/schemas/draft/server-card.json',
        'website_url' => null,       // optional homepage/docs URL stamped on the card
    ],
],

Server Card per l'individuazione: proposta sperimentale ​

Una Server Card MCP è un documento JSON a un URL noto che descrive nome, versione e capacità di un server prima della connessione. Rankbeam può pubblicarne una per segnalare la presenza del server agli strumenti compatibili. È disattivata per impostazione predefinita e la sua attivazione non abilita trasporti o modifiche MCP.

php
// config/seo-pro.php
'mcp' => [
    'server_card' => [
        'enabled' => true,   // default: false
    ],
],

Quando è attiva, GET /.well-known/mcp/server-card.json restituisce una scheda di questa forma:

json
{
  "$schema": "https://modelcontextprotocol.io/schemas/draft/server-card.json",
  "name": "com.example/rankbeam-seo",
  "version": "1.0.0",
  "title": "Rankbeam SEO MCP server",
  "description": "Read — and optionally edit — this site's SEO over the Model Context Protocol…",
  "_meta": {
    "io.rankbeam.seo/transport": "stdio",
    "io.rankbeam.seo/launch": "php artisan seo-pro:mcp",
    "io.rankbeam.seo/tool_count": 10,
    "io.rankbeam.seo/tools": [ { "name": "seo_resolve", "description": "…" } ]
  }
}

La scheda elenca solo gli strumenti attualmente abilitati: in sola lettura non pubblicizza quelli operativi o di modifica.

Basata su una proposta

L'implementazione segue la proposta MCP Server Card SEP-2127. Percorso noto, URL $schema e campi possono cambiare: sono configurabili tramite path, schema_url, name e website_url. Il server di Rankbeam usa stdio, con php artisan seo-pro:mcp, quindi la scheda non contiene un blocco HTTP remotes. È un'indicazione per l'individuazione, non un endpoint HTTP a cui collegarsi. Verifica compatibilità e formato nel tuo client prima di usarla; lasciala disattivata se non serve.

Note sul protocollo ​

Il server implementa direttamente JSON-RPC 2.0 per initialize, con negoziazione della versione e delle capacità, tools/list, tools/call e ping. Dichiara la versione 2025-06-18 e comprende anche 2025-03-26 e 2024-11-05. Risponde con -32601 ai metodi sconosciuti e -32700 alle righe malformate. Un errore dello strumento viene restituito come risultato isError, leggibile dall'assistente, anziché errore di trasporto. Le notifiche senza id, come notifications/initialized, non ricevono risposta.

Uso senza Filament ed estensioni ​

SeoPro::mcp() restituisce il registro degli strumenti. Puoi esaminare quelli esposti o registrarne di tuoi:

php
use Rankbeam\Seo\Pro\Facades\SeoPro;

SeoPro::mcp()->all();                 // enabled tools, keyed by name
SeoPro::mcp()->register($myCustomTool); // any Rankbeam\Seo\Pro\Mcp\McpTool

Uno strumento personalizzato implementa McpTool: name, description, inputSchema, isEnabled e handle. Estendi AbstractTool per riusare la risoluzione dei modelli consentiti; le altre operazioni del tuo strumento richiedono i propri controlli.

rankbeam/laravel-seo è distribuito con licenza MIT.