Skip to main content
Glama
vedmaka

openwebui-mcp

by vedmaka

openwebui-mcp

Open WebUI MCP server built on FastMCP (standalone, v4) and the openwebui-sdk library

Lets any MCP client (Claude Desktop, Cursor, agents) ask Open WebUI models through the full tool-calling loop, not just plain chat

NOTE

TheOpen WebUI SDK, the Open WebUI CLI and this MCP server are tested against Open WebUI 0.6.5

Quick start

There is no pre-configured Open WebUI identity - every caller supplies their own per request (see Authentication). Streamable HTTP is the transport to use for that:

OPENWEBUI_BASE_URL=http://localhost:8080 \
  uvx openwebui-mcp --transport streamable-http --host 0.0.0.0 --port 8000

Point your MCP client at http://<host>:8000/mcp?apiKey=sk-... (or send an Authorization: Bearer header instead - see Authentication).

IMPORTANT

stdio transport (the MCP SDK default) has no per-request channel at all - no URL, no headers. It falls back to a single, server-wideOPENWEBUI_API_KEY instead (see Authentication) - without that set, every ask and list_models call over stdio fails with a clear error. Prefer streamable-http or SSE for multi-user deployments, since stdio has no way to give each caller their own identity.

Connect an MCP client

Codex CLI (~/.codex/config.toml) - register the server as owui and let it call tools without approval:

[mcp_servers.owui]
url = "http://<host>:8000/mcp?apiKey=sk-..."
default_tools_approval_mode = "auto"

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "openwebui": {
      "type": "streamable-http",
      "url": "http://<host>:8000/mcp?apiKey=sk-..."
    }
  }
}

For SSE clients, or to run the server as a locally-spawned subprocess instead, open the collapsible options below (or see Run)

Run the server:

uvx openwebui-mcp --transport sse --host 0.0.0.0 --port 8000

Claude Desktop (claude_desktop_config.json) - SSE endpoint is http://<host>:8000/sse:

{
  "mcpServers": {
    "openwebui": {
      "type": "sse",
      "url": "http://<host>:8000/sse"
    }
  }
}

For multi-user deployments, an Authorization: Bearer header authenticates each client to Open WebUI with their own key - see Authentication. Unlike streamable-http, SSE does not support the apiKey query parameter.

A bare http://<host>:8000 returns 404 on initialize for both transports; point the client URL at the full /mcp (streamable-http) or /sse (SSE) path. rmcp and other streamable-http clients use the same URL shown in Quick start above.

Related MCP server: mcp-model-proxy

Proactive ask skill

The repo ships a skill that makes an agent consult the ask tool eagerly instead of only when it happens to choose to:

skills/owui-proactive-ask/SKILL.md

It instructs the agent to call mcp__owui__ask before answering every explicit or implicit question (advice, explanations, recommendations, troubleshooting, follow-ups), pass relevant conversation context via history, keep remote tools enabled (use_tools: true), and validate the OWUI answer against local evidence before replying. It also covers failure handling (retry, fall back, say it failed - never fake an OWUI result).

Install it with the agent skills CLI (npx skills) or manually:

# global install for Codex
npx skills add ./skills/owui-proactive-ask -g -a codex -y

# global install for Claude Code
npx skills add ./skills/owui-proactive-ask -g -a claude-code -y

# or copy the folder into your agent's skills directory
cp -r skills/owui-proactive-ask ~/.agents/skills/

The skill references the tool as mcp__owui__ask, so register the MCP server under the name owui (Codex-style clients name MCP tools mcp__<server>__<tool>, see [mcp_servers.owui] in Quick start above).

The skill pairs with OPENWEBUI_ASK_DESCRIPTION and OPENWEBUI_INSTRUCTIONS (see Configure): the skill makes the agent call ask, while the description and instructions tell the model why and when.

Common usage

The typical setup is a single specialized model per use case. Model the remote side of this MCP as a domain expert and route every question to it automatically:

  1. Create a specialized model in the Open WebUI workspace, e.g. a "my-kb-model" an expert with a knowledge base and tools attached

  2. Match the tool description to the model - set OPENWEBUI_ASK_DESCRIPTION to what the model does ("ask the expert model...") so agents know when to call it (see Configure)

  3. Select the model with OPENWEBUI_DEFAULT_MODEL=my-kb-model (the id from list_models or from the UI, listed in gray under the model name)

  4. Enforce it with OPENWEBUI_ENFORCE_DEFAULT_MODEL=true so every ask call goes to the selected model automatically, ignoring whatever model the client passes

Optionally, if you use OWUI + MCP as a knowledge base for your agent, install the Proactive ask skill to instruct the agent to consult this MCP proactively instead of only when it feels like it.

Tools

Exactly two tools are exposed

ask

Send a prompt to a model with Open WebUI tool support

  • prompt (required) - the user message

  • model (optional) - the model id to ask, e.g. one returned by list_models. Omitted, the server uses the configured OPENWEBUI_DEFAULT_MODEL; if that is also unset the call fails with an error

  • system (optional) - a system prompt leading the conversation

  • temperature (optional) - sampling temperature override

  • use_tools (optional, default true) - enable the tools attached to the model

  • history (optional) - prior turns [{"role": "user"|"assistant", "content": "..."}] sent before prompt so the remote model keeps context from earlier questions

Stateless: each ask call is a fresh conversation on the remote model - it never remembers previous calls. To carry context across questions, pass the relevant earlier exchanges in history (e.g. your prior question and its answer), or inline the context into prompt. Agents that keep their own conversation log should replay the needed turns via history

To lock every call to one model regardless of what the client passes, set OPENWEBUI_ENFORCE_DEFAULT_MODEL=true (requires OPENWEBUI_DEFAULT_MODEL); ask then ignores the model argument entirely

To control what agents see about this tool, set OPENWEBUI_ASK_DESCRIPTION - it replaces only the first summary line of the tool description (the text agents read to decide how to call ask). The IMPORTANT - this MCP server is stateless block, the argument docs and the default-model guidance are always present. Unset, the built-in summary line is used

Tools attached to the model run server-side through Open WebUI's Socket.IO tool loop, so answers can be produced with real tool calls. Result is a struct with answer, reasoning and tool_calls

list_models

List the models the connected Open WebUI user can see. Each entry carries the model id, display name and the tool_ids attached to it

Authentication

Token-based. The server talks to Open WebUI as Authorization: Bearer <token>.

On streamable-http and SSE, each caller supplies their own Open WebUI identity per request - no fixed key is pre-configured on the server. Two ways to pass it, checked in this order:

  1. An Authorization: Bearer <token> header (works on both transports, including SSE - a header persists across the whole connection).

  2. An apiKey query parameter on the MCP URL:

    https://<host>:8000/mcp?apiKey=sk-12345

    Works on streamable-http. Not SSE - the transport hands follow-up requests a bare relative URL, which drops the query string, for any compliant SSE client.

This lets multiple users share one HTTP endpoint, each authenticating to Open WebUI as themselves - handy for clients (e.g. Claude web) that can't set an Authorization header, via the query parameter instead. A request with neither credential fails - there is no shared fallback identity to silently use.

stdio transport has no per-request channel (no URL, no headers) to carry a caller's own identity, so it falls back to a single, server-wide OPENWEBUI_API_KEY instead. That setting is only read on stdio - it is never consulted on streamable-http or SSE, so it can't leak into another caller's request there. Without it set, every ask and list_models call made over stdio fails:

OPENWEBUI_BASE_URL=http://localhost:8080
OPENWEBUI_API_KEY=sk-...  # stdio only; ignored on streamable-http/SSE

TLS to Open WebUI

If Open WebUI is served over https with a certificate the process does not trust (self-signed, private/Traefik CA, or a MITM proxy CA), the SDK raises CERTIFICATE_VERIFY_FAILED. Fix by trusting the right CA, never by silently disabling checks unless you must:

OPENWEBUI_CA_BUNDLE=/path/to/ca.pem     # trust a specific PEM CA (covers JSON routes + Socket.IO tool loop)
OPENWEBUI_SSL_VERIFY=false              # skip verification (JSON routes only; not recommended)

The CA bundle path is applied as SSL_CERT_FILE, so all Python TLS callers (urllib and aiohttp) pick it up. OPENWEBUI_SSL_VERIFY=false only relaxes the urllib (JSON) routes; the Socket.IO tool loop still verifies, so prefer the CA bundle for self-signed servers

Install

Run straight from PyPI, no local checkout needed:

uvx openwebui-mcp --help

Or install it as a tool so the openwebui-mcp command is always available:

uv tool install openwebui-mcp
openwebui-mcp --help

Requires Python 3.11+

Cloning the repo is only needed for development: uv sync (creates .venv-docker) then uv run openwebui-mcp --help

Configure

Copy .env.example to .env or export the variables. Precedence is the first defined env var in each alias list

Setting

Env vars (first wins)

Default

Open WebUI URL

OPENWEBUI_BASE_URL, OPENWEBUI_URL, OWUI_URL

required

Open WebUI API key (stdio only, see Authentication)

OPENWEBUI_API_KEY, OWUI_API_KEY

none

Default model for ask

OPENWEBUI_DEFAULT_MODEL, OWUI_DEFAULT_MODEL

none

Enforce default model

OPENWEBUI_ENFORCE_DEFAULT_MODEL, OWUI_ENFORCE_DEFAULT_MODEL

false

ask tool description

OPENWEBUI_ASK_DESCRIPTION, OWUI_ASK_DESCRIPTION

built-in docstring

Server instructions

OPENWEBUI_INSTRUCTIONS, OWUI_INSTRUCTIONS

none

Transport

OPENWEBUI_MCP_TRANSPORT

stdio

Chat timeout ms

OWUI_TIMEOUT_MS

120000

Open WebUI CA bundle

OPENWEBUI_CA_BUNDLE, OWUI_CA_BUNDLE

none

Skip TLS verify

OPENWEBUI_SSL_VERIFY, OWUI_SSL_VERIFY

true

Run

uv run openwebui-mcp                      # stdio (default) - needs OPENWEBUI_API_KEY, see Authentication
uv run openwebui-mcp --transport sse      # SSE over HTTP
uv run openwebui-mcp --transport streamable-http --host 0.0.0.0 --port 8000

Development

uv run pytest
uv run pyright src tests

Layout

  • src/openwebui_mcp/server.py - FastMCP server, the two tools, TLS apply, per-request Open WebUI identity resolution

  • src/openwebui_mcp/config.py - env-driven settings

  • src/openwebui_mcp/__main__.py - CLI entry point

  • skills/owui-proactive-ask/ - agent skill that forces proactive use of ask

  • tests/ - config + server + TLS unit tests, incl. a protocol-level call_tool round trip

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A dual-transport MCP server that exposes your API as tools to LLM clients, supporting both stdio transport for local clients like Claude Desktop and HTTP/SSE transport for remote clients like OpenAI's Responses API.
    -
  • A
    license
    B
    quality
    D
    maintenance
    A minimal local MCP server that wraps any Claude Messages API-compatible upstream into a unified ask_model tool. It enables MCP clients to interact with these models through a standard tool interface using stdio transport.
    1
    8
    MIT