mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
🔁 feat: Allow "http" as Alias for "streamable-http" in MCP Options (#8624)
- Updated StreamableHTTPOptionsSchema to accept "http" alongside "streamable-http". - Enhanced isStreamableHTTPOptions function to handle both types and validate URLs accordingly. - Added tests to ensure correct processing of "http" type options and rejection of websocket URLs.
This commit is contained in:
parent
a01536ddb7
commit
365e3bca95
3 changed files with 65 additions and 4 deletions
|
|
@ -45,9 +45,12 @@ function isSSEOptions(options: t.MCPOptions): options is t.SSEOptions {
|
|||
* @returns True if options are for a streamable HTTP transport
|
||||
*/
|
||||
function isStreamableHTTPOptions(options: t.MCPOptions): options is t.StreamableHTTPOptions {
|
||||
if ('url' in options && options.type === 'streamable-http') {
|
||||
const protocol = new URL(options.url).protocol;
|
||||
return protocol !== 'ws:' && protocol !== 'wss:';
|
||||
if ('url' in options && 'type' in options) {
|
||||
const optionType = options.type as string;
|
||||
if (optionType === 'streamable-http' || optionType === 'http') {
|
||||
const protocol = new URL(options.url).protocol;
|
||||
return protocol !== 'ws:' && protocol !== 'wss:';
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -142,6 +145,7 @@ export class MCPConnection extends EventEmitter {
|
|||
} else if (isWebSocketOptions(options)) {
|
||||
type = 'websocket';
|
||||
} else if (isStreamableHTTPOptions(options)) {
|
||||
// Could be either 'streamable-http' or 'http', normalize to 'streamable-http'
|
||||
type = 'streamable-http';
|
||||
} else if (isSSEOptions(options)) {
|
||||
type = 'sse';
|
||||
|
|
|
|||
|
|
@ -140,6 +140,31 @@ describe('Environment Variable Extraction (MCP)', () => {
|
|||
|
||||
expect(result.headers).toEqual(options.headers);
|
||||
});
|
||||
|
||||
it('should accept "http" as an alias for "streamable-http"', () => {
|
||||
const options = {
|
||||
type: 'http',
|
||||
url: 'https://example.com/api',
|
||||
headers: {
|
||||
Authorization: 'Bearer token',
|
||||
},
|
||||
};
|
||||
|
||||
const result = StreamableHTTPOptionsSchema.parse(options);
|
||||
|
||||
expect(result.type).toBe('http');
|
||||
expect(result.url).toBe('https://example.com/api');
|
||||
expect(result.headers).toEqual(options.headers);
|
||||
});
|
||||
|
||||
it('should reject websocket URLs with "http" type', () => {
|
||||
const options = {
|
||||
type: 'http',
|
||||
url: 'ws://example.com/socket',
|
||||
};
|
||||
|
||||
expect(() => StreamableHTTPOptionsSchema.parse(options)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('processMCPEnv', () => {
|
||||
|
|
@ -298,6 +323,38 @@ describe('Environment Variable Extraction (MCP)', () => {
|
|||
expect(result.type).toBe('streamable-http');
|
||||
});
|
||||
|
||||
it('should maintain http type in processed options', () => {
|
||||
const obj = {
|
||||
type: 'http' as const,
|
||||
url: 'https://example.com/api',
|
||||
};
|
||||
|
||||
const result = processMCPEnv(obj as unknown as MCPOptions);
|
||||
|
||||
expect(result.type).toBe('http');
|
||||
});
|
||||
|
||||
it('should process headers in http options', () => {
|
||||
const user = createTestUser({ id: 'test-user-123' });
|
||||
const obj = {
|
||||
type: 'http' as const,
|
||||
url: 'https://example.com',
|
||||
headers: {
|
||||
Authorization: '${TEST_API_KEY}',
|
||||
'User-Id': '{{LIBRECHAT_USER_ID}}',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
|
||||
const result = processMCPEnv(obj as unknown as MCPOptions, user);
|
||||
|
||||
expect('headers' in result && result.headers).toEqual({
|
||||
Authorization: 'test-api-key-value',
|
||||
'User-Id': 'test-user-123',
|
||||
'Content-Type': 'application/json',
|
||||
});
|
||||
});
|
||||
|
||||
it('should process dynamic user fields in headers', () => {
|
||||
const user = createTestUser({
|
||||
id: 'user-123',
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export const SSEOptionsSchema = BaseOptionsSchema.extend({
|
|||
});
|
||||
|
||||
export const StreamableHTTPOptionsSchema = BaseOptionsSchema.extend({
|
||||
type: z.literal('streamable-http'),
|
||||
type: z.union([z.literal('streamable-http'), z.literal('http')]),
|
||||
headers: z.record(z.string(), z.string()).optional(),
|
||||
url: z
|
||||
.string()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue