From 3ef496609ca5a2d89b89e04a883364ff31d0d8c7 Mon Sep 17 00:00:00 2001 From: centdix <40307056+centdix@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:01:24 +0100 Subject: [PATCH] fix(mcp): use computed base_internal_url instead of static default (#7701) * fix(mcp): use computed base_internal_url instead of static default Pass the actual base_internal_url (computed from the runtime port) to the MCP backend instead of using the static BASE_INTERNAL_URL which defaults to http://localhost:8000. This fixes internal API calls when the server runs on a non-default port. Co-Authored-By: Claude Opus 4.5 * fix * remove BASE_INTERNAL_URL --------- Co-authored-by: Claude Opus 4.5 --- backend/windmill-api/src/lib.rs | 2 +- backend/windmill-api/src/mcp/core.rs | 12 ++++++------ backend/windmill-common/src/lib.rs | 2 -- backend/windmill-common/src/worker.rs | 9 +++++---- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/backend/windmill-api/src/lib.rs b/backend/windmill-api/src/lib.rs index f329bdcc3b..8a44ee8360 100644 --- a/backend/windmill-api/src/lib.rs +++ b/backend/windmill-api/src/lib.rs @@ -419,7 +419,7 @@ pub async fn run_server( if server_mode || mcp_mode { use mcp::add_www_authenticate_header; let (mcp_router, mcp_cancellation_token) = - setup_mcp_server(db.clone(), user_db).await?; + setup_mcp_server(db.clone(), user_db, _base_internal_url.clone()).await?; // Apply middleware: auth check inside WWW-Authenticate wrapper so 401s get the header let mcp_router = mcp_router .route_layer(from_extractor::()) diff --git a/backend/windmill-api/src/mcp/core.rs b/backend/windmill-api/src/mcp/core.rs index be5bd92f86..570b4c0de7 100644 --- a/backend/windmill-api/src/mcp/core.rs +++ b/backend/windmill-api/src/mcp/core.rs @@ -75,11 +75,12 @@ impl McpAuth for ApiAuthed { pub struct WindmillBackend { pub db: DB, pub user_db: UserDB, + pub base_internal_url: String, } impl WindmillBackend { - pub fn new(db: DB, user_db: UserDB) -> Self { - Self { db, user_db } + pub fn new(db: DB, user_db: UserDB, base_internal_url: String) -> Self { + Self { db, user_db, base_internal_url } } } @@ -355,9 +356,7 @@ impl McpBackend for WindmillBackend { let query_string = build_query_string(args_map, &endpoint_tool.query_params_schema); let full_url = format!( "{}/api{}{}", - windmill_common::BASE_INTERNAL_URL.as_str(), - path_template, - query_string + self.base_internal_url, path_template, query_string ); // Prepare request body @@ -462,11 +461,12 @@ pub async fn add_www_authenticate_header( pub async fn setup_mcp_server( db: DB, user_db: UserDB, + base_internal_url: String, ) -> anyhow::Result<(Router, CancellationToken)> { let cancellation_token = CancellationToken::new(); let session_manager = Arc::new(LocalSessionManager::default()); - let backend = WindmillBackend::new(db, user_db); + let backend = WindmillBackend::new(db, user_db, base_internal_url); let runner = Runner::new(backend); let service_config = StreamableHttpServerConfig { diff --git a/backend/windmill-common/src/lib.rs b/backend/windmill-common/src/lib.rs index e107fa564d..072e9e985c 100644 --- a/backend/windmill-common/src/lib.rs +++ b/backend/windmill-common/src/lib.rs @@ -152,8 +152,6 @@ lazy_static::lazy_static! { pub static ref BASE_URL: Arc> = Arc::new(RwLock::new("".to_string())); pub static ref IS_READY: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); - - pub static ref BASE_INTERNAL_URL: String = std::env::var("BASE_INTERNAL_URL").unwrap_or("http://localhost:8000".to_string()); pub static ref HUB_BASE_URL: Arc> = Arc::new(RwLock::new(DEFAULT_HUB_BASE_URL.to_string())); diff --git a/backend/windmill-common/src/worker.rs b/backend/windmill-common/src/worker.rs index cf7660051d..73e6c7b8c7 100644 --- a/backend/windmill-common/src/worker.rs +++ b/backend/windmill-common/src/worker.rs @@ -35,7 +35,7 @@ use crate::{ indexer::TantivyIndexerSettings, server::Smtp, utils::{merge_nested_raw_values_to_array, merge_raw_values_to_array}, - KillpillSender, BASE_INTERNAL_URL, DB, + KillpillSender, DB, }; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)] @@ -274,6 +274,8 @@ pub const ROOT_CACHE_NOMOUNT_DIR: &str = concatcp!(TMP_DIR, "/cache_nomount/"); pub static MIN_VERSION_IS_LATEST: AtomicBool = AtomicBool::new(false); +const DEFAULT_BASE_INTERNAL_URL: &str = "http://localhost:8000"; + #[derive(Clone)] pub struct HttpClient { pub client: ClientWithMiddleware, @@ -298,7 +300,7 @@ impl HttpClient { let base_url = self .base_internal_url .clone() - .unwrap_or(BASE_INTERNAL_URL.clone().to_owned()); + .unwrap_or(DEFAULT_BASE_INTERNAL_URL.to_owned()); let response_builder = self.client.post(format!("{}{}", base_url, url)).json(body); @@ -327,7 +329,7 @@ impl HttpClient { let base_url = self .base_internal_url .clone() - .unwrap_or(BASE_INTERNAL_URL.clone().to_owned()); + .unwrap_or(DEFAULT_BASE_INTERNAL_URL.to_owned()); let response = self .client @@ -1226,7 +1228,6 @@ pub fn get_windmill_memory_usage() -> Option { } } - #[derive(Serialize, Deserialize)] pub enum PingType { Initial,