Add front end logic for MCP connectors

This commit is contained in:
Manoj Aggarwal 2026-01-13 21:10:03 -08:00
parent 792548b379
commit c78ea98a68
8 changed files with 71 additions and 65 deletions

View file

@ -141,40 +141,46 @@ async def load_mcp_tools(
tools: list[StructuredTool] = []
for connector in result.scalars():
try:
# Extract server config
# Extract server configs array
config = connector.config or {}
server_config = config.get("server_config", {})
command = server_config.get("command")
args = server_config.get("args", [])
env = server_config.get("env", {})
if not command:
logger.warning(f"MCP connector {connector.id} missing command, skipping")
server_configs = config.get("server_configs", [])
if not server_configs:
logger.warning(f"MCP connector {connector.id} missing server_configs, skipping")
continue
# Create MCP client
mcp_client = MCPClient(command, args, env)
# Process each server config
for server_config in server_configs:
command = server_config.get("command")
args = server_config.get("args", [])
env = server_config.get("env", {})
# Connect and discover tools
async with mcp_client.connect():
tool_definitions = await mcp_client.list_tools()
if not command:
logger.warning(f"MCP connector {connector.id} server config missing command, skipping")
continue
logger.info(
f"Discovered {len(tool_definitions)} tools from MCP server "
f"'{command}' (connector {connector.id})"
)
# Create MCP client
mcp_client = MCPClient(command, args, env)
# Create LangChain tools from definitions
for tool_def in tool_definitions:
try:
tool = await _create_mcp_tool_from_definition(tool_def, mcp_client)
tools.append(tool)
except Exception as e:
logger.exception(
f"Failed to create tool '{tool_def.get('name')}' "
f"from connector {connector.id}: {e!s}",
)
# Connect and discover tools
async with mcp_client.connect():
tool_definitions = await mcp_client.list_tools()
logger.info(
f"Discovered {len(tool_definitions)} tools from MCP server "
f"'{command}' (connector {connector.id})"
)
# Create LangChain tools from definitions
for tool_def in tool_definitions:
try:
tool = await _create_mcp_tool_from_definition(tool_def, mcp_client)
tools.append(tool)
except Exception as e:
logger.exception(
f"Failed to create tool '{tool_def.get('name')}' "
f"from connector {connector.id}: {e!s}",
)
except Exception as e:
logger.exception(

View file

@ -2018,12 +2018,12 @@ async def create_mcp_connector(
"You don't have permission to create connectors in this search space",
)
# Create the connector with server config
# Create the connector with server configs array
db_connector = SearchSourceConnector(
name=connector_data.name,
connector_type=SearchSourceConnectorType.MCP_CONNECTOR,
is_indexable=False, # MCP connectors are not indexable
config={"server_config": connector_data.server_config.model_dump()},
config={"server_configs": [sc.model_dump() for sc in connector_data.server_configs]},
periodic_indexing_enabled=False,
indexing_frequency_minutes=None,
search_space_id=search_space_id,
@ -2035,7 +2035,7 @@ async def create_mcp_connector(
await session.refresh(db_connector)
logger.info(
f"Created MCP connector {db_connector.id} for server '{connector_data.server_config.command}' "
f"Created MCP connector {db_connector.id} with {len(connector_data.server_configs)} server(s) "
f"for user {user.id} in search space {search_space_id}"
)
@ -2202,9 +2202,9 @@ async def update_mcp_connector(
if connector_update.name is not None:
connector.name = connector_update.name
if connector_update.server_config is not None:
if connector_update.server_configs is not None:
connector.config = {
"server_config": connector_update.server_config.model_dump()
"server_configs": [sc.model_dump() for sc in connector_update.server_configs]
}
connector.updated_at = datetime.now(UTC)

View file

@ -93,23 +93,23 @@ class MCPConnectorCreate(BaseModel):
"""Schema for creating an MCP connector."""
name: str
server_config: MCPServerConfig
server_configs: list[MCPServerConfig] # Array of MCP server configurations
class MCPConnectorUpdate(BaseModel):
"""Schema for updating an MCP connector."""
name: str | None = None
server_config: MCPServerConfig | None = None
server_configs: list[MCPServerConfig] | None = None
class MCPConnectorRead(BaseModel):
"""Schema for reading an MCP connector with server config."""
"""Schema for reading an MCP connector with server configs."""
id: int
name: str
connector_type: SearchSourceConnectorType
server_config: MCPServerConfig
server_configs: list[MCPServerConfig]
search_space_id: int
user_id: uuid.UUID
created_at: datetime
@ -121,13 +121,14 @@ class MCPConnectorRead(BaseModel):
def from_connector(cls, connector: SearchSourceConnectorRead) -> "MCPConnectorRead":
"""Convert from base SearchSourceConnectorRead."""
config = connector.config or {}
server_config = MCPServerConfig(**config.get("server_config", {}))
server_configs_data = config.get("server_configs", [])
server_configs = [MCPServerConfig(**sc) for sc in server_configs_data]
return cls(
id=connector.id,
name=connector.name,
connector_type=connector.connector_type,
server_config=server_config,
server_configs=server_configs,
search_space_id=connector.search_space_id,
user_id=connector.user_id,
created_at=connector.created_at,