Server MCP, OAuth e ability
Il server MCP di Nucleo espone il sito agli agenti AI, che accedono con OAuth e lavorano solo entro gli scope che concedi.
In questa pagina
01Panoramica
Ogni operazione di Nucleo è una ability nucleo/* registrata con l'Abilities API di WordPress. Nucleo aggiunge a ogni ability il controllo dei permessi, il controllo degli scope OAuth e il limite di frequenza sulle scritture.
Il server MCP di Nucleo è un server JSON-RPC 2.0 ed espone le ability come tool MCP. Il server ha due trasporti: HTTP su /wp-json/nucleo/v1/mcp e STDIO con wp nucleo mcp.
Su HTTP il client si autentica con un token OAuth emesso dal sito stesso, che fa anche da authorization server. Il token porta degli scope: ogni ability appartiene a un solo scope. Le stesse ability rispondono anche sull'endpoint REST del core wp-abilities/v1, con i controlli di capability: il token Bearer non vale su quell'endpoint, quindi lo scope OAuth non si applica.
Tutta l'area è Free. Solo dodici ability sono Pro: senza licenza attiva non si registrano.
02Server MCP
Endpoint HTTP /wp-json/nucleo/v1/mcp
Cosa fa: riceve un messaggio JSON-RPC 2.0 nel corpo e risponde con application/json. Ogni risposta porta l'header MCP-Protocol-Version: 2025-06-18.
Come si usa: POST https://<sito>/wp-json/nucleo/v1/mcp con Authorization: Bearer nca_…. Accetta anche un utente già autenticato con application password o cookie WordPress.
Parametri: corpo JSON con jsonrpc: "2.0", method, id e params facoltativi. I metodi supportati sono descritti in Metodi MCP.
Permessi: prima la verifica HTTPS (vedi Limiti noti), poi utente autenticato (is_user_logged_in()). Senza utente risponde 401 con codice nucleo_mcp_unauthorized e header WWW-Authenticate: Bearer resource_metadata="<home>/.well-known/oauth-protected-resource".
Edizione: Free
Limiti noti:
- Solo
POST. Nessun flusso SSE, nessuna sessione (Mcp-Session-Id), nessuna richiestaGET. - Un messaggio senza
idè una notifica: la risposta è202senza corpo. - Il batch JSON-RPC (array) è rifiutato con
-32600. - Una richiesta in chiaro, fuori dagli ambienti
localedevelopment, riceve400con codicehttps_required. Il messaggio di errore indica di controllare che il proxy inoltriX-Forwarded-Proto: https. - Se il server toglie l'header
Authorization, la pagina Agenti AI lo segnala.
Trasporto STDIO wp nucleo mcp
Cosa fa: avvia il server MCP su STDIN e STDOUT. Legge una richiesta JSON-RPC per riga e scrive una risposta per riga.
Come si usa: wp nucleo mcp --user=<id|login>. Il client MCP lancia il comando come processo locale.
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
--user | stringa | id o login di un utente | nessuno | Opzione globale di WP-CLI. Senza utente il comando termina con errore. |
Permessi: quelli dell'utente indicato. Non c'è un token OAuth, quindi nessun filtro per scope: il server elenca tutte le ability registrate.
Edizione: Free
Limiti noti:
- Le righe vuote si ignorano.
- Il comando nasconde gli errori del database e scarta ogni altro output su STDOUT.
- Una risposta non codificabile diventa un errore
-32603.
Metodi MCP
Cosa fa: il server risponde a quattro metodi. Gli altri restituiscono -32601.
| Metodo | Risposta |
|---|---|
initialize | protocolVersion: "2025-06-18", capabilities: {tools: {listChanged: false}}, serverInfo: {name: "nucleo", version: <versione plugin>}, instructions |
ping | oggetto vuoto |
tools/list | tutte le ability con prefisso nucleo/, filtrate per scope del token |
tools/call | esegue una ability con params.name e params.arguments |
Come si usa: il nome del tool è il nome dell'ability con - al posto di /. Esempio: l'ability nucleo/doc-get diventa il tool nucleo-doc-get. Il campo instructions chiede all'agente di chiamare nucleo-guide prima di scrivere.
Parametri: in tools/list ogni tool ha name, description, inputSchema (lo schema dell'ability, oppure {"type":"object"}) e annotations facoltative. Le annotazioni vengono da meta.annotations dell'ability: readonly diventa readOnlyHint, destructive diventa destructiveHint, idempotent diventa idempotentHint.
Permessi: tools/list filtra solo per scope, non per capability. Un tool elencato può quindi fallire per permessi WordPress insufficienti.
Edizione: Free
Limiti noti: l'esito di tools/call dipende dal caso:
- l'ability restituisce un array:
content(testo JSON),structuredContent(lo stesso array) eisError: trueseokvalefalse, oppure se l'array non haoke haerrorsnon vuoto (per esempiosite-importekit-apply); - l'ability restituisce un
WP_Error:isError: true,structuredContent{ok: false, error: {code, message, data?}}e lo stesso JSON come testo.datacontiene i dati dell'errore senzastatus; - manca lo scope:
isError: truee testoinsufficient_scope: requires scope <scope>.. Il server controlla lo scope prima di eseguire.
Errori JSON-RPC:
| Codice | Caso |
|---|---|
-32700 | JSON non valido |
-32600 | non è un oggetto, batch, jsonrpc diverso da 2.0, method assente |
-32601 | metodo non supportato |
-32602 | name non stringa, arguments non oggetto, tool sconosciuto |
-32603 | risposta non codificabile (solo STDIO) |
Collegare un client MCP
Cosa fa: riassume i passi per collegare un client al server MCP.
Come si usa:
In wp-admin apri Nucleo AI → Agenti AI (admin.php?page=nucleo-agents). La pagina mostra l'URL del server MCP con il pulsante di copia.
Usa l'URL. La pagina propone due esempi: Claude Code claude mcp add --transport http nucleo <url>, Claude Desktop {"mcpServers":{"nucleo":{"url":"<url>"}}}.
Il client chiama l'endpoint senza token e riceve 401 con WWW-Authenticate.
Il client legge /.well-known/oauth-protected-resource, poi /.well-known/oauth-authorization-server.
Il client ottiene un client_id in uno di tre modi: URL del proprio documento di metadati, registrazione dinamica (se attiva) o client aggiunto a mano nella pagina AI agents. Un client confidenziale creato nella stessa pagina riceve anche un client secret, da usare allo scambio del codice.
Il client apre il browser sulla schermata di consenso. Un utente WordPress collegato approva gli scope.
Il client scambia il codice con i token su /wp-json/nucleo/v1/oauth/token e chiama il server MCP con Authorization: Bearer nca_….
Per un client locale sul server, in alternativa: wp nucleo mcp --user=<login>.
Parametri: nessuno.
Permessi: la pagina AI agents richiede manage_options. Il consenso richiede un utente collegato con le capability degli scope scelti.
Edizione: Free
Limiti noti: se la registrazione dinamica è spenta, la pagina avvisa di aggiungere l'agente con Add agent.
03Scoperta OAuth
/.well-known/oauth-protected-resource
Cosa fa: pubblica i metadati della risorsa protetta (RFC 9728).
Come si usa: GET https://<sito>/.well-known/oauth-protected-resource.
Parametri: nessuno. Risposta:
| Chiave | Valore |
|---|---|
resource | rest_url('nucleo/v1/mcp') |
authorization_servers | [home_url()] |
scopes_supported | i cinque scope |
bearer_methods_supported | ["header"] |
Permessi: pubblico
Edizione: Free
Limiti noti: il documento passa da parse_request di WordPress. Viene servito solo se il percorso, relativo alla home di WordPress, è esattamente .well-known/oauth-protected-resource. Con il sito in una sottocartella il percorso segue la home di WordPress.
/.well-known/oauth-authorization-server
Cosa fa: pubblica i metadati dell'authorization server (RFC 8414).
Come si usa: GET https://<sito>/.well-known/oauth-authorization-server.
Parametri: nessuno. Risposta:
| Chiave | Valore |
|---|---|
issuer | home_url() |
authorization_endpoint | admin_url('admin.php?page=nucleo-authorize') |
token_endpoint | rest_url('nucleo/v1/oauth/token') |
revocation_endpoint | rest_url('nucleo/v1/oauth/revoke') |
registration_endpoint | rest_url('nucleo/v1/oauth/register'), solo se la registrazione dinamica è attiva |
response_types_supported | ["code"] |
grant_types_supported | ["authorization_code", "refresh_token"] |
code_challenge_methods_supported | ["S256"] |
token_endpoint_auth_methods_supported | ["none", "client_secret_post", "client_secret_basic"] |
scopes_supported | i cinque scope |
client_id_metadata_document_supported | true |
Permessi: pubblico
Edizione: Free
Limiti noti: client pubblici (none) e confidenziali (client_secret_post o client_secret_basic). Il secret dei client confidenziali è descritto in Client confidenziale.
04Client OAuth
I client stanno nella tabella {prefix}nucleo_oauth_clients. Il campo kind vale pre, cimd o dcr. Il client confidenziale ha l'hash del suo secret nel campo secret_hash. Le tabelle si creano all'attivazione o al primo uso (opzione nucleo_oauth_db, versione 2).
Client pre-registrato
Cosa fa: crea un client con un nome e un redirect URL. Il client_id ha prefisso ncl_.
Come si usa: Nucleo AI → Agenti AI, modulo Add agent. Nella stessa tabella Connected agents ci sono Revoke tokens (revoca i token attivi, il client resta) e Delete (elimina il client e tutti i suoi token).
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
| Name | stringa | 1–200 caratteri | nessuno | obbligatorio |
| Redirect URL | stringa | vedi Regole sui redirect URI | nessuno | un solo URL |
Permessi: manage_options, con nonce check_admin_referer
Edizione: Free
Limiti noti: codici di errore missing_name, name_too_long, invalid_redirect, save_failed. Un solo redirect per client.
Client confidenziale
Cosa fa: crea un client che si autentica al token endpoint con un client secret generato dal plugin di 40 caratteri. Il secret si mostra una sola volta: nel database resta solo il suo hash.
Come si usa: Nucleo AI → Agenti AI, riquadro Add confidential agent, pulsante Create confidential agent. Il secret compare nella stessa pagina subito dopo la creazione. Il transient che lo trasporta dura 60 secondi, poi il secret non è più leggibile. Il client lo presenta allo scambio del codice e al rinnovo (vedi Scambio del codice).
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
| Name | stringa | fino a 200 caratteri | nessuno | obbligatorio |
| Redirect URLs | stringa | uno per riga; https, oppure http solo su localhost o 127.0.0.1 | nessuno | obbligatorio |
Permessi: manage_options
Edizione: Free
Limiti noti: codice di errore invalid_redirect se manca un redirect o se un redirect non è ammesso. Il secret non si recupera: se si perde, si elimina il client e se ne crea uno nuovo. La registrazione dinamica non crea client confidenziali.
Client ID Metadata Document
Cosa fa: accetta come client_id un URL https. Nucleo scarica il documento JSON a quell'URL, lo valida e salva il client con kind cimd.
Come si usa: il client passa il proprio URL come client_id alla schermata di consenso. Nessuna registrazione preventiva.
Parametri: campi del documento:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
client_id | stringa | identico all'URL del documento | nessuno | obbligatorio |
redirect_uris | array | lista non vuota; https con host, oppure http su localhost, 127.0.0.1, [::1]; niente frammento né credenziali | nessuno | obbligatorio |
client_name | stringa | massimo 200 caratteri | "" | facoltativo |
logo_uri | stringa | URL https | assente | facoltativo; la schermata di consenso non lo mostra |
token_endpoint_auth_method | stringa | none | assente | facoltativo |
Permessi: pubblico (il download avviene durante la schermata di consenso)
Edizione: Free
Limiti noti: protezione SSRF: solo https, niente localhost, niente credenziali nell'URL, tutti gli IP risolti devono essere pubblici. La richiesta fissa l'host al primo IPv4 verificato; un host con soli indirizzi IPv6 viene rifiutato. Timeout 5 secondi, nessun redirect, risposta massima 65536 byte, solo stato 200. Cache in un transient per un'ora. Se la lista dei domini ammessi non è vuota, l'host del client_id deve appartenerne a uno (o esserne un sottodominio) prima del download; altrimenti il client non viene risolto.
Registrazione dinamica POST /wp-json/nucleo/v1/oauth/register
Cosa fa: registra un client (RFC 7591) con kind dcr e restituisce 201 con client_id, client_name, redirect_uris. Il client registrato è sempre pubblico: nessun secret.
Come si usa: attiva Dynamic registration in Nucleo AI → Agenti AI (opzione nucleo_oauth_dcr). Poi il client invia JSON o un form.
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
redirect_uris | array | lista non vuota, vedi Regole sui redirect URI | nessuno | obbligatorio |
client_name | stringa | massimo 200 caratteri | "" | facoltativo |
Permessi: pubblico. L'interruttore richiede manage_options.
Edizione: Free
Limiti noti:
- Disattivata di default. Spenta, risponde
403conerror: access_denied. - Metadati non validi:
400conerror: invalid_client_metadata. - Con la lista dei domini ammessi non vuota, anche l'host di ogni redirect deve appartenerne a uno (o esserne un sottodominio); altrimenti
400conerror: invalid_client_metadata. - Gli altri campi del corpo si ignorano.
- Nessun limite di frequenza sull'endpoint.
Regole sui redirect URI
Cosa fa: definisce quali redirect si registrano e quali si accettano nella richiesta.
Come si usa: si applicano a tutti e tre i tipi di client.
Parametri: nessuno.
Permessi: non applicabile
Edizione: Free
Limiti noti:
- In registrazione:
httpscon host e senza credenziali, oppurehttpsulocalhost,127.0.0.1o[::1]; niente frammento. - In autorizzazione: il redirect deve coincidere carattere per carattere con uno registrato.
- Per
httpsu loopback la porta può variare (RFC 8252): devono coincidere host, path, query e frammento. - Ogni altro
httpè rifiutato.
05Flusso di autorizzazione
Schermata di consenso admin.php?page=nucleo-authorize
Cosa fa: valida la richiesta di autorizzazione, mostra la schermata Authorize AI agent e, all'approvazione, rimanda al client con un codice.
Come si usa: il client apre nel browser https://<sito>/wp-admin/admin.php?page=nucleo-authorize&response_type=code&client_id=…&redirect_uri=…&scope=…&state=…&code_challenge=…&code_challenge_method=S256&resource=…. L'utente sceglie gli scope e preme Approve o Cancel.
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
response_type | stringa | code | nessuno | altrimenti unsupported_response_type |
client_id | stringa | ncl_… registrato, oppure URL https del documento di metadati | nessuno | obbligatorio |
redirect_uri | stringa | uno dei redirect del client | nessuno | obbligatorio |
scope | stringa | scope separati da spazi | nessuno | almeno uno; uno sconosciuto o ripetuto dà invalid_scope |
state | stringa | massimo 512 caratteri | "" | restituito al client |
code_challenge | stringa | 43 caratteri base64url | nessuno | obbligatorio |
code_challenge_method | stringa | S256 | nessuno | plain rifiutato |
resource | stringa | esattamente rest_url('nucleo/v1/mcp') | nessuno | altrimenti invalid_target |
Permessi: utente collegato (capability read per la pagina). Ogni scope scelto richiede la capability dello scope (vedi Scope). Il POST richiede il nonce nucleo_authorize.
Edizione: Free
Limiti noti:
- Il consenso è sempre richiesto: il sito non ricorda le approvazioni.
- Client o redirect non validi, compreso un client fuori dalla lista dei domini ammessi: pagina di errore
400, senza redirect. - Dopo la verifica del redirect gli errori tornano al client come
?error=<codice>&state=<state>. - Codici restituiti:
unsupported_response_type,invalid_request,invalid_scope,invalid_target,access_denied(rifiuto o nessuno scope scelto),server_error. - La schermata mostra nome del client, dominio del
client_id, redirect, nome dell'utente e risorsa. Gli scope che l'utente non può concedere appaiono disattivati. - Il codice emesso ha prefisso
ncc_, vale 60 secondi ed è monouso.
PKCE
Cosa fa: lega il codice al client che l'ha chiesto (RFC 7636).
Come si usa: il client genera un code_verifier, invia code_challenge = base64url(SHA-256(verifier)) senza padding e code_challenge_method=S256. Allo scambio invia il code_verifier.
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
code_verifier | stringa | 43–128 caratteri A-Z a-z 0-9 - . _ ~ | nessuno | obbligatorio allo scambio |
code_challenge | stringa | 43 caratteri A-Z a-z 0-9 - _ | nessuno | obbligatorio all'autorizzazione |
Permessi: non applicabile
Edizione: Free
Limiti noti: solo S256. Verifier errato: invalid_grant.
Scambio del codice POST /wp-json/nucleo/v1/oauth/token (authorization_code)
Cosa fa: scambia il codice con un access token e un refresh token.
Come si usa: POST con grant_type=authorization_code, in form o JSON. Il client confidenziale presenta il secret con client_secret nel corpo, oppure con l'header Authorization: Basic (client_id e secret codificati, come da RFC 6749). Non si usano entrambi: un client che li presenta insieme riceve invalid_client.
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
grant_type | stringa | authorization_code | nessuno | |
code | stringa | codice ncc_… | nessuno | obbligatorio |
client_id | stringa | lo stesso dell'autorizzazione | nessuno | obbligatorio |
client_secret | stringa | secret del client confidenziale | nessuno | obbligatorio per i client confidenziali, se non si usa Authorization: Basic |
code_verifier | stringa | vedi PKCE | nessuno | obbligatorio |
redirect_uri | stringa | identico a quello dell'autorizzazione | nessuno | obbligatorio |
resource | stringa | identico a quello dell'autorizzazione | nessuno | obbligatorio: se manca o è diverso, invalid_target |
Risposta 200: access_token, token_type: "Bearer", expires_in: 3600, refresh_token, scope.
Permessi: pubblico. Il client pubblico non si autentica; il client confidenziale si autentica con il secret.
Edizione: Free
Limiti noti:
- Errori
400in formato RFC 6749 (error,error_description) conCache-Control: no-store. - Codici:
invalid_request(parametro mancante),unsupported_grant_type,invalid_client(client sconosciuto o fuori dalla lista dei domini, credenziali malformate, secret errato o mancante per un client confidenziale),invalid_grant(codice errato, scaduto, già usato, redirect diverso, verifier errato, utente senza più le capability),invalid_target. - Fuori dagli ambienti
localedevelopmentuna richiesta in chiaro ricevehttps_required. - Gli scope emessi sono solo quelli per cui l'utente ha ancora la capability.
Rinnovo POST /wp-json/nucleo/v1/oauth/token (refresh_token)
Cosa fa: emette una nuova coppia di token e consuma il refresh token usato (rotazione).
Come si usa: POST con grant_type=refresh_token. Il client confidenziale si autentica come allo scambio del codice.
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
client_id | stringa | client del token | nessuno | obbligatorio |
client_secret | stringa | secret del client confidenziale | nessuno | obbligatorio per i client confidenziali, se non si usa Authorization: Basic |
refresh_token | stringa | ncr_… | nessuno | obbligatorio |
scope | stringa | sottoinsieme degli scope concessi | gli scope originali | facoltativo |
Permessi: pubblico. Il client confidenziale si autentica con il secret.
Edizione: Free
Limiti noti:
- Il riuso di un refresh token già ruotato revoca tutta la catena (
invalid_grant, "session revoked"). - Un token revocato da admin o da
/oauth/revokedàinvalid_grante non tocca la catena. - Scope più ampi degli originali:
invalid_scope. - Refresh scaduto:
invalid_grant. - Client fuori dalla lista dei domini o credenziali errate:
invalid_client.
Revoca POST /wp-json/nucleo/v1/oauth/revoke
Cosa fa: revoca un token (RFC 7009). Per access e refresh token revoca l'intera catena.
Come si usa: POST con token=<token>.
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
token | stringa | access, refresh o codice | nessuno | obbligatorio |
Permessi: pubblico, nessuna autenticazione del client
Edizione: Free
Limiti noti: risponde 200 con {} anche per un token sconosciuto. Senza token risponde 400 invalid_request. Fuori dagli ambienti local e development una richiesta in chiaro riceve https_required.
Autenticazione Bearer
Cosa fa: trasforma l'header Authorization: Bearer nca_… nell'utente WordPress del token e registra gli scope della richiesta. Vale solo sulle rotte REST di Nucleo (/wp-json/nucleo/v1/…).
Come si usa: header Authorization (o REDIRECT_HTTP_AUTHORIZATION) su una richiesta alle rotte nucleo/v1.
Parametri: nessuno.
Permessi: token non revocato, non scaduto, resource uguale a rest_url('nucleo/v1/mcp') (i token senza resource restano validi), client ancora ammesso dalla lista dei domini, utente esistente.
Edizione: Free
Limiti noti:
- La richiesta è riconosciuta solo se lo schema è
Bearerobearer, seguito da un tokennca_. - Un token non valido lascia la richiesta anonima: il server MCP risponde
401. last_useddel client si aggiorna al più ogni 5 minuti.
Fuori dalle rotte nucleo/v1 il token non autentica nulla. Su wp/v2 e su wp-abilities/v1 la richiesta resta quella di WordPress: cookie o application password, con le sole capability dell'utente. Dentro le rotte nucleo/v1 gli scope limitano le ability nucleo/*.
Formato e durata dei token
Cosa fa: descrive token e catene.
Come si usa: non applicabile.
Parametri:
| Oggetto | Prefisso | Durata |
|---|---|---|
| Codice di autorizzazione | ncc_ | 60 secondi, monouso |
| Access token | nca_ | 3600 secondi |
| Refresh token | ncr_ | 2592000 secondi (30 giorni) |
| Client | ncl_ | finché un admin non lo elimina |
| Client secret (confidenziale) | nessuno | 40 caratteri casuali, finché il client non viene eliminato; nel database solo l'hash |
| Catena | chn_ | identifica i token nati dallo stesso consenso |
Permessi: non applicabile
Edizione: Free
Limiti noti: token opachi di 32 byte casuali in base64url. Nel database ({prefix}nucleo_oauth_tokens) finisce solo l'hash SHA-256. Stato revoked: 0 attivo, 1 consumato, 2 revocato da admin o via RFC 7009. Durate fisse, senza filtri.
06Scope
Ogni scope corrisponde a una capability WordPress. Il consenso e il refresh concedono uno scope solo se l'utente ha quella capability. Ogni ability appartiene a un solo scope. Lo scope si somma alla capability propria dell'ability: servono entrambi. Le ability Pro sono segnate con (Pro).
nucleo:read
Cosa fa: abilita le ability di lettura. Etichetta nel consenso: "Read documents, layouts and site status".
Come si usa: scope=nucleo:read.
Parametri: abilita nucleo/site-describe, nucleo/guide, nucleo/catalog-list, nucleo/catalog-get, nucleo/doc-list, nucleo/doc-get, nucleo/doc-validate, nucleo/doc-preview, nucleo/doc-revisions, nucleo/doc-texts, nucleo/quality-check, nucleo/quality-scan, nucleo/tokens-get, nucleo/layout-list, nucleo/layout-explain, nucleo/audit-list, nucleo/bind-fields, nucleo/section-list, nucleo/menu-list, nucleo/gap-list, nucleo/model-get, nucleo/model-validate, nucleo/components-list, nucleo/fields-get, nucleo/content-list, nucleo/content-get, nucleo/terms-get, nucleo/docs-search, nucleo/assets-report (Pro), nucleo/kit-list (Pro).
Permessi: edit_posts
Edizione: Free
Limiti noti: alcune letture chiedono una capability più alta di quella dello scope: nucleo/assets-report, nucleo/model-get, nucleo/model-validate (manage_options), nucleo/layout-list, nucleo/layout-explain (edit_theme_options).
nucleo:write
Cosa fa: abilita creazione e modifica di documenti, contenuti e media. Etichetta: "Create and edit documents and media".
Come si usa: scope=nucleo:write.
Parametri: abilita nucleo/doc-create, nucleo/doc-patch, nucleo/doc-rollback, nucleo/doc-texts-set, nucleo/media-import, nucleo/media-upload, nucleo/media-formats, nucleo/gap-report, nucleo/fields-set, nucleo/content-upsert, nucleo/terms-set, nucleo/doc-translate (Pro).
Permessi: edit_posts
Edizione: Free
Limiti noti: con un token, publish: true o uno stato publish, future o private al primo livello richiedono anche nucleo:publish, per ogni ability. nucleo/doc-patch, nucleo/doc-texts-set, nucleo/doc-rollback, nucleo/fields-set, nucleo/doc-create con postId e nucleo/layout-conditions-set richiedono nucleo:publish anche su un post già pubblicato, programmato o privato. Senza lo scope la chiamata risponde insufficient_scope.
nucleo:publish
Cosa fa: abilita la pubblicazione. Etichetta: "Publish documents".
Come si usa: scope=nucleo:publish.
Parametri: abilita nucleo/doc-publish. Serve anche alle altre ability per pubblicare e per modificare un post online. Con un token, la route REST nucleo/v1/editor-mode richiede nucleo:write, e anche nucleo:publish se il post è pubblicato, programmato o privato.
Permessi: publish_pages
Edizione: Free
Limiti noti: nessuno rilevato.
nucleo:design
Cosa fa: abilita design system, layout, menu, regole asset e ottimizzazione CSS. Etichetta: "Edit design, tokens, layouts and asset rules".
Come si usa: scope=nucleo:design.
Parametri: abilita nucleo/tokens-set, nucleo/fonts-import, nucleo/menu-set, nucleo/layout-conditions-set, nucleo/assets-rules-set, nucleo/critical-set, nucleo/critical-request, nucleo/model-set, nucleo/assets-audit (Pro), nucleo/css-purge (Pro), nucleo/css-status (Pro), nucleo/css-optimize (Pro), nucleo/css-optimize-apply (Pro), nucleo/css-optimize-off (Pro), nucleo/kit-apply (Pro).
Permessi: edit_theme_options
Edizione: Free per lo scope; alcune ability sono Pro
Limiti noti: nucleo/css-status è una lettura ma sta in questo scope. nucleo/assets-rules-set, nucleo/model-set e tutte le nucleo/css-* e nucleo/assets-audit chiedono manage_options. La mappa contiene anche presets-apply, che non corrisponde a nessuna ability registrata.
nucleo:admin
Cosa fa: abilita stato, cache, impostazioni, import/export e opzioni del sito. Etichetta: "Manage the cache, status and settings".
Come si usa: scope=nucleo:admin.
Parametri: abilita nucleo/status, nucleo/cache-rebuild, nucleo/settings-get, nucleo/settings-set, nucleo/site-export, nucleo/site-import, nucleo/site-options-set, nucleo/icons-set, nucleo/component-activate, nucleo/mail-log, nucleo/woo-checkout-fields-set (Pro), nucleo/woo-checkout-parts-set (Pro).
Permessi: manage_options
Edizione: Free
Limiti noti: nucleo/component-activate chiede in più activate_plugins. nucleo/settings-get, nucleo/site-export e nucleo/mail-log sono letture ma stanno in questo scope.
07Ruolo agente
Ruolo nucleo_agent
Cosa fa: crea il ruolo "Nucleo Agent" per utenti dedicati agli agenti AI. Il ruolo modifica documenti e media, non pubblica e non tocca le opzioni.
Come si usa: crea un utente con ruolo Nucleo Agent e autorizza l'agente con quell'utente nella schermata di consenso, oppure usa wp nucleo mcp --user=<login>.
Parametri: capability del ruolo:
| Capability | Valore |
|---|---|
read | true |
edit_posts | true |
edit_pages | true |
edit_published_pages | true |
upload_files | true |
Permessi: l'installazione avviene all'attivazione del plugin e dopo un aggiornamento di versione.
Edizione: Free
Limiti noti:
- Con queste capability l'utente può concedere solo
nucleo:readenucleo:write. - Il ruolo si crea solo se manca: un ruolo già presente non si aggiorna.
Con edit_published_pages l'agente modifica pagine già pubblicate, e quei salvataggi vanno online.
08Meccanismi comuni delle ability
Registrazione e regola Free/Pro
Cosa fa: registra le ability nucleo/* nella categoria nucleo dell'Abilities API. Salta le ability Pro senza licenza.
Come si usa: automatica, sugli hook wp_abilities_api_categories_init e wp_abilities_api_init. Ogni ability definisce name(), args(), execute() e permitted().
Parametri: l'elenco delle ability Pro è nel blocco qui sotto.
Le dodici ability Pro sono nucleo/doc-translate, nucleo/assets-audit, nucleo/css-purge, nucleo/assets-report, nucleo/kit-list, nucleo/kit-apply, nucleo/css-status, nucleo/css-optimize, nucleo/css-optimize-apply, nucleo/css-optimize-off, nucleo/woo-checkout-fields-set e nucleo/woo-checkout-parts-set. Senza licenza attiva non esistono: non compaiono in tools/list né in wp-abilities/v1.
Permessi: non applicabile
Edizione: la licenza decide. Senza licenza attiva le ability Pro non si registrano.
Limiti noti:
- Serve l'Abilities API di WordPress.
- Un nome con maiuscole non si registra.
- Un nome già registrato non si sovrascrive.
- Ogni ability ha
meta.show_in_rest: true. - Se lo schema di input non ha campi obbligatori, Nucleo aggiunge
default: [], così le letture rispondono anche inGET.
Controllo dei permessi
Cosa fa: il permission_callback di ogni ability controlla prima la capability WordPress (permitted()), poi lo scope OAuth.
Come si usa: automatico su ogni superficie (MCP, REST wp-abilities/v1, WP-CLI).
Parametri: nessuno.
Permessi: capability propria dell'ability (vedi Tabella delle ability) e, con token OAuth, lo scope dell'ability.
Edizione: Free
Limiti noti: senza token (cookie, application password, WP-CLI) vale solo la capability. Scope mancante: WP_Error insufficient_scope, status 403, dati scope con lo scope richiesto. Su MCP il server controlla lo scope prima dell'esecuzione, perché WordPress valida l'input prima dei permessi.
Limite di frequenza
Cosa fa: limita le scritture per utente e per gruppo di scope, su una finestra fissa.
Come si usa: si regola con il filtro nucleo/rate_limit.
add_filter('nucleo/rate_limit', fn () => 120);Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
nucleo/rate_limit | intero (filtro) | intero | 60 | chiamate per finestra |
| finestra | intero (fissa) | 60 secondi | non filtrabile |
Permessi: non applicabile
Edizione: Free
Limiti noti:
- Vale solo per le ability senza
readonly: truenelle annotazioni. - Chiave:
<id utente>|<scope dell'ability>; ogni scope ha un contatore separato. - Finestra fissa allineata a multipli di 60 secondi: a cavallo di due finestre passano fino al doppio del limite.
- Oltre il limite l'ability non esegue e restituisce
{"ok": false, "error": {"code": "rate_limited", "message": "…", "retryAfter": 60}}. - Il contatore usa l'object cache persistente se c'è, altrimenti una riga in
wp_options.
Formato dell'esito
Cosa fa: definisce la forma delle risposte delle ability.
Come si usa: il chiamante legge ok.
Parametri: tre forme:
| Forma | Esempio | Su MCP |
|---|---|---|
| Successo | {"ok": true, …campi dell'ability} | structuredContent, isError: false |
| Errore di dominio | {"ok": false, "error": {"code": "not_found", "message": "…"}} | structuredContent, isError: true |
WP_Error | codice e messaggio, per input non valido o permessi | structuredContent {ok: false, error: {code, message, data?}}, isError: true |
Codici ricorrenti in error.code: not_found, invalid_input, invalid_document, rate_limited. Codici WP_Error comuni: invalid_input, insufficient_scope.
Permessi: non applicabile
Edizione: Free
Limiti noti: la forma non è imposta dall'interfaccia. Alcune ability restituiscono lo stesso errore come WP_Error o come ok: false secondo il caso (esempio: nucleo/doc-preview usa WP_Error invalid_input e ok: false con not_found). Gli oggetti error possono avere campi in più, come errors o retryAfter. I dettagli sono nelle singole ability.
Compilazione senza salvataggio
Cosa fa: normalizza, valida e compila un documento. Non scrive nulla. Restituisce {"ok": true, "html", "css"} oppure {"ok": false, "error": {"code": "invalid_document", "message", "errors": [...]}}.
Come si usa: la chiama nucleo/doc-preview. La usano anche l'editor backend e l'anteprima dei kit.
Parametri: un documento Nucleo e un flag, false di default. true aggiunge data-nc-id ai nodi, per l'editor.
Permessi: quelli dell'ability chiamante
Edizione: Free
Limiti noti: nessuno rilevato.
Anteprima firmata (?nucleo_preview=)
Cosa fa: mostra nel tema la versione corrente di un documento, anche in bozza, a chi ha il link.
Come si usa: nucleo/doc-preview con postId restituisce previewUrl, valido 1800 secondi. Il link è il permalink del post con ?nucleo_preview=<token>.
Parametri:
| Nome | Tipo | Valori ammessi | Default | Note |
|---|---|---|---|---|
nucleo_preview | stringa | token base64url di postId.scadenza.firma | nessuno | firma HMAC-SHA256 con wp_salt('nonce') |
| durata | intero | secondi | 600 | nucleo/doc-preview usa 1800 |
Permessi: nessuno sulla richiesta: vale il token
Edizione: Free
Limiti noti:
- Risposte:
403token non valido o scaduto,404documento assente,422documento non compilabile. - Headers
X-Robots-Tag: noindexeCache-Control: no-store.
Il token non è legato a un utente. Chiunque abbia il link vede la bozza fino alla scadenza.
Dry-run
Cosa fa: controlla l'input e riporta le azioni previste senza scrivere.
Come si usa: parametro dryRun: true nelle ability che lo dichiarano nello schema.
Parametri: lo dichiarano nucleo/doc-create, nucleo/doc-patch, nucleo/content-upsert, nucleo/terms-set, nucleo/kit-apply, nucleo/site-import, nucleo/model-set. nucleo/model-set ha anche confirm per accettare le modifiche distruttive.
Permessi: quelli dell'ability
Edizione: Free (nucleo/kit-apply è Pro)
Limiti noti: non è un meccanismo comune: ogni ability lo implementa a modo suo. Le altre scritture non hanno dry-run. Una chiamata in dry-run non è marcata readonly, quindi conta nel limite di frequenza.
09Tabella delle ability
Tutte le 70 ability registrate. "Tipo" segue l'annotazione readonly. "Capability" riassume la capability principale; i dettagli sono nelle singole ability.
| Ability | Tipo | Scope | Capability | Edizione |
|---|---|---|---|---|
nucleo/assets-report | lettura | nucleo:read | manage_options | Pro |
nucleo/audit-list | lettura | nucleo:read | edit_posts | Free |
nucleo/bind-fields | lettura | nucleo:read | edit_posts | Free |
nucleo/catalog-get | lettura | nucleo:read | edit_posts | Free |
nucleo/catalog-list | lettura | nucleo:read | edit_posts | Free |
nucleo/components-list | lettura | nucleo:read | edit_pages | Free |
nucleo/content-get | lettura | nucleo:read | edit_posts del tipo | Free |
nucleo/content-list | lettura | nucleo:read | edit_posts del tipo | Free |
nucleo/css-status | lettura | nucleo:design | manage_options | Pro |
nucleo/doc-get | lettura | nucleo:read | edit_post | Free |
nucleo/doc-list | lettura | nucleo:read | edit_posts | Free |
nucleo/doc-preview | lettura | nucleo:read | edit_post o edit_posts | Free |
nucleo/doc-revisions | lettura | nucleo:read | edit_post | Free |
nucleo/doc-texts | lettura | nucleo:read | edit_post | Free |
nucleo/doc-validate | lettura | nucleo:read | edit_posts | Free |
nucleo/docs-search | lettura | nucleo:read | edit_posts | Free |
nucleo/fields-get | lettura | nucleo:read | edit_post o edit_term | Free |
nucleo/gap-list | lettura | nucleo:read | edit_posts | Free |
nucleo/guide | lettura | nucleo:read | edit_posts | Free |
nucleo/kit-list | lettura | nucleo:read | edit_posts | Pro |
nucleo/layout-explain | lettura | nucleo:read | edit_theme_options | Free |
nucleo/layout-list | lettura | nucleo:read | edit_theme_options | Free |
nucleo/mail-log | lettura | nucleo:admin | manage_options | Free |
nucleo/menu-list | lettura | nucleo:read | edit_posts | Free |
nucleo/model-get | lettura | nucleo:read | manage_options | Free |
nucleo/model-validate | lettura | nucleo:read | manage_options | Free |
nucleo/quality-check | lettura | nucleo:read | edit_post o edit_posts | Free |
nucleo/quality-scan | lettura | nucleo:read | edit_posts | Free |
nucleo/section-list | lettura | nucleo:read | edit_posts | Free |
nucleo/settings-get | lettura | nucleo:admin | manage_options | Free |
nucleo/site-describe | lettura | nucleo:read | edit_posts | Free |
nucleo/site-export | lettura | nucleo:admin | manage_options | Free |
nucleo/status | lettura | nucleo:admin | manage_options | Free |
nucleo/terms-get | lettura | nucleo:read | edit_posts e assign_terms | Free |
nucleo/tokens-get | lettura | nucleo:read | edit_posts | Free |
nucleo/assets-audit | scrittura | nucleo:design | manage_options | Pro |
nucleo/assets-rules-set | scrittura | nucleo:design | manage_options | Free |
nucleo/cache-rebuild | scrittura | nucleo:admin | manage_options | Free |
nucleo/component-activate | scrittura | nucleo:admin | activate_plugins | Free |
nucleo/content-upsert | scrittura | nucleo:write | edit_posts | Free |
nucleo/critical-request | scrittura | nucleo:design | edit_theme_options | Free |
nucleo/critical-set | scrittura | nucleo:design | edit_theme_options | Free |
nucleo/css-optimize | scrittura | nucleo:design | manage_options | Pro |
nucleo/css-optimize-apply | scrittura | nucleo:design | manage_options | Pro |
nucleo/css-optimize-off | scrittura | nucleo:design | manage_options | Pro |
nucleo/css-purge | scrittura | nucleo:design | manage_options | Pro |
nucleo/doc-create | scrittura | nucleo:write | edit_pages/edit_posts, edit_theme_options per layout e sezioni | Free |
nucleo/doc-patch | scrittura | nucleo:write | edit_post (+ publish_post con publish) | Free |
nucleo/doc-publish | scrittura | nucleo:publish | publish_post | Free |
nucleo/doc-rollback | scrittura | nucleo:write | edit_post | Free |
nucleo/doc-texts-set | scrittura | nucleo:write | edit_post (+ publish_post con publish) | Free |
nucleo/doc-translate | scrittura | nucleo:write | edit_post (+ publish_post con publish) | Pro |
nucleo/fields-set | scrittura | nucleo:write | edit_post o edit_term | Free |
nucleo/fonts-import | scrittura | nucleo:design | edit_theme_options | Free |
nucleo/gap-report | scrittura | nucleo:write | edit_pages | Free |
nucleo/icons-set | scrittura | nucleo:admin | manage_options | Free |
nucleo/kit-apply | scrittura | nucleo:design | edit_theme_options | Pro |
nucleo/layout-conditions-set | scrittura | nucleo:design | edit_post | Free |
nucleo/media-formats | scrittura | nucleo:write | upload_files | Free |
nucleo/media-import | scrittura | nucleo:write | upload_files | Free |
nucleo/media-upload | scrittura | nucleo:write | upload_files | Free |
nucleo/menu-set | scrittura | nucleo:design | edit_theme_options | Free |
nucleo/model-set | scrittura | nucleo:design | manage_options | Free |
nucleo/settings-set | scrittura | nucleo:admin | manage_options | Free |
nucleo/site-import | scrittura | nucleo:admin | manage_options | Free |
nucleo/site-options-set | scrittura | nucleo:admin | manage_options | Free |
nucleo/terms-set | scrittura | nucleo:write | manage_terms della tassonomia | Free |
nucleo/tokens-set | scrittura | nucleo:design | edit_theme_options | Free |
nucleo/woo-checkout-fields-set | scrittura | nucleo:admin | manage_options | Pro |
nucleo/woo-checkout-parts-set | scrittura | nucleo:admin | manage_options | Pro |
Questa pagina ti è stata utile?