💁 refactor: Better Config UX for MCP STDIO with customUserVars (#12226)

* refactor: Better UX for MCP stdio with Custom User Variables

- Updated the ConnectionsRepository to prevent connections when customUserVars are defined, improving security and access control.
- Modified the MCPServerInspector to skip capabilities fetch when customUserVars are present, streamlining server inspection.
- Added tests to validate connection restrictions with customUserVars, ensuring robust handling of various server configurations.

This change enhances the overall integrity of the connection management process by enforcing stricter rules around custom user variables.

* fix: guard against empty customUserVars and add JSDoc context

- Extract `hasCustomUserVars()` helper to guard against truthy `{}`
  (Zod's `.record().optional()` yields `{}` on empty input, not `undefined`)
- Add JSDoc to `isAllowedToConnectToServer` explaining why customUserVars
  servers are excluded from app-level connections

* test: improve customUserVars test coverage and fixture hygiene

- Add no-connection-provided test for MCPServerInspector (production path)
- Fix test descriptions to match actual fixture values
- Replace real package name with fictional @test/mcp-stdio-server
This commit is contained in:
Danny Avila 2026-03-14 21:22:25 -04:00 committed by GitHub
parent 7bc793b18d
commit 8318446704
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 116 additions and 6 deletions

View file

@ -1,8 +1,9 @@
import { logger } from '@librechat/data-schemas';
import { MCPConnectionFactory } from '~/mcp/MCPConnectionFactory';
import { MCPConnection } from './connection';
import { MCPServersRegistry } from '~/mcp/registry/MCPServersRegistry';
import type * as t from './types';
import { MCPServersRegistry } from '~/mcp/registry/MCPServersRegistry';
import { MCPConnectionFactory } from '~/mcp/MCPConnectionFactory';
import { hasCustomUserVars } from './utils';
import { MCPConnection } from './connection';
const CONNECT_CONCURRENCY = 3;
@ -139,12 +140,19 @@ export class ConnectionsRepository {
return `[MCP][${serverName}]`;
}
/**
* App-level (shared) connections cannot serve servers that need per-user context:
* env/header placeholders like `{{MY_KEY}}` are only resolved by `processMCPEnv()`
* when real `customUserVars` values exist which requires a user-level connection.
*/
private isAllowedToConnectToServer(config: t.ParsedServerConfig) {
if (config.inspectionFailed) {
return false;
}
//the repository is not allowed to be connected in case the Connection repository is shared (ownerId is undefined/null) and the server requires Auth or startup false.
if (this.ownerId === undefined && (config.startup === false || config.requiresOAuth)) {
if (
this.ownerId === undefined &&
(config.startup === false || config.requiresOAuth || hasCustomUserVars(config))
) {
return false;
}
return true;