Lenses

Gerencie, explore, transforme e junte dados em vários clusters usando diferentes versões do Apache Kafka via Lenses.io (incluindo a Edição Comunitária gratuita).

Documentação

🌊🔍 Servidor MCP Lenses para Apache Kafka 🔎🌊

Python 3.13 FastMCP MCP License: Apache 2.0

Este é o servidor MCP (Model Context Protocol) Lenses para Apache Kafka. O Lenses oferece uma solução de experiência de desenvolvedor para engenheiros que criam aplicações em tempo real conectadas ao Kafka. É construído para a empresa e apoiado por um poderoso modelo de IAM e governança.

Com o Lenses, você pode encontrar, explorar, transformar, integrar e replicar dados em um ambiente multi-Kafka e multi-fornecedor. Agora, todo esse poder está acessível através de suas ferramentas de IA e Agentes de IA via MCP, trazendo contexto em tempo real para seus fluxos de trabalho de engenharia com agentes.

A maneira mais rápida de experimentar o servidor MCP é com a Lenses Community Edition gratuita, que executa o Lenses MCP Server como um servidor MCP remoto e vem com um cluster Kafka de broker único pré-configurado com dados de demonstração, ideal para desenvolvimento local ou avaliação (passos aqui).

Sumário

1. Instalar uv e Python

Usamos uv para gerenciamento de dependências e configuração do projeto. Se você não tiver o uv instalado, siga o guia de instalação oficial.

Este projeto requer Python 3.13 (qualquer versão 3.13.x). Para verificar sua versão do Python, execute:

uv run python --version

2. Configurar Variáveis de Ambiente

Copie o arquivo de ambiente de exemplo e configure-o com base no seu método de autenticação:

cp .env.example .env

Variáveis obrigatórias dependem da sua escolha de autenticação:

  • Para OAuth (recomendado): LENSES_URL e MCP_ADVERTISED_URL
  • Para Chave de API (alternativa): LENSES_URL e LENSES_API_KEY

3. Autenticação OAuth 2.1 (Recomendada)

OAuth 2.1 é o método de autenticação recomendado para todas as implantações do Lenses MCP. Ele fornece autorização segura baseada em escopos, sem compartilhar chaves de API estáticas.

Como funciona

OAuth 2.1 usa tokens de portador validados via RFC 7662 Token Introspection. O fluxo envolve três participantes:

  1. Cliente MCP — Sua ferramenta de IA (Claude, Cursor, etc.)
  2. Servidor de Autorização — Lenses HQ em LENSES_ADVERTISED_URL
  3. Servidor MCP — Este servidor (o servidor de recursos)

Quando você se conecta, o cliente automaticamente:

  1. Descobre metadados OAuth deste servidor (/.well-known/oauth-protected-resource/mcp)
  2. Registra-se com o servidor de autorização
  3. Inicia a autorização OAuth (com PKCE) e obtém um token de acesso
  4. Usa o token para autenticar solicitações a este servidor MCP

Este servidor então valida o token com o Lenses HQ antes de permitir acesso aos recursos do Kafka.

Configuração simples

Para usar OAuth, você deve definir OAUTH_ENABLED como true, então você só precisa definir duas variáveis de ambiente:

OAUTH_ENABLED=true
LENSES_URL=https://lenses.example.com
MCP_ADVERTISED_URL=http://localhost:8000
  • LENSES_URL — Sua instância Lenses (usada internamente e como servidor de autorização OAuth)
  • MCP_ADVERTISED_URL — A URL pública onde este servidor MCP é acessível pelos clientes

TRANSPORT assume automaticamente o valor de http quando MCP_ADVERTISED_URL está definido.

Avançado: implantações com planos separados

Se o servidor MCP acessa o Lenses em um endereço interno, mas os clientes o acessam em uma URL pública:

OAUTH_ENABLED=true
LENSES_URL=http://lenses-hq.internal:9991
LENSES_ADVERTISED_URL=https://lenses.example.com
MCP_ADVERTISED_URL=https://mcp.example.com

Escopos de autorização

O servidor anuncia três escopos:

EscopoDescrição
readAcesso somente leitura aos recursos do Lenses (tópicos, ambientes, conectores, etc.)
writeCriar e atualizar recursos
deleteExcluir recursos

Quando você autentica, será solicitado a conceder esses escopos. Seu token só concederá os escopos que você selecionar.

Configuração do Lenses HQ

O Lenses HQ deve suportar OAuth 2.0 e introspecção de token. Certifique-se de que a configuração do seu Lenses HQ inclua:

oauth2:
  authorizationServer:
    unauthenticatedIntrospection: true

Isso permite que o servidor MCP valide tokens sem credenciais de cliente.

4. Chave de API Lenses (Alternativa)

Para compatibilidade retroativa e testes, você pode usar uma chave de API estática em vez de OAuth. Isso não é recomendado para produção, mas pode ser útil para desenvolvimento local ou sistemas legados.

Crie uma chave de API Lenses provisionando uma Conta de Serviço IAM no Lenses. Adicione a chave de API a .env:

LENSES_URL=https://lenses.example.com
LENSES_API_KEY=<YOUR_LENSES_API_KEY>

Ao usar autenticação por chave de API, TRANSPORT assume o valor padrão de stdio (somente local), a menos que você defina explicitamente MCP_ADVERTISED_URL.

5. Executando o Servidor Localmente

Primeiro, instale as dependências:

uv sync

Com OAuth (Recomendado)

Execute com transporte stdio (para ferramentas de IA locais):

OAUTH_ENABLED=true \
LENSES_URL=https://lenses.example.com \
MCP_ADVERTISED_URL=http://localhost:8000 \
uv run src/lenses_mcp/server.py

Ou execute com transporte HTTP (para clientes remotos):

OAUTH_ENABLED=true \
LENSES_URL=https://lenses.example.com \
MCP_ADVERTISED_URL=http://localhost:8000 \
uv run fastmcp run src/lenses_mcp/server.py --transport=http --port=8000

Para configurar no Claude Desktop, Cursor ou ferramentas similares:

{
  "mcpServers": {
    "Lenses": {
      "command": "uv",
      "args": [
        "run",
        "--project", "<ABSOLUTE_PATH_TO_THIS_REPO>",
        "--with", "fastmcp",
        "fastmcp",
        "run",
        "<ABSOLUTE_PATH_TO_THIS_REPO>/src/lenses_mcp/server.py"
      ],
      "env": {
        "OAUTH_ENABLED": "true",
        "LENSES_URL": "https://lenses.example.com",
        "MCP_ADVERTISED_URL": "http://localhost:8000"
      },
      "transport": "stdio"
    }
  }
}

Com Chave de API (Legado)

Usando uma chave de API estática:

LENSES_URL=https://lenses.example.com \
LENSES_API_KEY=<YOUR_LENSES_API_KEY> \
uv run src/lenses_mcp/server.py

Ou com transporte HTTP:

LENSES_URL=https://lenses.example.com \
LENSES_API_KEY=<YOUR_LENSES_API_KEY> \
uv run fastmcp run src/lenses_mcp/server.py --transport=http --port=8000

Para configurar no Claude Desktop, Cursor ou ferramentas similares:

{
  "mcpServers": {
    "Lenses.io": {
      "command": "uv",
      "args": [
        "run",
        "--project", "<ABSOLUTE_PATH_TO_THIS_REPO>",
        "--with", "fastmcp",
        "fastmcp",
        "run",
        "<ABSOLUTE_PATH_TO_THIS_REPO>/src/lenses_mcp/server.py"
      ],
      "env": {
        "LENSES_URL": "https://lenses.example.com",
        "LENSES_API_KEY": "<YOUR_LENSES_API_KEY>"
      },
      "transport": "stdio"
    }
  }
}

Nota: Alguns clientes podem exigir o caminho absoluto para uv no comando.

6. Executando com Docker

O servidor Lenses MCP está disponível como uma imagem Docker em lensesio/mcp. Você pode executá-lo com OAuth (recomendado) ou autenticação por chave de API.

Com OAuth (Recomendado)

Transporte stdio (para ferramentas de IA locais):

docker run --rm -it \
  -e OAUTH_ENABLED=true \
  -e LENSES_URL=https://lenses.example.com \
  -e MCP_ADVERTISED_URL=http://localhost:8000 \
  lensesio/mcp

Transporte HTTP (para clientes remotos, escuta em http://0.0.0.0:8000/mcp):

docker run --rm -it -p 8000:8000 \
  -e OAUTH_ENABLED=true \
  -e LENSES_URL=https://lenses.example.com \
  -e MCP_ADVERTISED_URL=http://localhost:8000 \
  -e TRANSPORT=http \
  lensesio/mcp

Para implantações com planos separados, onde o servidor MCP acessa o Lenses internamente, mas os clientes usam uma URL pública:

docker run --rm -it -p 8000:8000 \
  -e OAUTH_ENABLED=true \
  -e LENSES_URL=http://lenses-hq.internal:9991 \
  -e LENSES_ADVERTISED_URL=https://lenses.example.com \
  -e MCP_ADVERTISED_URL=https://mcp.example.com \
  -e TRANSPORT=http \
  lensesio/mcp

Com Chave de API (Legado)

Transporte stdio (para ferramentas de IA locais):

docker run --rm -it \
  -e LENSES_API_KEY=<YOUR_API_KEY> \
  -e LENSES_URL=https://lenses.example.com \
  lensesio/mcp

Transporte HTTP (para clientes remotos, escuta em http://0.0.0.0:8000/mcp):

docker run --rm -it -p 8000:8000 \
  -e LENSES_API_KEY=<YOUR_API_KEY> \
  -e LENSES_URL=https://lenses.example.com \
  -e TRANSPORT=http \
  lensesio/mcp

Referência de Variáveis de Ambiente

VariávelObrigatóriaPadrãoDescrição
OAUTH_ENABLEDNãofalseAtiva/desativa OAuth
LENSES_URLSimhttp://localhost:9991URL da instância Lenses no formato [scheme]://[host]:[port]. Use https:// para conexões seguras (usa automaticamente wss:// para WebSockets)
MCP_ADVERTISED_URLPara OAuth-URL base pública deste servidor MCP, conforme acessível pelos clientes. Definir isso ativa OAuth e define o padrão de TRANSPORT como http
LENSES_API_KEYPara autenticação por chave de API-Sua chave de API Lenses (crie via Conta de Serviço IAM). Necessária apenas se não estiver usando OAuth
TRANSPORTNãohttp se MCP_ADVERTISED_URL estiver definido, caso contrário stdioModo de transporte: stdio, http
PORTNão8000Porta para escutar (usada apenas com transporte http)
LENSES_ADVERTISED_URLNãoLENSES_URLURL pública do Lenses HQ anunciada aos clientes MCP para OAuth. Substitua apenas em implantações com planos separados
MCP_SCOPESNãoread,write,deleteEscopos OAuth separados por vírgula anunciados nos metadados de recursos protegidos
INTROSPECTION_URLNãoDescoberto a partir dos metadados de LENSES_ADVERTISED_URLSubstituição para a URL do endpoint de introspecção de token RFC 7662
INTROSPECTION_CACHE_TTLNão0 (desativado)TTL de cache para resultados de introspecção em segundos
OTEL_ENABLEDNãofalseExportar rastreamentos OpenTelemetry (veja seção 7)
OTEL_EXPORTERNãootlpotlp para enviar a um coletor, ou console para imprimir spans para depuração
OTEL_SERVICE_NAMENãolenses-mcpNome do serviço relatado ao backend de rastreamento
OTEL_EXPORTER_OTLP_ENDPOINTNãohttp://localhost:4318URL base do coletor. Lida pelo SDK OpenTelemetry, então todas as variáveis OTEL_* padrão se aplicam
OTEL_EXPORTER_OTLP_PROTOCOLNãohttp/protobufhttp/protobuf (porta 4318) ou grpc (porta 4317, requer o extra otlp-grpc)

Variáveis de ambiente legadas (para compatibilidade retroativa):

  • LENSES_API_HTTP_URL, LENSES_API_HTTP_PORT
  • LENSES_API_WEBSOCKET_URL, LENSES_API_WEBSOCKET_PORT

Elas são derivadas automaticamente de LENSES_URL, mas podem ser definidas explicitamente para substituição.

Endpoints de Transporte

  • stdio: Entrada/saída padrão (sem endpoint de rede)
  • http: Endpoint HTTP em /mcp
  • sse: Endpoint Server-Sent Events em /sse

Construindo a Imagem Docker Localmente

Para construir a imagem Docker localmente:

docker build -t lensesio/mcp .

7. Rastreamento OpenTelemetry

O servidor é construído sobre FastMCP 4, que emite um span OpenTelemetry para cada solicitação MCP — tools/call <tool_name>, tools/list, prompts/get <prompt_name> e assim por diante. Os spans carregam o nome da ferramenta ou prompt, o ID da sessão MCP, a versão do protocolo negociada e o status de erro quando uma chamada falha.

O rastreamento está desativado por padrão e não custa nada até você ativá-lo.

Ativando

OTEL_ENABLED=true \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \
uv run python src/lenses_mcp/server.py

Com Docker:

docker run -p 8000:8000 \
   -e LENSES_URL=<your-lenses-url> \
   -e LENSES_API_KEY=<your-api-key> \
   -e TRANSPORT=http \
   -e OTEL_ENABLED=true \
   -e OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318 \
   lensesio/mcp

OTEL_EXPORTER_OTLP_ENDPOINT é uma URL base — o SDK acrescenta /v1/traces para HTTP. Aponte-o para a raiz do coletor, não para o caminho de traces. Use OTEL_EXPORTER_OTLP_TRACES_ENDPOINT se precisar especificar a URL completa.

Exportadores

O exportador OTLP HTTP (porta 4318) está incluído por padrão. O exportador gRPC (porta 4317) adiciona grpcio e acrescenta aproximadamente 27MB à imagem, então é um extra opcional:

uv sync --extra otlp-grpc
# then
OTEL_EXPORTER_OTLP_PROTOCOL=grpc OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317 ...

Solicitar grpc sem o extra instalado registra um aviso e deixa o rastreamento desativado; isso nunca impede o servidor de iniciar. O mesmo vale para qualquer outra configuração incorreta de telemetria — um coletor inacessível ou um nome de exportador inválido é registrado e o servidor continua atendendo solicitações.

Verificando localmente

A verificação mais rápida não precisa de coletor — imprima spans no stderr:

OTEL_ENABLED=true OTEL_EXPORTER=console uv run python src/lenses_mcp/server.py

O exportador de console escreve em stderr, não em stdout: com o transporte stdio padrão, o stdout carrega o wire JSON-RPC e qualquer outra coisa impressa lá o corromperia. Redirecione stderr para um arquivo se os spans congestionarem seu terminal:

OTEL_ENABLED=true OTEL_EXPORTER=console \
uv run python src/lenses_mcp/server.py 2>spans.log

Para uma interface de traces, o Jaeger aceita OTLP/HTTP na porta 4318 e serve sua interface na porta 16686:

docker run -p 16686:16686 -p 4318:4318 \
  -e COLLECTOR_OTLP_ENABLED=true jaegertracing/all-in-one:1.62.0

Em seguida, navegue até http://localhost:16686 e selecione o serviço lenses-mcp.

Propagação de contexto de trace

Os spans são emitidos por solicitação MCP; não há span pai em nível de sessão. Um trace aninhado só se forma quando o cliente propaga o contexto de trace (traceparent no _meta da solicitação), que o FastMCP extrai e usa como pai. Clientes que não são instrumentados com OpenTelemetry produzem um trace raiz por chamada, o que é esperado. Para obter traces agrupados, instrumente o agente que chama este servidor.

8. Servidor MCP Context7 Opcional

A documentação do Lenses está disponível no Context7. É opcional, mas altamente recomendado usar o Servidor MCP Context7 e ajustar seus prompts com use context7 para garantir que a documentação disponível para o LLM esteja atualizada.

Apêndice: Detalhes do Fluxo OAuth

Sequência de validação de token

O servidor MCP valida tokens de portador usando a seguinte sequência:

  1. Metadados de Recursos Protegidos (RFC 9728) — RemoteAuthProvider serve /.well-known/oauth-protected-resource/mcp para que os clientes possam descobrir qual servidor de autorização usar e quais escopos estão disponíveis.

  2. Descoberta Automática — Na primeira solicitação recebida, o DiscoveryTokenVerifier busca preguiçosamente {LENSES_ADVERTISED_URL}/.well-known/oauth-authorization-server para descobrir o introspection_endpoint. A URL do endpoint também pode ser definida explicitamente via INTROSPECTION_URL.

  3. Introspecção de Token (RFC 7662) — Para cada token de portador recebido, o verificador faz um POST para o endpoint de introspecção (/oauth2/introspect) sem autenticação do cliente. O servidor de autorização responde com:

    • active — se o token é válido
    • scope — escopos concedidos (ex.: read write)
    • client_id — o proprietário do token
    • exp — timestamp de expiração

    Tokens inativos ou expirados são rejeitados antes de chegarem à API do Lenses.

  4. Encaminhamento de Token — Tokens válidos são encaminhados para a API do Lenses via Authorization: Bearer <token> para que o Lenses possa realizar suas próprias verificações de autorização.

Escopos de autorização

O servidor anuncia três escopos em seus metadados de recurso protegido:

EscopoDescrição
readAcesso somente leitura aos recursos do Lenses (tópicos, ambientes, conectores, etc.)
writeCriar e atualizar recursos
deleteExcluir recursos

Os escopos não são aplicados globalmente no nível de introspecção — um token com qualquer subconjunto desses escopos é aceito. A aplicação de escopos por ferramenta pode ser adicionada usando o decorador require_scopes do FastMCP.

Configuração e Requisitos

Em uma implantação simples, apenas duas variáveis de ambiente são necessárias:

LENSES_URL=https://lenses.example.com
MCP_ADVERTISED_URL=http://localhost:8000

Para implantações de plano dividido onde o servidor MCP alcança o Lenses em um endereço interno, mas os clientes usam uma URL pública, defina:

LENSES_URL=http://lenses-hq.internal:9991
LENSES_ADVERTISED_URL=https://lenses.example.com
MCP_ADVERTISED_URL=https://mcp.example.com

O Lenses HQ deve suportar:

  • Metadados do Servidor de Autorização OAuth 2.0 (RFC 8414) em /.well-known/oauth-authorization-server
  • Introspecção de Token (RFC 7662) no introspection_endpoint, com autenticação do cliente desabilitada
  • PKCE com S256 (RFC 7636) para fluxos de autorização do cliente

O servidor MCP não envia credenciais do cliente ao fazer introspecção. O Lenses HQ deve ser configurado com:

oauth2:
  authorizationServer:
    unauthenticatedIntrospection: true

Sem essa configuração, todo token de portador será rejeitado como inválido.