Sign inSign up

n8500x/mcp-chat-all

By n8500x

•Updated 2 months ago

Chat any backend: Kafka, k8s/OCP, Postgres, MSSQL, Oracle, Redis, Mongo, AWS/Azure, Cloudera

Image
0

2.8K

n8500x/mcp-chat-all repository overview

⁠mcp-chat-all — chat with any backend

A service-agnostic chatbot (web and CLI) that connects to any Model Context Protocol⁠ server(s) you list in a config file and drives any OpenAI-compatible LLM (cloud or on-prem) via litellm⁠. No code is tied to a backend — you describe your servers in config.yaml, and the host connects, aggregates their tools, namespaces them (server__tool), and runs an agentic tool-calling loop.

config.yaml ──▶ mcp-chat-all ──▶ connects to N MCP servers (stdio + remote SSE/HTTP)
                             aggregates + namespaces their tools
                             ├─ web UI  (Streamlit, port 8501)
                             └─ CLI     (one-shot or REPL)

⁠Highlights
  • Load backends from the UI — the sidebar lists every bundled tool set as a simple on/off toggle; flip one on to load its tools for the session. Credentials come from the container environment (env-file / -e). A backend commented out (#) in the config can still be toggled on at runtime — a session-only load that does not edit the config file.
  • Four themes — candy (default, glossy Candy-Crush), matrix (green terminal with live digital-rain), atlassian (clean, professional enterprise skin), or claude (dark VS Code editor with the Claude coral accent). Pick with -e MCP_CHAT_THEME=claude or config theme:.
  • Pick what loads at startup — MCP_ENABLE_BACKENDS (only these) or MCP_DISABLE_BACKENDS (all but these); the sidebar toggles show that selection on first paint and still flip at runtime.
  • Hot reload — edit a mounted tools.*.yaml while it runs and the change is live with no restart: the server re-reads on mtime change, the UI re-probes, and every add/update/remove is logged per tool (LOADED tool: … / UNLOADED tool: …).
  • On-prem / airgapped — self-contained image, all TLS ignored by default (internal CAs), nothing phones home; point it at a self-hosted vLLM/LocalAI.
  • Conversation memory — remembers earlier turns so you can ask follow-ups.
  • Deep-agent mode — a config-driven deep.py (planning + sub-agents + virtual filesystem) baked in for long multi-step investigations over the same tools; run it with --entrypoint python … deep.py "<task>" (see DEEP_AGENT.md).
  • Live streaming — tool calls show as they run and the answer streams in as markdown (tables build up as the data arrives); the view auto-scrolls to follow.
  • Shell-style history — ↑/↓ walk previous prompts, Ctrl+R reverse-searches them; survives clearing the conversation.
  • Multi-cluster — Flink / Kafka Connect / Kafbat targets are per-question, so one chat reaches many clusters.
  • Scales to huge Kafka clusters — fast confluent-kafka path, tunable waits (KAFKA_TIMEOUT/KAFKA_CMD_TIMEOUT) and a paged list_topics (prefix/limit) for clusters with 9000+ topics.
  • Ignore all TLS by default (self-signed / internal-CA / hostname mismatch); MCP_TLS_VERIFY=true to re-enable.
  • Kubernetes/Helm — a chart pulls each backend's secrets from k8s Secrets (secretKeyRef); see the helm/mcp-chat chart in the repo.
⁠All backends via docker compose
cp creds.env.example creds.env     # fill in the backends you use
docker compose up                  # → http://localhost:8501

docker-compose.yml runs the image with every backend wired (config.all.yaml), pulling creds from creds.env. Set only what you use; load the rest from the sidebar anytime.

⁠On-prem / airgapped deployment

Self-contained and airgap-friendly: every CLI + dependency is baked in, all TLS verification is off by default (internal CAs, self-signed, hostname mismatch), and nothing calls out at runtime. Point the LLM at a self-hosted endpoint:

-e LLM_MODEL=openai/mistral-7b-instruct \
-e LLM_API_BASE=http://vllm.internal:8000/v1 \
-e LLM_API_KEY=dummy          # some servers still want a non-empty key

Move the image across the airgap and deploy:

# connected host — pin a tag (not :latest)
docker save n8500x/mcp-chat-all:20260803-183945 | gzip > mcp-chat-all.tgz
# airgapped host
gunzip -c mcp-chat-all.tgz | docker load        # or push to your internal registry

# Kubernetes / OpenShift — secrets come from k8s Secrets (secretKeyRef)
helm upgrade --install mcp-chat helm/mcp-chat -n mcp-chat --create-namespace \
  -f helm/mcp-chat/values-example.yaml          # edit: model, backends, secretRefs

MCP_TLS_VERIFY=true re-enables TLS verification everywhere if you'd rather trust a specific CA. Use host.docker.internal (not localhost) to reach the model from inside a container.

⁠1. Fastest start (30 seconds)

Create a config.yaml and run. This example talks to a filesystem MCP server:

# config.yaml
title: "MCP Chat"
llm:
  model: openai/gpt-4o
  api_key: ${LLM_API_KEY}
servers:
  filesystem:
    command: npx
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
docker run --rm -p 8501:8501 \
  -e LLM_API_KEY=sk-... \
  -v "$PWD/config.yaml:/app/config.yaml:ro" \
  -v "$PWD/data:/data:ro" \
  n8500x/mcp-chat-all:latest

Open http://localhost:8501⁠ and start chatting. That's it.

The image bundles Node, so npx-based MCP servers (filesystem, github, …) work out of the box — nothing else to install.


⁠2. How it works

You provide a config; the container does the rest.

You set in configThe host does
servers: (any number)connects to each, over stdio or HTTP/SSE
tool namesnamespaces them server__tool so they never collide
llm:routes every model call through litellm
system_prompt:steers the assistant
⁠Two kinds of server
servers:
  # stdio — the host spawns it as a subprocess
  files:
    command: npx
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]

  # remote — the host connects to a hosted endpoint
  remote_api:
    url: https://mcp.example.com/sse
    transport: sse          # or: http  (streamable-http)
    headers:
      Authorization: "Bearer ${REMOTE_MCP_TOKEN}"

${VAR} and ${VAR:-default} expand from the environment at load time, so secrets never have to live in the file. Add disabled: true to skip an entry.

⁠Any LLM
llm:
  model: openai/gpt-4o                  # cloud (OpenAI, Anthropic, Azure, Bedrock…)
  # model: openai/mistral-7b-instruct   # on-prem: vLLM / LocalAI / LM Studio
  # api_base: http://vllm-host:8000/v1
  # model: ollama/llama3                # Ollama
  api_key: ${LLM_API_KEY:-}

⁠3. No-code tools — declare an MCP server in YAML

Don't want to write a Python MCP server at all? The image ships a generic, config-driven adapter (generic_server.py). Declare each tool in a tools.yaml — a name, its inputs, and an action (an HTTP call or a shell command) — and wire it in like any other server. {param} placeholders are filled from the call arguments.

# tools.yaml
defaults:
  http:
    base_url: ${API_BASE}
    headers: { Authorization: "Bearer ${API_TOKEN}" }
tools:
  - name: get_order
    description: "Look up an order by id."
    parameters:
      type: object
      properties: { id: { type: string } }
      required: [id]
    http: { method: GET, path: "/orders/{id}" }
  - name: disk_free
    description: "Show disk usage."
    parameters: { type: object, properties: {} }
    shell: { command: ["df", "-h"] }
# in your chat config.yaml
servers:
  orders:
    command: python
    args: ["generic_server.py"]
    env:
      TOOLS_CONFIG: /app/tools.yaml
      API_BASE: https://api.internal
      API_TOKEN: ${API_TOKEN}

Shell commands are passed as an argv list (never through a shell), so tool arguments can't inject extra commands.

⁠4. Backends & deployments — one image, any system

Every backend is just a declared tools file (tools.<backend>.yaml) that the generic server loads. Pick which one at runtime with -e TOOLS_CONFIG=/app/tools.<backend>.yaml and pass that backend's connection env. One image covers everything — n8500x/mcp-chat-all bundles every CLI (Kafka, kubectl/oc, psql, sqlcmd, sqlplus, redis-cli, mongosh, aws, az); HTTP backends like Cloudera Manager need nothing extra.

BackendTOOLS_CONFIGConnection env / mounts
Cloudera Managertools.cloudera.yamlCM_URL, CM_USER, CM_PASSWORD (HTTP, no CLI)
YARN ResourceManagertools.yarn.yamlYARN_RM_URL (+ optional YARN_USER/YARN_PASSWORD) — Spark3 jobs are YARN apps
Spark3 History Servertools.sparkhistory.yamlSPARK_HISTORY_URL (+ optional SPARK_HISTORY_USER/SPARK_HISTORY_PASSWORD)
Apache Flinktools.flink.yamlFLINK_URL (JobManager REST — HTTP, no CLI)
Prometheustools.prometheus.yamlPROMETHEUS_URL (+ optional PROMETHEUS_USER/PROMETHEUS_PASSWORD) — HTTP
Elasticsearch (ELK)tools.elasticsearch.yamlELASTIC_URL (+ optional ELASTIC_USER/ELASTIC_PASSWORD) — HTTP
Grafanatools.grafana.yamlGRAFANA_URL, GRAFANA_TOKEN
Confluencetools.confluence.yamlCONFLUENCE_URL, CONFLUENCE_USER, CONFLUENCE_API_TOKEN
Kafka Connecttools.kafkaconnect.yamlendpoint per call + KCONNECT_USER/KCONNECT_PASSWORD (HTTP)
Kafbat UI (kafka-ui)tools.kafbat.yamlKAFBAT_URL, KAFBAT_CLUSTER (+ optional KAFBAT_USER/KAFBAT_PASSWORD) — UI API over a disparate Kafka cluster
Confluent Schema Registrytools.schemaregistry.yamlSCHEMA_REGISTRY_URL (+ optional SCHEMA_REGISTRY_USER/SCHEMA_REGISTRY_PASSWORD)
Kafkatools.kafka.yamlKAFKA_BOOTSTRAP_SERVERS, KAFKA_SASL_USERNAME/PASSWORD, CA cert
Kubernetestools.k8s.yamlmount kubeconfig
OpenShifttools.ocp.yamlmount kubeconfig
PostgreSQLtools.postgres.yamlPGHOST, PGUSER, PGPASSWORD, PGDATABASE
SQL Servertools.mssql.yamlMSSQL_SERVER (host only), MSSQL_PORT (default 1433), MSSQL_USER, MSSQL_PASSWORD, MSSQL_DB
Oracletools.oracle.yamlORACLE_USER, ORACLE_PASSWORD, ORACLE_DSN (Easy Connect or TNS alias); TNS via ORACLE_TNSNAMES/_B64 rendered at runtime
Redistools.redis.yamlREDIS_HOST (single) or REDIS_CLUSTERS (multi) + REDIS_PASSWORD; OCP TLS route :443
MongoDBtools.mongodb.yamlMONGODB_URI
AWS / Azuretools.cloud.yamlmount ~/.aws / ~/.azure

Every command below also needs -p 8501:8501 and an LLM (-e LLM_API_KEY=sk-...). Open http://localhost:8501⁠ when it's up.

Cloudera Manager (REST API — no CLI):

docker run --rm -p 8501:8501 -e LLM_API_KEY=sk-... \
  -e TOOLS_CONFIG=/app/tools.cloudera.yaml \
  -e CM_URL=https://cm-host:7183/api/v45 -e CM_USER=admin -e CM_PASSWORD=... \
  n8500x/mcp-chat-all:latest

Kafka (SASL_SSL / SCRAM — the entrypoint writes client.properties from env):

docker run --rm -p 8501:8501 -e LLM_API_KEY=sk-... \
  -e TOOLS_CONFIG=/app/tools.kafka.yaml \
  -e KAFKA_BOOTSTRAP_SERVERS=broker1:9093,broker2:9093 \
  -e KAFKA_SASL_USERNAME=my-user -e KAFKA_SASL_PASSWORD=my-pass \
  -v "$PWD/ca.pem:/certs/ca.pem:ro" \
  n8500x/mcp-chat-all:latest

PostgreSQL (use a read-only role):

docker run --rm -p 8501:8501 -e LLM_API_KEY=sk-... \
  -e TOOLS_CONFIG=/app/tools.postgres.yaml \
  -e PGHOST=db -e PGUSER=ro -e PGPASSWORD=... -e PGDATABASE=app \
  n8500x/mcp-chat-all:latest

SQL Server · Oracle · Redis · MongoDB (same shape, swap the env):

# SQL Server
-e TOOLS_CONFIG=/app/tools.mssql.yaml \
-e MSSQL_SERVER=host -e MSSQL_USER=ro -e MSSQL_PASSWORD=... -e MSSQL_DB=app
# Oracle
-e TOOLS_CONFIG=/app/tools.oracle.yaml \
-e ORACLE_USER=ro -e ORACLE_PASSWORD=... -e ORACLE_DSN=host:1521/service
# Redis (OCP TLS route :443; route host passed per query)
-e TOOLS_CONFIG=/app/tools.redis.yaml \
-e REDIS_HOST=redis-a.apps.ocp.example.com -e REDIS_PASSWORD=...
# MongoDB
-e TOOLS_CONFIG=/app/tools.mongodb.yaml \
-e MONGODB_URI="mongodb://ro:pass@host:27017/db"

Kubernetes / OpenShift (mount your kubeconfig):

docker run --rm -p 8501:8501 -e LLM_API_KEY=sk-... \
  -e TOOLS_CONFIG=/app/tools.k8s.yaml \
  -v "$HOME/.kube/config:/root/.kube/config:ro" \
  n8500x/mcp-chat-all:latest
# OpenShift: -e TOOLS_CONFIG=/app/tools.ocp.yaml (same mount)

AWS / Azure (mount your credentials):

docker run --rm -p 8501:8501 -e LLM_API_KEY=sk-... \
  -e TOOLS_CONFIG=/app/tools.cloud.yaml \
  -v "$HOME/.aws:/root/.aws:ro" -v "$HOME/.azure:/root/.azure:ro" \
  n8500x/mcp-chat-all:latest

Then ask, e.g., "which consumer groups have lag over 1000?", "describe the orders table", "which pods are crash-looping in the payments namespace?" — the model calls the backend's tools and summarises. Everything is read-only when you connect with a read-only credential.

⁠Many backends at once, and runtime updates

Load several backends together — use the bundled config.multi.yaml, which wires each backend as its own server so tools are namespaced (flink__…, kafka__…) and never collide:

docker run --rm -p 8501:8501 -e LLM_API_KEY=sk-... \
  -e MCP_CHAT_CONFIG=/app/config.multi.yaml \
  -e FLINK_CLUSTERS="prod-a=https://flink-a:8081" \
  -e KAFKA_BOOTSTRAP_SERVERS=broker:9093 -e KAFKA_SASL_USERNAME=u -e KAFKA_SASL_PASSWORD=p \
  n8500x/mcp-chat-all:latest

(Or point one server's TOOLS_CONFIG at several files: "/app/tools.flink.yaml,/app/tools.cloudera.yaml" or a glob "/app/mytools/*.yaml".)

Add or change tools at runtime — mount a tools file/dir and edit it; the generic server re-reads on every request, so new or updated tools take effect without a restart. Hit ↻ Refresh tools in the UI to re-list them:

docker run --rm -p 8501:8501 -e LLM_API_KEY=sk-... \
  -e TOOLS_CONFIG=/tools/mytools.yaml \
  -v "$PWD/mytools.yaml:/tools/mytools.yaml" \
  n8500x/mcp-chat-all:latest
# edit mytools.yaml on the host → click "↻ Refresh tools" → new tools appear

Multi-cluster (e.g. Flink) — the target endpoint is a per-call argument, so one chat can query many clusters. Set FLINK_CLUSTERS="name=url, …" and the assistant discovers them via a list_clusters tool, then passes the chosen URL.


⁠5. CLI instead of the web UI

Override the entrypoint to use the REPL / one-shot client:

# one-shot
docker run --rm -v "$PWD/config.yaml:/app/config.yaml:ro" \
  -e LLM_API_KEY=sk-... --entrypoint python n8500x/mcp-chat-all:latest \
  chat.py "list the files under /data"

# interactive REPL
docker run --rm -it -v "$PWD/config.yaml:/app/config.yaml:ro" \
  -e LLM_API_KEY=sk-... --entrypoint python n8500x/mcp-chat-all:latest chat.py

Tool calls are printed to stderr so you can see what the model invokes.


⁠6. Reference

⁠Environment variables
VariablePurpose
MCP_CHAT_CONFIGPath to the config file inside the container (default /app/config.yaml)
MCP_CHAT_THEMEUI theme: candy (default), matrix, or atlassian
LLM_MODEL / LLM_API_BASE / LLM_API_KEYmodel string, on-prem base URL, key
KAFKA_TIMEOUTKafka librdkafka request timeout, seconds (default 90) — raise for huge clusters
KAFKA_CMD_TIMEOUTKafka per-tool subprocess deadline, seconds (default 300; keep > KAFKA_TIMEOUT)
MCP_TLS_VERIFYset true to re-enable TLS verification (off by default)
any ${VAR} used in your configexpanded at load time — pass secrets this way

The image reads no fixed backend env of its own — every setting comes from your config (which may reference the environment).

⁠Baked-in examples

Every example ships inside the image under /app, so you can run one without writing anything — just point MCP_CHAT_CONFIG at it:

File (in /app)What it is
config.generic.yamlone config, any backend — pick with TOOLS_CONFIG (default in mcp-chat-all)
config.example.yamlgeneric starter (filesystem server)
tools.<backend>.yamldeclared tools for kafka, k8s, ocp, postgres, mssql, oracle, redis, mongodb, cloud, cloudera
tools.example.yamlno-code tool declarations for generic_server.py
kafka.env.exampleenvironment template for the Kafka example
README.mdfull documentation
# try it with zero config files of your own:
docker run --rm -p 8501:8501 -e LLM_API_KEY=sk-... \
  -e MCP_CHAT_CONFIG=/app/config.example.yaml n8500x/mcp-chat-all:latest
⁠Ports
PortService
8501Streamlit web UI
⁠Config keys
KeyDefaultMeaning
title / subtitle"MCP Chat"UI header text
system_promptgenericinstruction handed to the LLM
max_rounds10max tool-call rounds per turn
suggestions[]up to 4 clickable example prompts on the empty screen
llm.model—any litellm model string (required)
llm.api_base—OpenAI-compatible base URL (on-prem)
llm.api_key—key for the LLM endpoint
servers.<name>.command / args / env—stdio server
servers.<name>.url / transport / headers—remote (sse|http) server
servers.<name>.disabledfalseskip this server
⁠Tags
TagDescription
latestmost recent build
YYYYMMDD-HHMMSSimmutable, timestamped builds

⁠7. Build your own

FROM n8500x/mcp-chat-all:latest
# bake in a config and any extra server dependencies
COPY config.yaml /app/config.yaml
RUN pip install --no-cache-dir confluent-kafka

License / source: internal MLOps tooling. Read-only by design when paired with read-only MCP servers.

Tag summary

Content type

Image

Digest

sha256:6e907b24b…

Size

841.9 MB

Last updated

2 months ago

docker pull n8500x/mcp-chat-all