@forklaunch/core 0.15.3 → 0.15.5

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/lib/http/index.js CHANGED
@@ -3100,11 +3100,6 @@ var import_common10 = require("@forklaunch/common");
3100
3100
  var import_fastmcp_fork = require("@forklaunch/fastmcp-fork");
3101
3101
  var import_zod = require("@forklaunch/validator/zod");
3102
3102
 
3103
- // src/http/guards/isVersionedInputSchema.ts
3104
- function isUnionable(schema) {
3105
- return schema.length > 1;
3106
- }
3107
-
3108
3103
  // src/http/router/unpackRouters.ts
3109
3104
  function unpackRouters(routers, recursiveBasePath = []) {
3110
3105
  return routers.reduce((acc, router) => {
@@ -3134,8 +3129,12 @@ function generateInputSchema(schemaValidator, body, params, query, requestHeader
3134
3129
  ..."contentType" in body ? { contentType: body.contentType } : {},
3135
3130
  body: schemaValidator.schemify(discriminatedBody.schema)
3136
3131
  } : {},
3137
- ...params ? { params: schemaValidator.schemify(params) } : {},
3138
- ...query ? { query: schemaValidator.schemify(query) } : {},
3132
+ ...params ? {
3133
+ params: schemaValidator.schemify(params)
3134
+ } : {},
3135
+ ...query ? {
3136
+ query: schemaValidator.schemify(query)
3137
+ } : {},
3139
3138
  ...requestHeaders ? {
3140
3139
  headers: schemaValidator.schemify({
3141
3140
  ...requestHeaders,
@@ -3198,163 +3197,172 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
3198
3197
  )
3199
3198
  );
3200
3199
  }
3201
- mcpServer.addTool({
3202
- name: route.contractDetails.name,
3203
- description: route.contractDetails.summary,
3204
- parameters: isUnionable(inputSchemas) ? schemaValidator.union(inputSchemas) : inputSchemas[0],
3205
- execute: async (args) => {
3206
- const { contentType, body, params, query, headers } = args;
3207
- let url = `${protocol}://${host}:${port}${fullPath}${route.path}`;
3208
- if (params) {
3209
- for (const key in params) {
3210
- url = url.replace(
3211
- `:${key}`,
3212
- encodeURIComponent(params[key])
3213
- );
3214
- }
3215
- }
3216
- let bodySchema;
3217
- let responsesSchemas;
3218
- if (route.contractDetails.versions) {
3219
- Object.values(route.contractDetails.versions).forEach(
3220
- (version2, index) => {
3221
- if (version2.body && schemaValidator.parse(inputSchemas[index], args).ok) {
3222
- bodySchema = version2.body;
3223
- responsesSchemas = version2.responses;
3224
- }
3225
- }
3226
- );
3227
- } else {
3228
- bodySchema = route.contractDetails.body;
3229
- responsesSchemas = route.contractDetails.responses;
3230
- }
3231
- const discriminatedBody = bodySchema ? discriminateBody(schemaValidator, bodySchema) : void 0;
3232
- let parsedBody;
3233
- if (discriminatedBody) {
3234
- switch (discriminatedBody.parserType) {
3235
- case "json": {
3236
- parsedBody = (0, import_common10.safeStringify)(body);
3237
- break;
3200
+ inputSchemas.forEach((inputSchema, index) => {
3201
+ mcpServer.addTool({
3202
+ name: route.contractDetails.name + (Object.keys(route.contractDetails.versions ?? {}).length > 1 ? ` [v${Object.keys(route.contractDetails.versions ?? {})[index]}]` : ""),
3203
+ description: route.contractDetails.summary,
3204
+ parameters: inputSchema,
3205
+ execute: async (args) => {
3206
+ const { contentType, body, params, query, headers } = args;
3207
+ let url = `${protocol}://${host}:${port}${fullPath}${route.path}`;
3208
+ if (params) {
3209
+ for (const key in params) {
3210
+ url = url.replace(
3211
+ `:${key}`,
3212
+ encodeURIComponent(params[key])
3213
+ );
3238
3214
  }
3239
- case "text": {
3240
- parsedBody = body;
3241
- break;
3242
- }
3243
- case "file": {
3244
- parsedBody = body;
3245
- break;
3215
+ }
3216
+ let bodySchema;
3217
+ let responsesSchemas;
3218
+ if (route.contractDetails.versions) {
3219
+ const version2 = route.contractDetails.versions[index];
3220
+ if (version2.body && schemaValidator.parse(inputSchema, args).ok) {
3221
+ bodySchema = version2.body;
3222
+ responsesSchemas = version2.responses;
3246
3223
  }
3247
- case "multipart": {
3248
- const formData = new FormData();
3249
- if ((0, import_common10.isRecord)(body)) {
3250
- for (const key in body) {
3251
- if (typeof body[key] === "string" || body[key] instanceof Blob) {
3252
- formData.append(key, body[key]);
3253
- } else {
3254
- throw new Error("Body is not a valid multipart object");
3224
+ } else {
3225
+ bodySchema = route.contractDetails.body;
3226
+ responsesSchemas = route.contractDetails.responses;
3227
+ }
3228
+ const discriminatedBody = bodySchema ? discriminateBody(schemaValidator, bodySchema) : void 0;
3229
+ let parsedBody;
3230
+ if (discriminatedBody) {
3231
+ switch (discriminatedBody.parserType) {
3232
+ case "json": {
3233
+ parsedBody = (0, import_common10.safeStringify)(body);
3234
+ break;
3235
+ }
3236
+ case "text": {
3237
+ parsedBody = body;
3238
+ break;
3239
+ }
3240
+ case "file": {
3241
+ parsedBody = Buffer.from((0, import_common10.safeStringify)(body));
3242
+ break;
3243
+ }
3244
+ case "multipart": {
3245
+ const formData = new FormData();
3246
+ if ((0, import_common10.isRecord)(body)) {
3247
+ for (const key in body) {
3248
+ if (typeof body[key] === "string") {
3249
+ if (schemaValidator.isInstanceOf(
3250
+ body[key],
3251
+ schemaValidator.file
3252
+ )) {
3253
+ formData.append(
3254
+ key,
3255
+ new Blob([Buffer.from(body[key])])
3256
+ );
3257
+ } else {
3258
+ formData.append(key, body[key]);
3259
+ }
3260
+ } else {
3261
+ throw new Error("Body is not a valid multipart object");
3262
+ }
3255
3263
  }
3264
+ } else {
3265
+ throw new Error("Body is not a valid multipart object");
3256
3266
  }
3257
- } else {
3258
- throw new Error("Body is not a valid multipart object");
3267
+ parsedBody = formData;
3268
+ break;
3259
3269
  }
3260
- parsedBody = formData;
3261
- break;
3262
- }
3263
- case "urlEncoded": {
3264
- if ((0, import_common10.isRecord)(body)) {
3265
- parsedBody = new URLSearchParams(
3266
- Object.entries(body).map(([key, value]) => [
3267
- key,
3268
- (0, import_common10.safeStringify)(value)
3269
- ])
3270
- );
3271
- } else {
3272
- throw new Error("Body is not a valid url encoded object");
3270
+ case "urlEncoded": {
3271
+ if ((0, import_common10.isRecord)(body)) {
3272
+ parsedBody = new URLSearchParams(
3273
+ Object.entries(body).map(([key, value]) => [
3274
+ key,
3275
+ (0, import_common10.safeStringify)(value)
3276
+ ])
3277
+ );
3278
+ } else {
3279
+ throw new Error("Body is not a valid url encoded object");
3280
+ }
3281
+ break;
3282
+ }
3283
+ default: {
3284
+ (0, import_common10.isNever)(discriminatedBody.parserType);
3285
+ parsedBody = (0, import_common10.safeStringify)(body);
3286
+ break;
3273
3287
  }
3274
- break;
3275
- }
3276
- default: {
3277
- (0, import_common10.isNever)(discriminatedBody.parserType);
3278
- parsedBody = (0, import_common10.safeStringify)(body);
3279
- break;
3280
3288
  }
3281
3289
  }
3282
- }
3283
- if (query) {
3284
- const queryString = new URLSearchParams(
3285
- Object.entries(query).map(([key, value]) => [
3286
- key,
3287
- (0, import_common10.safeStringify)(value)
3288
- ])
3289
- ).toString();
3290
- url += queryString ? `?${queryString}` : "";
3291
- }
3292
- const response = await fetch(encodeURI(url), {
3293
- method: route.method.toUpperCase(),
3294
- headers: {
3295
- ...headers,
3296
- ...discriminatedBody?.contentType != "multipart/form-data" ? {
3297
- "Content-Type": contentType ?? discriminatedBody?.contentType
3298
- } : {}
3299
- },
3300
- body: parsedBody
3301
- });
3302
- if (response.status >= 300) {
3303
- throw new Error(
3304
- `Error received while proxying request to ${url}: ${await response.text()}`
3305
- );
3306
- }
3307
- if (!responsesSchemas) {
3308
- throw new Error("No responses schemas found");
3309
- }
3310
- const contractContentType = discriminateResponseBodies(
3311
- schemaValidator,
3312
- responsesSchemas
3313
- )[response.status].contentType;
3314
- switch (contentTypeMap && contentTypeMap[contractContentType] ? contentTypeMap[contractContentType] : contractContentType) {
3315
- case "application/json":
3316
- return {
3317
- content: [
3318
- {
3319
- type: "text",
3320
- text: (0, import_common10.safeStringify)(await response.json())
3321
- }
3322
- ]
3323
- };
3324
- case "text/plain":
3325
- return {
3326
- content: [
3327
- { type: "text", text: await response.text() }
3328
- ]
3329
- };
3330
- case "application/octet-stream":
3331
- return {
3332
- content: [
3333
- {
3334
- type: "resource",
3335
- resource: {
3336
- uri: response.url,
3337
- blob: Buffer.from(
3338
- await (await response.blob()).arrayBuffer()
3339
- ).toString("base64")
3290
+ if (query) {
3291
+ const queryString = new URLSearchParams(
3292
+ Object.entries(query).map(([key, value]) => [
3293
+ key,
3294
+ (0, import_common10.safeStringify)(value)
3295
+ ])
3296
+ ).toString();
3297
+ url += queryString ? `?${queryString}` : "";
3298
+ }
3299
+ const response = await fetch(encodeURI(url), {
3300
+ method: route.method.toUpperCase(),
3301
+ headers: {
3302
+ ...headers,
3303
+ ...discriminatedBody?.contentType != "multipart/form-data" ? {
3304
+ "Content-Type": contentType ?? discriminatedBody?.contentType
3305
+ } : {}
3306
+ },
3307
+ body: parsedBody
3308
+ });
3309
+ if (response.status >= 300) {
3310
+ throw new Error(
3311
+ `Error received while proxying request to ${url}: ${await response.text()}`
3312
+ );
3313
+ }
3314
+ if (!responsesSchemas) {
3315
+ throw new Error("No responses schemas found");
3316
+ }
3317
+ const contractContentType = discriminateResponseBodies(
3318
+ schemaValidator,
3319
+ responsesSchemas
3320
+ )[response.status].contentType;
3321
+ switch (contentTypeMap && contentTypeMap[contractContentType] ? contentTypeMap[contractContentType] : contractContentType) {
3322
+ case "application/json":
3323
+ return {
3324
+ content: [
3325
+ {
3326
+ type: "text",
3327
+ text: (0, import_common10.safeStringify)(await response.json())
3340
3328
  }
3341
- }
3342
- ]
3343
- };
3344
- case "text/event-stream":
3345
- return {
3346
- content: [
3347
- { type: "text", text: await response.text() }
3348
- ]
3349
- };
3350
- default:
3351
- return {
3352
- content: [
3353
- { type: "text", text: await response.text() }
3354
- ]
3355
- };
3329
+ ]
3330
+ };
3331
+ case "text/plain":
3332
+ return {
3333
+ content: [
3334
+ { type: "text", text: await response.text() }
3335
+ ]
3336
+ };
3337
+ case "application/octet-stream":
3338
+ return {
3339
+ content: [
3340
+ {
3341
+ type: "resource",
3342
+ resource: {
3343
+ uri: response.url,
3344
+ blob: Buffer.from(
3345
+ await (await response.blob()).arrayBuffer()
3346
+ ).toString("base64")
3347
+ }
3348
+ }
3349
+ ]
3350
+ };
3351
+ case "text/event-stream":
3352
+ return {
3353
+ content: [
3354
+ { type: "text", text: await response.text() }
3355
+ ]
3356
+ };
3357
+ default:
3358
+ return {
3359
+ content: [
3360
+ { type: "text", text: await response.text() }
3361
+ ]
3362
+ };
3363
+ }
3356
3364
  }
3357
- }
3365
+ });
3358
3366
  });
3359
3367
  });
3360
3368
  });