list_environmentsLABSCO SUMMARY
Kafka operations through Lenses' governance, not straight at the brokers.
Authorization is the reason to route through Lenses: the token is granted read, write and delete scopes at consent time, forwarded to the Lenses API, and Lenses runs its own checks on top, so an agent's reach is the reach you approved. execute_sql is the part that changes daily work — a question about what is actually in a topic becomes a query instead of a console consumer and a lot of scrolling.
What it is
Lenses' own server for Apache Kafka. It fronts a Lenses instance rather than the brokers, so topics, connectors, consumer groups, SQL and dataset metadata across the environments Lenses manages become tools, under the IAM model Lenses already enforces.
What you get
- Topics listed and inspected, with partitions and broker configs, created plain or with a schema, reconfigured, given more partitions, and messages resent
- Kafka Connect worked end to end: connectors listed and inspected, created, paused or resumed, tasks restarted, configuration validated, connectors deleted
- Consumer groups listed overall or per topic, with offsets updated or cleared down to a single topic partition
- SQL executed against the estate, plus SQL processors created, inspected and deleted, with their deployment targets and pod logs
- Datasets and their metadata: message metrics, topic descriptions, topic tags
- Environments listed, inspected, created and health-checked
Requirements
Python 3.13 and uv, or the lensesio/mcp Docker image. LENSES_URL points at your Lenses instance. OAuth 2.1 is the recommended route: set OAUTH_ENABLED to true and MCP_ADVERTISED_URL to the public URL clients reach this server on, and Lenses HQ must be configured with unauthenticatedIntrospection so tokens can be introspected. A Lenses API key from an IAM service account, in LENSES_API_KEY, is the fallback. Started directly with uv run src/lenses_mcp/server.py, TRANSPORT is stdio by default and http once MCP_ADVERTISED_URL is set, listening on PORT 8000 at /mcp. The client configuration launches it through fastmcp run instead, which speaks stdio, and still sets MCP_ADVERTISED_URL because OAuth will not start without it. The free Lenses Community Edition runs this server for you against a preconfigured single-broker cluster with demo data.
Setup effort
One command — docker run --rm -it -p 8000:8000 -e OAUTH_ENABLED=true -e LENSES_URL=<YOUR_LENSES_URL> -e MCP_ADVERTISED_URL=http://localhost:8000 -e TRANSPORT=http lensesio/mcp
USE CASES
Working out what is actually in a topic
Query the data with SQL rather than tailing a console consumer, after checking the topic's partitions and config.
Chasing a consumer group that has fallen behind
List the groups reading that topic, then move or clear offsets — for the whole group or one topic partition.
Getting a stuck connector running again
Read the connector's definition, validate its configuration, and restart the failing task instead of bouncing the worker.
Standing a new topic up properly the first time
Create it with its schema, set the config, and add partitions when throughput asks for them.
Finding out why a stream processor stopped
Read the SQL processor's definition, then pull the pod logs from its deployment target.
Checking an environment before you trust its numbers
List the environments Lenses manages and run a health check on the one you are about to touch.
41 tools
Listed in project docs. Your client may show a different list.
get_environmentcreate_environmentcheck_environment_healthlist_kafka_connectorsget_kafka_connector_target_definitioncreate_kafka_connectorset_action_on_kafka_connectorrestart_kafka_connector_taskdelete_kafka_connectorvalidate_connector_configurationlist_consumer_groupslist_consumer_groups_by_topicupdate_consumer_group_offsetsdelete_consumer_group_offsetsupdate_consumer_group_topic_partition_offsetdelete_consumer_group_topic_partition_offsetexecute_sqllist_sql_processorsget_sql_processorcreate_sql_processordelete_sql_processorget_deployment_targetsget_pod_logslist_topicsget_topicget_topic_partitionscreate_topiccreate_topic_with_schemaupdate_topic_configget_topic_broker_configsadd_topic_partitionsresend_messagelist_datasetsget_datasetget_dataset_message_metricslist_topic_metadataget_topic_metadataupdate_topic_metadataupdate_dataset_topic_descriptionupdate_dataset_topic_tagsBEFORE YOU INSTALL
What to know first
Tools you get
41 tools named in the project's documentation. A read-scoped OAuth token still lists all 41, but create, update and delete calls are refused.
Optional
LENSES_API_KEY in your environment
Where it runs
Both documented clients run the server on your machine.
INSTALLATION
Connect your client
Server setup
Setup
git clone https://github.com/lensesio/lenses-mcp.git
cd lenses-mcpInstall uv and Python 3.13 (any 3.13.x release) — verify with:
uv run python --version
cp .env.example .env
uv syncChoose auth: OAuth 2.1 (recommended) needs LENSES_URL + MCP_ADVERTISED_URL + OAUTH_ENABLED=true; the API-key fallback needs LENSES_URL + LENSES_API_KEY (create one by provisioning an IAM Service Account in Lenses)
Run it: uv run src/lenses_mcp/server.py (stdio), or uv run fastmcp run src/lenses_mcp/server.py --transport=http --port=8000 (http)
Docker alternative (HTTP, for the Cursor configuration below): docker run --rm -it -p 8000:8000 -e OAUTH_ENABLED=true -e LENSES_URL=<YOUR_LENSES_URL> -e MCP_ADVERTISED_URL=http://localhost:8000 -e TRANSPORT=http lensesio/mcp
docker
docker run --rm -it -p 8000:8000 -e OAUTH_ENABLED=true -e LENSES_URL=<YOUR_LENSES_URL> -e MCP_ADVERTISED_URL=http://localhost:8000 -e TRANSPORT=http lensesio/mcpMCP Clients
Claude Desktop
{
"mcpServers": {
"Lenses": {
"command": "uv",
"args": [
"run",
"--project",
"<YOUR_ABSOLUTE_PATH_TO_REPO>",
"--with",
"fastmcp",
"fastmcp",
"run",
"<YOUR_ABSOLUTE_PATH_TO_REPO>/src/lenses_mcp/server.py"
],
"env": {
"OAUTH_ENABLED": "true",
"LENSES_URL": "<YOUR_LENSES_URL>",
"MCP_ADVERTISED_URL": "http://localhost:8000"
},
"transport": "stdio"
}
}
}Both <YOUR_ABSOLUTE_PATH_TO_REPO> values are the full path of your lenses-mcp clone. Some clients need the absolute path to uv as the command.
Cursor
{
"mcpServers": {
"Lenses": {
"type": "http",
"url": "http://localhost:8000/mcp"
}
}
}Start the server first with the Docker command above. <YOUR_LENSES_URL> is the URL of your Lenses instance. The container then serves http://localhost:8000/mcp.