mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-16 15:35:31 +01:00
🏷️ feat: Request Placeholders for Custom Endpoint & MCP Headers (#9095)
* feat: Add conversation ID support to custom endpoint headers
- Add LIBRECHAT_CONVERSATION_ID to customUserVars when provided
- Pass conversation ID to header resolution for dynamic headers
- Add comprehensive test coverage
Enables custom endpoints to access conversation context using {{LIBRECHAT_CONVERSATION_ID}} placeholder.
* fix: filter out unresolved placeholders from headers (thanks @MrunmayS)
* feat: add support for request body placeholders in custom endpoint headers
- Add {{LIBRECHAT_BODY_*}} placeholders for conversationId, parentMessageId, messageId
- Update tests to reflect new body placeholder functionality
* refactor resolveHeaders
* style: minor styling cleanup
* fix: type error in unit test
* feat: add body to other endpoints
* feat: add body for mcp tool calls
* chore: remove changes that unnecessarily increase scope after clarification of requirements
* refactor: move http.ts to packages/api and have RequestBody intersect with Express request body
* refactor: processMCPEnv now uses single object argument pattern
* refactor: update processMCPEnv to use 'options' parameter and align types across MCP connection classes
* feat: enhance MCP connection handling with dynamic request headers to pass request body fields
---------
Co-authored-by: Gopal Sharma <gopalsharma@gopal.sharma1>
Co-authored-by: s10gopal <36487439+s10gopal@users.noreply.github.com>
Co-authored-by: Dustin Healy <dustinhealy1@gmail.com>
This commit is contained in:
parent
627f0bffe5
commit
d7d02766ea
25 changed files with 353 additions and 171 deletions
|
|
@ -1,14 +1,15 @@
|
|||
import { logger } from '@librechat/data-schemas';
|
||||
import type { TokenMethods } from '@librechat/data-schemas';
|
||||
import type { TUser } from 'librechat-data-provider';
|
||||
import type { FlowStateManager } from '~/flow/manager';
|
||||
import type { MCPOAuthTokens } from '~/mcp/oauth';
|
||||
import { MCPConnectionFactory } from '../MCPConnectionFactory';
|
||||
import type * as t from '~/mcp/types';
|
||||
import { MCPConnectionFactory } from '~/mcp/MCPConnectionFactory';
|
||||
import { MCPConnection } from '~/mcp/connection';
|
||||
import { MCPOAuthHandler } from '~/mcp/oauth';
|
||||
import { MCPConnection } from '../connection';
|
||||
import { processMCPEnv } from '~/utils';
|
||||
import type * as t from '../types';
|
||||
|
||||
jest.mock('../connection');
|
||||
jest.mock('~/mcp/connection');
|
||||
jest.mock('~/mcp/oauth');
|
||||
jest.mock('~/utils');
|
||||
jest.mock('@librechat/data-schemas', () => ({
|
||||
|
|
@ -74,7 +75,7 @@ describe('MCPConnectionFactory', () => {
|
|||
const connection = await MCPConnectionFactory.create(basicOptions);
|
||||
|
||||
expect(connection).toBe(mockConnectionInstance);
|
||||
expect(mockProcessMCPEnv).toHaveBeenCalledWith(mockServerConfig, undefined, undefined);
|
||||
expect(mockProcessMCPEnv).toHaveBeenCalledWith({ options: mockServerConfig });
|
||||
expect(mockMCPConnection).toHaveBeenCalledWith({
|
||||
serverName: 'test-server',
|
||||
serverConfig: mockServerConfig,
|
||||
|
|
@ -115,7 +116,7 @@ describe('MCPConnectionFactory', () => {
|
|||
const connection = await MCPConnectionFactory.create(basicOptions, oauthOptions);
|
||||
|
||||
expect(connection).toBe(mockConnectionInstance);
|
||||
expect(mockProcessMCPEnv).toHaveBeenCalledWith(mockServerConfig, mockUser, undefined);
|
||||
expect(mockProcessMCPEnv).toHaveBeenCalledWith({ options: mockServerConfig, user: mockUser });
|
||||
expect(mockMCPConnection).toHaveBeenCalledWith({
|
||||
serverName: 'test-server',
|
||||
serverConfig: mockServerConfig,
|
||||
|
|
@ -132,12 +133,12 @@ describe('MCPConnectionFactory', () => {
|
|||
serverConfig: mockServerConfig,
|
||||
};
|
||||
|
||||
const oauthOptions = {
|
||||
const oauthOptions: t.OAuthConnectionOptions = {
|
||||
useOAuth: true as const,
|
||||
user: mockUser,
|
||||
flowManager: mockFlowManager,
|
||||
tokenMethods: {
|
||||
findToken: undefined as unknown as () => Promise<any>,
|
||||
findToken: undefined as unknown as TokenMethods['findToken'],
|
||||
createToken: jest.fn(),
|
||||
updateToken: jest.fn(),
|
||||
deleteTokens: jest.fn(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue