[PR #20914] [CLOSED] fix(startup): auto-initialize tool servers from TOOL_SERVER_CONNECTIONS env var #64685

Closed
opened 2026-05-06 10:19:55 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/20914
Author: @SpootyMcSpoot
Created: 1/24/2026
Status: Closed

Base: devHead: fix/tool-server-connections-auto-init


📝 Commits (10+)

📊 Changes

1 file changed (+30 additions, -0 deletions)

View changed files

📝 backend/open_webui/main.py (+30 -0)

📄 Description

Pull Request Checklist

Before submitting, make sure you've checked the following:

  • Target branch: Verify that the pull request targets the dev branch.
  • Description: Provide a concise description of the changes made in this pull request down below.
  • Changelog: Ensure a changelog entry following the format of Keep a Changelog is added at the bottom of the PR description.
  • Documentation: No documentation update required - uses existing TOOL_SERVER_CONNECTIONS env var.
  • Dependencies: No new dependencies added.
  • Testing: Comprehensive manual and automated testing performed (see Testing section below).
  • Agentic AI Code: This PR has gone through manual review and extensive manual testing in Kubernetes environment.
  • Code review: Self-review completed, follows existing code patterns in lifespan().
  • Title Prefix: fix

Changelog Entry

Description

Fix the issue where TOOL_SERVER_CONNECTIONS environment variable is set but tool servers are not actually initialized until the user manually visits the Admin Panel and clicks Save.

Problem: TOOL_SERVER_CONNECTIONS is a PersistentConfig that only pre-populates the Admin Panel settings. The tools don't become available until set_tool_servers() is called, which currently only happens when a user manually saves the config.

Solution: Call set_tool_servers() during application startup (in the lifespan() function) when TOOL_SERVER_CONNECTIONS has entries. This makes tools available immediately without requiring manual intervention.

Added

  • Startup initialization in lifespan() function to call set_tool_servers() when TOOL_SERVER_CONNECTIONS is configured
  • Import of set_tool_servers from open_webui.utils.tools

Changed

  • N/A

Deprecated

  • N/A

Removed

  • N/A

Fixed

  • Tool servers configured via TOOL_SERVER_CONNECTIONS environment variable now initialize automatically on startup without requiring manual Admin Panel save (Fixes #18140)

Security

  • N/A

Breaking Changes

  • N/A

Additional Information

Use Case: Users deploying Open-WebUI in Kubernetes/containerized environments want to pre-configure tool servers via environment variables for GitOps/IaC workflows. Currently this requires:

  1. Set TOOL_SERVER_CONNECTIONS env var
  2. Wait for pod to start
  3. Manually log into Admin Panel
  4. Navigate to External Tools
  5. Click Save (without changing anything)
  6. Tools finally become available

With this fix, steps 3-6 are eliminated - tools work immediately on startup.

Code Pattern: The implementation follows the exact same pattern used for ENABLE_BASE_MODELS_CACHE initialization at lines 628-647 in main.py, using a mock Request object.


Comprehensive Testing Documentation

Unit Tests (10/10 Passed)

Created standalone unit test suite (test_tool_server_startup_standalone.py) covering:

Test Name Description Result
initialization_called_when_connections_exist Verifies set_tool_servers() is called when TOOL_SERVER_CONNECTIONS has entries PASS
initialization_skipped_when_no_connections Verifies set_tool_servers() is NOT called when empty PASS
error_handling_on_initialization_failure Verifies errors are caught and logged, app continues PASS
multiple_tool_servers_count Verifies multiple servers are all counted PASS
tool_servers_populated_in_app_state Verifies TOOL_SERVERS populated in app.state PASS
openapi_server_config_format Validates OpenAPI server config format PASS
mcp_server_config_format Validates MCP server config format PASS
authenticated_server_config_format Validates bearer auth config format PASS
logging_message_format Validates log message format PASS
empty_list_vs_none_handling Verifies empty list and None both skip init PASS

Integration Testing in Kubernetes

Environment:

  • Kubernetes cluster (MicroK8s)
  • Open-WebUI deployed via Helm chart
  • MCPO (MCP-to-OpenAPI proxy) tool servers

Test Configuration:

env:
  - name: TOOL_SERVER_CONNECTIONS
    value: '[{"url":"http://mcpo-filesystem:8080/openapi.json","info":{"id":"filesystem","name":"Filesystem"},"type":"openapi","auth_type":"none"},{"url":"http://mcpo-fetch:8080/openapi.json","info":{"id":"fetch","name":"Fetch"},"type":"openapi","auth_type":"none"},{"url":"http://mcpo-memory:8080/openapi.json","info":{"id":"memory","name":"Memory"},"type":"openapi","auth_type":"none"},{"url":"http://mcpo-sequential-thinking:8080/openapi.json","info":{"id":"sequential-thinking","name":"Sequential Thinking"},"type":"openapi","auth_type":"none"},{"url":"http://mcpo-time:8080/openapi.json","info":{"id":"time","name":"Time"},"type":"openapi","auth_type":"none"}]'

Test Results:

  1. Startup Initialization Test

    • Method: Deployed pod and observed startup logs
    • Expected: Log message "Initializing N tool server(s) from TOOL_SERVER_CONNECTIONS..."
    • Actual:
      INFO | open_webui.main:lifespan:653 - Initializing 5 tool server(s) from TOOL_SERVER_CONNECTIONS...
      INFO | open_webui.main:lifespan:674 - Tool servers initialized successfully
      
    • Result: PASS
  2. Health Check Test

    • Method: curl http://localhost:8080/health
    • Expected: {"status":true}
    • Actual: {"status":true}
    • Result: PASS
  3. Pod Stability Test

    • Method: Observed pod status over 10+ minutes
    • Expected: Pod remains Running, no restarts
    • Actual: open-webui-xxx 1/1 Running 0 12m
    • Result: PASS
  4. Regression Test - Manual Save

    • Method: After startup, navigated to Admin Panel > External Tools and clicked Save
    • Expected: Manual save flow still works, tools remain available
    • Actual: Save completed without error, tools working
    • Result: PASS
  5. Empty Configuration Test

    • Method: Deployed without TOOL_SERVER_CONNECTIONS env var
    • Expected: No initialization log, app starts normally
    • Actual: No "Initializing" log, app started normally
    • Result: PASS
  6. Error Handling Test

    • Method: Configured unreachable tool server URL
    • Expected: Error logged, app continues to start
    • Actual: ERROR | Failed to initialize tool servers: ..., app continued
    • Result: PASS

Code Review Checklist

  • Import added at correct location (line 63, with other utils imports)
  • Follows existing code pattern (same as ENABLE_BASE_MODELS_CACHE init at lines 628-647)
  • Uses proper async/await
  • Includes error handling with try/except
  • Logs initialization start and success/failure
  • References issue number in comment
  • No security vulnerabilities introduced (uses internal mock request only)

Screenshots or Videos

Startup logs showing auto-initialization:

INFO     | open_webui.main:lifespan:605 - Installing external dependencies of functions and tools...
INFO     | open_webui.main:lifespan:653 - Initializing 5 tool server(s) from TOOL_SERVER_CONNECTIONS...
INFO     | open_webui.main:lifespan:674 - Tool servers initialized successfully

Health endpoint confirms service running:

$ curl http://localhost:8080/health
{"status":true}

Pod status (stable, no restarts):

NAME                        READY   STATUS    RESTARTS   AGE
open-webui-xxx              1/1     Running   0          12m

Unit test results:

======================================================================
Tool Server Startup Initialization Tests
======================================================================

Running tests...

  PASS: initialization_called_when_connections_exist
  PASS: initialization_skipped_when_no_connections
  PASS: error_handling_on_initialization_failure
  PASS: multiple_tool_servers_count
  PASS: tool_servers_populated_in_app_state
  PASS: openapi_server_config_format
  PASS: mcp_server_config_format
  PASS: authenticated_server_config_format
  PASS: logging_message_format
  PASS: empty_list_vs_none_handling

----------------------------------------------------------------------
Results: 10 passed, 0 failed
----------------------------------------------------------------------

All tests passed!

Testing Confirmation

  • I have personally tested ALL changes in this PR
  • How I tested:
    • Created and ran 10 unit tests (all passed)
    • Deployed to Kubernetes with 5 MCPO tool servers
    • Verified startup initialization logs
    • Verified health endpoint
    • Verified pod stability (no restarts)
    • Verified no regression in manual Admin Panel save flow
    • Tested error handling with unreachable server
    • Tested empty configuration (no env var set)
  • Verified no regressions - existing manual save flow in Admin Panel still works as expected

Contributor License Agreement

By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/20914 **Author:** [@SpootyMcSpoot](https://github.com/SpootyMcSpoot) **Created:** 1/24/2026 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `fix/tool-server-connections-auto-init` --- ### 📝 Commits (10+) - [`fe6783c`](https://github.com/open-webui/open-webui/commit/fe6783c16699911c7be17392596d579333fb110c) Merge pull request #19030 from open-webui/dev - [`fc05e0a`](https://github.com/open-webui/open-webui/commit/fc05e0a6c5d39da60b603b4d520f800d6e36f748) Merge pull request #19405 from open-webui/dev - [`e3faec6`](https://github.com/open-webui/open-webui/commit/e3faec62c58e3a83d89aa3df539feacefa125e0c) Merge pull request #19416 from open-webui/dev - [`9899293`](https://github.com/open-webui/open-webui/commit/9899293f050ad50ae12024cbebee7e018acd851e) Merge pull request #19448 from open-webui/dev - [`140605e`](https://github.com/open-webui/open-webui/commit/140605e660b8186a7d5c79fb3be6ffb147a2f498) Merge pull request #19462 from open-webui/dev - [`6f1486f`](https://github.com/open-webui/open-webui/commit/6f1486ffd0cb288d0e21f41845361924e0d742b3) Merge pull request #19466 from open-webui/dev - [`d95f533`](https://github.com/open-webui/open-webui/commit/d95f533214e3fe5beb5e41ec1f349940bc4c7043) Merge pull request #19729 from open-webui/dev - [`a727153`](https://github.com/open-webui/open-webui/commit/a7271532f8a38da46785afcaa7e65f9a45e7d753) 0.6.43 (#20093) - [`6adde20`](https://github.com/open-webui/open-webui/commit/6adde203cd292a9e3af9c64a2ae36b603fed096a) Merge pull request #20394 from open-webui/dev - [`f9b0534`](https://github.com/open-webui/open-webui/commit/f9b0534e0c442631d1cb7205169588b9b6204179) Merge pull request #20522 from open-webui/dev ### 📊 Changes **1 file changed** (+30 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/main.py` (+30 -0) </details> ### 📄 Description # Pull Request Checklist **Before submitting, make sure you've checked the following:** - [x] **Target branch:** Verify that the pull request targets the `dev` branch. - [x] **Description:** Provide a concise description of the changes made in this pull request down below. - [x] **Changelog:** Ensure a changelog entry following the format of [Keep a Changelog](https://keepachangelog.com/) is added at the bottom of the PR description. - [x] **Documentation:** No documentation update required - uses existing TOOL_SERVER_CONNECTIONS env var. - [x] **Dependencies:** No new dependencies added. - [x] **Testing:** Comprehensive manual and automated testing performed (see Testing section below). - [x] **Agentic AI Code:** This PR has gone through manual review and extensive manual testing in Kubernetes environment. - [x] **Code review:** Self-review completed, follows existing code patterns in lifespan(). - [x] **Title Prefix:** fix --- # Changelog Entry ### Description Fix the issue where `TOOL_SERVER_CONNECTIONS` environment variable is set but tool servers are not actually initialized until the user manually visits the Admin Panel and clicks Save. **Problem:** `TOOL_SERVER_CONNECTIONS` is a `PersistentConfig` that only pre-populates the Admin Panel settings. The tools don't become available until `set_tool_servers()` is called, which currently only happens when a user manually saves the config. **Solution:** Call `set_tool_servers()` during application startup (in the `lifespan()` function) when `TOOL_SERVER_CONNECTIONS` has entries. This makes tools available immediately without requiring manual intervention. ### Added - Startup initialization in `lifespan()` function to call `set_tool_servers()` when `TOOL_SERVER_CONNECTIONS` is configured - Import of `set_tool_servers` from `open_webui.utils.tools` ### Changed - N/A ### Deprecated - N/A ### Removed - N/A ### Fixed - Tool servers configured via `TOOL_SERVER_CONNECTIONS` environment variable now initialize automatically on startup without requiring manual Admin Panel save (Fixes #18140) ### Security - N/A ### Breaking Changes - N/A --- ### Additional Information **Use Case:** Users deploying Open-WebUI in Kubernetes/containerized environments want to pre-configure tool servers via environment variables for GitOps/IaC workflows. Currently this requires: 1. Set `TOOL_SERVER_CONNECTIONS` env var 2. Wait for pod to start 3. Manually log into Admin Panel 4. Navigate to External Tools 5. Click Save (without changing anything) 6. Tools finally become available With this fix, steps 3-6 are eliminated - tools work immediately on startup. **Code Pattern:** The implementation follows the exact same pattern used for `ENABLE_BASE_MODELS_CACHE` initialization at lines 628-647 in main.py, using a mock Request object. --- ## Comprehensive Testing Documentation ### Unit Tests (10/10 Passed) Created standalone unit test suite (`test_tool_server_startup_standalone.py`) covering: | Test Name | Description | Result | |-----------|-------------|--------| | `initialization_called_when_connections_exist` | Verifies `set_tool_servers()` is called when TOOL_SERVER_CONNECTIONS has entries | PASS | | `initialization_skipped_when_no_connections` | Verifies `set_tool_servers()` is NOT called when empty | PASS | | `error_handling_on_initialization_failure` | Verifies errors are caught and logged, app continues | PASS | | `multiple_tool_servers_count` | Verifies multiple servers are all counted | PASS | | `tool_servers_populated_in_app_state` | Verifies TOOL_SERVERS populated in app.state | PASS | | `openapi_server_config_format` | Validates OpenAPI server config format | PASS | | `mcp_server_config_format` | Validates MCP server config format | PASS | | `authenticated_server_config_format` | Validates bearer auth config format | PASS | | `logging_message_format` | Validates log message format | PASS | | `empty_list_vs_none_handling` | Verifies empty list and None both skip init | PASS | ### Integration Testing in Kubernetes **Environment:** - Kubernetes cluster (MicroK8s) - Open-WebUI deployed via Helm chart - MCPO (MCP-to-OpenAPI proxy) tool servers **Test Configuration:** ```yaml env: - name: TOOL_SERVER_CONNECTIONS value: '[{"url":"http://mcpo-filesystem:8080/openapi.json","info":{"id":"filesystem","name":"Filesystem"},"type":"openapi","auth_type":"none"},{"url":"http://mcpo-fetch:8080/openapi.json","info":{"id":"fetch","name":"Fetch"},"type":"openapi","auth_type":"none"},{"url":"http://mcpo-memory:8080/openapi.json","info":{"id":"memory","name":"Memory"},"type":"openapi","auth_type":"none"},{"url":"http://mcpo-sequential-thinking:8080/openapi.json","info":{"id":"sequential-thinking","name":"Sequential Thinking"},"type":"openapi","auth_type":"none"},{"url":"http://mcpo-time:8080/openapi.json","info":{"id":"time","name":"Time"},"type":"openapi","auth_type":"none"}]' ``` **Test Results:** 1. **Startup Initialization Test** - **Method:** Deployed pod and observed startup logs - **Expected:** Log message "Initializing N tool server(s) from TOOL_SERVER_CONNECTIONS..." - **Actual:** ``` INFO | open_webui.main:lifespan:653 - Initializing 5 tool server(s) from TOOL_SERVER_CONNECTIONS... INFO | open_webui.main:lifespan:674 - Tool servers initialized successfully ``` - **Result:** PASS 2. **Health Check Test** - **Method:** `curl http://localhost:8080/health` - **Expected:** `{"status":true}` - **Actual:** `{"status":true}` - **Result:** PASS 3. **Pod Stability Test** - **Method:** Observed pod status over 10+ minutes - **Expected:** Pod remains Running, no restarts - **Actual:** `open-webui-xxx 1/1 Running 0 12m` - **Result:** PASS 4. **Regression Test - Manual Save** - **Method:** After startup, navigated to Admin Panel > External Tools and clicked Save - **Expected:** Manual save flow still works, tools remain available - **Actual:** Save completed without error, tools working - **Result:** PASS 5. **Empty Configuration Test** - **Method:** Deployed without TOOL_SERVER_CONNECTIONS env var - **Expected:** No initialization log, app starts normally - **Actual:** No "Initializing" log, app started normally - **Result:** PASS 6. **Error Handling Test** - **Method:** Configured unreachable tool server URL - **Expected:** Error logged, app continues to start - **Actual:** `ERROR | Failed to initialize tool servers: ...`, app continued - **Result:** PASS ### Code Review Checklist - [x] Import added at correct location (line 63, with other utils imports) - [x] Follows existing code pattern (same as ENABLE_BASE_MODELS_CACHE init at lines 628-647) - [x] Uses proper async/await - [x] Includes error handling with try/except - [x] Logs initialization start and success/failure - [x] References issue number in comment - [x] No security vulnerabilities introduced (uses internal mock request only) --- ### Screenshots or Videos **Startup logs showing auto-initialization:** ``` INFO | open_webui.main:lifespan:605 - Installing external dependencies of functions and tools... INFO | open_webui.main:lifespan:653 - Initializing 5 tool server(s) from TOOL_SERVER_CONNECTIONS... INFO | open_webui.main:lifespan:674 - Tool servers initialized successfully ``` **Health endpoint confirms service running:** ``` $ curl http://localhost:8080/health {"status":true} ``` **Pod status (stable, no restarts):** ``` NAME READY STATUS RESTARTS AGE open-webui-xxx 1/1 Running 0 12m ``` **Unit test results:** ``` ====================================================================== Tool Server Startup Initialization Tests ====================================================================== Running tests... PASS: initialization_called_when_connections_exist PASS: initialization_skipped_when_no_connections PASS: error_handling_on_initialization_failure PASS: multiple_tool_servers_count PASS: tool_servers_populated_in_app_state PASS: openapi_server_config_format PASS: mcp_server_config_format PASS: authenticated_server_config_format PASS: logging_message_format PASS: empty_list_vs_none_handling ---------------------------------------------------------------------- Results: 10 passed, 0 failed ---------------------------------------------------------------------- All tests passed! ``` --- ### Testing Confirmation - [x] I have personally tested ALL changes in this PR - [x] **How I tested:** - Created and ran 10 unit tests (all passed) - Deployed to Kubernetes with 5 MCPO tool servers - Verified startup initialization logs - Verified health endpoint - Verified pod stability (no restarts) - Verified no regression in manual Admin Panel save flow - Tested error handling with unreachable server - Tested empty configuration (no env var set) - [x] Verified no regressions - existing manual save flow in Admin Panel still works as expected --- ### Contributor License Agreement By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-06 10:19:55 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#64685