Lenses

Gestiona, explora, transforma y une datos a través de múltiples clústeres utilizando diferentes variantes de Apache Kafka mediante Lenses.io (incluyendo la edición comunitaria gratuita).

Documentación

🌊🔍 Servidor MCP Lenses para Apache Kafka 🔎🌊

Python 3.13 FastMCP MCP License: Apache 2.0

Este es el servidor MCP (Model Context Protocol) de Lenses para Apache Kafka. Lenses ofrece una solución de experiencia de desarrollo para ingenieros que construyen aplicaciones en tiempo real conectadas a Kafka. Está diseñado para la empresa y respaldado por un potente modelo de IAM y gobernanza.

Con Lenses, puedes encontrar, explorar, transformar, integrar y replicar datos en un entorno multi-Kafka y de múltiples proveedores. Ahora, todo este poder es accesible a través de tus herramientas de IA y Agentes de IA mediante MCP, aportando contexto en tiempo real a tus flujos de trabajo de ingeniería agénticos.

La forma más rápida de probar el servidor MCP es con la Lenses Community Edition gratuita, que ejecuta Lenses MCP Server como un servidor MCP remoto e incluye un clúster de Kafka de un solo broker preconfigurado con datos de demostración, ideal para desarrollo local o evaluación (pasos aquí).

Tabla de Contenidos

1. Instalar uv y Python

Usamos uv para la gestión de dependencias y la configuración del proyecto. Si no tienes uv instalado, sigue la guía de instalación oficial.

Este proyecto requiere Python 3.13 (cualquier versión 3.13.x). Para verificar tu versión de Python, ejecuta:

uv run python --version

2. Configurar Variables de Entorno

Copia el archivo de entorno de ejemplo y configúralo según tu método de autenticación:

cp .env.example .env

Las variables requeridas dependen de tu elección de autenticación:

  • Para OAuth (recomendado): LENSES_URL y MCP_ADVERTISED_URL
  • Para Clave API (alternativa): LENSES_URL y LENSES_API_KEY

3. Autenticación OAuth 2.1 (Recomendada)

OAuth 2.1 es el método de autenticación recomendado para todas las implementaciones de Lenses MCP. Proporciona autorización segura basada en ámbitos sin compartir claves API estáticas.

Cómo funciona

OAuth 2.1 utiliza tokens de portador que se validan mediante RFC 7662 Token Introspection. El flujo involucra tres participantes:

  1. Cliente MCP — Tu herramienta de IA (Claude, Cursor, etc.)
  2. Servidor de Autorización — Lenses HQ en LENSES_ADVERTISED_URL
  3. Servidor MCP — Este servidor (el servidor de recursos)

Cuando te conectas, el cliente automáticamente:

  1. Descubre los metadatos OAuth de este servidor (/.well-known/oauth-protected-resource/mcp)
  2. Se registra con el servidor de autorización
  3. Inicia la autorización OAuth (con PKCE) y obtiene un token de acceso
  4. Usa el token para autenticar solicitudes a este servidor MCP

Este servidor luego valida el token con Lenses HQ antes de permitir el acceso a los recursos de Kafka.

Configuración simple

Para usar OAuth, debes establecer OAUTH_ENABLED en true, y solo necesitas configurar dos variables de entorno:

OAUTH_ENABLED=true
LENSES_URL=https://lenses.example.com
MCP_ADVERTISED_URL=http://localhost:8000
  • LENSES_URL — Tu instancia de Lenses (usada internamente y como servidor de autorización OAuth)
  • MCP_ADVERTISED_URL — La URL pública donde este servidor MCP es accesible para los clientes

TRANSPORT toma automáticamente el valor predeterminado de http cuando MCP_ADVERTISED_URL está configurado.

Avanzado: implementaciones de plano dividido

Si el servidor MCP accede a Lenses mediante una dirección interna pero los clientes lo alcanzan mediante una 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

Ámbitos de autorización

El servidor anuncia tres ámbitos:

ÁmbitoDescripción
readAcceso de solo lectura a los recursos de Lenses (temas, entornos, conectores, etc.)
writeCrear y actualizar recursos
deleteEliminar recursos

Cuando te autentiques, se te pedirá que otorgues estos ámbitos. Tu token solo otorgará los ámbitos que selecciones.

Configuración de Lenses HQ

Lenses HQ debe admitir OAuth 2.0 e introspección de tokens. Asegúrate de que la configuración de Lenses HQ incluya:

oauth2:
  authorizationServer:
    unauthenticatedIntrospection: true

Esto permite que el servidor MCP valide tokens sin credenciales de cliente.

4. Clave API de Lenses (Alternativa)

Para compatibilidad con versiones anteriores y pruebas, puedes usar una clave API estática en lugar de OAuth. No se recomienda para producción, pero puede ser útil para desarrollo local o sistemas heredados.

Crea una clave API de Lenses aprovisionando una Cuenta de Servicio IAM en Lenses. Agrega la clave API a .env:

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

Al usar autenticación con clave API, TRANSPORT toma el valor predeterminado de stdio (solo local) a menos que establezcas explícitamente MCP_ADVERTISED_URL.

5. Ejecutar el Servidor Localmente

Primero, instala las dependencias:

uv sync

Con OAuth (Recomendado)

Ejecuta con transporte stdio (para herramientas de IA locales):

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

O ejecuta con 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 en Claude Desktop, Cursor o herramientas 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"
    }
  }
}

Con Clave API (Legado)

Usando una clave API estática:

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

O con 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 en Claude Desktop, Cursor o herramientas 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: Algunos clientes pueden requerir la ruta absoluta a uv en el comando.

6. Ejecutar con Docker

El servidor MCP de Lenses está disponible como imagen Docker en lensesio/mcp. Puedes ejecutarlo con OAuth (recomendado) o autenticación con clave API.

Con OAuth (Recomendado)

Transporte stdio (para herramientas de IA locales):

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, escucha en 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 implementaciones de plano dividido donde el servidor MCP accede a Lenses internamente pero los clientes usan una 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

Con Clave API (Legado)

Transporte stdio (para herramientas de IA locales):

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, escucha en 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

Referencia de Variables de Entorno

VariableRequeridaPredeterminadoDescripción
OAUTH_ENABLEDNofalseHabilita/deshabilita OAuth
LENSES_URLhttp://localhost:9991URL de la instancia de Lenses en formato [scheme]://[host]:[port]. Usa https:// para conexiones seguras (usa automáticamente wss:// para WebSockets)
MCP_ADVERTISED_URLPara OAuth-URL base pública de este servidor MCP tal como la alcanzan los clientes. Configurar esto habilita OAuth y establece TRANSPORT a http por defecto
LENSES_API_KEYPara autenticación con clave API-Tu clave API de Lenses (crea una mediante Cuenta de Servicio IAM). Solo se necesita si no usas OAuth
TRANSPORTNohttp si MCP_ADVERTISED_URL está configurado, si no stdioModo de transporte: stdio, http
PORTNo8000Puerto de escucha (solo se usa con transporte http)
LENSES_ADVERTISED_URLNoLENSES_URLURL pública de Lenses HQ anunciada a los clientes MCP para OAuth. Anula solo en implementaciones de plano dividido
MCP_SCOPESNoread,write,deleteÁmbitos OAuth separados por comas anunciados en los metadatos de recursos protegidos
INTROSPECTION_URLNoDescubierto desde los metadatos de LENSES_ADVERTISED_URLAnulación para la URL del endpoint de introspección de tokens RFC 7662
INTROSPECTION_CACHE_TTLNo0 (deshabilitado)TTL de caché para resultados de introspección en segundos
OTEL_ENABLEDNofalseExportar trazas OpenTelemetry (ver sección 7)
OTEL_EXPORTERNootlpotlp para enviar a un colector, o console para imprimir tramos para depuración
OTEL_SERVICE_NAMENolenses-mcpNombre del servicio reportado al backend de trazabilidad
OTEL_EXPORTER_OTLP_ENDPOINTNohttp://localhost:4318URL base del colector. La lee el SDK de OpenTelemetry, por lo que se aplican todas las variables estándar de OTEL_*
OTEL_EXPORTER_OTLP_PROTOCOLNohttp/protobufhttp/protobuf (puerto 4318) o grpc (puerto 4317, requiere el extra otlp-grpc)

Variables de entorno heredadas (para compatibilidad con versiones anteriores):

  • LENSES_API_HTTP_URL, LENSES_API_HTTP_PORT
  • LENSES_API_WEBSOCKET_URL, LENSES_API_WEBSOCKET_PORT

Se derivan automáticamente de LENSES_URL pero se pueden establecer explícitamente para anular.

Endpoints de Transporte

  • stdio: Entrada/salida estándar (sin endpoint de red)
  • http: Endpoint HTTP en /mcp
  • sse: Endpoint de Server-Sent Events en /sse

Construir la Imagen Docker Localmente

Para construir la imagen Docker localmente:

docker build -t lensesio/mcp .

7. Trazabilidad OpenTelemetry

El servidor está construido sobre FastMCP 4, que emite un tramo OpenTelemetry para cada solicitud MCP — tools/call <tool_name>, tools/list, prompts/get <prompt_name> y así sucesivamente. Los tramos llevan el nombre de la herramienta o prompt, el ID de sesión MCP, la versión del protocolo negociada y el estado de error cuando una llamada falla.

La trazabilidad está desactivada por defecto y no cuesta nada hasta que la actives.

Habilitación

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

Con 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 es una URL base — el SDK agrega /v1/traces para HTTP. Apúntalo a la raíz del colector, no a la ruta de trazas. Usa OTEL_EXPORTER_OTLP_TRACES_ENDPOINT si necesitas especificar la URL completa.

Exportadores

El exportador OTLP HTTP (puerto 4318) está incluido por defecto. El exportador gRPC (puerto 4317) incorpora grpcio y agrega aproximadamente 27MB a la imagen, por lo que es un extra opcional:

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

Solicitar grpc sin el extra instalado registra una advertencia y deja la trazabilidad desactivada; nunca impide que el servidor se inicie. Lo mismo ocurre con cualquier otra configuración incorrecta de telemetría — un colector inalcanzable o un nombre de exportador incorrecto se registra y el servidor continúa atendiendo solicitudes.

Verificación local

La verificación más rápida no necesita colector — imprime los tramos en stderr:

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

El exportador de consola escribe en stderr, no en stdout: con el transporte stdio predeterminado, stdout lleva el cable JSON-RPC y cualquier otra cosa impresa allí lo corrompería. Redirige stderr a un archivo si los tramos saturan tu terminal:

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

Para una interfaz de trazas, Jaeger acepta OTLP/HTTP en 4318 y sirve su interfaz en 16686:

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

Luego navega a http://localhost:16686 y selecciona el servicio lenses-mcp.

Propagación del contexto de trazas

Los tramos se emiten por solicitud MCP; no hay un tramo padre a nivel de sesión. Una traza anidada solo se forma cuando el cliente propaga el contexto de trazas (traceparent en la solicitud _meta), que FastMCP extrae y usa como padre. Los clientes que no están instrumentados con OpenTelemetry producen una traza raíz por llamada, lo cual es esperado. Para obtener trazas agrupadas, instrumenta el agente que llama a este servidor.

8. Servidor MCP Context7 Opcional

La documentación de Lenses está disponible en Context7. Es opcional pero muy recomendable usar el Servidor MCP Context7 y ajustar tus prompts con use context7 para asegurar que la documentación disponible para el LLM esté actualizada.

Apéndice: Detalles del Flujo OAuth

Secuencia de validación de tokens

El servidor MCP valida los tokens de portador usando la siguiente secuencia:

  1. Metadatos de Recursos Protegidos (RFC 9728) — RemoteAuthProvider sirve /.well-known/oauth-protected-resource/mcp para que los clientes puedan descubrir qué servidor de autorización usar y qué ámbitos están disponibles.

  2. Auto-descubrimiento — En la primera solicitud entrante, el DiscoveryTokenVerifier obtiene de forma diferida {LENSES_ADVERTISED_URL}/.well-known/oauth-authorization-server para descubrir el introspection_endpoint. La URL del endpoint también se puede establecer explícitamente mediante INTROSPECTION_URL.

  3. Introspección de tokens (RFC 7662) — Para cada token de portador entrante, el verificador envía un POST al endpoint de introspección (/oauth2/introspect) sin autenticación de cliente. El servidor de autorización responde con:

    • active — si el token es válido
    • scope — los alcances otorgados (p. ej., read write)
    • client_id — el propietario del token
    • exp — la marca de tiempo de expiración

    Los tokens inactivos o expirados se rechazan antes de llegar a la API de Lenses.

  4. Reenvío de tokens — Los tokens válidos se reenvían a la API de Lenses mediante Authorization: Bearer <token> para que Lenses pueda realizar sus propias comprobaciones de autorización.

Alcances de autorización

El servidor anuncia tres alcances en sus metadatos de recursos protegidos:

AlcanceDescripción
readAcceso de solo lectura a los recursos de Lenses (temas, entornos, conectores, etc.)
writeCrear y actualizar recursos
deleteEliminar recursos

Los alcances no se aplican globalmente a nivel de introspección: se acepta un token con cualquier subconjunto de estos alcances. La aplicación de alcances por herramienta se puede agregar usando el decorador require_scopes de FastMCP.

Configuración y requisitos

En una implementación simple, solo se requieren dos variables de entorno:

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

Para implementaciones de plano dividido donde el servidor MCP llega a Lenses mediante una dirección interna pero los clientes usan una URL pública, configure:

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

Lenses HQ debe admitir:

  • Metadatos del servidor de autorización OAuth 2.0 (RFC 8414) en /.well-known/oauth-authorization-server
  • Introspección de tokens (RFC 7662) en el introspection_endpoint, con autenticación de cliente deshabilitada
  • PKCE con S256 (RFC 7636) para flujos de autorización de cliente

El servidor MCP no envía credenciales de cliente al realizar la introspección. Lenses HQ debe configurarse con:

oauth2:
  authorizationServer:
    unauthenticatedIntrospection: true

Sin esta configuración, cada token de portador será rechazado como inválido.