Open WebUI MCP Troubleshooting Guide: Fix Tool Discovery, OAuth, MCPO, and Streaming Errors
Most Open WebUI MCP troubleshooting cases depend on these root causes:
- Misconfigured connection type.
- Rotating WEBUI_SECRET_KEY.
- MCPO container that loses its config on restart.
- Reverse proxy buffering SSE streams.
- Container DNS failing to resolve a bridge service.
This guide walks through every failure mode, so you can tell whether the problem is native MCP, the MCPO bridge, or your reverse proxy.
Table of Contents
MCP Integration Paths: Native Support vs MCPO Proxy
Open WebUI added native MCP support in version 0.6.31, so it can talk directly to any MCP server that offers a Streamable HTTP endpoint; no extra proxy needed. Older versions, or MCP servers that only run over stdio, still need mcpo, a lightweight proxy that wraps the MCP server and turns it into a normal OpenAPI/REST service Open WebUI can read through its OpenAPI Tool Server connector.
If you haven’t set this up yet, this Open WebUI MCP setup guide walks through both paths step by step, including which one to pick for your setup.
Every Open WebUI MCP troubleshooting case should start by figuring out which path you’re on, since the fixes are different. Native MCP problems sit in the connection type, OAuth, or transport settings under Admin Settings, while MCPO problems come from the proxy process itself, its Docker container, or the config file it loads at startup.
| Symptom | Native MCP (Streamable HTTP) | MCPO Bridge (OpenAPI) |
|---|---|---|
| Tool doesn’t appear | Wrong “Type” field, not set to MCP/Streamable HTTP | mcpo container not running, or wrong port mapping |
| Auth fails | OAuth 2.1 flow broken, redirect URI mismatch | API key blank or wrong header name |
| Config resets on restart | N/A, config stored in Open WebUI DB | config.json not mounted as a volume |
| Timeout on long calls | Tool call spins, no execution timeout on function side but UI gives up ~60s | mcpo returns HTTP 200 after Open WebUI already gave up |
Next, work through the checks below for your specific path; start with tool discovery if your server isn’t showing up, or jump to OAuth and secret key checks if authentication is the problem.
Remote MCP Servers Not Appearing in Tool List
This is the most common Open WebUI MCP troubleshooting complaint, and it depends on the connection Type. When adding a server under Admin Settings > External Tools, you must select “MCP Streamable HTTP” rather than the default OpenAPI type, or the server will save but never populate tools.
Checks to run:
- Confirm your Open WebUI version is 0.6.31 or newer; native MCP does not exist on older builds.
- Open Admin Panel > Settings > Integrations > External Tool Servers and verify Type reads MCP, not OpenAPI, for the entry.
- Hard-refresh the browser (Ctrl+F5) after adding or editing a connection; the UI sometimes caches a stale tool list.
- Check that the model you’re chatting with has “Function Calling” set to Native in Advanced Params; tools registered but not enabled per-model will never surface.
- Tail the container logs for discovery errors:
docker logs -f open-webui | grep -i mcp
If the server still doesn’t appear after these steps, delete the connection entirely, refresh, and re-add it rather than editing the broken entry.
Failed OAuth Callbacks and Redirect Loops
OAuth-protected MCP servers introduce a different category of Open WebUI MCP troubleshooting work because the failure surface is the browser redirect chain rather than the tool schema. Most OAuth loops, 401s, or unresponsive consent screens come from an environment variable that’s missing, misnamed, or pointing at the wrong URL.
Work through this checklist in order:
1. In Admin Settings > General, confirm the WebUI URL field matches your externally reachable domain, since OAuth providers validate the redirect URI with this value.
2. Open browser DevTools > Application > Cookies and look for an oauth_session_id cookie or oauth_id_token after attempting login; a missing cookie means the callback never completed.
3. Verify WEBUI_SECRET_KEY is stable across restarts; OAuth tokens are encrypted with it, and a rotating key causes silent decryption failures that look like “auth succeeded but tool still shows disconnected”.
4. If you’re behind Nginx, Caddy, or Traefik, confirm the proxy forwards the Host and X-Forwarded-Proto headers unmodified; OAuth providers reject callbacks if the scheme in the redirect doesn’t match what they issued.
5. Retest with the proxy temporarily bypassed (direct container port) to isolate whether the reverse proxy or the OAuth provider config is at fault.
Missing or Rotating WEBUI_SECRET_KEY
Most Open WebUI MCP troubleshooting cases that look like OAuth broke or users keep getting logged out are secret-key issues. Open WebUI generates a random WEBUI_SECRET_KEY on first boot and stores it at /app/backend/.webui_secret_key inside the container; if that file isn’t on a persistent volume, every restart creates a new key, invalidating all session JWTs and any encrypted OAuth tokens for MCP tools.
Fix it permanently:
# 1. Stop the stack
docker compose down
# 2. Generate a stable 32-byte key
openssl rand -hex 32
# copy the output, e.g. a3f8c2e1d9b4...
# 3. Add it to docker-compose.yml
# environment:
# - WEBUI_SECRET_KEY=<paste-key-here>
# 4. Bring it back up and verify
docker compose up -d
docker compose exec open-webui env | grep WEBUI_SECRET_KEY
Quick checks to fix it:
- 403 Forbidden on
/auth/signin: key changed between restarts; set a permanent one. - Logs show “Signature verification failed“: container was recreated without the persisted key.
- Logs show “Loading WEBUI_SECRET_KEY from file“: the env var isn’t set; the app fell back to file storage; confirm that the file’s volume is actually persisted.
- Multi-replica deployments must share the same key across every instance, or tokens signed by one node get rejected by another.
Invalid Schema Errors on Tool Discovery
When Open WebUI can reach an MCP or MCPO endpoint but rejects the tools it returns, the cause is a malformed OpenAPI/JSON schema on the tool definitions. This kind of Open WebUI MCP troubleshooting requires reading raw output rather than the UI.
1. Query the MCPO endpoint directly:
curl http://localhost:8000/openapi.json | jq .
Confirm it’s valid JSON with proper parameters and required fields for every tool.
2. For native MCP servers, make sure each tool’s inputSchema uses standard JSON Schema types. Older or custom-built MCP servers sometimes use non-standard formats, and Open WebUI can quietly reject those tools without showing an error.
3. Check for duplicate tool names across your connected servers. If two servers use the same tool ID, Open WebUI can mix them up and hide one server’s tools completely.
4. If a single tool has a broken schema, it can block the entire server’s tool list from loading; isolate it by disabling tools in the MCP server config.
MCPO Persistence Mistakes
MCPO doesn’t store anything itself; it just reads its tool list from a config.json file when it starts up. This means persistence is a Docker volume issue, not a bug in the app. The most common mistake in Open WebUI MCP troubleshooting is running MCPO without mounting that file, so every time the container restarts, your custom tools disappear:
# Correct: config.json lives on a named volume, survives restarts
docker run -d -p 8000:8000 \
-v mcpo_config:/app/config \
--name mcpo --restart always \
ghcr.io/open-webui/mcpo:main \
mcpo --config /app/config/config.json
# Copy your actual config into the volume once
docker cp ./config.json <container_id>:/app/config/config.json
Other persistence issues to check:
- Rebuilding the mcpo image but forgetting to copy
config.jsonback into the new container’s volume. - Editing
config.jsonon the host but not restarting mcpo; it only loads the file at startup, not when you save changes. - Running mcpo quickly with
uvxfor testing (no--restartalways, no volume), then expecting it to keep running after a server reboot. - Pointing two different mcpo instances at the same volume; they can silently overwrite each other’s tool definitions.
SSE and Streamable HTTP Proxy Errors
If tools load fine but chat replies freeze mid-response, show broken formatting, or tool calls hang forever behind Nginx, Caddy, or Traefik, your reverse proxy is likely buffering the stream. This is one of the most misdiagnosed problems in Open WebUI MCP troubleshooting, since it looks like an LLM or MCP issue when it’s really just a proxy setting.
Nginx buffers responses by default, which splits streamed data randomly and can break markdown formatting like bold text or corrupt tool responses mid-stream.
Here’s the Nginx config you need to fix it:
location / {
proxy_pass http://open-webui:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# CRITICAL: disable buffering for SSE/Streamable HTTP
proxy_buffering off;
proxy_request_buffering off;
proxy_cache off;
tcp_nodelay on;
add_header X-Accel-Buffering "no" always;
}
Caddy and Traefik users should confirm flush/streaming settings are enabled on their reverse proxy, since both can buffer SSE by default depending on version. Test the fix by tailing the response headers with:
curl -N -v https://yourdomain.com/api/chat
Confirm data arrives incrementally rather than all at once.
Container DNS and Host Resolution Failures
Another common issue in Open WebUI MCP troubleshooting is Docker networking. Open WebUI, mcpo, and any local MCP server must be able to resolve each other by name. Two common issues cause this:
- On Docker Desktop (Mac/Windows),
host.docker.internalresolves automatically; on Linux, it does not unless you add it. - When Open WebUI and mcpo run in the same Docker Compose network, use the service name rather than localhost, since each container has its own network namespace.
Fix Linux DNS resolution by adding the host gateway mapping:
docker run -d -p 3000:8080 \
--add-host=host.docker.internal:host-gateway \
-v open-webui:/app/backend/data \
--name open-webui --restart always \
ghcr.io/open-webui/open-webui:main
Then verify connectivity from inside the container before touching the UI:
docker exec open-webui curl --fail --silent --show-error http://mcpo:8000/openapi.json
docker exec open-webui curl --fail --silent --show-error http://host.docker.internal:8000/openapi.json
If both curl commands fail, the problem is Docker networking, not Open WebUI or mcpo configuration. Check that both containers share a Docker network with:
docker network inspect
Fix Timeouts on Slow MCP Tool Calls
Open WebUI itself doesn’t cut off tool or pipe execution on the backend, but the chat UI and its /api/completions call can act like they’ve given up after about 60 seconds, even though mcpo is still working in the background.
This is a known gap in current versions, and it leads to a confusing Open WebUI MCP troubleshooting situation. MCPO logs show a normal successful response, but the chat already marked the tool call as failed.
A few things to fix it include:
If your MCP server needs user interaction in the browser, know that it waits 300 seconds by default before timing out, and you can change this with the WEBSOCKET_EVENT_CALLER_TIMEOUT setting.
For tools that take a long time through mcpo, break the task into smaller steps if the tool supports it, since there’s currently no way to extend the timeout on the completions call itself.
While a slow call is running, watch the logs with docker logs -f mcpo. If the request shows up but the response comes back only after 60 seconds, the timeout is on Open WebUI’s side, not the MCP server’s.
This is a known bug, not a config mistake, so keep an eye on the related GitHub issue if it’s affecting your production setup.
Log Checks for Open WebUI MCP Troubleshooting
Before trying any single fix above, run through these quick checks first whenever you’re starting a new Open WebUI MCP troubleshooting case:
For connection, auth, and key errors:
docker logs -f open-webui | grep -i -E "mcp|oauth|secret"
For proxy-level request/response and startup config errors:
docker logs -f mcpo
Open your browser’s DevTools, go to the Network tab, and filter for /api/ and /mcp/ calls to see the real HTTP status codes instead of the generic error message in the UI.
Confirm the key is set and stable:
docker compose exec open-webui env | grep WEBUI_SECRET_KEY
Run curl -N on your chat endpoint to check that a proxy in between isn’t buffering the stream.
Deploy on PerLod for Stable MCP Hosting
Because native MCP and MCPO both depend on stable networking, persistent storage, and enough memory to keep multiple tool-server containers running concurrently, a properly sized VPS or GPU-backed host removes an entire category of Open WebUI MCP troubleshooting work before it starts. You can deploy Open WebUI and its MCP bridges on PerLod’s AI hosting infrastructure with dedicated resources, predictable container networking, and enough RAM space to avoid the DNS and timeout issues covered above.
If errors persist after following this guide, refer to this Open WebUI error-fixing tutorial for issues outside the MCP scope, such as model connection and database errors.
Conclusion
Every Open WebUI MCP troubleshooting case gets easier once you split native MCP issues from MCPO bridge issues. Proxy buffering and Docker DNS problems cause most of the confusing failures, so check proxy_buffering off and your host.docker.internal setup early to save time. Once you have a stable WEBUI_SECRET_KEY, a persisted mcpo config volume, and a properly set up reverse proxy, most MCP integrations run smoothly.
We hope you enjoy this guide.
FAQs
Why don’t my remote MCP servers show up in Open WebUI?
The connection Type is set to OpenAPI instead of MCP Streamable HTTP; you must fix the Type field and refresh.
Why do my OAuth logins keep failing for MCP tools?
The WebUI URL setting doesn’t match your real domain, or WEBUI_SECRET_KEY is rotating between restarts and breaking token decryption.
How do I fix host.docker.internal not resolving on Linux?
Add --add-host=host.docker.internal:host-gateway to your docker run command or in the Compose file.