🧩 refactor: Decouple MCP Config from Startup Config (#10689)

* Decouple mcp config from start up config

* Chore: Work on AI Review and Copilot Comments

- setRawConfig is not needed since the private raw config is not needed any more
- !!serversLoading bug fixed
- added unit tests for route /api/mcp/servers
- copilot comments addressed

* chore: remove comments

* chore: rename data-provider dir for MCP

* chore: reorganize mcp specific query hooks

* fix: consolidate imports for MCP server manager

* chore: add dev-staging branch to frontend review workflow triggers

* feat: add GitHub Actions workflow for building and pushing Docker images to GitHub Container Registry and Docker Hub

* fix: update label for tag input in BookmarkForm tests to improve clarity

---------

Co-authored-by: Atef Bellaaj <slalom.bellaaj@external.daimlertruck.com>
Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
Atef Bellaaj 2025-11-26 21:26:40 +01:00 committed by Danny Avila
parent 98b188f26c
commit ef1b7f0157
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
36 changed files with 548 additions and 301 deletions

View file

@ -228,6 +228,7 @@ export const agents = ({ path = '', options }: { path?: string; options?: object
export const mcp = {
tools: `${BASE_URL}/api/mcp/tools`,
servers: `${BASE_URL}/api/mcp/servers`,
};
export const revertAgentVersion = (agent_id: string) => `${agents({ path: `${agent_id}/revert` })}`;

View file

@ -6,6 +6,7 @@ import * as ag from './types/agents';
import * as m from './types/mutations';
import * as q from './types/queries';
import * as f from './types/files';
import * as mcp from './types/mcpServers';
import * as config from './config';
import request from './request';
import * as s from './schemas';
@ -538,6 +539,18 @@ export const deleteAgentAction = async ({
}),
);
/**
* MCP Servers
*/
/**
*
* Ensure and List loaded mcp server configs from the cache Enriched with effective permissions.
*/
export const getMCPServers = async (): Promise<mcp.MCPServersListResponse> => {
return request.get(endpoints.mcp.servers);
};
/**
* Imports a conversations file.
*

View file

@ -57,6 +57,8 @@ export enum QueryKeys {
resourcePermissions = 'resourcePermissions',
effectivePermissions = 'effectivePermissions',
graphToken = 'graphToken',
/* MCP Servers */
mcpServers = 'mcpServers',
}
// Dynamic query keys that require parameters

View file

@ -180,3 +180,32 @@ export const MCPOptionsSchema = z.union([
export const MCPServersSchema = z.record(z.string(), MCPOptionsSchema);
export type MCPOptions = z.infer<typeof MCPOptionsSchema>;
/**
* Helper to omit server-managed fields that should not come from UI
*/
const omitServerManagedFields = <T extends z.ZodObject<z.ZodRawShape>>(schema: T) =>
schema.omit({
startup: true,
timeout: true,
initTimeout: true,
chatMenu: true,
serverInstructions: true,
requiresOAuth: true,
customUserVars: true,
oauth_headers: true,
});
/**
* MCP Server configuration that comes from UI input only
* Omits server-managed fields like startup, timeout, customUserVars, etc.
* Allows: title, description, url, iconPath, oauth (user credentials)
*/
export const MCPServerUserInputSchema = z.union([
omitServerManagedFields(StdioOptionsSchema),
omitServerManagedFields(WebSocketOptionsSchema),
omitServerManagedFields(SSEOptionsSchema),
omitServerManagedFields(StreamableHTTPOptionsSchema),
]);
export type MCPServerUserInput = z.infer<typeof MCPServerUserInputSchema>;

View file

@ -1,4 +1,5 @@
import type { MCPOptions } from '../mcp';
import { PermissionBits } from '../accessPermissions';
import type { MCPOptions, MCPServerUserInput } from '../mcp';
/**
* Base MCP Server interface
@ -19,3 +20,33 @@ export interface IMCPServerDB {
* Similar to Agent type - includes populated author fields
*/
export type MCPServerDB = IMCPServerDB;
/**
* Parameters for creating a new user-managed MCP server
* Note: Only UI-editable fields are allowed (excludes server-managed fields)
*/
export type MCPServerCreateParams = {
config: MCPServerUserInput; // UI fields only (title, description, url, oauth, iconPath)
};
/**
* Parameters for updating an existing user-managed MCP server
* Note: Only UI-editable fields are allowed (excludes server-managed fields)
*/
export type MCPServerUpdateParams = {
config?: MCPServerUserInput; // UI fields only (title, description, url, oauth, iconPath)
};
/**
* Response for MCP server list endpoint
*/
export type MCPServerDBObjectResponse = {
_id?: string;
mcp_id?: string;
author?: string | null;
createdAt?: Date;
updatedAt?: Date;
effectivePermissions?: PermissionBits;
} & MCPOptions;
export type MCPServersListResponse = Record<string, MCPServerDBObjectResponse>;