💾 chore: Enhance Local Storage Handling and Update MCP SDK (#6809)

* feat: Update MCP package version and dependencies; refactor ToolContentPart type

* refactor: Change module type to commonjs and update rollup configuration, remove unused dev dependency

* refactor: Change async calls to synchronous for MCP and FlowStateManager retrieval

* chore: Add eslint disable comment for i18next rule in DropdownPopup component

* fix: improve statefulness of mcp servers selected if some were removed since last session

* feat: implement conversation storage cleanup functions and integrate them into mutation success handlers

* feat: enhance storage condition logic in useLocalStorageAlt to prevent unnecessary local storage writes

* refactor: streamline local storage update logic in useLocalStorageAlt
This commit is contained in:
Danny Avila 2025-04-09 18:38:48 -04:00 committed by GitHub
parent 24c0433dcf
commit e16a6190a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 420 additions and 382 deletions

View file

@ -1,6 +1,7 @@
const axios = require('axios'); const axios = require('axios');
const { EventSource } = require('eventsource'); const { EventSource } = require('eventsource');
const { Time, CacheKeys } = require('librechat-data-provider'); const { Time, CacheKeys } = require('librechat-data-provider');
const { MCPManager, FlowStateManager } = require('librechat-mcp');
const logger = require('./winston'); const logger = require('./winston');
global.EventSource = EventSource; global.EventSource = EventSource;
@ -9,11 +10,10 @@ let mcpManager = null;
let flowManager = null; let flowManager = null;
/** /**
* @returns {Promise<MCPManager>} * @returns {MCPManager}
*/ */
async function getMCPManager() { function getMCPManager() {
if (!mcpManager) { if (!mcpManager) {
const { MCPManager } = await import('librechat-mcp');
mcpManager = MCPManager.getInstance(logger); mcpManager = MCPManager.getInstance(logger);
} }
return mcpManager; return mcpManager;
@ -21,11 +21,10 @@ async function getMCPManager() {
/** /**
* @param {(key: string) => Keyv} getLogStores * @param {(key: string) => Keyv} getLogStores
* @returns {Promise<FlowStateManager>} * @returns {FlowStateManager}
*/ */
async function getFlowStateManager(getLogStores) { function getFlowStateManager(getLogStores) {
if (!flowManager) { if (!flowManager) {
const { FlowStateManager } = await import('librechat-mcp');
flowManager = new FlowStateManager(getLogStores(CacheKeys.FLOWS), { flowManager = new FlowStateManager(getLogStores(CacheKeys.FLOWS), {
ttl: Time.ONE_MINUTE * 3, ttl: Time.ONE_MINUTE * 3,
logger, logger,

View file

@ -108,7 +108,7 @@ const getAvailableTools = async (req, res) => {
const pluginManifest = availableTools; const pluginManifest = availableTools;
const customConfig = await getCustomConfig(); const customConfig = await getCustomConfig();
if (customConfig?.mcpServers != null) { if (customConfig?.mcpServers != null) {
const mcpManager = await getMCPManager(); const mcpManager = getMCPManager();
await mcpManager.loadManifestTools(pluginManifest); await mcpManager.loadManifestTools(pluginManifest);
} }

View file

@ -20,7 +20,7 @@ router.get('/:action_id/oauth/callback', async (req, res) => {
const { action_id } = req.params; const { action_id } = req.params;
const { code, state } = req.query; const { code, state } = req.query;
const flowManager = await getFlowStateManager(getLogStores); const flowManager = getFlowStateManager(getLogStores);
let identifier = action_id; let identifier = action_id;
try { try {
let decodedState; let decodedState;

View file

@ -189,7 +189,7 @@ async function createActionTool({
expires_at: Date.now() + Time.TWO_MINUTES, expires_at: Date.now() + Time.TWO_MINUTES,
}, },
}; };
const flowManager = await getFlowStateManager(getLogStores); const flowManager = getFlowStateManager(getLogStores);
await flowManager.createFlowWithHandler( await flowManager.createFlowWithHandler(
`${identifier}:oauth_login:${config.metadata.thread_id}:${config.metadata.run_id}`, `${identifier}:oauth_login:${config.metadata.thread_id}:${config.metadata.run_id}`,
'oauth_login', 'oauth_login',
@ -265,7 +265,7 @@ async function createActionTool({
encrypted_oauth_client_id: encrypted.oauth_client_id, encrypted_oauth_client_id: encrypted.oauth_client_id,
encrypted_oauth_client_secret: encrypted.oauth_client_secret, encrypted_oauth_client_secret: encrypted.oauth_client_secret,
}); });
const flowManager = await getFlowStateManager(getLogStores); const flowManager = getFlowStateManager(getLogStores);
const refreshData = await flowManager.createFlowWithHandler( const refreshData = await flowManager.createFlowWithHandler(
`${identifier}:refresh`, `${identifier}:refresh`,
'oauth_refresh', 'oauth_refresh',

View file

@ -66,7 +66,7 @@ const AppService = async (app) => {
}); });
if (config.mcpServers != null) { if (config.mcpServers != null) {
const mcpManager = await getMCPManager(); const mcpManager = getMCPManager();
await mcpManager.initializeMCP(config.mcpServers, processMCPEnv); await mcpManager.initializeMCP(config.mcpServers, processMCPEnv);
await mcpManager.mapAvailableTools(availableTools); await mcpManager.mapAvailableTools(availableTools);
} }

View file

@ -49,7 +49,7 @@ async function createMCPTool({ req, toolKey, provider }) {
/** @type {(toolArguments: Object | string, config?: GraphRunnableConfig) => Promise<unknown>} */ /** @type {(toolArguments: Object | string, config?: GraphRunnableConfig) => Promise<unknown>} */
const _call = async (toolArguments, config) => { const _call = async (toolArguments, config) => {
try { try {
const mcpManager = await getMCPManager(); const mcpManager = getMCPManager();
const result = await mcpManager.callTool({ const result = await mcpManager.callTool({
serverName, serverName,
toolName, toolName,

View file

@ -17,6 +17,20 @@ import useLocalStorage from '~/hooks/useLocalStorageAlt';
import { useVerifyAgentToolAuth } from '~/data-provider'; import { useVerifyAgentToolAuth } from '~/data-provider';
import { ephemeralAgentByConvoId } from '~/store'; import { ephemeralAgentByConvoId } from '~/store';
const storageCondition = (value: unknown, rawCurrentValue?: string | null) => {
if (rawCurrentValue) {
try {
const currentValue = rawCurrentValue?.trim() ?? '';
if (currentValue === 'true' && value === false) {
return true;
}
} catch (e) {
console.error(e);
}
}
return value !== undefined && value !== null && value !== '' && value !== false;
};
function CodeInterpreter({ conversationId }: { conversationId?: string | null }) { function CodeInterpreter({ conversationId }: { conversationId?: string | null }) {
const localize = useLocalize(); const localize = useLocalize();
const key = conversationId ?? Constants.NEW_CONVO; const key = conversationId ?? Constants.NEW_CONVO;
@ -55,6 +69,7 @@ function CodeInterpreter({ conversationId }: { conversationId?: string | null })
`${LocalStorageKeys.LAST_CODE_TOGGLE_}${key}`, `${LocalStorageKeys.LAST_CODE_TOGGLE_}${key}`,
isCodeToggleEnabled, isCodeToggleEnabled,
setValue, setValue,
storageCondition,
); );
const handleChange = useCallback( const handleChange = useCallback(

View file

@ -8,14 +8,43 @@ import { ephemeralAgentByConvoId } from '~/store';
import MCPIcon from '~/components/ui/MCPIcon'; import MCPIcon from '~/components/ui/MCPIcon';
import { useLocalize } from '~/hooks'; import { useLocalize } from '~/hooks';
const storageCondition = (value: unknown, rawCurrentValue?: string | null) => {
if (rawCurrentValue) {
try {
const currentValue = rawCurrentValue?.trim() ?? '';
if (currentValue.length > 2) {
return true;
}
} catch (e) {
console.error(e);
}
}
return Array.isArray(value) && value.length > 0;
};
function MCPSelect({ conversationId }: { conversationId?: string | null }) { function MCPSelect({ conversationId }: { conversationId?: string | null }) {
const localize = useLocalize(); const localize = useLocalize();
const hasSetFetched = useRef(false);
const key = conversationId ?? Constants.NEW_CONVO; const key = conversationId ?? Constants.NEW_CONVO;
const hasSetFetched = useRef<string | null>(null);
const { data: mcpServerSet, isFetched } = useAvailableToolsQuery(EModelEndpoint.agents, {
select: (data) => {
const serverNames = new Set<string>();
data.forEach((tool) => {
if (tool.pluginKey.includes(Constants.mcp_delimiter)) {
const parts = tool.pluginKey.split(Constants.mcp_delimiter);
serverNames.add(parts[parts.length - 1]);
}
});
return serverNames;
},
});
const [ephemeralAgent, setEphemeralAgent] = useRecoilState(ephemeralAgentByConvoId(key)); const [ephemeralAgent, setEphemeralAgent] = useRecoilState(ephemeralAgentByConvoId(key));
const mcpState = useMemo(() => { const mcpState = useMemo(() => {
return ephemeralAgent?.mcp ?? []; return ephemeralAgent?.mcp ?? [];
}, [ephemeralAgent?.mcp]); }, [ephemeralAgent?.mcp]);
const setSelectedValues = useCallback( const setSelectedValues = useCallback(
(values: string[] | null | undefined) => { (values: string[] | null | undefined) => {
if (!values) { if (!values) {
@ -35,33 +64,23 @@ function MCPSelect({ conversationId }: { conversationId?: string | null }) {
`${LocalStorageKeys.LAST_MCP_}${key}`, `${LocalStorageKeys.LAST_MCP_}${key}`,
mcpState, mcpState,
setSelectedValues, setSelectedValues,
storageCondition,
); );
const { data: mcpServers, isFetched } = useAvailableToolsQuery(EModelEndpoint.agents, {
select: (data) => {
const serverNames = new Set<string>();
data.forEach((tool) => {
if (tool.pluginKey.includes(Constants.mcp_delimiter)) {
const parts = tool.pluginKey.split(Constants.mcp_delimiter);
serverNames.add(parts[parts.length - 1]);
}
});
return [...serverNames];
},
});
useEffect(() => { useEffect(() => {
if (hasSetFetched.current) { if (hasSetFetched.current === key) {
return; return;
} }
if (!isFetched) { if (!isFetched) {
return; return;
} }
hasSetFetched.current = true; hasSetFetched.current = key;
if ((mcpServers?.length ?? 0) > 0) { if ((mcpServerSet?.size ?? 0) > 0) {
setMCPValues(mcpValues.filter((mcp) => mcpServerSet?.has(mcp)));
return; return;
} }
setMCPValues([]); setMCPValues([]);
}, [isFetched, setMCPValues, mcpServers?.length]); }, [isFetched, setMCPValues, mcpServerSet, key, mcpValues]);
const renderSelectedValues = useCallback( const renderSelectedValues = useCallback(
(values: string[], placeholder?: string) => { (values: string[], placeholder?: string) => {
@ -76,7 +95,11 @@ function MCPSelect({ conversationId }: { conversationId?: string | null }) {
[localize], [localize],
); );
if (!mcpServers || mcpServers.length === 0) { const mcpServers = useMemo(() => {
return Array.from(mcpServerSet ?? []);
}, [mcpServerSet]);
if (!mcpServerSet || mcpServerSet.size === 0) {
return null; return null;
} }

View file

@ -3,6 +3,7 @@ import { useClearConversationsMutation } from 'librechat-data-provider/react-que
import { Label, Button, OGDialog, OGDialogTrigger, Spinner } from '~/components'; import { Label, Button, OGDialog, OGDialogTrigger, Spinner } from '~/components';
import { useLocalize, useNewConvo } from '~/hooks'; import { useLocalize, useNewConvo } from '~/hooks';
import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; import OGDialogTemplate from '~/components/ui/OGDialogTemplate';
import { clearAllConversationStorage } from '~/utils';
export const ClearChats = () => { export const ClearChats = () => {
const localize = useLocalize(); const localize = useLocalize();
@ -15,6 +16,7 @@ export const ClearChats = () => {
{}, {},
{ {
onSuccess: () => { onSuccess: () => {
clearAllConversationStorage();
newConversation(); newConversation();
}, },
}, },

View file

@ -83,6 +83,7 @@ const DropdownPopup: React.FC<DropdownProps> = ({
)} )}
{item.label} {item.label}
{item.kbd != null && ( {item.kbd != null && (
// eslint-disable-next-line i18next/no-literal-string
<kbd className="ml-auto hidden font-sans text-xs text-black/50 group-hover:inline group-focus:inline dark:text-white/50"> <kbd className="ml-auto hidden font-sans text-xs text-black/50 group-hover:inline group-focus:inline dark:text-white/50">
{item.kbd} {item.kbd}
</kbd> </kbd>

View file

@ -4,6 +4,7 @@ import { MutationKeys, QueryKeys, dataService, request } from 'librechat-data-pr
import type { UseMutationResult } from '@tanstack/react-query'; import type { UseMutationResult } from '@tanstack/react-query';
import type * as t from 'librechat-data-provider'; import type * as t from 'librechat-data-provider';
import useClearStates from '~/hooks/Config/useClearStates'; import useClearStates from '~/hooks/Config/useClearStates';
import { clearAllConversationStorage } from '~/utils';
import store from '~/store'; import store from '~/store';
/* login/logout */ /* login/logout */
@ -79,6 +80,7 @@ export const useDeleteUserMutation = (
onSuccess: (...args) => { onSuccess: (...args) => {
resetDefaultPreset(); resetDefaultPreset();
clearStates(); clearStates();
clearAllConversationStorage();
queryClient.removeQueries(); queryClient.removeQueries();
options?.onSuccess?.(...args); options?.onSuccess?.(...args);
}, },

View file

@ -18,6 +18,7 @@ import {
updateConvoFields, updateConvoFields,
updateConversation, updateConversation,
deleteConversation, deleteConversation,
clearConversationStorage,
} from '~/utils'; } from '~/utils';
export type TGenTitleMutation = UseMutationResult< export type TGenTitleMutation = UseMutationResult<
@ -562,6 +563,7 @@ export const useDeleteConversationMutation = (
const current = queryClient.getQueryData<t.ConversationData>([QueryKeys.allConversations]); const current = queryClient.getQueryData<t.ConversationData>([QueryKeys.allConversations]);
refetch({ refetchPage: (page, index) => index === (current?.pages.length ?? 1) - 1 }); refetch({ refetchPage: (page, index) => index === (current?.pages.length ?? 1) - 1 });
onSuccess?.(_data, vars, context); onSuccess?.(_data, vars, context);
clearConversationStorage(conversationId);
}, },
..._options, ..._options,
}, },
@ -897,7 +899,7 @@ export const useUploadAssistantAvatarMutation = (
unknown // context unknown // context
> => { > => {
return useMutation([MutationKeys.assistantAvatarUpload], { return useMutation([MutationKeys.assistantAvatarUpload], {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
mutationFn: ({ postCreation, ...variables }: t.AssistantAvatarVariables) => mutationFn: ({ postCreation, ...variables }: t.AssistantAvatarVariables) =>
dataService.uploadAssistantAvatar(variables), dataService.uploadAssistantAvatar(variables),
...(options || {}), ...(options || {}),

View file

@ -11,13 +11,16 @@ export default function useLocalStorage<T>(
key: string, key: string,
defaultValue: T, defaultValue: T,
globalSetState?: (value: T) => void, globalSetState?: (value: T) => void,
storageCondition?: (value: T, rawCurrentValue?: string | null) => boolean,
): [T, (value: T) => void] { ): [T, (value: T) => void] {
const [value, setValue] = useState(defaultValue); const [value, setValue] = useState(defaultValue);
useEffect(() => { useEffect(() => {
const item = localStorage.getItem(key); const item = localStorage.getItem(key);
if (!item) { if (!item && !storageCondition) {
localStorage.setItem(key, JSON.stringify(defaultValue));
} else if (!item && storageCondition && storageCondition(defaultValue)) {
localStorage.setItem(key, JSON.stringify(defaultValue)); localStorage.setItem(key, JSON.stringify(defaultValue));
} }
@ -47,9 +50,14 @@ export default function useLocalStorage<T>(
const setValueWrap = (value: T) => { const setValueWrap = (value: T) => {
try { try {
setValue(value); setValue(value);
localStorage.setItem(key, JSON.stringify(value)); const storeLocal = () => {
if (typeof window !== 'undefined') { localStorage.setItem(key, JSON.stringify(value));
window.dispatchEvent(new StorageEvent('storage', { key })); window?.dispatchEvent(new StorageEvent('storage', { key }));
};
if (!storageCondition) {
storeLocal();
} else if (storageCondition(value, localStorage.getItem(key))) {
storeLocal();
} }
globalSetState?.(value); globalSetState?.(value);
} catch (e) { } catch (e) {

View file

@ -1,4 +1,4 @@
import { LocalStorageKeys, TConversation } from 'librechat-data-provider'; import { LocalStorageKeys, TConversation, isUUID } from 'librechat-data-provider';
export function getLocalStorageItems() { export function getLocalStorageItems() {
const items = { const items = {
@ -45,3 +45,36 @@ export function clearLocalStorage(skipFirst?: boolean) {
} }
}); });
} }
export function clearConversationStorage(conversationId?: string | null) {
if (!conversationId) {
return;
}
if (!isUUID.safeParse(conversationId)?.success) {
console.warn(
`Conversation ID ${conversationId} is not a valid UUID. Skipping local storage cleanup.`,
);
return;
}
const keys = Object.keys(localStorage);
keys.forEach((key) => {
if (key.includes(conversationId)) {
localStorage.removeItem(key);
}
});
}
export function clearAllConversationStorage() {
const keys = Object.keys(localStorage);
keys.forEach((key) => {
if (
key.startsWith(LocalStorageKeys.LAST_MCP_) ||
key.startsWith(LocalStorageKeys.LAST_CODE_TOGGLE_) ||
key.startsWith(LocalStorageKeys.TEXT_DRAFT) ||
key.startsWith(LocalStorageKeys.ASST_ID_PREFIX) ||
key.startsWith(LocalStorageKeys.AGENT_ID_PREFIX) ||
key.startsWith(LocalStorageKeys.LAST_CONVO_SETUP)
) {
localStorage.removeItem(key);
}
});
}

587
package-lock.json generated
View file

@ -18649,304 +18649,6 @@
"zod": ">= 3" "zod": ">= 3"
} }
}, },
"node_modules/@modelcontextprotocol/sdk": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.8.0.tgz",
"integrity": "sha512-e06W7SwrontJDHwCawNO5SGxG+nU9AAx+jpHHZqGl/WrDBdWOpvirC+s58VpJTB5QemI4jTRcjWT4Pt3Q1NPQQ==",
"dependencies": {
"content-type": "^1.0.5",
"cors": "^2.8.5",
"cross-spawn": "^7.0.3",
"eventsource": "^3.0.2",
"express": "^5.0.1",
"express-rate-limit": "^7.5.0",
"pkce-challenge": "^4.1.0",
"raw-body": "^3.0.0",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.24.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
"dependencies": {
"mime-types": "^3.0.0",
"negotiator": "^1.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
"dependencies": {
"bytes": "^3.1.2",
"content-type": "^1.0.5",
"debug": "^4.4.0",
"http-errors": "^2.0.0",
"iconv-lite": "^0.6.3",
"on-finished": "^2.4.1",
"qs": "^6.14.0",
"raw-body": "^3.0.0",
"type-is": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/body-parser/node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/cookie": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
"engines": {
"node": ">=6.6.0"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/express": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/express/-/express-5.0.1.tgz",
"integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==",
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.0.1",
"content-disposition": "^1.0.0",
"content-type": "~1.0.4",
"cookie": "0.7.1",
"cookie-signature": "^1.2.1",
"debug": "4.3.6",
"depd": "2.0.0",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "^2.0.0",
"fresh": "2.0.0",
"http-errors": "2.0.0",
"merge-descriptors": "^2.0.0",
"methods": "~1.1.2",
"mime-types": "^3.0.0",
"on-finished": "2.4.1",
"once": "1.4.0",
"parseurl": "~1.3.3",
"proxy-addr": "~2.0.7",
"qs": "6.13.0",
"range-parser": "~1.2.1",
"router": "^2.0.0",
"safe-buffer": "5.2.1",
"send": "^1.1.0",
"serve-static": "^2.1.0",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "^2.0.0",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
"dependencies": {
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"on-finished": "^2.4.1",
"parseurl": "^1.3.3",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/fresh": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.6.3",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/send": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
"dependencies": {
"debug": "^4.3.5",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"mime-types": "^3.0.1",
"ms": "^2.1.3",
"on-finished": "^2.4.1",
"range-parser": "^1.2.1",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
"dependencies": {
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"parseurl": "^1.3.3",
"send": "^1.2.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
"dependencies": {
"content-type": "^1.0.5",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@mongodb-js/saslprep": { "node_modules/@mongodb-js/saslprep": {
"version": "1.1.9", "version": "1.1.9",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz",
@ -36071,14 +35773,6 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/pkce-challenge": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-4.1.0.tgz",
"integrity": "sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ==",
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/pkg-dir": { "node_modules/pkg-dir": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@ -43978,10 +43672,10 @@
}, },
"packages/mcp": { "packages/mcp": {
"name": "librechat-mcp", "name": "librechat-mcp",
"version": "1.1.0", "version": "1.2.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@modelcontextprotocol/sdk": "^1.8.0", "@modelcontextprotocol/sdk": "^1.9.0",
"diff": "^7.0.0", "diff": "^7.0.0",
"eventsource": "^3.0.2", "eventsource": "^3.0.2",
"express": "^4.21.2" "express": "^4.21.2"
@ -44010,7 +43704,6 @@
"rollup": "^4.22.4", "rollup": "^4.22.4",
"rollup-plugin-generate-package-json": "^3.2.0", "rollup-plugin-generate-package-json": "^3.2.0",
"rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-typescript2": "^0.35.0",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.0.4" "typescript": "^5.0.4"
}, },
@ -44018,6 +43711,98 @@
"keyv": "^4.5.4" "keyv": "^4.5.4"
} }
}, },
"packages/mcp/node_modules/@modelcontextprotocol/sdk": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.9.0.tgz",
"integrity": "sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==",
"dependencies": {
"content-type": "^1.0.5",
"cors": "^2.8.5",
"cross-spawn": "^7.0.3",
"eventsource": "^3.0.2",
"express": "^5.0.1",
"express-rate-limit": "^7.5.0",
"pkce-challenge": "^5.0.0",
"raw-body": "^3.0.0",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.24.1"
},
"engines": {
"node": ">=18"
}
},
"packages/mcp/node_modules/@modelcontextprotocol/sdk/node_modules/express": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.0",
"content-disposition": "^1.0.0",
"content-type": "^1.0.5",
"cookie": "^0.7.1",
"cookie-signature": "^1.2.1",
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"finalhandler": "^2.1.0",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"merge-descriptors": "^2.0.0",
"mime-types": "^3.0.0",
"on-finished": "^2.4.1",
"once": "^1.4.0",
"parseurl": "^1.3.3",
"proxy-addr": "^2.0.7",
"qs": "^6.14.0",
"range-parser": "^1.2.1",
"router": "^2.2.0",
"send": "^1.1.0",
"serve-static": "^2.2.0",
"statuses": "^2.0.1",
"type-is": "^2.0.1",
"vary": "^1.1.2"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"packages/mcp/node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
"dependencies": {
"mime-types": "^3.0.0",
"negotiator": "^1.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"packages/mcp/node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
"dependencies": {
"bytes": "^3.1.2",
"content-type": "^1.0.5",
"debug": "^4.4.0",
"http-errors": "^2.0.0",
"iconv-lite": "^0.6.3",
"on-finished": "^2.4.1",
"qs": "^6.14.0",
"raw-body": "^3.0.0",
"type-is": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"packages/mcp/node_modules/brace-expansion": { "packages/mcp/node_modules/brace-expansion": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@ -44027,6 +43812,49 @@
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
} }
}, },
"packages/mcp/node_modules/content-disposition": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"packages/mcp/node_modules/cookie-signature": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
"engines": {
"node": ">=6.6.0"
}
},
"packages/mcp/node_modules/finalhandler": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
"dependencies": {
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"on-finished": "^2.4.1",
"parseurl": "^1.3.3",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"packages/mcp/node_modules/fresh": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
"engines": {
"node": ">= 0.8"
}
},
"packages/mcp/node_modules/glob": { "packages/mcp/node_modules/glob": {
"version": "10.4.5", "version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
@ -44047,6 +43875,17 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"packages/mcp/node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"packages/mcp/node_modules/jackspeak": { "packages/mcp/node_modules/jackspeak": {
"version": "3.4.3", "version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
@ -44062,6 +43901,44 @@
"@pkgjs/parseargs": "^0.11.0" "@pkgjs/parseargs": "^0.11.0"
} }
}, },
"packages/mcp/node_modules/media-typer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
"engines": {
"node": ">= 0.8"
}
},
"packages/mcp/node_modules/merge-descriptors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"packages/mcp/node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"engines": {
"node": ">= 0.6"
}
},
"packages/mcp/node_modules/mime-types": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">= 0.6"
}
},
"packages/mcp/node_modules/minimatch": { "packages/mcp/node_modules/minimatch": {
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@ -44077,6 +43954,50 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"packages/mcp/node_modules/negotiator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
"engines": {
"node": ">= 0.6"
}
},
"packages/mcp/node_modules/pkce-challenge": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz",
"integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==",
"engines": {
"node": ">=16.20.0"
}
},
"packages/mcp/node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"packages/mcp/node_modules/raw-body": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.6.3",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"packages/mcp/node_modules/rimraf": { "packages/mcp/node_modules/rimraf": {
"version": "5.0.10", "version": "5.0.10",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
@ -44091,6 +44012,54 @@
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
},
"packages/mcp/node_modules/send": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
"dependencies": {
"debug": "^4.3.5",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"mime-types": "^3.0.1",
"ms": "^2.1.3",
"on-finished": "^2.4.1",
"range-parser": "^1.2.1",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 18"
}
},
"packages/mcp/node_modules/serve-static": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
"dependencies": {
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"parseurl": "^1.3.3",
"send": "^1.2.0"
},
"engines": {
"node": ">= 18"
}
},
"packages/mcp/node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
"dependencies": {
"content-type": "^1.0.5",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"engines": {
"node": ">= 0.6"
}
} }
} }
} }

View file

@ -1,21 +1,21 @@
{ {
"name": "librechat-mcp", "name": "librechat-mcp",
"version": "1.1.0", "version": "1.2.0",
"type": "module", "type": "commonjs",
"description": "MCP services for LibreChat", "description": "MCP services for LibreChat",
"main": "dist/index.js", "main": "dist/index.js",
"module": "dist/index.es.js", "module": "dist/index.es.js",
"types": "./dist/types/index.d.ts", "types": "./dist/types/index.d.ts",
"exports": { "exports": {
".": { ".": {
"import": "./dist/index.es.js", "require": "./dist/index.js",
"types": "./dist/types/index.d.ts" "types": "./dist/types/index.d.ts"
} }
}, },
"scripts": { "scripts": {
"clean": "rimraf dist", "clean": "rimraf dist",
"build": "npm run clean && rollup -c --configPlugin=@rollup/plugin-typescript", "build": "npm run clean && rollup -c --bundleConfigAsCjs",
"build:watch": "rollup -c -w --configPlugin=@rollup/plugin-typescript", "build:watch": "rollup -c -w --bundleConfigAsCjs",
"test": "jest --coverage --watch", "test": "jest --coverage --watch",
"test:ci": "jest --coverage --ci", "test:ci": "jest --coverage --ci",
"verify": "npm run test:ci", "verify": "npm run test:ci",
@ -60,7 +60,6 @@
"rollup": "^4.22.4", "rollup": "^4.22.4",
"rollup-plugin-generate-package-json": "^3.2.0", "rollup-plugin-generate-package-json": "^3.2.0",
"rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-typescript2": "^0.35.0",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.0.4" "typescript": "^5.0.4"
}, },
@ -68,7 +67,7 @@
"registry": "https://registry.npmjs.org/" "registry": "https://registry.npmjs.org/"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/sdk": "^1.8.0", "@modelcontextprotocol/sdk": "^1.9.0",
"diff": "^7.0.0", "diff": "^7.0.0",
"eventsource": "^3.0.2", "eventsource": "^3.0.2",
"express": "^4.21.2" "express": "^4.21.2"

View file

@ -1,11 +1,11 @@
// rollup.config.js // rollup.config.js
import typescript from 'rollup-plugin-typescript2';
import resolve from '@rollup/plugin-node-resolve';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
import terser from '@rollup/plugin-terser';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import terser from '@rollup/plugin-terser';
import replace from '@rollup/plugin-replace';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')); const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8'));
@ -24,16 +24,18 @@ const plugins = [
}), }),
typescript({ typescript({
tsconfig: './tsconfig.json', tsconfig: './tsconfig.json',
useTsconfigDeclarationDir: true, outDir: './dist',
sourceMap: true,
inlineSourceMap: true,
}), }),
terser(), terser(),
]; ];
const esmBuild = { const cjsBuild = {
input: 'src/index.ts', input: 'src/index.ts',
output: { output: {
file: pkg.module, file: pkg.main,
format: 'esm', format: 'cjs',
sourcemap: true, sourcemap: true,
exports: 'named', exports: 'named',
}, },
@ -42,4 +44,4 @@ const esmBuild = {
plugins, plugins,
}; };
export default esmBuild; export default cjsBuild;

View file

@ -8,6 +8,7 @@ import {
} from 'librechat-data-provider'; } from 'librechat-data-provider';
import type { JsonSchemaType, TPlugin } from 'librechat-data-provider'; import type { JsonSchemaType, TPlugin } from 'librechat-data-provider';
import { ToolSchema, ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js'; import { ToolSchema, ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js';
import type * as t from '@modelcontextprotocol/sdk/types.js';
export type StdioOptions = z.infer<typeof StdioOptionsSchema>; export type StdioOptions = z.infer<typeof StdioOptionsSchema>;
export type WebSocketOptions = z.infer<typeof WebSocketOptionsSchema>; export type WebSocketOptions = z.infer<typeof WebSocketOptionsSchema>;
@ -44,25 +45,7 @@ export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'err
export type MCPTool = z.infer<typeof ToolSchema>; export type MCPTool = z.infer<typeof ToolSchema>;
export type MCPToolListResponse = z.infer<typeof ListToolsResultSchema>; export type MCPToolListResponse = z.infer<typeof ListToolsResultSchema>;
export type ToolContentPart = export type ToolContentPart = t.TextContent | t.ImageContent | t.EmbeddedResource | t.AudioContent;
| {
type: 'text';
text: string;
}
| {
type: 'image';
data: string;
mimeType: string;
}
| {
type: 'resource';
resource: {
uri: string;
mimeType?: string;
text?: string;
blob?: string;
};
};
export type ImageContent = Extract<ToolContentPart, { type: 'image' }>; export type ImageContent = Extract<ToolContentPart, { type: 'image' }>;
export type MCPToolCallResponse = export type MCPToolCallResponse =
| undefined | undefined