@frontmcp/adapters 1.8.3 → 1.8.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/index.js CHANGED
@@ -46,7 +46,7 @@ module.exports = __toCommonJS(index_exports);
46
46
 
47
47
  // libs/adapters/src/openapi/openapi.adapter.ts
48
48
  var import_mcp_from_openapi3 = require("mcp-from-openapi");
49
- var import_sdk4 = require("@frontmcp/sdk");
49
+ var import_sdk5 = require("@frontmcp/sdk");
50
50
 
51
51
  // libs/adapters/src/openapi/openapi-spec-poller.ts
52
52
  var import_mcp_from_openapi = require("mcp-from-openapi");
@@ -219,6 +219,7 @@ var OpenApiSpecPoller = class {
219
219
 
220
220
  // libs/adapters/src/openapi/openapi.security.ts
221
221
  var import_mcp_from_openapi2 = require("mcp-from-openapi");
222
+ var import_sdk2 = require("@frontmcp/sdk");
222
223
  async function createSecurityContextFromAuth(tool2, ctx, options) {
223
224
  if (options.securityResolver) {
224
225
  return await options.securityResolver(tool2, ctx);
@@ -273,7 +274,7 @@ async function createSecurityContextFromAuth(tool2, ctx, options) {
273
274
  throw err;
274
275
  }
275
276
  const errorMessage = err instanceof Error ? err.message : String(err);
276
- throw new Error(`authProviderMapper['${scheme}'] threw an error: ${errorMessage}`);
277
+ throw new Error(`authProviderMapper['${scheme}'] threw an error: ${errorMessage}`, { cause: err });
277
278
  }
278
279
  }
279
280
  }
@@ -321,19 +322,163 @@ function extractSecuritySchemes(tools) {
321
322
  }
322
323
  return schemes;
323
324
  }
325
+ function describeSecuritySchemes(tools) {
326
+ const schemes = /* @__PURE__ */ new Map();
327
+ for (const tool2 of tools) {
328
+ for (const mapper of tool2.mapper) {
329
+ if (mapper.security?.scheme && !schemes.has(mapper.security.scheme)) {
330
+ schemes.set(mapper.security.scheme, mapper.security);
331
+ }
332
+ }
333
+ }
334
+ return schemes;
335
+ }
336
+ function schemeParametersOf(tools) {
337
+ const parameters = /* @__PURE__ */ new Map();
338
+ for (const tool2 of tools) {
339
+ for (const mapper of tool2.mapper) {
340
+ const scheme = mapper.security?.scheme;
341
+ if (scheme && !parameters.has(scheme)) parameters.set(scheme, mapper);
342
+ }
343
+ }
344
+ return parameters;
345
+ }
346
+ function headerCredentialSource(parameter, options) {
347
+ if (!parameter) return void 0;
348
+ const staticHeaders = new Headers(options.additionalHeaders ?? {});
349
+ if (carriesSchemeParameter(parameter, new URL("http://startup.invalid/"), staticHeaders)) return "static";
350
+ if (options.headersMapper && (parameter.type === "header" || parameter.type === "cookie")) return "per-request";
351
+ return void 0;
352
+ }
353
+ function isBearerScheme(security) {
354
+ if (!security || security.type !== "http") return false;
355
+ return (security.httpScheme ?? "bearer").toLowerCase() === "bearer";
356
+ }
357
+ function credentialFieldOf(security) {
358
+ if (security?.type === "apiKey") return "apiKey";
359
+ if (security?.type === "oauth2" || security?.type === "openIdConnect") return "oauth2Token";
360
+ if (security?.type === "http" && security.httpScheme?.toLowerCase() === "basic") return "basic";
361
+ return "jwt";
362
+ }
363
+ function formatMissingSecurityMappingsError(adapterName, tools, missingMappings) {
364
+ const schemes = describeSecuritySchemes(tools);
365
+ const fieldOf = (scheme) => credentialFieldOf(schemes.get(scheme));
366
+ const firstField = fieldOf(missingMappings[0] ?? "");
367
+ const bearerSchemes = missingMappings.filter((scheme) => isBearerScheme(schemes.get(scheme)));
368
+ const lines = [
369
+ `[OpenAPI Adapter: ${adapterName}] Invalid security configuration.`,
370
+ `Missing auth provider mappings for security schemes: ${missingMappings.join(", ")}`,
371
+ "",
372
+ "Your OpenAPI spec requires these security schemes, but no credential option covers them.",
373
+ "",
374
+ "Add one of the following to your adapter configuration:",
375
+ "",
376
+ "1. authProviderMapper (recommended): a function per scheme that returns the credential issued for the API:",
377
+ " authProviderMapper: {",
378
+ ...missingMappings.map((scheme) => ` '${scheme}': (ctx) => getApiCredential(ctx), // the ${fieldOf(scheme)}`),
379
+ " }",
380
+ "",
381
+ "2. securityResolver:",
382
+ ` securityResolver: async (tool, ctx) => ({ ${firstField}: await getApiCredential(ctx) })`,
383
+ "",
384
+ "3. staticAuth (one credential for every caller):",
385
+ ` staticAuth: { ${firstField}: process.env.API_CREDENTIAL }`
386
+ ];
387
+ if (bearerSchemes.length > 0) {
388
+ lines.push(
389
+ "",
390
+ `4. passthroughCallerToken: true, for the HTTP bearer schemes (${bearerSchemes.join(", ")}) only, and only if the API`,
391
+ " accepts the MCP client's own token (same issuer and audience). It sends nothing for other schemes."
392
+ );
393
+ }
394
+ return lines.join("\n");
395
+ }
396
+ function authenticationRequiredError(tool2) {
397
+ const required = requiredSecurityOf(tool2);
398
+ const schemes = [...new Map(required.map((security) => [security.scheme, security])).values()];
399
+ const schemesStr = schemes.map((security) => `${security.scheme} (${security.type})`).join(", ") || "unknown";
400
+ const first = schemes[0];
401
+ const firstScheme = first?.scheme ?? "BearerAuth";
402
+ const field = credentialFieldOf(first);
403
+ const bearerSchemes = schemes.filter(isBearerScheme).map((security) => security.scheme);
404
+ const solutions = [
405
+ ` 1. Add authProviderMapper: { '${firstScheme}': (ctx) => getApiCredential(ctx) }, returning the ${field} issued for the API`,
406
+ ` 2. Add securityResolver: async (tool, ctx) => ({ ${field}: await getApiCredential(ctx) })`,
407
+ ` 3. Add staticAuth: { ${field}: process.env.API_CREDENTIAL }`
408
+ ];
409
+ if (bearerSchemes.length > 0) {
410
+ solutions.push(
411
+ ` 4. Set passthroughCallerToken: true, only if the API accepts the MCP client's own token (it fills ${bearerSchemes.join(", ")} only)`
412
+ );
413
+ }
414
+ return new Error(
415
+ `Authentication required for tool '${tool2.name}': no credential for its security schemes.
416
+ Required security schemes: ${schemesStr}
417
+ Solutions:
418
+ ` + solutions.join("\n")
419
+ );
420
+ }
421
+ function requiredSecurityOf(tool2) {
422
+ return tool2.mapper.flatMap((mapper) => mapper.security && mapper.required === true ? [mapper.security] : []);
423
+ }
424
+ function authorizationSchemeOf(security) {
425
+ if (security?.type === "http") return (security.httpScheme ?? "bearer").toLowerCase();
426
+ if (security?.type === "oauth2" || security?.type === "openIdConnect") return "bearer";
427
+ return void 0;
428
+ }
429
+ function carriesSchemeParameter(mapper, url, headers) {
430
+ if (mapper.type === "query") return !!url.searchParams.get(mapper.key);
431
+ if (mapper.type === "cookie") {
432
+ return (headers.get("cookie") ?? "").split(";").some((pair) => {
433
+ const [name, ...value2] = pair.trim().split("=");
434
+ return name === mapper.key && value2.join("=") !== "";
435
+ });
436
+ }
437
+ if (mapper.type !== "header") return false;
438
+ const value = headers.get(mapper.key)?.trim();
439
+ if (!value) return false;
440
+ const scheme = authorizationSchemeOf(mapper.security);
441
+ if (!scheme) return true;
442
+ const space = value.indexOf(" ");
443
+ return space > 0 && value.slice(0, space).toLowerCase() === scheme && value.slice(space + 1).trim() !== "";
444
+ }
445
+ function assertRequestHasCredential(tool2, url, headers) {
446
+ const securityMappers = tool2.mapper.filter((mapper) => mapper.security && mapper.required === true);
447
+ if (securityMappers.length === 0) return;
448
+ const parsedUrl = new URL(url);
449
+ if (!securityMappers.some((mapper) => carriesSchemeParameter(mapper, parsedUrl, headers))) {
450
+ throw authenticationRequiredError(tool2);
451
+ }
452
+ }
324
453
  function validateSecurityConfiguration(tools, options) {
454
+ const result = validateCredentialSources(tools, options);
455
+ const schemesInInput = inputSecuritySchemes(options);
456
+ if (schemesInInput !== "all" && schemesInInput.size > 0) {
457
+ const include = options.generateOptions?.includeSecurityInInput;
458
+ const sources = [
459
+ (options.securitySchemesInInput?.length ?? 0) > 0 ? "securitySchemesInInput" : void 0,
460
+ Array.isArray(include) && include.length > 0 ? "an includeSecurityInInput list" : void 0
461
+ ].filter((source) => source !== void 0);
462
+ result.securityRiskScore = "high";
463
+ result.warnings.push(
464
+ `SECURITY WARNING: ${sources.join(" and ")} ${sources.length > 1 ? "are" : "is"} enabled. The model provides the credential for security schemes ${[...schemesInInput].join(", ")} in tool inputs, used when the server supplies none. Credentials may be logged or exposed, and the model chooses whose account a call uses.`
465
+ );
466
+ }
467
+ return result;
468
+ }
469
+ function validateCredentialSources(tools, options) {
325
470
  const result = {
326
471
  valid: true,
327
472
  missingMappings: [],
328
473
  warnings: [],
329
474
  securityRiskScore: "low"
330
475
  };
331
- const securitySchemes = extractSecuritySchemes(tools);
332
- const includeSecurityInInput = options.generateOptions?.includeSecurityInInput ?? false;
333
- if (includeSecurityInInput) {
476
+ const securitySchemes = describeSecuritySchemes(tools);
477
+ const inputSchemes = inputSecuritySchemes(options);
478
+ if (inputSchemes === "all") {
334
479
  result.securityRiskScore = "high";
335
480
  result.warnings.push(
336
- "SECURITY WARNING: includeSecurityInInput is enabled. Users will provide authentication directly in tool inputs. This increases security risk as credentials may be logged or exposed."
481
+ "SECURITY WARNING: includeSecurityInInput is enabled. Users will provide authentication directly in tool inputs (used for a scheme when the server supplies none). This increases security risk as credentials may be logged or exposed."
337
482
  );
338
483
  return result;
339
484
  }
@@ -351,21 +496,23 @@ function validateSecurityConfiguration(tools, options) {
351
496
  );
352
497
  return withPassthroughRisk(result, securitySchemes, options);
353
498
  }
354
- const schemesInInput = new Set(options.securitySchemesInInput || []);
499
+ const schemesInInput = inputSchemes;
355
500
  if (options.authProviderMapper || schemesInInput.size > 0) {
356
- result.securityRiskScore = schemesInInput.size > 0 ? "medium" : "low";
357
- if (schemesInInput.size > 0) {
358
- result.warnings.push(
359
- `INFO: Per-scheme security control enabled. Schemes in input: ${Array.from(schemesInInput).join(", ")}`
360
- );
361
- }
501
+ result.securityRiskScore = "low";
362
502
  const passthroughFallback = [];
363
- for (const scheme of securitySchemes) {
503
+ const perRequestHeaders = [];
504
+ const schemeParameters = schemeParametersOf(tools);
505
+ for (const [scheme, security] of securitySchemes) {
364
506
  if (schemesInInput.has(scheme)) {
365
507
  continue;
366
508
  }
367
509
  if (!options.authProviderMapper?.[scheme]) {
368
- if (options.passthroughCallerToken === true) {
510
+ const headerSource = headerCredentialSource(schemeParameters.get(scheme), options);
511
+ if (headerSource === "static") {
512
+ continue;
513
+ } else if (headerSource === "per-request") {
514
+ perRequestHeaders.push(scheme);
515
+ } else if (options.passthroughCallerToken === true && isBearerScheme(security)) {
369
516
  passthroughFallback.push(scheme);
370
517
  } else {
371
518
  result.valid = false;
@@ -378,6 +525,11 @@ function validateSecurityConfiguration(tools, options) {
378
525
  `ERROR: Missing auth provider mappings for security schemes: ${result.missingMappings.join(", ")}`
379
526
  );
380
527
  }
528
+ if (perRequestHeaders.length > 0) {
529
+ result.warnings.push(
530
+ `INFO: Security schemes with no authProviderMapper entry (${perRequestHeaders.join(", ")}) take their credential from headersMapper. An operation that requires only them is refused when headersMapper sets none.`
531
+ );
532
+ }
381
533
  withPassthroughRisk(result, securitySchemes, options);
382
534
  if (passthroughFallback.length > 0) {
383
535
  result.warnings.push(
@@ -387,10 +539,17 @@ function validateSecurityConfiguration(tools, options) {
387
539
  return result;
388
540
  }
389
541
  if (securitySchemes.size > 0 && options.passthroughCallerToken !== true) {
390
- const schemesStr = Array.from(securitySchemes).join(", ");
542
+ const schemesStr = Array.from(securitySchemes.keys()).join(", ");
543
+ result.securityRiskScore = "medium";
544
+ result.warnings.push(
545
+ `SECURITY WARNING: No auth configuration provided, so the adapter has no credentials for the API (security schemes: ${schemesStr}). Operations that require authentication fail unless additionalHeaders or headersMapper sets their credential. The MCP client's own token is not forwarded: configure authProviderMapper, securityResolver or staticAuth, or set passthroughCallerToken: true if the API is meant to receive the caller's MCP token.`
546
+ );
547
+ }
548
+ const unfilled = [...securitySchemes].filter(([, security]) => !isBearerScheme(security)).map(([scheme]) => scheme);
549
+ if (options.passthroughCallerToken === true && unfilled.length > 0) {
391
550
  result.securityRiskScore = "medium";
392
551
  result.warnings.push(
393
- `SECURITY WARNING: No auth configuration provided, so the adapter has no credentials for the API (security schemes: ${schemesStr}). Operations that require authentication will fail. The MCP client's own token is not forwarded: configure authProviderMapper, securityResolver or staticAuth, or set passthroughCallerToken: true if the API is meant to receive the caller's MCP token.`
552
+ `SECURITY WARNING: The adapter has no credentials for the API for security schemes: ${unfilled.join(", ")}. passthroughCallerToken sends only a bearer token, which these schemes don't use, so operations that require only them fail unless additionalHeaders or headersMapper sets their credential. Configure authProviderMapper, securityResolver or staticAuth for them.`
394
553
  );
395
554
  }
396
555
  return withPassthroughRisk(result, securitySchemes, options);
@@ -399,10 +558,11 @@ function canPassThroughCallerToken(options) {
399
558
  return options.passthroughCallerToken === true && !options.securityResolver && !hasStaticAuth(options);
400
559
  }
401
560
  function withPassthroughRisk(result, securitySchemes, options) {
402
- if (securitySchemes.size === 0 || !canPassThroughCallerToken(options)) {
561
+ const bearerSchemes = [...securitySchemes].filter(([, security]) => isBearerScheme(security));
562
+ if (bearerSchemes.length === 0 || !canPassThroughCallerToken(options)) {
403
563
  return result;
404
564
  }
405
- const schemesStr = Array.from(securitySchemes).join(", ");
565
+ const schemesStr = bearerSchemes.map(([scheme]) => scheme).join(", ");
406
566
  const when = options.authProviderMapper ? " whenever no authProviderMapper function returns a credential" : "";
407
567
  result.securityRiskScore = "high";
408
568
  result.warnings.push(
@@ -410,33 +570,74 @@ function withPassthroughRisk(result, securitySchemes, options) {
410
570
  );
411
571
  return result;
412
572
  }
413
- async function resolveToolSecurity(tool2, ctx, options) {
573
+ async function resolveToolSecurity(tool2, ctx, options, request = {}) {
414
574
  const securityResolver = new import_mcp_from_openapi2.SecurityResolver();
415
575
  const securityContext = await createSecurityContextFromAuth(tool2, ctx, options);
416
576
  const hasAuth = securityContext.jwt || securityContext.apiKey || securityContext.basic || securityContext.oauth2Token || securityContext.apiKeys && Object.keys(securityContext.apiKeys).length > 0 || securityContext.customHeaders && Object.keys(securityContext.customHeaders).length > 0;
417
577
  const requiresSecurity = tool2.mapper.some((m) => m.security && m.required === true);
418
- if (requiresSecurity && !hasAuth) {
419
- const requiredSchemes = tool2.mapper.filter((m) => m.security && m.required === true).map((m) => m.security?.scheme ?? "unknown");
420
- const uniqueSchemes = [...new Set(requiredSchemes)];
421
- const schemesStr = uniqueSchemes.join(", ") || "unknown";
422
- const firstScheme = uniqueSchemes[0] || "BearerAuth";
423
- throw new Error(
424
- `Authentication required for tool '${tool2.name}' but no auth configuration found.
425
- Required security schemes: ${schemesStr}
426
- Solutions:
427
- 1. Add authProviderMapper: { '${firstScheme}': (ctx) => ctx.authInfo.user?.token }
428
- 2. Add securityResolver: async (tool, ctx) => ({ jwt: await getApiToken(ctx) })
429
- 3. Add staticAuth: { jwt: process.env.API_TOKEN }
430
- 4. Set passthroughCallerToken: true, only if the API accepts the MCP client's own token
431
- 5. Set generateOptions.includeSecurityInInput: true (not recommended for production)`
432
- );
578
+ const fromInput = request.input ? await resolveInputSecurity(tool2, request.input, options, securityResolver) : void 0;
579
+ const hasInputCredential = !!fromInput && Object.keys(fromInput.headers).length + Object.keys(fromInput.query).length + Object.keys(fromInput.cookies).length > 0;
580
+ if (requiresSecurity && !hasAuth && !hasInputCredential && !request.deferCredentialCheck) {
581
+ throw authenticationRequiredError(tool2);
433
582
  }
434
- return await securityResolver.resolve(tool2.mapper, securityContext);
583
+ const resolved = await securityResolver.resolve(tool2.mapper, securityContext);
584
+ if (!fromInput) return resolved;
585
+ return {
586
+ ...resolved,
587
+ headers: { ...fromInput.headers, ...resolved.headers },
588
+ query: { ...fromInput.query, ...resolved.query },
589
+ cookies: { ...fromInput.cookies, ...resolved.cookies }
590
+ };
591
+ }
592
+ function inputSecuritySchemes(options) {
593
+ const include = options.generateOptions?.includeSecurityInInput;
594
+ if (include === true) return "all";
595
+ return /* @__PURE__ */ new Set([...Array.isArray(include) ? include : [], ...options.securitySchemesInInput ?? []]);
596
+ }
597
+ function isInputScheme(scheme, options) {
598
+ const schemes = inputSecuritySchemes(options);
599
+ return schemes === "all" || schemes.has(scheme);
600
+ }
601
+ function inputCredentialContext(security, value) {
602
+ const bare = value.replace(/^(?:bearer|basic)\s+/i, "");
603
+ if (security.type === "apiKey") {
604
+ return security.apiKeyName ? { apiKeys: { [security.apiKeyName]: value } } : { apiKey: value };
605
+ }
606
+ if (security.type === "oauth2" || security.type === "openIdConnect") return { oauth2Token: bare };
607
+ if (security.type === "http") {
608
+ const httpScheme = (security.httpScheme ?? "bearer").toLowerCase();
609
+ if (httpScheme === "bearer") return { jwt: bare };
610
+ if (httpScheme === "basic") return { basic: bare };
611
+ }
612
+ return void 0;
613
+ }
614
+ async function resolveInputSecurity(tool2, input, options, securityResolver) {
615
+ const resolved = { headers: {}, query: {}, cookies: {} };
616
+ for (const mapper of tool2.mapper) {
617
+ const security = mapper.security;
618
+ if (!security || !isInputScheme(security.scheme, options)) continue;
619
+ const value = input[mapper.inputKey];
620
+ if (typeof value !== "string" || value === "") continue;
621
+ if (/[\r\n\x00\f\v]/.test(value)) {
622
+ throw new import_sdk2.PublicMcpError(
623
+ `Invalid value for '${mapper.inputKey}': contains control characters (possible header injection attack)`,
624
+ "INVALID_HEADER_VALUE",
625
+ 400
626
+ );
627
+ }
628
+ const context = inputCredentialContext(security, value);
629
+ if (!context) continue;
630
+ const one = await securityResolver.resolve([mapper], (0, import_mcp_from_openapi2.createSecurityContext)(context));
631
+ Object.assign(resolved.headers, one.headers);
632
+ Object.assign(resolved.query, one.query);
633
+ Object.assign(resolved.cookies, one.cookies);
634
+ }
635
+ return resolved;
435
636
  }
436
637
 
437
638
  // libs/adapters/src/openapi/openapi.tool.ts
438
639
  var import_lazy_zod2 = require("@frontmcp/lazy-zod");
439
- var import_sdk3 = require("@frontmcp/sdk");
640
+ var import_sdk4 = require("@frontmcp/sdk");
440
641
  var import_utils3 = require("@frontmcp/utils");
441
642
 
442
643
  // libs/adapters/src/openapi/openapi.frontmcp-schema.ts
@@ -680,7 +881,7 @@ function formatZodIssues(issues, prefix) {
680
881
  }
681
882
 
682
883
  // libs/adapters/src/openapi/openapi.utils.ts
683
- var import_sdk2 = require("@frontmcp/sdk");
884
+ var import_sdk3 = require("@frontmcp/sdk");
684
885
  var import_utils2 = require("@frontmcp/utils");
685
886
  function coerceToString(value, paramName, location) {
686
887
  if (value === null || value === void 0) {
@@ -738,7 +939,7 @@ function buildRequest(tool2, input, security, baseUrl) {
738
939
  case "header": {
739
940
  const headerValue = coerceToString(value, mapper.key, "header");
740
941
  if (/[\r\n\x00\f\v]/.test(headerValue)) {
741
- throw new import_sdk2.PublicMcpError(
942
+ throw new import_sdk3.PublicMcpError(
742
943
  `Invalid header value for '${mapper.key}': contains control characters (possible header injection attack)`,
743
944
  "INVALID_HEADER_VALUE",
744
945
  400
@@ -903,7 +1104,7 @@ function createOpenApiTool(openapiTool, options, logger) {
903
1104
  if (toolTransform.ui) {
904
1105
  toolMetadata["ui"] = toolTransform.ui;
905
1106
  }
906
- return (0, import_sdk3.tool)(toolMetadata)(async (input, toolCtx) => {
1107
+ return (0, import_sdk4.tool)(toolMetadata)(async (input, toolCtx) => {
907
1108
  const ctx = toolCtx.context;
908
1109
  const transformContext = {
909
1110
  ctx,
@@ -915,7 +1116,10 @@ function createOpenApiTool(openapiTool, options, logger) {
915
1116
  inputTransforms,
916
1117
  transformContext
917
1118
  );
918
- const security = await resolveToolSecurity(openapiTool, ctx, options);
1119
+ const security = await resolveToolSecurity(openapiTool, ctx, options, {
1120
+ input: injectedInput,
1121
+ deferCredentialCheck: true
1122
+ });
919
1123
  const { url, headers, body: requestBody } = buildRequest(openapiTool, injectedInput, security, options.baseUrl);
920
1124
  applyAdditionalHeaders(headers, options.additionalHeaders);
921
1125
  if (options.headersMapper) {
@@ -931,6 +1135,7 @@ function createOpenApiTool(openapiTool, options, logger) {
931
1135
  throw new Error(`headersMapper failed for tool '${openapiTool.name}': ${errorMessage}`, { cause: err });
932
1136
  }
933
1137
  }
1138
+ assertRequestHasCredential(openapiTool, url, headers);
934
1139
  let finalBody = requestBody;
935
1140
  if (options.bodyMapper && requestBody) {
936
1141
  try {
@@ -1152,7 +1357,7 @@ function createConsoleLogger(prefix) {
1152
1357
  child: (childPrefix) => createConsoleLogger(`${prefix}:${childPrefix}`)
1153
1358
  };
1154
1359
  }
1155
- var OpenapiAdapter = class extends import_sdk4.DynamicAdapter {
1360
+ var OpenapiAdapter = class extends import_sdk5.DynamicAdapter {
1156
1361
  generator;
1157
1362
  logger;
1158
1363
  options;
@@ -1179,8 +1384,9 @@ var OpenapiAdapter = class extends import_sdk4.DynamicAdapter {
1179
1384
  if (!this.generator) {
1180
1385
  this.generator = await this.initializeGenerator();
1181
1386
  }
1182
- const hasPerSchemeControl = this.options.securitySchemesInInput && this.options.securitySchemesInInput.length > 0;
1183
- const includeSecurityInInput = hasPerSchemeControl || (this.options.generateOptions?.includeSecurityInInput ?? false);
1387
+ const inputSchemes = inputSecuritySchemes(this.options);
1388
+ const hasPerSchemeControl = inputSchemes !== "all" && inputSchemes.size > 0;
1389
+ const includeSecurityInInput = inputSchemes === "all" || hasPerSchemeControl;
1184
1390
  let openapiTools = await this.generator.generateTools({
1185
1391
  includeOperations: this.options.generateOptions?.includeOperations,
1186
1392
  excludeOperations: this.options.generateOptions?.excludeOperations,
@@ -1196,7 +1402,7 @@ var OpenapiAdapter = class extends import_sdk4.DynamicAdapter {
1196
1402
  formatResolvers: this.options.generateOptions?.formatResolvers
1197
1403
  });
1198
1404
  if (hasPerSchemeControl) {
1199
- openapiTools = openapiTools.map((tool2) => this.filterSecuritySchemes(tool2));
1405
+ openapiTools = openapiTools.map((tool2) => this.filterSecuritySchemes(tool2, inputSchemes));
1200
1406
  }
1201
1407
  const validation = validateSecurityConfiguration(openapiTools, this.options);
1202
1408
  this.logger.info("Security Analysis:");
@@ -1215,28 +1421,7 @@ var OpenapiAdapter = class extends import_sdk4.DynamicAdapter {
1215
1421
  });
1216
1422
  }
1217
1423
  if (!validation.valid) {
1218
- throw new Error(
1219
- `[OpenAPI Adapter: ${this.options.name}] Invalid security configuration.
1220
- Missing auth provider mappings for security schemes: ${validation.missingMappings.join(", ")}
1221
-
1222
- Your OpenAPI spec requires these security schemes, but no auth configuration was provided.
1223
-
1224
- Add one of the following to your adapter configuration:
1225
-
1226
- 1. authProviderMapper (recommended):
1227
- authProviderMapper: {
1228
- ` + validation.missingMappings.map((s) => ` '${s}': (authInfo) => authInfo.user?.${s.toLowerCase()}Token,`).join("\n") + `
1229
- }
1230
-
1231
- 2. securityResolver:
1232
- securityResolver: async (tool, ctx) => ({ jwt: await getApiToken(ctx) })
1233
-
1234
- 3. staticAuth:
1235
- staticAuth: { jwt: process.env.API_TOKEN }
1236
-
1237
- 4. Include security in input (NOT recommended for production):
1238
- generateOptions: { includeSecurityInInput: true }`
1239
- );
1424
+ throw new Error(formatMissingSecurityMappingsError(this.options.name, openapiTools, validation.missingMappings));
1240
1425
  }
1241
1426
  let transformedTools = openapiTools;
1242
1427
  if (this.options.descriptionMode && this.options.descriptionMode !== "summaryOnly") {
@@ -1528,12 +1713,12 @@ ${opDescription}`;
1528
1713
  };
1529
1714
  }
1530
1715
  /**
1531
- * Filter security schemes in tool input based on securitySchemesInInput option.
1532
- * Removes security inputs that should be resolved from context instead of user input.
1716
+ * Filter security schemes in tool input to the ones named for it (`securitySchemesInInput`, or an
1717
+ * `includeSecurityInInput` list). Removes security inputs that should be resolved from context
1718
+ * instead of user input.
1533
1719
  * @private
1534
1720
  */
1535
- filterSecuritySchemes(tool2) {
1536
- const allowedSchemes = new Set(this.options.securitySchemesInInput || []);
1721
+ filterSecuritySchemes(tool2, allowedSchemes) {
1537
1722
  if (allowedSchemes.size === 0) return tool2;
1538
1723
  const schemesToRemove = /* @__PURE__ */ new Set();
1539
1724
  const inputKeysToRemove = /* @__PURE__ */ new Set();
@@ -1890,7 +2075,7 @@ ${this.formatSchemaAsSummary(schema)}`;
1890
2075
  }
1891
2076
  };
1892
2077
  OpenapiAdapter = __decorateClass([
1893
- (0, import_sdk4.Adapter)({
2078
+ (0, import_sdk5.Adapter)({
1894
2079
  name: "openapi",
1895
2080
  description: "OpenAPI adapter for FrontMCP - Automatically generates MCP tools from OpenAPI specifications"
1896
2081
  })