librechat-data-provider 0.7.82 → 0.7.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react-query/index.es.js +1 -1
- package/dist/react-query/index.es.js.map +1 -1
- package/package.json +1 -1
- package/specs/mcp.spec.ts +101 -1
- package/src/config.ts +20 -0
- package/src/generate.ts +3 -2
- package/src/mcp.ts +18 -0
- package/src/schemas.ts +1 -0
package/package.json
CHANGED
package/specs/mcp.spec.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StdioOptionsSchema, processMCPEnv, MCPOptions } from '../src/mcp';
|
|
1
|
+
import { StdioOptionsSchema, StreamableHTTPOptionsSchema, processMCPEnv, MCPOptions } from '../src/mcp';
|
|
2
2
|
|
|
3
3
|
describe('Environment Variable Extraction (MCP)', () => {
|
|
4
4
|
const originalEnv = process.env;
|
|
@@ -50,6 +50,74 @@ describe('Environment Variable Extraction (MCP)', () => {
|
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
+
describe('StreamableHTTPOptionsSchema', () => {
|
|
54
|
+
it('should validate a valid streamable-http configuration', () => {
|
|
55
|
+
const options = {
|
|
56
|
+
type: 'streamable-http',
|
|
57
|
+
url: 'https://example.com/api',
|
|
58
|
+
headers: {
|
|
59
|
+
Authorization: 'Bearer token',
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const result = StreamableHTTPOptionsSchema.parse(options);
|
|
65
|
+
|
|
66
|
+
expect(result).toEqual(options);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should reject websocket URLs', () => {
|
|
70
|
+
const options = {
|
|
71
|
+
type: 'streamable-http',
|
|
72
|
+
url: 'ws://example.com/socket',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
expect(() => StreamableHTTPOptionsSchema.parse(options)).toThrow();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should reject secure websocket URLs', () => {
|
|
79
|
+
const options = {
|
|
80
|
+
type: 'streamable-http',
|
|
81
|
+
url: 'wss://example.com/socket',
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
expect(() => StreamableHTTPOptionsSchema.parse(options)).toThrow();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should require type field to be set explicitly', () => {
|
|
88
|
+
const options = {
|
|
89
|
+
url: 'https://example.com/api',
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Type is now required, so parsing should fail
|
|
93
|
+
expect(() => StreamableHTTPOptionsSchema.parse(options)).toThrow();
|
|
94
|
+
|
|
95
|
+
// With type provided, it should pass
|
|
96
|
+
const validOptions = {
|
|
97
|
+
type: 'streamable-http' as const,
|
|
98
|
+
url: 'https://example.com/api',
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const result = StreamableHTTPOptionsSchema.parse(validOptions);
|
|
102
|
+
expect(result.type).toBe('streamable-http');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should validate headers as record of strings', () => {
|
|
106
|
+
const options = {
|
|
107
|
+
type: 'streamable-http',
|
|
108
|
+
url: 'https://example.com/api',
|
|
109
|
+
headers: {
|
|
110
|
+
'X-API-Key': '123456',
|
|
111
|
+
'User-Agent': 'MCP Client',
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const result = StreamableHTTPOptionsSchema.parse(options);
|
|
116
|
+
|
|
117
|
+
expect(result.headers).toEqual(options.headers);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
53
121
|
describe('processMCPEnv', () => {
|
|
54
122
|
it('should create a deep clone of the input object', () => {
|
|
55
123
|
const originalObj: MCPOptions = {
|
|
@@ -173,5 +241,37 @@ describe('Environment Variable Extraction (MCP)', () => {
|
|
|
173
241
|
// Second user's config should be unchanged
|
|
174
242
|
expect('headers' in resultUser2 && resultUser2.headers?.['User-Id']).toBe(user2Id);
|
|
175
243
|
});
|
|
244
|
+
|
|
245
|
+
it('should process headers in streamable-http options', () => {
|
|
246
|
+
const userId = 'test-user-123';
|
|
247
|
+
const obj: MCPOptions = {
|
|
248
|
+
type: 'streamable-http',
|
|
249
|
+
url: 'https://example.com',
|
|
250
|
+
headers: {
|
|
251
|
+
Authorization: '${TEST_API_KEY}',
|
|
252
|
+
'User-Id': '{{LIBRECHAT_USER_ID}}',
|
|
253
|
+
'Content-Type': 'application/json',
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const result = processMCPEnv(obj, userId);
|
|
258
|
+
|
|
259
|
+
expect('headers' in result && result.headers).toEqual({
|
|
260
|
+
Authorization: 'test-api-key-value',
|
|
261
|
+
'User-Id': 'test-user-123',
|
|
262
|
+
'Content-Type': 'application/json',
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('should maintain streamable-http type in processed options', () => {
|
|
267
|
+
const obj: MCPOptions = {
|
|
268
|
+
type: 'streamable-http',
|
|
269
|
+
url: 'https://example.com/api',
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const result = processMCPEnv(obj);
|
|
273
|
+
|
|
274
|
+
expect(result.type).toBe('streamable-http');
|
|
275
|
+
});
|
|
176
276
|
});
|
|
177
277
|
});
|
package/src/config.ts
CHANGED
|
@@ -52,6 +52,7 @@ export const excludedKeys = new Set([
|
|
|
52
52
|
'model',
|
|
53
53
|
'files',
|
|
54
54
|
'spec',
|
|
55
|
+
'disableParams',
|
|
55
56
|
]);
|
|
56
57
|
|
|
57
58
|
export enum SettingsViews {
|
|
@@ -505,10 +506,28 @@ export const intefaceSchema = z
|
|
|
505
506
|
export type TInterfaceConfig = z.infer<typeof intefaceSchema>;
|
|
506
507
|
export type TBalanceConfig = z.infer<typeof balanceSchema>;
|
|
507
508
|
|
|
509
|
+
export const turnstileOptionsSchema = z
|
|
510
|
+
.object({
|
|
511
|
+
language: z.string().default('auto'),
|
|
512
|
+
size: z.enum(['normal', 'compact', 'flexible', 'invisible']).default('normal'),
|
|
513
|
+
})
|
|
514
|
+
.default({
|
|
515
|
+
language: 'auto',
|
|
516
|
+
size: 'normal',
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
export const turnstileSchema = z.object({
|
|
520
|
+
siteKey: z.string(),
|
|
521
|
+
options: turnstileOptionsSchema.optional(),
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
export type TTurnstileConfig = z.infer<typeof turnstileSchema>;
|
|
525
|
+
|
|
508
526
|
export type TStartupConfig = {
|
|
509
527
|
appTitle: string;
|
|
510
528
|
socialLogins?: string[];
|
|
511
529
|
interface?: TInterfaceConfig;
|
|
530
|
+
turnstile?: TTurnstileConfig;
|
|
512
531
|
balance?: TBalanceConfig;
|
|
513
532
|
discordLoginEnabled: boolean;
|
|
514
533
|
facebookLoginEnabled: boolean;
|
|
@@ -578,6 +597,7 @@ export const configSchema = z.object({
|
|
|
578
597
|
filteredTools: z.array(z.string()).optional(),
|
|
579
598
|
mcpServers: MCPServersSchema.optional(),
|
|
580
599
|
interface: intefaceSchema,
|
|
600
|
+
turnstile: turnstileSchema.optional(),
|
|
581
601
|
fileStrategy: fileSourceSchema.default(FileSources.local),
|
|
582
602
|
actions: z
|
|
583
603
|
.object({
|
package/src/generate.ts
CHANGED
|
@@ -358,7 +358,7 @@ export function validateSettingDefinitions(settings: SettingsConfiguration): voi
|
|
|
358
358
|
// continue;
|
|
359
359
|
}
|
|
360
360
|
setting.includeInput =
|
|
361
|
-
setting.type === SettingTypes.Number ? setting.includeInput ?? true : false; // Default to true if type is number
|
|
361
|
+
setting.type === SettingTypes.Number ? (setting.includeInput ?? true) : false; // Default to true if type is number
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
if (setting.component === ComponentTypes.Slider && setting.type === SettingTypes.Number) {
|
|
@@ -445,7 +445,8 @@ export function validateSettingDefinitions(settings: SettingsConfiguration): voi
|
|
|
445
445
|
|
|
446
446
|
// Validate optionType and conversation schema
|
|
447
447
|
if (setting.optionType !== OptionTypes.Custom) {
|
|
448
|
-
const conversationSchema =
|
|
448
|
+
const conversationSchema =
|
|
449
|
+
tConversationSchema.shape[setting.key as keyof Omit<TConversation, 'disableParams'>];
|
|
449
450
|
if (!conversationSchema) {
|
|
450
451
|
errors.push({
|
|
451
452
|
code: ZodIssueCode.custom,
|
package/src/mcp.ts
CHANGED
|
@@ -82,10 +82,28 @@ export const SSEOptionsSchema = BaseOptionsSchema.extend({
|
|
|
82
82
|
),
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
export const StreamableHTTPOptionsSchema = BaseOptionsSchema.extend({
|
|
86
|
+
type: z.literal('streamable-http'),
|
|
87
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
88
|
+
url: z
|
|
89
|
+
.string()
|
|
90
|
+
.url()
|
|
91
|
+
.refine(
|
|
92
|
+
(val) => {
|
|
93
|
+
const protocol = new URL(val).protocol;
|
|
94
|
+
return protocol !== 'ws:' && protocol !== 'wss:';
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
message: 'Streamable HTTP URL must not start with ws:// or wss://',
|
|
98
|
+
},
|
|
99
|
+
),
|
|
100
|
+
});
|
|
101
|
+
|
|
85
102
|
export const MCPOptionsSchema = z.union([
|
|
86
103
|
StdioOptionsSchema,
|
|
87
104
|
WebSocketOptionsSchema,
|
|
88
105
|
SSEOptionsSchema,
|
|
106
|
+
StreamableHTTPOptionsSchema,
|
|
89
107
|
]);
|
|
90
108
|
|
|
91
109
|
export const MCPServersSchema = z.record(z.string(), MCPOptionsSchema);
|
package/src/schemas.ts
CHANGED