🧰 refactor: Decouple MCP Tools from System Tools (#9748)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run

This commit is contained in:
Danny Avila 2025-09-21 07:56:40 -04:00 committed by GitHub
parent 9d2aba5df5
commit 386900fb4f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 1032 additions and 1195 deletions

View file

@ -1,79 +1,52 @@
import { useMemo } from 'react';
import { Constants } from 'librechat-data-provider';
import type { AgentToolType } from 'librechat-data-provider';
import type { TPlugin } from 'librechat-data-provider';
import type { MCPServerInfo } from '~/common';
type GroupedToolType = AgentToolType & { tools?: AgentToolType[] };
type GroupedToolsRecord = Record<string, GroupedToolType>;
interface VisibleToolsResult {
toolIds: string[];
mcpServerNames: string[];
}
/**
* Custom hook to calculate visible tool IDs based on selected tools and their parent groups.
* If any subtool of a group is selected, the parent group tool is also made visible.
* Custom hook to calculate visible tool IDs based on selected tools.
* Separates regular LibreChat tools from MCP servers.
*
* @param selectedToolIds - Array of selected tool IDs
* @param allTools - Record of all available tools
* @param regularTools - Array of regular LibreChat tools
* @param mcpServersMap - Map of all MCP servers
* @returns Object containing separate arrays of visible tool IDs for regular and MCP tools
*/
export function useVisibleTools(
selectedToolIds: string[] | undefined,
allTools: GroupedToolsRecord | undefined,
regularTools: TPlugin[] | undefined,
mcpServersMap: Map<string, MCPServerInfo>,
): VisibleToolsResult {
return useMemo(() => {
const mcpServers = new Set<string>();
const selectedSet = new Set<string>();
const regularToolIds = new Set<string>();
const regularToolIds: string[] = [];
for (const toolId of selectedToolIds ?? []) {
if (!toolId.includes(Constants.mcp_delimiter)) {
selectedSet.add(toolId);
continue;
}
const serverName = toolId.split(Constants.mcp_delimiter)[1];
if (!serverName) {
continue;
}
mcpServers.add(serverName);
}
if (allTools) {
for (const [toolId, toolObj] of Object.entries(allTools)) {
if (selectedSet.has(toolId)) {
regularToolIds.add(toolId);
}
if (toolObj.tools?.length) {
for (const subtool of toolObj.tools) {
if (selectedSet.has(subtool.tool_id)) {
regularToolIds.add(toolId);
break;
}
}
// MCP tools/servers
if (toolId.includes(Constants.mcp_delimiter)) {
const serverName = toolId.split(Constants.mcp_delimiter)[1];
if (serverName) {
mcpServers.add(serverName);
}
}
}
if (mcpServersMap) {
for (const [mcpServerName] of mcpServersMap) {
if (mcpServers.has(mcpServerName)) {
continue;
}
/** Legacy check */
if (selectedSet.has(mcpServerName)) {
mcpServers.add(mcpServerName);
}
// Legacy MCP server check (just server name)
else if (mcpServersMap.has(toolId)) {
mcpServers.add(toolId);
}
// Regular LibreChat tools
else if (regularTools?.some((t) => t.pluginKey === toolId)) {
regularToolIds.push(toolId);
}
}
return {
toolIds: Array.from(regularToolIds).sort((a, b) => a.localeCompare(b)),
toolIds: regularToolIds.sort((a, b) => a.localeCompare(b)),
mcpServerNames: Array.from(mcpServers).sort((a, b) => a.localeCompare(b)),
};
}, [allTools, mcpServersMap, selectedToolIds]);
}, [regularTools, mcpServersMap, selectedToolIds]);
}