feat: add body for mcp tool calls

This commit is contained in:
Dustin Healy 2025-08-10 14:45:07 -07:00
parent 888e3a31cf
commit 274987712c
3 changed files with 14 additions and 6 deletions

View file

@ -189,6 +189,7 @@ async function createMCPTool({ req, res, toolKey, provider: _provider }) {
},
oauthStart,
oauthEnd,
body: req.body,
});
if (isAssistantsEndpoint(provider) && Array.isArray(result)) {

View file

@ -3,7 +3,7 @@ import { CallToolResultSchema, ErrorCode, McpError } from '@modelcontextprotocol
import type { OAuthClientInformation } from '@modelcontextprotocol/sdk/shared/auth.js';
import type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
import type { TokenMethods } from '@librechat/data-schemas';
import type { TUser } from 'librechat-data-provider';
import type { TUser, RequestBody } from 'librechat-data-provider';
import type { MCPOAuthTokens, MCPOAuthFlowMetadata } from './oauth/types';
import type { FlowStateManager } from '~/flow/manager';
import type { JsonSchemaType } from '~/types/zod';
@ -373,6 +373,7 @@ export class MCPManager {
oauthEnd,
signal,
returnOnOAuth = false,
body,
}: {
user: TUser;
serverName: string;
@ -383,6 +384,7 @@ export class MCPManager {
oauthEnd?: () => Promise<void>;
signal?: AbortSignal;
returnOnOAuth?: boolean;
body?: RequestBody;
}): Promise<MCPConnection> {
const userId = user.id;
if (!userId) {
@ -432,7 +434,7 @@ export class MCPManager {
);
}
config = { ...(processMCPEnv(config, user, customUserVars) ?? {}) };
config = { ...(processMCPEnv(config, user, customUserVars, body) ?? {}) };
/** If no in-memory tokens, tokens from persistent storage */
let tokens: MCPOAuthTokens | null = null;
if (tokenMethods?.findToken) {
@ -859,6 +861,7 @@ export class MCPManager {
oauthStart,
oauthEnd,
customUserVars,
body,
}: {
user?: TUser;
serverName: string;
@ -871,6 +874,7 @@ export class MCPManager {
flowManager: FlowStateManager<MCPOAuthTokens | null>;
oauthStart?: (authURL: string) => Promise<void>;
oauthEnd?: () => Promise<void>;
body?: RequestBody;
}): Promise<t.FormattedToolResponse> {
/** User-specific connection */
let connection: MCPConnection | undefined;
@ -890,6 +894,7 @@ export class MCPManager {
oauthEnd,
signal: options?.signal,
customUserVars,
body,
});
} else {
/** App-level connection */

View file

@ -141,12 +141,14 @@ function processSingleValue({
* @param obj - The object to process
* @param user - The user object containing all user fields
* @param customUserVars - vars that user set in settings
* @param body - the body of the request that is being processed
* @returns - The processed object with environment variables replaced
*/
export function processMCPEnv(
obj: Readonly<MCPOptions>,
user?: TUser,
customUserVars?: Record<string, string>,
body?: RequestBody,
): MCPOptions {
if (obj === null || obj === undefined) {
return obj;
@ -157,7 +159,7 @@ export function processMCPEnv(
if ('env' in newObj && newObj.env) {
const processedEnv: Record<string, string> = {};
for (const [key, originalValue] of Object.entries(newObj.env)) {
processedEnv[key] = processSingleValue({ originalValue, customUserVars, user });
processedEnv[key] = processSingleValue({ originalValue, customUserVars, user, body });
}
newObj.env = processedEnv;
}
@ -165,7 +167,7 @@ export function processMCPEnv(
if ('args' in newObj && newObj.args) {
const processedArgs: string[] = [];
for (const originalValue of newObj.args) {
processedArgs.push(processSingleValue({ originalValue, customUserVars, user }));
processedArgs.push(processSingleValue({ originalValue, customUserVars, user, body }));
}
newObj.args = processedArgs;
}
@ -175,14 +177,14 @@ export function processMCPEnv(
if ('headers' in newObj && newObj.headers) {
const processedHeaders: Record<string, string> = {};
for (const [key, originalValue] of Object.entries(newObj.headers)) {
processedHeaders[key] = processSingleValue({ originalValue, customUserVars, user });
processedHeaders[key] = processSingleValue({ originalValue, customUserVars, user, body });
}
newObj.headers = processedHeaders;
}
// Process URL if it exists (for WebSocket, SSE, StreamableHTTP types)
if ('url' in newObj && newObj.url) {
newObj.url = processSingleValue({ originalValue: newObj.url, customUserVars, user });
newObj.url = processSingleValue({ originalValue: newObj.url, customUserVars, user, body });
}
return newObj;