WP24Horas
PARCEIRO RECOMENDADO Vai colocar um WordPress no ar? Comece com uma hospedagem que acompanha o seu projeto. Conhecer a HostGator link patrocinado

Desenvolvimento e Programação

Como conectar WordPress a um agente de IA com Abilities API e MCP

Por Asllan Maciel8 min de leitura
Agente de IA conectado com segurança a ferramentas MCP e a um site WordPress

Um agente de IA não deveria receber acesso genérico ao painel, ao banco ou a todas as rotas REST do WordPress. Ele precisa de ferramentas pequenas, descritas por contratos e limitadas às operações necessárias. A Abilities API organiza esse catálogo no WordPress; um adaptador MCP pode apresentá-lo ao agente.

Neste tutorial vamos construir e testar o WP Abilities MCP Bridge, um exemplo em Node.js que:

  • autentica no WordPress com uma Application Password;
  • descobre as Abilities pela REST API;
  • aplica uma allowlist local;
  • bloqueia escrita e destruição por padrão;
  • converte o input_schema em schema de ferramenta;
  • registra uma ferramenta MCP por Ability autorizada;
  • executa a chamada sem entregar a credencial ao modelo.

O código foi validado com Node.js 22, SDK TypeScript MCP 2.0 e WordPress 7.1-RC1 em Docker. O fluxo real aprovou execução como administrador, negação como assinante e recusa depois da revogação da credencial.

O papel de cada camada

A integração tem quatro fronteiras diferentes:

  1. o agente escolhe uma ferramenta MCP pelo nome, descrição e schema;
  2. o bridge restringe quais Abilities podem virar ferramentas;
  3. a Application Password identifica um usuário no WordPress;
  4. a permission_callback da Ability decide se aquele usuário pode executar a operação sobre aquele objeto.

MCP não substitui a autorização do WordPress. A allowlist também não substitui a permission_callback. As duas proteções se complementam: uma reduz o catálogo exposto ao agente; a outra aplica a política no sistema que possui os dados.

Fluxo seguro entre agente de IA, ferramentas MCP, controles de acesso e WordPress
O bridge apresenta apenas ferramentas autorizadas; identidade e permissão continuam sendo verificadas pelo WordPress.

Pré-requisitos

  • WordPress 6.9 ou superior com uma Ability exposta em REST;
  • HTTPS no ambiente de produção;
  • usuário de integração com o menor privilégio possível;
  • Application Password exclusiva para esse bridge;
  • Node.js 20 ou superior.

Usaremos wp24/get-post-summary, criada nos artigos anteriores. Ela recebe post_id, exige que o usuário possa editar o post e retorna somente campos previstos no output_schema.

Estrutura do projeto

O projeto distribuível acompanha este artigo e usa esta organização:


wp-abilities-mcp-bridge/
|-- src/
|   |-- config.mjs
|   |-- schema.mjs
|   |-- server.mjs
|   `-- wordpress-client.mjs
|-- test/
|-- .env.example
`-- package.json

Instale as dependências:


npm install

Baixe gratuitamente o WP Abilities MCP Bridge 0.1.0 e extraia o pacote em uma pasta local antes de executar os comandos. SHA-256: D15A87875776C208A42081EEAE901856831A08722A69FB92FF972FA4E5E00988.

O exemplo usa os pacotes oficiais separados da linha 2.0 do SDK:


{
  "dependencies": {
    "@modelcontextprotocol/server": "^2.0.0",
    "zod": "^4.0.0"
  }
}

Configuração sem colocar segredos no código

O bridge lê a configuração do ambiente:


WP_URL=https://example.com
WP_USERNAME=agente-editorial
WP_APPLICATION_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx
WP_ABILITY_ALLOWLIST=wp24/get-post-summary,wp24/site-summary
WP_ALLOW_MUTATIONS=false

WP_ABILITY_ALLOWLIST é obrigatória. Fora de localhost, WP_URL precisa usar HTTPS. Mutações ficam bloqueadas enquanto WP_ALLOW_MUTATIONS não for explicitamente habilitada.

Não passe a Application Password em argumentos de linha de comando nem a inclua no arquivo de configuração versionado. Configure-a no gerenciador de secrets do processo que inicia o servidor MCP.

Cliente da REST API

O cliente mantém o cabeçalho Basic Auth dentro do processo:


function basicAuth(username, password) {
  return `Basic ${Buffer.from(`${username}:${password}`, 'utf8').toString('base64')}`;
}

export class WordPressAbilitiesClient {
  constructor(config, fetchImpl = fetch) {
    this.config = config;
    this.fetch = fetchImpl;
    this.authorization = basicAuth(config.username, config.applicationPassword);
  }

  async discover() {
    return this.request('/wp-json/wp-abilities/v1/abilities');
  }
}

O segredo não entra na URL, no nome da ferramenta nem na resposta enviada ao agente. O bridge também não escreve logs em stdout, porque o transporte stdio reserva esse canal para mensagens MCP.

GET, POST e DELETE conforme as anotações

O método HTTP é escolhido pelas anotações da Ability:


async execute(ability, input) {
  const annotations = ability.meta?.annotations ?? {};
  const path = `/wp-json/wp-abilities/v1/abilities/${ability.name}/run`;

  if (annotations.destructive === true) {
    return this.request(withQuery(path, input), { method: 'DELETE' });
  }

  if (annotations.readonly === true) {
    return this.request(withQuery(path, input), { method: 'GET' });
  }

  return this.request(path, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ input }),
  });
}

No RC1 testado, a entrada GET parametrizada funcionou como input[post_id]=4. Confirme esse detalhe contra a versão final e a documentação corrente do endpoint.

A allowlist é uma fronteira local

Descobrir uma Ability não significa que ela deve ser entregue ao agente. A seleção exige nome autorizado e, por padrão, somente leitura não destrutiva:


export function selectAllowedAbilities(abilities, config) {
  return abilities.filter((ability) => {
    if (!config.allowlist.has(ability.name)) return false;

    const annotations = ability.meta?.annotations ?? {};
    if (!config.allowMutations && (
      annotations.readonly !== true ||
      annotations.destructive === true
    )) return false;

    return true;
  });
}

Essa política é deliberadamente conservadora. Uma Ability sem readonly: true não é tratada como leitura por suposição.

Transformando uma Ability em ferramenta MCP

Depois da descoberta, cada Ability aprovada é registrada no servidor:


server.registerTool(
  'wp_wp24__get-post-summary',
  {
    title: ability.label,
    description: ability.description,
    inputSchema: jsonSchemaToZod(ability.input_schema),
    annotations: {
      readOnlyHint: true,
      destructiveHint: false,
      idempotentHint: true,
    },
  },
  async (input) => {
    const result = await client.execute(ability, input);
    return {
      content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
      structuredContent: result,
    };
  },
);

O nome é normalizado para evitar colisões entre namespace e nome. wp24/get-post-summary vira wp_wp24__get-post-summary.

O input_schema é convertido para Zod no bridge. O exemplo cobre objetos, arrays, strings, números, inteiros, booleanos, nulos, enums, campos obrigatórios, limites e additionalProperties: false. Um produto genérico deve decidir explicitamente como tratar palavras-chave de JSON Schema que ainda não suporta.

Servindo por stdio

O SDK recebe uma fábrica assíncrona, permitindo descobrir as Abilities antes de aceitar chamadas:


serveStdio(() => buildServer());

Se a credencial não autenticar ou nenhuma Ability autorizada for descoberta, o processo falha fechado: o agente não recebe um servidor vazio que pareça saudável.

Configurando o cliente MCP

O formato exato varia entre clientes, mas a configuração conceitual é:


{
  "mcpServers": {
    "wordpress-wp24": {
      "command": "node",
      "args": ["CAMINHO/ABSOLUTO/wp-abilities-mcp-bridge/src/server.mjs"],
      "env": {
        "WP_URL": "https://example.com",
        "WP_USERNAME": "agente-editorial",
        "WP_APPLICATION_PASSWORD": "SEGREDO_NO_GERENCIADOR_DO_CLIENTE",
        "WP_ABILITY_ALLOWLIST": "wp24/get-post-summary"
      }
    }
  }
}

Prefira a integração de secrets oferecida pelo cliente ou pelo sistema operacional. O JSON acima mostra os nomes das variáveis, não recomenda gravar o segredo em texto puro.

O que o agente recebe

Com uma única Ability na allowlist, o teste MCP listou somente:


wp_wp24__get-post-summary

Uma chamada com post_id: 4 retornou conteúdo estruturado com ID, título, status, tipo, URL e resumo. O agente não recebeu senha de aplicativo, cabeçalho Authorization, cookies do painel, acesso arbitrário à REST API ou ferramentas fora da allowlist.

Teste real no WordPress 7.1-RC1

O ambiente isolado usou WordPress 7.1-RC1, PHP 8.3 e MariaDB. O mesmo bridge foi iniciado três vezes com credenciais efêmeras:

Cenário Descoberta MCP Execução
administrador autorizado ferramenta listada sucesso
assinante autenticado ferramenta listada erro rest_ability_cannot_execute
Application Password revogada inicialização recusada não executada

Esse resultado separa autenticação de autorização. O assinante provou sua identidade e conseguiu descobrir o contrato, mas a permission_callback negou o post. Depois da revogação, nem a descoberta autenticada foi aceita.

Também encontramos dois diagnósticos úteis durante o ensaio:

  • uma instalação com links permanentes simples pode não resolver /wp-json/...; teste a rota antes de culpar o bridge;
  • para habilitar Application Passwords somente em um ambiente HTTP local de teste, o filtro aplicável é wp_is_application_passwords_available. Nunca replique esse bypass em produção.

Testes automatizados

Execute:


npm test

A suíte cobre configuração, HTTPS, allowlist, bloqueio de mutações, conversão de schema, métodos HTTP, erros REST, ausência de segredo em URLs e uma conexão MCP stdio completa com listagem e chamada de ferramenta.

Checklist para produção

  1. use HTTPS entre bridge e WordPress;
  2. crie um usuário exclusivo por integração e ambiente;
  3. conceda o menor conjunto de capabilities;
  4. use uma Application Password exclusiva e revogável;
  5. mantenha a allowlist curta e revisada;
  6. comece somente com Abilities de leitura;
  7. trate anotação ausente como risco, não como permissão;
  8. preserve permission_callback específica no WordPress;
  9. valide entrada e saída com schemas restritivos;
  10. nunca registre Authorization ou o segredo;
  11. monitore falhas, duração e usuário no lado WordPress;
  12. teste negação e revogação antes da implantação;
  13. revise proxies que removem o cabeçalho Authorization;
  14. separe bridges de produção, homologação e desenvolvimento.

Próximo passo

O bridge fecha o fluxo técnico: descoberta, seleção, autenticação, autorização, execução e revogação. A próxima etapa da série vai aplicar o mesmo método à migração de uma função real de plugin, incluindo inventário, classificação de risco e desenho do contrato da Ability.

Fontes oficiais

Sobre o autor

Asllan Maciel

Asllan Maciel, Fundador do WP24Horas, Consultor de Marketing Digital e amante do Empreendedorismo Digital. Tem um caso de amor com o WordPress.