feat: experimental mcp support

This commit is contained in:
Timothy Jaeryang Baek
2025-09-23 02:03:26 -04:00
parent aeb5288a3c
commit 777e81f7a8
10 changed files with 417 additions and 105 deletions
+54 -8
View File
@@ -1,3 +1,4 @@
from cmath import log
from fastapi import APIRouter, Depends, Request, HTTPException
from pydantic import BaseModel, ConfigDict
@@ -12,7 +13,7 @@ from open_webui.utils.tools import (
get_tool_server_url,
set_tool_servers,
)
from open_webui.utils.mcp.client import MCPClient
router = APIRouter()
@@ -87,6 +88,7 @@ async def set_connections_config(
class ToolServerConnection(BaseModel):
url: str
path: str
type: Optional[str] = "openapi" # openapi, mcp
auth_type: Optional[str]
key: Optional[str]
config: Optional[dict]
@@ -129,15 +131,59 @@ async def verify_tool_servers_config(
Verify the connection to the tool server.
"""
try:
if form_data.type == "mcp":
try:
async with MCPClient() as client:
auth = None
headers = None
token = None
if form_data.auth_type == "bearer":
token = form_data.key
elif form_data.auth_type == "session":
token = request.state.token.credentials
token = None
if form_data.auth_type == "bearer":
token = form_data.key
elif form_data.auth_type == "session":
token = request.state.token.credentials
elif form_data.auth_type == "system_oauth":
try:
if request.cookies.get("oauth_session_id", None):
token = await request.app.state.oauth_manager.get_oauth_token(
user.id,
request.cookies.get("oauth_session_id", None),
)
except Exception as e:
pass
url = get_tool_server_url(form_data.url, form_data.path)
return await get_tool_server_data(token, url)
if token:
headers = {"Authorization": f"Bearer {token}"}
await client.connect(form_data.url, auth=auth, headers=headers)
specs = await client.list_tool_specs()
return {
"status": True,
"specs": specs,
}
except Exception as e:
raise HTTPException(
status_code=400,
detail=f"Failed to create MCP client: {str(e)}",
)
else: # openapi
token = None
if form_data.auth_type == "bearer":
token = form_data.key
elif form_data.auth_type == "session":
token = request.state.token.credentials
elif form_data.auth_type == "system_oauth":
try:
if request.cookies.get("oauth_session_id", None):
token = await request.app.state.oauth_manager.get_oauth_token(
user.id,
request.cookies.get("oauth_session_id", None),
)
except Exception as e:
pass
url = get_tool_server_url(form_data.url, form_data.path)
return await get_tool_server_data(token, url)
except Exception as e:
raise HTTPException(
status_code=400,
+24
View File
@@ -43,6 +43,7 @@ router = APIRouter()
async def get_tools(request: Request, user=Depends(get_verified_user)):
tools = Tools.get_tools()
# OpenAPI Tool Servers
for server in await get_tool_servers(request):
tools.append(
ToolUserResponse(
@@ -68,6 +69,29 @@ async def get_tools(request: Request, user=Depends(get_verified_user)):
)
)
# MCP Tool Servers
for server in request.app.state.config.TOOL_SERVER_CONNECTIONS:
if server.get("type", "openapi") == "mcp":
tools.append(
ToolUserResponse(
**{
"id": f"server:mcp:{server.get('info', {}).get('id')}",
"user_id": f"server:mcp:{server.get('info', {}).get('id')}",
"name": server.get("info", {}).get("name", "MCP Tool Server"),
"meta": {
"description": server.get("info", {}).get(
"description", ""
),
},
"access_control": server.get("config", {}).get(
"access_control", None
),
"updated_at": int(time.time()),
"created_at": int(time.time()),
}
)
)
if user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL:
# Admin can see all tools
return tools