Skip to content

Commit 342d242

Browse files
committed
Merge branch 'fix/oauth-server-instructions'
Signed-off-by: Mohammed Naser <[email protected]> # Conflicts: # client/src/components/Chat/Messages/Content/ToolCall.tsx
2 parents 25212a2 + a90e7eb commit 342d242

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

packages/api/src/mcp/MCPManager.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pick from 'lodash/pick';
22
import { logger } from '@librechat/data-schemas';
3+
import { isEnabled } from '~/utils';
34
import { CallToolResultSchema, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
45
import type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
56
import type { TokenMethods, IUser } from '@librechat/data-schemas';
@@ -118,6 +119,15 @@ export class MCPManager extends UserConnectionManager {
118119
const configs = await MCPServersRegistry.getInstance().getAllServerConfigs();
119120
for (const [serverName, config] of Object.entries(configs)) {
120121
if (config.serverInstructions != null) {
122+
// Skip if serverInstructions is true/boolean or "true" string - this means
123+
// instructions should be fetched from server but weren't (e.g., OAuth server
124+
// that couldn't be connected to at startup)
125+
if (isEnabled(config.serverInstructions) && typeof config.serverInstructions !== 'string') {
126+
continue;
127+
}
128+
if (typeof config.serverInstructions === 'string' && config.serverInstructions.toLowerCase().trim() === 'true') {
129+
continue;
130+
}
121131
instructions[serverName] = config.serverInstructions as string;
122132
}
123133
}

packages/api/src/mcp/UserConnectionManager.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { MCPConnection } from './connection';
66
import type * as t from './types';
77
import { ConnectionsRepository } from '~/mcp/ConnectionsRepository';
88
import { mcpConfig } from './mcpConfig';
9+
import { isEnabled } from '~/utils';
910

1011
/**
1112
* Abstract base class for managing user-specific MCP connections with lifecycle management.
@@ -143,6 +144,25 @@ export abstract class UserConnectionManager {
143144
this.userConnections.get(userId)?.set(serverName, connection);
144145

145146
logger.info(`[MCP][User: ${userId}][${serverName}] Connection successfully established`);
147+
148+
// For OAuth servers, fetch and update serverInstructions if enabled but not yet fetched
149+
if (config.requiresOAuth && isEnabled(config.serverInstructions)) {
150+
try {
151+
const instructions = connection.client.getInstructions();
152+
if (instructions && typeof instructions === 'string') {
153+
await MCPServersRegistry.getInstance().updateServerInstructions(serverName, instructions);
154+
logger.debug(
155+
`[MCP][User: ${userId}][${serverName}] Fetched and updated server instructions`,
156+
);
157+
}
158+
} catch (instructionsError) {
159+
logger.warn(
160+
`[MCP][User: ${userId}][${serverName}] Failed to fetch server instructions:`,
161+
instructionsError,
162+
);
163+
}
164+
}
165+
146166
// Update timestamp on creation
147167
this.updateUserLastActivity(userId);
148168
return connection;

packages/api/src/mcp/registry/MCPServersRegistry.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,25 @@ export class MCPServersRegistry {
182182
return parsedConfig;
183183
}
184184

185+
/**
186+
* Updates the serverInstructions field for a server config.
187+
* Used to set instructions fetched from OAuth servers after successful connection.
188+
* @param serverName - The name of the server
189+
* @param instructions - The instructions string fetched from the server
190+
*/
191+
public async updateServerInstructions(serverName: string, instructions: string): Promise<void> {
192+
// Update in cache repository (YAML-defined servers)
193+
const configFromCache = await this.cacheConfigsRepo.get(serverName);
194+
if (configFromCache) {
195+
configFromCache.serverInstructions = instructions;
196+
await this.cacheConfigsRepo.update(serverName, configFromCache);
197+
// Clear read-through caches to ensure fresh data on next read
198+
await this.readThroughCache.clear();
199+
await this.readThroughCacheAll.clear();
200+
logger.debug(`[MCPServersRegistry] Updated serverInstructions for "${serverName}"`);
201+
}
202+
}
203+
185204
// TODO: This is currently used to determine if a server requires OAuth. However, this info can
186205
// can be determined through config.requiresOAuth. Refactor usages and remove this method.
187206
public async getOAuthServers(userId?: string): Promise<Set<string>> {

0 commit comments

Comments
 (0)