MCP — Model Context Protocol

Conecte agentes de IA (Claude, ChatGPT, copilotos internos) à sua operação Fhinck via o servidor MCP em integrations.fhinck.com/mcp.

Diferente dos endpoints REST tradicionais (autenticação por key no body), o MCP usa JWT RS256 no header Authorization, com scopes por ferramenta e chaves rotacionáveis via JWKS. Os dois mundos coexistem — REST continua funcionando como antes.

O que é o MCP

O Model Context Protocol é um padrão aberto (mantido pela Anthropic e comunidade) que define como agentes de IA descobrem e invocam ferramentas em sistemas externos. Em vez de programar cada integração à mão, um modelo (Claude, GPT, etc.) lê o catálogo de tools que seu servidor MCP publica e decide sozinho qual chamar para cumprir o pedido do usuário.

O servidor MCP da Fhinck expõe ferramentas de leitura e escrita sobre Master Data, eventos de ponto, classificação de aplicativos e diagnósticos operacionais. Cada chamada é autenticada, escopada por tenant e auditada em BigQuery.

Casos de uso

Endpoint

O servidor segue a especificação MCP 2025-03-26 (Streamable HTTP) com um endpoint único POST /mcp usando JSON-RPC 2.0. Subpaths utilitários complementam o endpoint canônico:

RecursoURLMétodo
Endpoint canônico JSON-RPC https://integrations.fhinck.com/mcp POST
SSE stream do servidor (notificações) https://integrations.fhinck.com/mcp GET (Accept: text/event-stream)
Listar ferramentas (atalho REST) https://integrations.fhinck.com/mcp/tools GET
Invocar ferramenta (atalho REST) https://integrations.fhinck.com/mcp/tools/<nome> POST
Health check https://integrations.fhinck.com/mcp/health GET
Readiness https://integrations.fhinck.com/mcp/ready GET
JWKS público (chaves de verificação) https://integrations.fhinck.com/.well-known/jwks.json GET
Qual usar? Para clientes MCP padrão (Claude Desktop, Anthropic SDK, MCP Inspector) use o endpoint canônico JSON-RPC em POST /mcp. Os atalhos REST (/mcp/tools/<nome>) existem para integrações server-side simples (cURL, scripts, N8N HTTP Request) que preferem não montar JSON-RPC à mão — são equivalentes funcionais, com a mesma autenticação e os mesmos scopes.

Autenticação — JWT RS256

Toda chamada autenticada ao MCP envia um JWT (JSON Web Token) assinado em RS256 no header Authorization:

HTTP — header obrigatório
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjQyYTFi...

O servidor valida quatro coisas em cada token:

  1. Assinatura RS256 — verificada contra a chave pública publicada em /.well-known/jwks.json. Você não precisa armazenar segredo nenhum para validar tokens; quem assina é o emissor Fhinck.
  2. Audience — o claim aud precisa ser exatamente fhinck-mcp. Tokens emitidos para a API REST tradicional (aud=gotadelimao) são automaticamente rejeitados.
  3. Issuer — o claim iss precisa estar na allowlist: fhinck-mcp-issuer (tokens de serviço via OAuth2 client_credentials) ou fhinck-api-exchange (tokens trocados a partir de um ID token Firebase, usado pelo chatbot do dashboard).
  4. Scopes — o claim scopes (ou scope) precisa conter o escopo exigido pela ferramenta chamada. Sem o escopo, a resposta é HTTP 403 com insufficient_scope.
Por que JWT e não uma key simples? O MCP foi desenhado para callers de IA que podem ter escopos diferentes (um chatbot do dashboard só lê do tenant do usuário logado; um worker N8N precisa cruzar tenants). JWTs permitem escopo granular, expiração curta (60 min), rotação de chave sem redeploy do cliente, e separação clara entre identidade humana (Firebase ID token) e identidade de serviço (OAuth2 client_credentials). É um modelo mais seguro do que um segredo único compartilhado.

Como obter um token

Dois fluxos, dependendo de quem está chamando:

Fluxo de serviço — OAuth2 client_credentials

Para automações server-side (workflows N8N, agentes autônomos, ETLs, copilotos hospedados). Use as credenciais client_id + client_secret entregues pelo time Fhinck no onboarding do MCP.

cURL — obter token de serviço
curl -X POST https://us-central1-fhinck-api.cloudfunctions.net/oauthToken \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "SEU_CLIENT_ID",
    "client_secret": "SEU_CLIENT_SECRET",
    "scope": "read:masterdata:SUA_EMPRESA write:masterdata:SUA_EMPRESA"
  }'

Resposta:

JSON — resposta do token endpoint
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "read:masterdata:SUA_EMPRESA write:masterdata:SUA_EMPRESA"
}

Fluxo de chatbot — troca de Firebase ID token

Para copilotos rodando no contexto de um usuário autenticado (ex.: chat do dashboard). O frontend pega o Firebase ID token do usuário logado e troca por um token MCP com escopos derivados do tenant do usuário.

cURL — trocar Firebase ID token
curl -X POST https://us-central1-fhinck-api.cloudfunctions.net/exchangeFirebaseToken \
  -H "Content-Type: application/json" \
  -d '{
    "firebase_id_token": "FIREBASE_ID_TOKEN_DO_USUARIO_LOGADO"
  }'

Modos de operação — service vs chatbot

O servidor resolve o mode de cada chamada para aplicar políticas diferentes:

ModoQuem usaCaracterística
service Workflows, agentes autônomos, ETLs Pode usar scopes cross-tenant (read:tickets:*). Token via oauthToken.
chatbot Copilotos no contexto de um usuário logado Scopes restritos ao tenant do usuário. Token via exchangeFirebaseToken. Algumas ferramentas analíticas são exclusivas deste modo.

Listar ferramentas disponíveis

O endpoint GET /mcp/tools retorna o catálogo de ferramentas que o servidor expõe. Não requer autenticação — é descoberta pública.

cURL — listar tools
curl https://integrations.fhinck.com/mcp/tools

Resposta resumida (a lista real tem ~20 ferramentas):

JSON — catálogo de tools
{
  "tools": [
    {
      "name": "searchEmployee",
      "description": "Busca colaboradores por nome, login ou e-mail.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "dataset": { "type": "string" },
          "query":   { "type": "string" },
          "limit":   { "type": "integer", "default": 10 }
        },
        "required": ["dataset", "query"]
      }
    },
    {
      "name": "whoIsManagerOf",
      "description": "Retorna o gestor direto de um colaborador.",
      "inputSchema": { "type": "object", "properties": { /* ... */ } }
    }
    /* ... demais ferramentas ... */
  ]
}

Endpoint canônico JSON-RPC (recomendado)

O endpoint canônico POST https://integrations.fhinck.com/mcp implementa a especificação MCP 2025-03-26 Streamable HTTP. Todo o protocolo passa por um único URL usando JSON-RPC 2.0. É o que clientes MCP padrão (Anthropic SDK, Claude Desktop, MCP Inspector) esperam.

Handshake — initialize

cURL — initialize
curl -X POST https://integrations.fhinck.com/mcp \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-03-26",
      "capabilities": {},
      "clientInfo": { "name": "meu-app", "version": "0.1.0" }
    }
  }'

Resposta:

JSON — initialize result
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-03-26",
    "capabilities": { "tools": { "listChanged": false } },
    "serverInfo": { "name": "fhinck-mcp", "version": "1.0.0" }
  }
}

Listar ferramentas — tools/list

cURL — tools/list
curl -X POST https://integrations.fhinck.com/mcp \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }'

Invocar ferramenta — tools/call

cURL — tools/call
curl -X POST https://integrations.fhinck.com/mcp \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "searchEmployee",
      "arguments": {
        "dataset": "SUA_EMPRESA",
        "query":   "joao silva",
        "limit":   5
      }
    }
  }'

Resposta (segue spec MCP — content + isError):

JSON — tools/call result
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"success\":true,\"data\":{\"matches\":[...]},\"humanSummary\":\"...\"}"
      }
    ],
    "isError": false,
    "_meta": {
      "humanSummary": "2 colaboradores encontrados.",
      "durationMs": 142
    }
  }
}

Erros JSON-RPC

Erros seguem os códigos canônicos JSON-RPC 2.0:

CódigoSignificadoQuando ocorre
-32700Parse errorBody não é JSON válido
-32600Invalid RequestEnvelope sem jsonrpc:"2.0" ou method
-32601Method not foundMétodo desconhecido (ex.: tools/foo)
-32602Invalid paramstools/call sem params.name
-32603Internal errorErro inesperado no servidor
-32000Tool dispatch failedErro durante execução da ferramenta

Batch JSON-RPC

O endpoint aceita um array de requests JSON-RPC no body — útil pra pipeline N8N que precisa listar e chamar em uma única roundtrip. A resposta é um array na mesma ordem.

Streaming (SSE)

Para receber notificações de progresso de uma ferramenta longa, mande o header Accept: text/event-stream. O servidor responde com SSE — o último evento (event: result) contém o envelope JSON-RPC final.

Chamar uma ferramenta (atalhos REST)

Equivalente ao tools/call JSON-RPC, mas em rota REST direta. Útil para cURL e scripts simples.

cURL — chamar searchEmployee
curl -X POST https://integrations.fhinck.com/mcp/tools/searchEmployee \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "dataset": "SUA_EMPRESA",
    "query":   "joao silva",
    "limit":   5
  }'

Shape da resposta

Toda ferramenta retorna o mesmo envelope, padronizado pela especificação MCP:

JSON — envelope de resposta
{
  "success": true,
  "data": {
    "matches": [
      { "employee": "Joao Silva",  "login": "jsilva",  "department": "TI" },
      { "employee": "Joana Silva", "login": "joanas",  "department": "RH" }
    ]
  },
  "humanSummary": "2 colaboradores encontrados.",
  "warnings": [],
  "meta": { "durationMs": 142, "apiCalls": 1 }
}

Em caso de erro:

JSON — envelope de erro
{
  "success": false,
  "requiresHumanEscalation": false,
  "escalationReason": "insufficient_scope",
  "humanSummary": "Token sem permissao para read:masterdata:SUA_EMPRESA.",
  "warnings": ["insufficient_scope: required one of read:masterdata:SUA_EMPRESA"],
  "meta": { "durationMs": 8, "apiCalls": 0 }
}

Scopes por ferramenta

Cada ferramenta declara o escopo mínimo exigido. Em modo chatbot, o escopo é sempre tenant-scoped (ex.: read:masterdata:ACME). Em modo service, é possível usar wildcard (read:tickets:*) para callers cross-tenant.

FamíliaScopeExemplo de ferramentas
Master Data — leitura read:masterdata:<empresa> searchEmployee, whoIsManagerOf, getCompanyOverview, masterDataQuery
Master Data — escrita write:masterdata:<empresa> masterDataMutate, categorizeURL, screenBlockToggle
Logs / transmissão read:logs:<empresa> data-searchLogs, diagnose-transmission
Tickets de suporte read:tickets:<empresa> ou read:tickets:* (service) lookupTicketContext, lookupExecutionStatus
Dashboard / analytics read:dashboard:<empresa> / read:analytics:<empresa> data-dashboardChartQuery, analyticsQuery (chatbot only)
Administrativo admin:* Bypass — concede todas as permissões. Reservado para automações internas Fhinck.

Erros comuns

CenárioHTTPSintoma no envelope
Token ausente ou inválido 401 tokenError: "JsonWebTokenError: invalid signature"
Token expirado (60 min) 401 tokenError: "TokenExpiredError: jwt expired"
Audience errada 401 tokenError: "JsonWebTokenError: jwt audience invalid"
Escopo insuficiente 400 escalationReason: "insufficient_scope"
Ferramenta inexistente 400 escalationReason: "unknown_tool"
Tenant não autorizado para o token 400 escalationReason: "cross_tenant_blocked"

Defesas adicionais do servidor

Rotação de chave (JWKS)

As chaves de assinatura RS256 do MCP são publicadas em https://integrations.fhinck.com/.well-known/jwks.json. Se você implementa um validador próprio do token (ex.: gateway que filtra antes de chamar o MCP), cache esse JWKS por no máximo 10 minutos e recarregue ao encontrar kid desconhecido. Durante uma janela de rotação, o JWKS publica a chave atual e a anterior em paralelo, permitindo que tokens emitidos antes da rotação continuem aceitos até expirarem.

Health checks

Auditoria

Toda chamada de ferramenta — sucesso ou falha — é registrada em fhinckbackendnew.mcp_audit.tool_calls no BigQuery com: nome da ferramenta, modo (service/chatbot), actorId (claim sub do token), tenant, latência, status e hash do input (sem PII). Logs ficam disponíveis para investigação de incidentes e auditoria de conformidade. Solicite extração com seu contato comercial Fhinck.

Próximos passos

Dúvidas, pedidos de novas ferramentas ou problemas com escopo: contato@fhinck.com.