Skip to content

Commit 945d3ff

Browse files
committed
clean up v2/mcp
1 parent 386fa99 commit 945d3ff

File tree

1 file changed

+0
-185
lines changed
  • src/backend/base/langflow/api/v2

1 file changed

+0
-185
lines changed

src/backend/base/langflow/api/v2/mcp.py

Lines changed: 0 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
import json
33
from io import BytesIO
44
from typing import Annotated
5-
from urllib.parse import urlparse
6-
from uuid import UUID
75

86
from fastapi import APIRouter, Depends, HTTPException, UploadFile
97
from lfx.base.agents.utils import safe_cache_get, safe_cache_set
@@ -20,9 +18,6 @@
2018
upload_user_file,
2119
)
2220
from langflow.logging import logger
23-
from langflow.services.database.models import Folder
24-
from langflow.services.database.models.api_key.crud import create_api_key
25-
from langflow.services.database.models.api_key.model import ApiKeyCreate
2621
from langflow.services.deps import get_settings_service, get_shared_component_cache_service, get_storage_service
2722
from langflow.services.settings.service import SettingsService
2823
from langflow.services.storage.service import StorageService
@@ -112,35 +107,6 @@ async def get_server_list(
112107
except json.JSONDecodeError:
113108
raise HTTPException(status_code=500, detail="Invalid server configuration file format.") from None
114109

115-
servers_updated = False
116-
created_api_key = False
117-
mcp_servers = servers.get("mcpServers", {})
118-
119-
for server_name, server_config in list(mcp_servers.items()):
120-
updated_config, config_changed, created_key = await _ensure_mcp_server_config(
121-
server_name=server_name,
122-
server_config=server_config,
123-
current_user=current_user,
124-
session=session,
125-
settings_service=settings_service,
126-
)
127-
if config_changed:
128-
servers_updated = True
129-
created_api_key = created_api_key or created_key
130-
mcp_servers[server_name] = updated_config
131-
132-
if servers_updated:
133-
servers["mcpServers"] = mcp_servers
134-
if created_api_key:
135-
await session.commit()
136-
await upload_server_config(
137-
servers,
138-
current_user,
139-
session,
140-
storage_service=storage_service,
141-
settings_service=settings_service,
142-
)
143-
144110
return servers
145111

146112

@@ -309,157 +275,6 @@ async def update_server(
309275
)
310276

311277

312-
def _extract_project_id_from_url(url: str) -> UUID | None:
313-
"""Return project UUID from a Langflow MCP URL if present."""
314-
try:
315-
parsed = urlparse(url)
316-
except ValueError:
317-
return None
318-
319-
path_parts = [part for part in parsed.path.split("/") if part]
320-
for idx, part in enumerate(path_parts):
321-
if part == "project" and idx + 1 < len(path_parts):
322-
candidate = path_parts[idx + 1]
323-
try:
324-
return UUID(candidate)
325-
except (ValueError, TypeError):
326-
return None
327-
return None
328-
329-
330-
async def _ensure_mcp_server_config(
331-
*,
332-
server_name: str,
333-
server_config: dict,
334-
current_user: CurrentActiveUser,
335-
session: DbSession,
336-
settings_service: SettingsService,
337-
) -> tuple[dict, bool, bool]:
338-
"""Normalize stored MCP server configs and ensure auth headers when required."""
339-
args = server_config.get("args")
340-
if not isinstance(args, list) or not args:
341-
return server_config, False, False
342-
343-
command = server_config.get("command")
344-
if command != "uvx":
345-
return server_config, False, False
346-
347-
if "mcp-proxy" not in args:
348-
return server_config, False, False
349-
350-
url_arg = next((arg for arg in reversed(args) if isinstance(arg, str) and arg.startswith("http")), None)
351-
if not url_arg:
352-
return server_config, False, False
353-
354-
project_id = _extract_project_id_from_url(url_arg)
355-
if project_id is None:
356-
return server_config, False, False
357-
358-
project: Folder | None = await session.get(Folder, project_id)
359-
if project is None:
360-
return server_config, False, False
361-
362-
generated_api_key = False
363-
should_generate_api_key = False
364-
365-
if settings_service.settings.mcp_composer_enabled:
366-
if project.auth_settings and project.auth_settings.get("auth_type") == "apikey":
367-
should_generate_api_key = True
368-
elif project.auth_settings:
369-
if project.auth_settings.get("auth_type") == "apikey":
370-
should_generate_api_key = True
371-
elif not settings_service.auth_settings.AUTO_LOGIN:
372-
should_generate_api_key = True
373-
374-
if settings_service.auth_settings.AUTO_LOGIN and not settings_service.auth_settings.SUPERUSER:
375-
should_generate_api_key = True
376-
377-
existing_header_tokens: list[str] | None = None
378-
preserved_args: list[str] = []
379-
uses_streamable = False
380-
381-
start_index = 1 if args[0] == "mcp-proxy" else 0
382-
if start_index == 0:
383-
preserved_args.append(args[0])
384-
385-
idx = start_index
386-
while idx < len(args):
387-
arg_item = args[idx]
388-
if arg_item == "--transport":
389-
uses_streamable = True
390-
idx += 2
391-
continue
392-
if arg_item == "--headers":
393-
existing_header_tokens = args[idx : idx + 3]
394-
idx += 3
395-
continue
396-
if isinstance(arg_item, str) and arg_item.startswith("http"):
397-
idx += 1
398-
continue
399-
preserved_args.append(arg_item)
400-
idx += 1
401-
402-
if isinstance(url_arg, str) and not url_arg.endswith("/sse"):
403-
uses_streamable = True
404-
405-
if not uses_streamable:
406-
if existing_header_tokens is None and should_generate_api_key:
407-
api_key_name = f"MCP Server {project.name}"
408-
new_api_key = await create_api_key(session, ApiKeyCreate(name=api_key_name), current_user.id)
409-
header_tokens = ["--headers", "x-api-key", new_api_key.api_key]
410-
generated_api_key = True
411-
412-
url_index = len(args) - 1
413-
for idx_arg in range(len(args) - 1, -1, -1):
414-
if args[idx_arg] == url_arg:
415-
url_index = idx_arg
416-
break
417-
418-
final_args = list(args)
419-
final_args[url_index:url_index] = header_tokens
420-
server_config["args"] = final_args
421-
await logger.adebug(
422-
"Added authentication headers for MCP server '%s' (project %s) while preserving SSE transport.",
423-
server_name,
424-
project_id,
425-
)
426-
return server_config, True, generated_api_key
427-
428-
return server_config, False, generated_api_key
429-
430-
streamable_http_url = url_arg.removesuffix("/sse")
431-
if not streamable_http_url.endswith("/streamable"):
432-
streamable_http_url = streamable_http_url.rstrip("/") + "/streamable"
433-
final_args: list[str] = ["mcp-proxy", "--transport", "streamablehttp"]
434-
435-
if preserved_args:
436-
final_args.extend(preserved_args)
437-
438-
header_tokens = existing_header_tokens
439-
if header_tokens is None and should_generate_api_key:
440-
api_key_name = f"MCP Server {project.name}"
441-
new_api_key = await create_api_key(session, ApiKeyCreate(name=api_key_name), current_user.id)
442-
header_tokens = ["--headers", "x-api-key", new_api_key.api_key]
443-
generated_api_key = True
444-
445-
if header_tokens:
446-
final_args.extend(header_tokens)
447-
448-
final_args.append(streamable_http_url)
449-
450-
config_updated = final_args != args
451-
452-
if config_updated:
453-
server_config["args"] = final_args
454-
await logger.adebug(
455-
"Normalized MCP server '%s' configuration for project %s (streamable HTTP + auth header).",
456-
server_name,
457-
project_id,
458-
)
459-
460-
return server_config, config_updated, generated_api_key
461-
462-
463278
@router.post("/servers/{server_name}")
464279
async def add_server(
465280
server_name: str,

0 commit comments

Comments
 (0)