Notavia Documentação da API Central de Ajuda →

MCP (assistentes de IA)

A Notavia expõe um servidor MCP (Model Context Protocol) remoto, para que assistentes de IA operem a conta de um usuário. É um servidor OAuth 2.1 + MCP sobre Streamable HTTP, sem sessão (stateless). Para guia de uso por quem não é desenvolvedor, veja a Central de Ajuda: Assistentes de IA.

Estado: em liberação gradual. Exige que a Notavia habilite a funcionalidade mcp-clientes para a conta e plano pago. A API de integração por X-Api-Key (restante desta documentação) não é o MCP e continua como está.

Visão geral

Item Valor
Servidor MCP (recurso) https://mcp.notavia.com.br/mcp
Servidor de autorização (issuer) https://app.notavia.com.br
Transporte Streamable HTTP, POST /mcp (JSON-RPC 2.0), sem Mcp-Session-Id
Autenticação Authorization: Bearer <access_token> em toda requisição
Limite 120 requisições por minuto por token (excedido: 429)

O servidor de autorização fica no host do portal porque a tela de consentimento usa a sessão de login do portal; o recurso fica em outro host e o descobre por metadados (RFC 9728).

Descoberta

Uma requisição sem token (ou com token inválido) recebe 401 com o ponteiro dos metadados:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.notavia.com.br/.well-known/oauth-protected-resource", scope="notavia.read"
Endpoint Padrão Conteúdo
GET https://mcp.notavia.com.br/.well-known/oauth-protected-resource RFC 9728 resource, authorization_servers, scopes_supported
GET https://app.notavia.com.br/.well-known/oauth-authorization-server RFC 8414 endpoints, code_challenge_methods_supported, registration_endpoint, client_id_metadata_document_supported
GET https://app.notavia.com.br/.well-known/openid-configuration OIDC Discovery os mesmos metadados
curl -s https://mcp.notavia.com.br/.well-known/oauth-protected-resource
curl -s https://app.notavia.com.br/.well-known/oauth-authorization-server

O resource do documento é idêntico à URL do MCP (https://mcp.notavia.com.br/mcp).

Endpoints OAuth (host do portal)

Endpoint Uso
GET/POST /connect/authorize Autorização (login + tela de consentimento). Exige PKCE S256
POST /connect/token Troca do código e renovação (application/x-www-form-urlencoded)
POST /connect/register Registro dinâmico de cliente (DCR, RFC 7591), JSON

Regras do fluxo:

Registro do cliente

Há duas formas, as duas aceitas pelos assistentes atuais.

CIMD — Client ID Metadata Document (preferido)

O client_id é uma URL https (com caminho, sem fragmento, porta ou credenciais) que serve um documento JSON:

{
  "client_id": "https://app.exemplo.com/oauth/client.json",
  "client_name": "Meu Assistente",
  "redirect_uris": ["https://claude.ai/api/mcp/auth_callback"],
  "token_endpoint_auth_method": "none"
}

O servidor busca o documento (sem seguir redirecionamentos, até 5 s e 64 KB) e exige que client_id seja idêntico à URL buscada. URLs que apontam para a rede interna (IPs privados, localhost, link-local) são recusadas.

DCR — registro dinâmico

curl -s -X POST https://app.notavia.com.br/connect/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "Meu Assistente",
    "redirect_uris": ["http://localhost/callback"],
    "token_endpoint_auth_method": "none"
  }'
{
  "client_id": "dcr_0f3a9c…",
  "client_name": "Meu Assistente",
  "redirect_uris": ["http://localhost/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none",
  "scope": "notavia.read notavia.emitir notavia.cancelar"
}

O registro é idempotente: o mesmo nome com os mesmos redirect_uris devolve sempre o mesmo client_id. Só clientes públicos (token_endpoint_auth_method: none) são aceitos.

redirect_uri permitidos

O redirect_uri só pode ser de um assistente conhecido ou de loopback — qualquer outro valor é recusado no registro (proteção contra desvio do código de autorização):

Origem Valores aceitos
Claude (claude.ai, Desktop, mobile) https://claude.ai/api/mcp/auth_callback (e https://claude.com/api/mcp/auth_callback)
ChatGPT https://chatgpt.com/connector_platform_oauth_redirect e https://chatgpt.com/connector/oauth/{callback_id}
OpenAI (portal de apps) https://platform.openai.com/apps-manage/oauth…
Aplicativos locais (Claude Code, Gemini CLI) http://localhost, http://127.0.0.1 ou http://[::1], qualquer porta e caminho (a porta é ignorada na comparação, RFC 8252)

Sem fragmento, sem credenciais embutidas, https na porta padrão. Precisa de outro assistente? Fale com o suporte.

Escopos

Escopo Permite
notavia.read Consultar notas, cadastros, cota e simulador de impostos. Sempre concedido
notavia.emitir Emitir documentos fiscais em nome da empresa
notavia.cancelar Cancelar documentos fiscais

notavia.emitir e notavia.cancelar só entram no token quando (1) o Admin da conta permitiu emissão por assistentes de IA, (2) o cliente pediu o escopo e (3) o usuário o marcou na tela de consentimento. Um escopo concedido deixa de valer na próxima chamada se a conta retirar a permissão.

Exemplo de fluxo (curl)

# 1) PKCE
VERIFIER=$(openssl rand -base64 48 | tr '+/' '-_' | tr -d '=\n')
CHALLENGE=$(printf %s "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=\n')

# 2) Abra no navegador (login + consentimento) e copie o "code" do redirecionamento:
echo "https://app.notavia.com.br/connect/authorize?response_type=code&client_id=$CLIENT_ID\
&redirect_uri=http%3A%2F%2Flocalhost%3A53124%2Fcallback&scope=notavia.read%20offline_access\
&state=xyz&code_challenge=$CHALLENGE&code_challenge_method=S256\
&resource=https%3A%2F%2Fmcp.notavia.com.br%2Fmcp"

# 3) Troca do código
curl -s -X POST https://app.notavia.com.br/connect/token \
  -d grant_type=authorization_code -d code="$CODE" \
  -d redirect_uri="http://localhost:53124/callback" -d client_id="$CLIENT_ID" \
  -d code_verifier="$VERIFIER" -d resource="https://mcp.notavia.com.br/mcp"

# 4) Renovação (o refresh anterior deixa de valer)
curl -s -X POST https://app.notavia.com.br/connect/token \
  -d grant_type=refresh_token -d refresh_token="$REFRESH" -d client_id="$CLIENT_ID" \
  -d resource="https://mcp.notavia.com.br/mcp"

Chamando o MCP

O transporte responde JSON direto ou um evento SSE (data: {...}); envie Accept: application/json, text/event-stream.

# Listar as ferramentas
curl -s https://mcp.notavia.com.br/mcp \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

# Chamar uma ferramenta
curl -s https://mcp.notavia.com.br/mcp \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"minha_conta","arguments":{}}}'

Ferramentas

Ferramenta Escopo Estado
minha_conta notavia.read Disponível
Consulta de notas, cadastros, simulador e tabelas fiscais notavia.read Em desenvolvimento
Preparar e emitir / cancelar (em dois passos) notavia.emitir / notavia.cancelar Em desenvolvimento

Toda ferramenta traz title e as anotações readOnlyHint / destructiveHint / idempotentHint. Ferramentas de escrita só aparecem em tools/list quando o token as cobre e a empresa permite. Emitir e cancelar são sempre em dois passos: preparar_* devolve uma prévia e um token de confirmação vinculado ao conteúdo exato; emitir_*/cancelar_* só executam com esse token, sem alteração. A emissão usa o mesmo pipeline assíncrono da API de integração (jobId), com idempotência.

Tokens de acesso pessoal (planejado)

Clientes que integram por código e não conseguem fazer o login no navegador (por exemplo a API do Grok ou SDKs) usarão um token de acesso pessoal: criado pelo Admin na área de Administração, com escopos limitados, validade obrigatória, exibido uma única vez (só o hash fica gravado) e revogável na hora. Vai no mesmo cabeçalho Authorization: Bearer. Não disponível ainda.

Erros

HTTP Quando
401 Sem token, token inválido, expirado ou revogado (WWW-Authenticate com resource_metadata)
402 Conta no plano Free (recurso só em planos pagos)
403 Conta suspensa/encerrada ou usuário sem acesso; ou escopo não concedido
404 Recurso não habilitado para a conta
429 Mais de 120 requisições por minuto no mesmo token

Erros de ferramenta (parâmetro inválido, escopo ausente) voltam como resultado MCP com isError: true.

Segurança em resumo

PKCE S256; redirect_uri por lista; refresh com rotação; tokens opacos revogáveis na hora; audiência do token validada; a conta, o papel e a restrição por CNPJ são relidos do banco a cada chamada; nenhum certificado, chave de API ou segredo sai em ferramenta alguma. Dados vindos de notas e cadastros chegam como dado, nunca como instrução — implemente o seu cliente da mesma forma.