LibreChat/api/server/controllers/__tests__/mcp.servers.spec.js
Danny Avila 53b3e166d8
Some checks failed
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Has been cancelled
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Has been cancelled
GitNexus Index / index (push) Has been cancelled
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Has been cancelled
Sync Helm Chart Tags / Ignore non-main push (push) Has been cancelled
Sync Helm Chart Tags / Sync chart tags (push) Has been cancelled
GitNexus Index / post-index (push) Has been cancelled
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Has been cancelled
📉 perf: Skip Redundant Permission Queries on MCP Servers List (#14077)
2026-07-02 11:45:23 -04:00

258 lines
8.2 KiB
JavaScript

const mongoose = require('mongoose');
const { MongoMemoryServer } = require('mongodb-memory-server');
const { SystemCapabilities } = require('@librechat/data-schemas');
const {
SystemRoles,
ResourceType,
AccessRoleIds,
PrincipalType,
} = require('librechat-data-provider');
jest.mock('@librechat/data-schemas', () => ({
...jest.requireActual('@librechat/data-schemas'),
getTransactionSupport: jest.fn().mockResolvedValue(false),
}));
jest.mock('~/server/services/GraphApiService', () => ({
entraIdPrincipalFeatureEnabled: jest.fn().mockReturnValue(false),
getUserOwnedEntraGroups: jest.fn().mockResolvedValue([]),
getUserEntraGroups: jest.fn().mockResolvedValue([]),
getEntraGroupDetailsBatch: jest.fn().mockResolvedValue([]),
getGroupMembers: jest.fn().mockResolvedValue([]),
getGroupOwners: jest.fn().mockResolvedValue([]),
}));
const mockRegistryInstance = {
getServerConfig: jest.fn(),
};
jest.mock('~/config', () => ({
logger: { debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() },
getMCPManager: jest.fn(),
getMCPServersRegistry: jest.fn(() => mockRegistryInstance),
}));
const mockResolveAllMcpConfigs = jest.fn();
jest.mock('~/server/services/MCP', () => ({
resolveConfigServers: jest.fn().mockResolvedValue({}),
resolveMcpConfigNames: jest.fn().mockResolvedValue([]),
resolveAllMcpConfigs: (...args) => mockResolveAllMcpConfigs(...args),
}));
jest.mock('~/server/services/Config', () => ({
cacheMCPServerTools: jest.fn(),
getMCPServerTools: jest.fn(),
}));
const { getMCPServersList, getMCPServerById } = require('~/server/controllers/mcp');
const { grantPermission } = require('~/server/services/PermissionService');
const { seedDefaultRoles } = require('~/models');
let mongoServer;
let SystemGrant;
let AclEntry;
let User;
const yamlConfig = {
type: 'streamable-http',
url: 'https://internal.example.com/mcp',
title: 'YAML Server',
source: 'yaml',
oauth: {
client_id: 'client-id',
authorization_url: 'https://internal.example.com/auth',
token_url: 'https://internal.example.com/token',
},
};
const createRes = () => {
const res = {};
res.status = jest.fn(() => res);
res.json = jest.fn(() => res);
return res;
};
const createDbConfig = (dbId) => ({
type: 'streamable-http',
url: 'https://user.example.com/mcp',
title: 'DB Server',
source: 'user',
dbId: String(dbId),
});
beforeAll(async () => {
mongoServer = await MongoMemoryServer.create();
await mongoose.connect(mongoServer.getUri());
const { createModels } = jest.requireActual('@librechat/data-schemas');
createModels(mongoose);
const dbModels = require('~/db/models');
Object.assign(mongoose.models, dbModels);
SystemGrant = dbModels.SystemGrant;
AclEntry = dbModels.AclEntry;
User = dbModels.User;
await seedDefaultRoles();
});
afterAll(async () => {
await mongoose.disconnect();
await mongoServer.stop();
});
let existsSpy;
beforeEach(async () => {
await SystemGrant.deleteMany({});
await AclEntry.deleteMany({});
await User.deleteMany({});
mockResolveAllMcpConfigs.mockReset();
mockRegistryInstance.getServerConfig.mockReset();
existsSpy = jest.spyOn(SystemGrant, 'exists');
});
afterEach(() => {
existsSpy.mockRestore();
});
const seedManageMcpGrant = async (role = SystemRoles.ADMIN) => {
await SystemGrant.create({
principalType: PrincipalType.ROLE,
principalId: role,
capability: SystemCapabilities.MANAGE_MCP_SERVERS,
grantedAt: new Date(),
});
};
const createUser = async (role = SystemRoles.USER) => {
const user = await User.create({
name: 'Test User',
email: `user-${new mongoose.Types.ObjectId().toString()}@example.com`,
provider: 'local',
role,
});
return { id: user._id.toString(), role, idOnTheSource: null };
};
describe('getMCPServersList', () => {
it('skips the capability probe when no server is DB-backed', async () => {
await seedManageMcpGrant();
const reqUser = await createUser(SystemRoles.ADMIN);
mockResolveAllMcpConfigs.mockResolvedValue({ yamlServer: { ...yamlConfig } });
const res = createRes();
await getMCPServersList({ user: reqUser }, res);
expect(existsSpy).not.toHaveBeenCalled();
const payload = res.json.mock.calls[0][0];
expect(payload.yamlServer.title).toBe('YAML Server');
expect(payload.yamlServer.url).toBeUndefined();
expect(payload.yamlServer.oauth.authorization_url).toBeUndefined();
});
it('skips the probe entirely for an empty server map', async () => {
const reqUser = await createUser();
mockResolveAllMcpConfigs.mockResolvedValue({});
const res = createRes();
await getMCPServersList({ user: reqUser }, res);
expect(existsSpy).not.toHaveBeenCalled();
expect(res.json).toHaveBeenCalledWith({});
});
it('applies the capability bypass to all servers when a DB-backed server is present', async () => {
await seedManageMcpGrant();
const reqUser = await createUser(SystemRoles.ADMIN);
const dbId = new mongoose.Types.ObjectId();
mockResolveAllMcpConfigs.mockResolvedValue({
dbServer: createDbConfig(dbId),
yamlServer: { ...yamlConfig },
});
const res = createRes();
await getMCPServersList({ user: reqUser }, res);
expect(existsSpy).toHaveBeenCalledTimes(1);
const payload = res.json.mock.calls[0][0];
expect(payload.dbServer.url).toBe('https://user.example.com/mcp');
expect(payload.yamlServer.url).toBe('https://internal.example.com/mcp');
});
it('falls back to ACL EDIT for DB-backed servers without the capability', async () => {
const reqUser = await createUser();
const dbId = new mongoose.Types.ObjectId();
await grantPermission({
principalType: PrincipalType.USER,
principalId: reqUser.id,
resourceType: ResourceType.MCPSERVER,
resourceId: dbId,
accessRoleId: AccessRoleIds.MCPSERVER_EDITOR,
grantedBy: reqUser.id,
});
mockResolveAllMcpConfigs.mockResolvedValue({
dbServer: createDbConfig(dbId),
yamlServer: { ...yamlConfig },
});
const res = createRes();
await getMCPServersList({ user: reqUser }, res);
expect(existsSpy).toHaveBeenCalledTimes(1);
const payload = res.json.mock.calls[0][0];
expect(payload.dbServer.url).toBe('https://user.example.com/mcp');
expect(payload.yamlServer.url).toBeUndefined();
});
it('leaves DB-backed servers redacted for viewer-only ACL', async () => {
const reqUser = await createUser();
const dbId = new mongoose.Types.ObjectId();
await grantPermission({
principalType: PrincipalType.USER,
principalId: reqUser.id,
resourceType: ResourceType.MCPSERVER,
resourceId: dbId,
accessRoleId: AccessRoleIds.MCPSERVER_VIEWER,
grantedBy: reqUser.id,
});
mockResolveAllMcpConfigs.mockResolvedValue({ dbServer: createDbConfig(dbId) });
const res = createRes();
await getMCPServersList({ user: reqUser }, res);
expect(existsSpy).toHaveBeenCalledTimes(1);
const payload = res.json.mock.calls[0][0];
expect(payload.dbServer.title).toBe('DB Server');
expect(payload.dbServer.url).toBeUndefined();
});
});
describe('getMCPServerById', () => {
it('still runs the capability probe for YAML servers on the detail route', async () => {
await seedManageMcpGrant();
const reqUser = await createUser(SystemRoles.ADMIN);
mockRegistryInstance.getServerConfig.mockResolvedValue({ ...yamlConfig });
const res = createRes();
await getMCPServerById({ user: reqUser, params: { serverName: 'yamlServer' } }, res);
expect(existsSpy).toHaveBeenCalledTimes(1);
expect(res.status).toHaveBeenCalledWith(200);
const payload = res.json.mock.calls[0][0];
expect(payload.url).toBe('https://internal.example.com/mcp');
expect(payload.oauth.authorization_url).toBe('https://internal.example.com/auth');
});
it('redacts YAML server details for users without the capability', async () => {
const reqUser = await createUser();
mockRegistryInstance.getServerConfig.mockResolvedValue({ ...yamlConfig });
const res = createRes();
await getMCPServerById({ user: reqUser, params: { serverName: 'yamlServer' } }, res);
expect(existsSpy).toHaveBeenCalledTimes(1);
const payload = res.json.mock.calls[0][0];
expect(payload.url).toBeUndefined();
expect(payload.oauth.authorization_url).toBeUndefined();
});
});