Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

deriva-mcp-ui

CI Status Coverage Status

Browser-based chatbot interface for DERIVA. Wraps an LLM and the deriva-mcp-core MCP server behind a web frontend, giving end users a natural-language interface to query and manage DERIVA catalogs without needing a desktop MCP client.

Features

  • Standard web login via Credenza (OAuth 2.0 + PKCE -- no token pasting)
  • Streaming responses via Server-Sent Events; press ESC to stop generation mid-stream
  • Full tool-calling loop: the LLM invokes DERIVA tools transparently; tool calls are shown in collapsible blocks in the UI
  • Three operating tiers (auto-detected from config, or forced via DERIVA_CHATBOT_MODE):
    • LLM -- full tool-calling loop via any LiteLLM-supported provider (Anthropic, OpenAI, Ollama, Azure, etc.)
    • RAG-only -- no API key required; answers directly from indexed documentation and catalog data via the MCP server's RAG subsystem
    • Local model -- full tool-calling via a local Ollama instance
  • Two catalog modes:
    • Default-catalog -- anchored to a specific catalog; schema context injected automatically on the first turn
    • General-purpose -- user or LLM specifies hostname and catalog ID
  • Conversation history preserved server-side across the browser session and across Credenza token re-authentication
  • Multiple session storage backends: memory (default), Redis/Valkey, PostgreSQL, SQLite
  • Centered chat column (65 rem) with right-aligned user messages -- layout consistent with modern chat UIs; user message alignment is configurable
  • Inline hyperlinks rendered as clickable numbered reference bubbles with a collapsed "References" section after each block -- no raw blue hyperlinks in responses
  • Auto-resizing message input; no Send button (Enter to send, ESC to stop)
  • Montserrat font, 1.6 line-height
  • Fully configurable branding: header color, input area color, chat background, response card style, and logo URL

Requirements

  • Python 3.11+
  • A running deriva-mcp-core instance reachable over HTTP
  • A Credenza instance for authentication (optional -- omit for anonymous/public deployments)
  • An LLM API key (Anthropic, OpenAI, etc.) or a local Ollama (or similar) instance -- not required for RAG-only mode

Installation

pip install deriva-mcp-ui
# or with uv:
uv add deriva-mcp-ui

With optional backends:

pip install "deriva-mcp-ui[redis]"      # Redis / Valkey
pip install "deriva-mcp-ui[sqlite]"     # SQLite
pip install "deriva-mcp-ui[postgresql]" # PostgreSQL

Configuration

All configuration is via environment variables with the DERIVA_CHATBOT_ prefix.

Required

Variable Description
DERIVA_CHATBOT_MCP_URL Base URL of the deriva-mcp-core server

The following are required only when Credenza authentication is enabled (i.e., when DERIVA_CHATBOT_CREDENZA_URL is set):

Variable Description
DERIVA_CHATBOT_CREDENZA_URL Base URL of the Credenza instance
DERIVA_CHATBOT_CLIENT_ID OAuth client ID registered in Credenza
DERIVA_CHATBOT_MCP_RESOURCE Resource URI for the MCP server (must match MCP server config)
DERIVA_CHATBOT_PUBLIC_URL Public HTTPS URL of this service (used as OAuth redirect base)

LLM provider (optional -- not required for RAG-only mode)

Variable Default Description
DERIVA_CHATBOT_LLM_API_KEY API key for the configured provider (Anthropic, OpenAI, etc.)
DERIVA_CHATBOT_LLM_MODEL claude-haiku-4-5 Model identifier (e.g. claude-haiku-4-5, gpt-4o-mini, ollama/llama3)
DERIVA_CHATBOT_LLM_PROVIDER Provider name; auto-detected from model string if omitted
DERIVA_CHATBOT_LLM_API_BASE Custom API base URL (required for Ollama and self-hosted endpoints)
DERIVA_CHATBOT_MODE auto auto, llm, or rag_only; forces operating tier

Default-catalog mode

Set both variables to anchor the chatbot to a specific catalog:

Variable Description
DERIVA_CHATBOT_DEFAULT_HOSTNAME DERIVA server hostname
DERIVA_CHATBOT_DEFAULT_CATALOG_ID Catalog ID or alias
DERIVA_CHATBOT_DEFAULT_CATALOG_LABEL Display name shown in the UI header (optional)

Auth and access control

Variable Default Description
DERIVA_CHATBOT_ALLOW_ANONYMOUS false When true, unauthenticated users get an anonymous session even when Credenza is configured
DERIVA_CHATBOT_ALLOW_RAG_TOGGLE false When true, users in LLM/local tier can switch to RAG-only mode per session from the UI

Branding and UI

Variable Default Description
DERIVA_CHATBOT_HEADER_TITLE DERIVA Data Assistant Text shown in the header bar
DERIVA_CHATBOT_HEADER_LOGO_URL static/deriva-logo.png Logo URL; must be static/<filename> or https:// (no other schemes)
DERIVA_CHATBOT_HEADER_BG_COLOR #1e3a5f CSS color for the header bar background
DERIVA_CHATBOT_INPUT_AREA_BG_COLOR #1e3a5f CSS color for the input area background and textarea border accent
DERIVA_CHATBOT_CHAT_BG_COLOR #f5f5f5 CSS color for the chat thread area background
DERIVA_CHATBOT_CODE_THEME vs2015 highlight.js theme name for code block syntax highlighting (e.g. github, vs)
DERIVA_CHATBOT_SHOW_RESPONSE_CARDS false When true, assistant responses are rendered in styled card bubbles
DERIVA_CHATBOT_CHAT_ALIGN_LEFT false When true, user messages are left-aligned (default: right-aligned, matching ChatGPT)

Tuning

Variable Default Description
DERIVA_CHATBOT_MAX_HISTORY_TURNS 10 Conversation turns retained per session
DERIVA_CHATBOT_MAX_MESSAGE_LENGTH 10000 Maximum user message length in characters
DERIVA_CHATBOT_SESSION_TTL 28800 Server-side session TTL in seconds (default 8h)
DERIVA_CHATBOT_HISTORY_TTL 604800 History-only TTL in seconds; history survives session expiry (7 days)
DERIVA_CHATBOT_STORAGE_BACKEND memory Session backend: memory, redis, valkey, postgresql, sqlite
DERIVA_CHATBOT_STORAGE_BACKEND_URL Connection URL for the selected backend
DERIVA_CHATBOT_DEBUG false Enable debug logging

Networking (Docker / internal hostnames)

Variable Default Description
DERIVA_CHATBOT_HOSTNAME_MAP {} JSON object mapping public hostnames to internal ones (e.g. {"localhost":"deriva"} for Docker deployments)
DERIVA_CHATBOT_SSL_VERIFY true Set to false to disable TLS certificate verification (useful for self-signed certs in dev/staging)

When the chatbot runs inside Docker, localhost in DERIVA_CHATBOT_MCP_URL and DERIVA_CHATBOT_CREDENZA_URL resolves to the container itself. Use DERIVA_CHATBOT_HOSTNAME_MAP to remap the public hostname to the internal Docker service name:

DERIVA_CHATBOT_HOSTNAME_MAP = {"localhost": "deriva"}
DERIVA_CHATBOT_SSL_VERIFY = false

This mirrors the DERIVA_MCP_HOSTNAME_MAP / DERIVA_MCP_SSL_VERIFY pattern used by deriva-mcp-core. In deriva-docker, both variables are populated automatically by generate-env.sh for localhost deployments.

Storage URL examples:

redis://localhost:6379/0
postgresql://user:pass@host/dbname
sqlite:///path/to/sessions.db

Logging

Variable Default Description
DERIVA_CHATBOT_APP_USE_SYSLOG false Enable syslog (LOCAL1) for app logs -- leave false under Docker
DERIVA_CHATBOT_ACCESS_LOGFILE_PATH deriva-mcp-ui-access.log Path for rotating uvicorn access log file
DERIVA_CHATBOT_ACCESS_USE_SYSLOG false Enable syslog (LOCAL2) for access logs

Running

deriva-mcp-ui

The server listens on 0.0.0.0:8001. Set DERIVA_CHATBOT_DEBUG=true for debug logging.

Docker

FROM ghcr.io/informatics-isi-edu/deriva-mcp-ui:latest

Or build locally:

docker build -t deriva-mcp-ui .

Example docker-compose.yml snippet:

deriva-mcp-ui:
  image: deriva-mcp-ui:latest
  environment:
    DERIVA_CHATBOT_MCP_URL: http://deriva-mcp-core:8000
    DERIVA_CHATBOT_CREDENZA_URL: https://auth.example.org
    DERIVA_CHATBOT_CLIENT_ID: deriva-mcp-ui
    DERIVA_CHATBOT_MCP_RESOURCE: https://mcp.example.org
    DERIVA_CHATBOT_PUBLIC_URL: https://example.org/chatbot
    DERIVA_CHATBOT_LLM_API_KEY: sk-ant-...
    DERIVA_CHATBOT_LLM_MODEL: claude-haiku-4-5
    DERIVA_CHATBOT_DEFAULT_HOSTNAME: data.example.org
    DERIVA_CHATBOT_DEFAULT_CATALOG_ID: "1"
    DERIVA_CHATBOT_DEFAULT_CATALOG_LABEL: "Example Catalog"
    DERIVA_CHATBOT_HEADER_BG_COLOR: "#1e3a5f"
    DERIVA_CHATBOT_STORAGE_BACKEND: redis
    DERIVA_CHATBOT_STORAGE_BACKEND_URL: redis://redis:6379/0

Deployment

Traefik (deriva-docker)

Add a deriva-mcp-ui service with these labels:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.chatbot.rule=PathPrefix(`/chatbot`)"
  - "traefik.http.middlewares.chatbot-strip.stripprefix.prefixes=/chatbot"
  - "traefik.http.routers.chatbot.middlewares=chatbot-strip"
  - "traefik.http.services.chatbot.loadbalancer.server.port=8001"

Access the UI at https://your-host/chatbot or https://your-host/chatbot/. A <base href> tag is injected automatically from DERIVA_CHATBOT_PUBLIC_URL, so relative asset URLs resolve correctly regardless of whether the trailing slash is present.

Apache (VM deployment)

ProxyPass /chatbot/ http://127.0.0.1:8001/
ProxyPassReverse /chatbot/ http://127.0.0.1:8001/

Credenza client registration

Add an entry to config/client_registry.json:

{
  "deriva-chatbot": {
    "desc": "DERIVA Chatbot (public, PKCE-only)",
    "enabled": true,
    "public": true,
    "allowed_grant_types": [
      "authorization_code"
    ],
    "allowed_redirect_uris": [
      "https://your-host.example.org/chatbot/callback"
    ],
    "allowed_resources": [
      "urn:deriva:rest:service:all",
      "https://your-host.example.org/mcp"
    ],
    "allowed_scopes": [
      "openid"
    ],
    "require_consent": true,
    "consent_display_name": "DERIVA Chatbot Server",
    "consent_labels": {
      "https://your-host.example.org/mcp": "Connect to the DERIVA MCP Server at this URL"
    },
    "max_session_ttl_seconds": 28800
  }
}

Set DERIVA_CHATBOT_MCP_RESOURCE to the resource URI listed in allowed_resources (e.g. https://your-host.example.org/mcp). Align DERIVA_CHATBOT_SESSION_TTL with max_session_ttl_seconds. Conversation history is preserved across token expiry and re-authentication -- users return to their existing conversation after logging in again.

Architecture

Browser (HTML + JS)
  |
  | HTTPS (session cookie)
  v
deriva-mcp-ui  (FastAPI, port 8001)
  |                    |
  | MCP over HTTP      | HTTPS
  | (bearer token)     | (LLM API -- optional)
  v                    v
deriva-mcp-core     LLM provider (Anthropic / OpenAI / Ollama / ...)
  |
  | HTTPS
  v
DERIVA (ERMrest, Hatrac)

The UI service is a stateless MCP client: each chat turn opens a fresh HTTP connection to the MCP server, runs the LiteLLM tool-calling loop, streams text back via SSE, then closes. No persistent MCP session is maintained.

Package structure

deriva-mcp-ui/
+-- pyproject.toml
+-- Dockerfile
+-- docs/
|   +-- workplan-deriva-mcp-ui.md
+-- src/
    +-- deriva_mcp_ui/
        +-- __init__.py
        +-- server.py        # FastAPI app, route registration, lifespan
        +-- config.py        # Settings (DERIVA_CHATBOT_* env vars, pydantic-settings)
        +-- auth.py          # Credenza OAuth client: /login, /callback, /logout routes
        +-- chat.py          # LiteLLM tool-calling loop, RAG-only path, SSE streaming
        +-- mcp_client.py    # MCP client: connect, list_tools, call_tool, open_session
        +-- audit.py         # Structured audit event logging
        +-- storage/         # Session store backends
        |   +-- __init__.py  # STORAGE_BACKENDS registry + factory
        |   +-- base.py      # SessionStore protocol + Session dataclass
        |   +-- memory.py
        |   +-- redis.py
        |   +-- valkey.py
        |   +-- postgresql.py
        |   +-- sqlite.py
        +-- static/
            +-- index.html   # Chat UI shell (branding injected at request time)
            +-- chat.js      # SSE client, message rendering, link transform, login state
            +-- deriva-logo.png

Template injection

Branding config values are injected into index.html at request time in the GET / route (server.py). Placeholders such as {{HEADER_BG_COLOR}} are replaced with html.escape()-sanitized values. This avoids a build step while still supporting per-deployment customization.

Development

git clone https://github.com/informatics-isi-edu/deriva-mcp-ui
cd deriva-mcp-ui
uv sync --extra dev
uv run pytest

Lint:

uv run ruff check src tests

Health Endpoint

The HTTP server exposes a health endpoint at GET /health that returns {"status": "ok"} with no authentication required. Suitable for Docker health probes and load balancer checks.

curl http://localhost:8001/health
# {"status":"ok"}

Development Status

deriva-mcp-ui is alpha-quality software. The API and configuration surface are still evolving and breaking changes may occur between releases without advance notice. It has been validated end-to-end against live DERIVA deployments, but has not yet seen broad production use. Use in production environments is at your own risk. Bug reports and contributions are welcome via the issue tracker.

License

Apache 2.0. See LICENSE.

About

Browser-based chatbot interface for DERIVA

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages