@executor-js/plugin-mcp 1.5.6 → 1.5.8

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.
Files changed (40) hide show
  1. package/dist/{AddMcpSource-4LLERUW5.js → AddMcpSource-ZDNQ7F6I.js} +70 -97
  2. package/dist/AddMcpSource-ZDNQ7F6I.js.map +1 -0
  3. package/dist/EditMcpSource-75NJRWZR.js +178 -0
  4. package/dist/EditMcpSource-75NJRWZR.js.map +1 -0
  5. package/dist/McpAccountsPanel-QBCSCJE7.js +83 -0
  6. package/dist/McpAccountsPanel-QBCSCJE7.js.map +1 -0
  7. package/dist/api/group.d.ts +106 -15
  8. package/dist/api/index.d.ts +121 -15
  9. package/dist/{chunk-N4EAF5CA.js → chunk-3AOD4VAW.js} +74 -5
  10. package/dist/chunk-3AOD4VAW.js.map +1 -0
  11. package/dist/{chunk-6OEQZ72N.js → chunk-3H5Y7JCQ.js} +65 -11
  12. package/dist/chunk-3H5Y7JCQ.js.map +1 -0
  13. package/dist/{chunk-HSJWIVME.js → chunk-6BJ6MZF7.js} +110 -52
  14. package/dist/chunk-6BJ6MZF7.js.map +1 -0
  15. package/dist/client.js +3 -3
  16. package/dist/core.js +152 -5
  17. package/dist/core.js.map +1 -1
  18. package/dist/index.js +2 -2
  19. package/dist/react/atoms.d.ts +128 -26
  20. package/dist/react/auth-method-config.d.ts +22 -7
  21. package/dist/react/client.d.ts +103 -15
  22. package/dist/sdk/connection.d.ts +1 -1
  23. package/dist/sdk/index.d.ts +3 -1
  24. package/dist/sdk/invoke.d.ts +1 -1
  25. package/dist/sdk/migrate-config.d.ts +6 -0
  26. package/dist/sdk/migrate-config.test.d.ts +1 -0
  27. package/dist/sdk/multi-placement-auth.test.d.ts +1 -0
  28. package/dist/sdk/plugin.d.ts +92 -5
  29. package/dist/sdk/types.d.ts +105 -15
  30. package/package.json +4 -4
  31. package/dist/AddMcpSource-4LLERUW5.js.map +0 -1
  32. package/dist/EditMcpSource-GKJRP75X.js +0 -313
  33. package/dist/EditMcpSource-GKJRP75X.js.map +0 -1
  34. package/dist/McpAccountsPanel-UX7MHEIG.js +0 -132
  35. package/dist/McpAccountsPanel-UX7MHEIG.js.map +0 -1
  36. package/dist/chunk-6OEQZ72N.js.map +0 -1
  37. package/dist/chunk-7FJ3PUUL.js +0 -21
  38. package/dist/chunk-7FJ3PUUL.js.map +0 -1
  39. package/dist/chunk-HSJWIVME.js.map +0 -1
  40. package/dist/chunk-N4EAF5CA.js.map +0 -1
@@ -38,9 +38,22 @@ var McpOAuthError = class extends Schema.TaggedErrorClass()(
38
38
 
39
39
  // src/sdk/types.ts
40
40
  import { Effect, Option, Schema as Schema2 } from "effect";
41
+ import {
42
+ ApiKeyAuthMethod,
43
+ ApiKeyAuthTemplate,
44
+ NoneAuthMethod,
45
+ apiKeyMethodFromAuthTemplate,
46
+ isApiKeyAuthTemplate,
47
+ normalizeAuthMethodSlugs
48
+ } from "@executor-js/sdk/http-auth";
41
49
  var McpRemoteTransport = Schema2.Literals(["streamable-http", "sse", "auto"]);
42
50
  var McpTransport = Schema2.Literals(["streamable-http", "sse", "stdio", "auto"]);
43
- var McpAuthTemplate = Schema2.Union([
51
+ var McpOAuthMethod = Schema2.Struct({
52
+ slug: Schema2.String,
53
+ kind: Schema2.Literal("oauth2")
54
+ });
55
+ var McpAuthMethod = Schema2.Union([NoneAuthMethod, ApiKeyAuthMethod, McpOAuthMethod]);
56
+ var McpAuthShorthand = Schema2.Union([
44
57
  Schema2.Struct({ kind: Schema2.Literal("none") }),
45
58
  Schema2.Struct({
46
59
  kind: Schema2.Literal("header"),
@@ -49,6 +62,46 @@ var McpAuthTemplate = Schema2.Union([
49
62
  }),
50
63
  Schema2.Struct({ kind: Schema2.Literal("oauth2") })
51
64
  ]);
65
+ var mcpAuthMethodFromShorthand = (auth) => {
66
+ if (auth.kind === "header") {
67
+ return {
68
+ slug: "header",
69
+ kind: "apikey",
70
+ placements: [
71
+ {
72
+ carrier: "header",
73
+ name: auth.headerName,
74
+ ...auth.prefix !== void 0 ? { prefix: auth.prefix } : {}
75
+ }
76
+ ]
77
+ };
78
+ }
79
+ return { slug: auth.kind, kind: auth.kind };
80
+ };
81
+ var McpAuthMethodInput = Schema2.Union([
82
+ Schema2.Struct({ slug: Schema2.optional(Schema2.String), kind: Schema2.Literal("none") }),
83
+ Schema2.Struct({ slug: Schema2.optional(Schema2.String), kind: Schema2.Literal("oauth2") }),
84
+ // Credential methods are authored request-shaped — the ONE apikey input
85
+ // dialect: `{ type: "apiKey", headers: { Authorization: ["Bearer ",
86
+ // variable("token")] }, queryParams: { … } }`. Stored configs and the
87
+ // catalog read as canonical placements; `apiKeyAuthTemplateFromMethod`
88
+ // serializes them back for read-modify-write flows.
89
+ ApiKeyAuthTemplate
90
+ ]);
91
+ var defaultMcpAuthSlug = (method) => {
92
+ if (method.kind !== "apikey") return method.kind;
93
+ if (method.placements.length === 1) {
94
+ return method.placements[0].carrier === "header" ? "header" : "query";
95
+ }
96
+ return "apikey";
97
+ };
98
+ var expandMcpAuthMethodInputs = (methods) => methods.map(
99
+ (method) => isApiKeyAuthTemplate(method) ? apiKeyMethodFromAuthTemplate(method) : method
100
+ );
101
+ var normalizeMcpAuthMethods = (methods) => normalizeAuthMethodSlugs(
102
+ expandMcpAuthMethodInputs(methods),
103
+ defaultMcpAuthSlug
104
+ );
52
105
  var StringMap = Schema2.Record(Schema2.String, Schema2.String);
53
106
  var McpRemoteIntegrationConfig = Schema2.Struct({
54
107
  transport: Schema2.Literal("remote"),
@@ -63,8 +116,9 @@ var McpRemoteIntegrationConfig = Schema2.Struct({
63
116
  queryParams: Schema2.optional(StringMap),
64
117
  /** Static headers sent on every request (non-credential) */
65
118
  headers: Schema2.optional(StringMap),
66
- /** Auth template — how the connection's value is rendered onto requests */
67
- auth: McpAuthTemplate
119
+ /** Declared auth methods — how a connection's values are rendered onto
120
+ * requests. A connection's `template` picks one by slug. */
121
+ authenticationTemplate: Schema2.Array(McpAuthMethod)
68
122
  });
69
123
  var McpStdioIntegrationConfig = Schema2.Struct({
70
124
  transport: Schema2.Literal("stdio"),
@@ -82,12 +136,7 @@ var McpIntegrationConfig = Schema2.Union([
82
136
  McpStdioIntegrationConfig
83
137
  ]);
84
138
  var decodeIntegrationConfig = Schema2.decodeUnknownOption(McpIntegrationConfig);
85
- var parseMcpIntegrationConfig = (config) => {
86
- if (typeof config === "object" && config !== null && "transport" in config && config.transport === "remote" && !("auth" in config)) {
87
- return Option.getOrNull(decodeIntegrationConfig({ ...config, auth: { kind: "none" } }));
88
- }
89
- return Option.getOrNull(decodeIntegrationConfig(config));
90
- };
139
+ var parseMcpIntegrationConfig = (config) => Option.getOrNull(decodeIntegrationConfig(config));
91
140
  var McpToolAnnotations = Schema2.Struct({
92
141
  title: Schema2.optional(Schema2.String),
93
142
  readOnlyHint: Schema2.optional(Schema2.Boolean),
@@ -113,7 +162,12 @@ export {
113
162
  McpOAuthError,
114
163
  McpRemoteTransport,
115
164
  McpTransport,
116
- McpAuthTemplate,
165
+ McpAuthMethod,
166
+ McpAuthShorthand,
167
+ mcpAuthMethodFromShorthand,
168
+ McpAuthMethodInput,
169
+ expandMcpAuthMethodInputs,
170
+ normalizeMcpAuthMethods,
117
171
  McpRemoteIntegrationConfig,
118
172
  McpStdioIntegrationConfig,
119
173
  McpIntegrationConfig,
@@ -121,4 +175,4 @@ export {
121
175
  McpToolAnnotations,
122
176
  McpToolBinding
123
177
  };
124
- //# sourceMappingURL=chunk-6OEQZ72N.js.map
178
+ //# sourceMappingURL=chunk-3H5Y7JCQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sdk/errors.ts","../src/sdk/types.ts"],"sourcesContent":["// MCP plugin tagged errors. Each carries an `HttpApiSchema` annotation so\n// it can be `.addError(...)` directly on the API group — handlers return\n// these and HttpApi encodes them as 4xx responses with a typed body. No\n// per-handler sanitisation step.\n\nimport { Schema } from \"effect\";\n\nexport class McpConnectionError extends Schema.TaggedErrorClass<McpConnectionError>()(\n \"McpConnectionError\",\n {\n transport: Schema.String,\n message: Schema.String,\n },\n { httpApiStatus: 400 },\n) {}\n\nexport class McpToolDiscoveryError extends Schema.TaggedErrorClass<McpToolDiscoveryError>()(\n \"McpToolDiscoveryError\",\n {\n stage: Schema.Literals([\"connect\", \"list_tools\"]),\n message: Schema.String,\n },\n { httpApiStatus: 400 },\n) {}\n\nexport class McpInvocationError extends Schema.TaggedErrorClass<McpInvocationError>()(\n \"McpInvocationError\",\n {\n toolName: Schema.String,\n message: Schema.String,\n },\n { httpApiStatus: 400 },\n) {}\n\nexport class McpOAuthError extends Schema.TaggedErrorClass<McpOAuthError>()(\n \"McpOAuthError\",\n {\n message: Schema.String,\n },\n { httpApiStatus: 400 },\n) {}\n","import { Effect, Option, Schema } from \"effect\";\nimport {\n ApiKeyAuthMethod,\n ApiKeyAuthTemplate,\n NoneAuthMethod,\n apiKeyMethodFromAuthTemplate,\n isApiKeyAuthTemplate,\n normalizeAuthMethodSlugs,\n} from \"@executor-js/sdk/http-auth\";\n\n// ---------------------------------------------------------------------------\n// MCP plugin v2 data model.\n//\n// An MCP integration is one server. Its `config` blob (opaque to core, stored\n// on the integration row) carries everything needed to dial the server plus\n// the declared auth methods describing how a connection's resolved credential\n// values are applied to the request. A connection IS the credential: at\n// execute time core resolves the connection's values through its provider\n// (refreshing OAuth tokens), and the plugin renders them onto the request per\n// the method the connection binds (D11).\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Transport / remote transport\n// ---------------------------------------------------------------------------\n\nexport const McpRemoteTransport = Schema.Literals([\"streamable-http\", \"sse\", \"auto\"]);\nexport type McpRemoteTransport = typeof McpRemoteTransport.Type;\n\n/** All transport types (used in the connector layer) */\nexport const McpTransport = Schema.Literals([\"streamable-http\", \"sse\", \"stdio\", \"auto\"]);\nexport type McpTransport = typeof McpTransport.Type;\n\n// ---------------------------------------------------------------------------\n// Auth methods — the shared placements vocabulary (`@executor-js/sdk/http-auth`)\n// plus MCP's own oauth variant. An integration declares zero or more methods,\n// each with a stable `slug` a connection binds against (`connection.template`),\n// mirroring the OpenAPI/GraphQL `authenticationTemplate` arrays.\n//\n// none — no credential (open server)\n// apikey — render the connection's values through the method's header/query\n// placements (one credential input per distinct placement\n// `variable`; servers like ui.sh authenticate via a `?token=`\n// query placement, and a method may mix carriers — e.g. a bearer\n// header plus a team-id query param)\n// oauth2 — the value is an OAuth access token, applied as a Bearer header\n// via the MCP SDK's OAuthClientProvider. MCP oauth carries no\n// stored endpoints: metadata is discovered live at connect time.\n// ---------------------------------------------------------------------------\n\nexport const McpOAuthMethod = Schema.Struct({\n slug: Schema.String,\n kind: Schema.Literal(\"oauth2\"),\n});\nexport type McpOAuthMethod = typeof McpOAuthMethod.Type;\n\nexport const McpAuthMethod = Schema.Union([NoneAuthMethod, ApiKeyAuthMethod, McpOAuthMethod]);\nexport type McpAuthMethod = typeof McpAuthMethod.Type;\n\n/** Single-method `auth` shorthand on `addServer` — agent convenience for the\n * common cases. Normalized into `authenticationTemplate` at the boundary;\n * never stored. */\nexport const McpAuthShorthand = Schema.Union([\n Schema.Struct({ kind: Schema.Literal(\"none\") }),\n Schema.Struct({\n kind: Schema.Literal(\"header\"),\n headerName: Schema.String,\n prefix: Schema.optional(Schema.String),\n }),\n Schema.Struct({ kind: Schema.Literal(\"oauth2\") }),\n]);\nexport type McpAuthShorthand = typeof McpAuthShorthand.Type;\n\n/** Expand the `auth` shorthand into a declared method. Slugs match what the\n * shorthand has always produced (`none` / `header` / `oauth2`) so existing\n * connections bound to them keep matching. */\nexport const mcpAuthMethodFromShorthand = (auth: McpAuthShorthand): McpAuthMethod => {\n if (auth.kind === \"header\") {\n return {\n slug: \"header\",\n kind: \"apikey\",\n placements: [\n {\n carrier: \"header\",\n name: auth.headerName,\n ...(auth.prefix !== undefined ? { prefix: auth.prefix } : {}),\n },\n ],\n };\n }\n return { slug: auth.kind, kind: auth.kind };\n};\n\n/** Input variant of `McpAuthMethod` — callers (UI, agents) may omit the slug;\n * `normalizeMcpAuthMethods` backfills it. */\nexport const McpAuthMethodInput = Schema.Union([\n Schema.Struct({ slug: Schema.optional(Schema.String), kind: Schema.Literal(\"none\") }),\n Schema.Struct({ slug: Schema.optional(Schema.String), kind: Schema.Literal(\"oauth2\") }),\n // Credential methods are authored request-shaped — the ONE apikey input\n // dialect: `{ type: \"apiKey\", headers: { Authorization: [\"Bearer \",\n // variable(\"token\")] }, queryParams: { … } }`. Stored configs and the\n // catalog read as canonical placements; `apiKeyAuthTemplateFromMethod`\n // serializes them back for read-modify-write flows.\n ApiKeyAuthTemplate,\n]);\nexport type McpAuthMethodInput = typeof McpAuthMethodInput.Type;\n\n/** The expansion target: input arms with the dialect resolved to canonical\n * placements (slug still optional — backfill is a separate pass). */\nexport type McpCanonicalAuthMethodInput =\n | Exclude<McpAuthMethodInput, ApiKeyAuthTemplate>\n | (Omit<ApiKeyAuthMethod, \"slug\"> & { readonly slug?: string });\n\n/** The default slug for a slug-less input method. Carrier-derived for the\n * single-placement apikey cases (`header` / `query`) — the slugs those\n * methods have always had — so the shorthand, UI, and migration paths all\n * converge on the same names. */\nconst defaultMcpAuthSlug = (method: McpCanonicalAuthMethodInput): string => {\n if (method.kind !== \"apikey\") return method.kind;\n if (method.placements.length === 1) {\n return method.placements[0]!.carrier === \"header\" ? \"header\" : \"query\";\n }\n return \"apikey\";\n};\n\n/** Expand request-shaped dialect entries into canonical placements; canonical\n * entries pass through. Slug backfill is the caller's concern\n * (`normalizeMcpAuthMethods` for declare flows, `mergeAuthTemplates` for the\n * custom-method merge). */\nexport const expandMcpAuthMethodInputs = (\n methods: readonly McpAuthMethodInput[],\n): readonly McpCanonicalAuthMethodInput[] =>\n methods.map(\n (method): McpCanonicalAuthMethodInput =>\n isApiKeyAuthTemplate(method)\n ? (apiKeyMethodFromAuthTemplate(method) as McpCanonicalAuthMethodInput)\n : (method as McpCanonicalAuthMethodInput),\n );\n\n/** Assign each method a stable slug: a caller-provided one wins, otherwise a\n * kind/carrier-derived default, suffixed `_2`, `_3`, … on collision. The\n * request-shaped dialect is expanded to canonical placements first. */\nexport const normalizeMcpAuthMethods = (\n methods: readonly McpAuthMethodInput[],\n): readonly McpAuthMethod[] =>\n normalizeAuthMethodSlugs(\n expandMcpAuthMethodInputs(methods),\n defaultMcpAuthSlug,\n ) as readonly McpAuthMethod[];\n\n// ---------------------------------------------------------------------------\n// Integration config — the opaque blob stored on the integration row. A\n// discriminated union on transport.\n// ---------------------------------------------------------------------------\n\nconst StringMap = Schema.Record(Schema.String, Schema.String);\n\nexport const McpRemoteIntegrationConfig = Schema.Struct({\n transport: Schema.Literal(\"remote\"),\n /** The MCP server endpoint URL */\n endpoint: Schema.String,\n /** Transport preference for this remote server */\n remoteTransport: McpRemoteTransport.pipe(\n Schema.optionalKey,\n Schema.withConstructorDefault(Effect.succeed(\"auto\" as const)),\n ),\n /** Static query params appended to the endpoint URL (non-credential) */\n queryParams: Schema.optional(StringMap),\n /** Static headers sent on every request (non-credential) */\n headers: Schema.optional(StringMap),\n /** Declared auth methods — how a connection's values are rendered onto\n * requests. A connection's `template` picks one by slug. */\n authenticationTemplate: Schema.Array(McpAuthMethod),\n});\nexport type McpRemoteIntegrationConfig = typeof McpRemoteIntegrationConfig.Type;\n\nexport const McpStdioIntegrationConfig = Schema.Struct({\n transport: Schema.Literal(\"stdio\"),\n /** The command to run */\n command: Schema.String,\n /** Arguments to the command */\n args: Schema.optional(Schema.Array(Schema.String)),\n /** Environment variables */\n env: Schema.optional(StringMap),\n /** Working directory */\n cwd: Schema.optional(Schema.String),\n});\nexport type McpStdioIntegrationConfig = typeof McpStdioIntegrationConfig.Type;\n\nexport const McpIntegrationConfig = Schema.Union([\n McpRemoteIntegrationConfig,\n McpStdioIntegrationConfig,\n]);\nexport type McpIntegrationConfig = typeof McpIntegrationConfig.Type;\n\nconst decodeIntegrationConfig = Schema.decodeUnknownOption(McpIntegrationConfig);\n\n/** Parse an opaque integration `config` blob into a typed MCP config, or null\n * if it isn't this plugin's (canonical) shape. Pre-canonical stored shapes\n * are rewritten by the one-off config migration (`migrate-config.ts`), not\n * decoded here — runtime code knows only the canonical model. */\nexport const parseMcpIntegrationConfig = (config: unknown): McpIntegrationConfig | null =>\n Option.getOrNull(decodeIntegrationConfig(config));\n\n// ---------------------------------------------------------------------------\n// Tool annotations — upstream MCP ToolAnnotations we honour (destructiveHint\n// drives requiresApproval).\n// ---------------------------------------------------------------------------\n\nexport const McpToolAnnotations = Schema.Struct({\n title: Schema.optional(Schema.String),\n readOnlyHint: Schema.optional(Schema.Boolean),\n destructiveHint: Schema.optional(Schema.Boolean),\n idempotentHint: Schema.optional(Schema.Boolean),\n openWorldHint: Schema.optional(Schema.Boolean),\n});\nexport type McpToolAnnotations = typeof McpToolAnnotations.Type;\n\n// ---------------------------------------------------------------------------\n// Tool binding — maps a persisted (sanitized) tool name back to its real MCP\n// tool name and upstream annotations, persisted per-connection so invokeTool\n// can dial the server with the correct name.\n// ---------------------------------------------------------------------------\n\nexport const McpToolBinding = Schema.Struct({\n /** Sanitized, address-safe tool name (the `<tool>` address segment). */\n toolId: Schema.String,\n /** The real MCP tool name as advertised by the server. */\n toolName: Schema.String,\n description: Schema.NullOr(Schema.String),\n inputSchema: Schema.optional(Schema.Unknown),\n outputSchema: Schema.optional(Schema.Unknown),\n annotations: Schema.optional(McpToolAnnotations),\n});\nexport type McpToolBinding = typeof McpToolBinding.Type;\n"],"mappings":"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","names":["Schema"]}
@@ -2,14 +2,18 @@ import {
2
2
  mcpPresets
3
3
  } from "./chunk-TW44CBXJ.js";
4
4
  import {
5
- McpAuthTemplate,
5
+ McpAuthMethodInput,
6
+ McpAuthShorthand,
6
7
  McpConnectionError,
7
8
  McpInvocationError,
8
9
  McpRemoteTransport,
9
10
  McpToolAnnotations,
10
11
  McpToolDiscoveryError,
12
+ expandMcpAuthMethodInputs,
13
+ mcpAuthMethodFromShorthand,
14
+ normalizeMcpAuthMethods,
11
15
  parseMcpIntegrationConfig
12
- } from "./chunk-6OEQZ72N.js";
16
+ } from "./chunk-3H5Y7JCQ.js";
13
17
 
14
18
  // src/sdk/manifest.ts
15
19
  import { Option, Schema } from "effect";
@@ -96,10 +100,18 @@ import {
96
100
  definePlugin,
97
101
  IntegrationAlreadyExistsError,
98
102
  IntegrationSlug,
103
+ mergeAuthTemplates,
99
104
  tool,
100
105
  ToolResult,
101
106
  ToolName
102
- } from "@executor-js/sdk/core";
107
+ } from "@executor-js/sdk";
108
+ import {
109
+ TOKEN_VARIABLE,
110
+ describeApiKeyAuthMethod,
111
+ describeNoneAuthMethod,
112
+ renderAuthPlacements,
113
+ requiredPlacementVariables
114
+ } from "@executor-js/sdk/http-auth";
103
115
 
104
116
  // src/sdk/connection.ts
105
117
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
@@ -242,7 +254,7 @@ import {
242
254
  ElicitationId,
243
255
  FormElicitation,
244
256
  UrlElicitation
245
- } from "@executor-js/sdk/core";
257
+ } from "@executor-js/sdk";
246
258
  var ArgsRecord = Schema2.Record(Schema2.String, Schema2.Unknown);
247
259
  var decodeArgsRecord = Schema2.decodeUnknownOption(ArgsRecord);
248
260
  var argsRecord = (value) => Option2.getOrElse(decodeArgsRecord(value), () => ({}));
@@ -563,7 +575,9 @@ var legacyOAuthClientSlugCandidates = (slug, integration) => {
563
575
  var oauthClientKey = (owner, slug) => `${owner}:${String(slug)}`;
564
576
  var legacyMcpClientMatches = (client, candidates, config) => {
565
577
  if (!candidates.has(String(client.slug))) return false;
566
- if (!config || config.transport !== "remote" || config.auth.kind !== "oauth2") return false;
578
+ if (!config || config.transport !== "remote" || !config.authenticationTemplate.some((method) => method.kind === "oauth2")) {
579
+ return false;
580
+ }
567
581
  return client.grant === "authorization_code" && (client.resource ?? null) === config.endpoint;
568
582
  };
569
583
  var McpStampSchema = Schema4.Struct({
@@ -592,8 +606,11 @@ var McpRemoteServerInputSchema = Schema4.Struct({
592
606
  headers: Schema4.optional(Schema4.Record(Schema4.String, Schema4.String)),
593
607
  queryParams: Schema4.optional(Schema4.Record(Schema4.String, Schema4.String)),
594
608
  slug: Schema4.optional(Schema4.String),
595
- /** How a connection's value is applied to requests. Defaults to none. */
596
- auth: Schema4.optional(McpAuthTemplate)
609
+ /** Declared auth methods a connection can be applied through. */
610
+ authenticationTemplate: Schema4.optional(Schema4.Array(McpAuthMethodInput)),
611
+ /** Single-method shorthand (legacy callers). Ignored when
612
+ * `authenticationTemplate` is present. Defaults to none. */
613
+ auth: Schema4.optional(McpAuthShorthand)
597
614
  });
598
615
  var McpStdioServerInputSchema = Schema4.Struct({
599
616
  transport: Schema4.Literal("stdio"),
@@ -611,6 +628,10 @@ var McpAddServerInputSchema = Schema4.Union([
611
628
  var McpAddServerOutputSchema = Schema4.Struct({
612
629
  slug: Schema4.String
613
630
  });
631
+ var McpConfigureAuthInputSchema = Schema4.Struct({
632
+ authenticationTemplate: Schema4.Array(McpAuthMethodInput),
633
+ mode: Schema4.optional(Schema4.Literals(["merge", "replace"]))
634
+ });
614
635
  var McpProbeEndpointInputSchema = Schema4.Struct({
615
636
  endpoint: Schema4.String,
616
637
  headers: Schema4.optional(Schema4.Record(Schema4.String, Schema4.String)),
@@ -666,7 +687,7 @@ var toIntegrationConfig = (input) => {
666
687
  remoteTransport: input.remoteTransport ?? "auto",
667
688
  queryParams: input.queryParams,
668
689
  headers: input.headers,
669
- auth: input.auth ?? { kind: "none" }
690
+ authenticationTemplate: input.authenticationTemplate ? normalizeMcpAuthMethods(input.authenticationTemplate) : [mcpAuthMethodFromShorthand(input.auth ?? { kind: "none" })]
670
691
  };
671
692
  };
672
693
  var McpCallToolResultJsonSchema = z.toJSONSchema(CallToolResultSchema);
@@ -764,7 +785,15 @@ var makeOAuthProvider = (accessToken) => ({
764
785
  saveDiscoveryState: () => void 0,
765
786
  discoveryState: () => void 0
766
787
  });
767
- var buildConnectorInput = (config, value, allowStdio) => {
788
+ var selectAuthMethod = (config, templateSlug) => {
789
+ const methods = config.authenticationTemplate;
790
+ if (templateSlug !== null) {
791
+ const match = methods.find((method) => method.slug === templateSlug);
792
+ if (match) return match;
793
+ }
794
+ return methods.length === 1 ? methods[0] : void 0;
795
+ };
796
+ var buildConnectorInput = (config, values, templateSlug, allowStdio) => {
768
797
  if (config.transport === "stdio") {
769
798
  if (!allowStdio) {
770
799
  return Effect5.fail(
@@ -783,18 +812,22 @@ var buildConnectorInput = (config, value, allowStdio) => {
783
812
  });
784
813
  }
785
814
  const headers = { ...config.headers ?? {} };
815
+ const queryParams = { ...config.queryParams ?? {} };
786
816
  let authProvider;
787
- const auth = config.auth;
788
- if (auth.kind === "header" && value !== null) {
789
- headers[auth.headerName] = auth.prefix ? `${auth.prefix}${value}` : value;
790
- } else if (auth.kind === "oauth2" && value !== null) {
791
- authProvider = makeOAuthProvider(value);
817
+ const auth = selectAuthMethod(config, templateSlug);
818
+ if (auth?.kind === "apikey") {
819
+ const rendered = renderAuthPlacements(auth.placements, values);
820
+ Object.assign(headers, rendered.headers);
821
+ Object.assign(queryParams, rendered.queryParams);
822
+ } else if (auth?.kind === "oauth2") {
823
+ const token = values[TOKEN_VARIABLE];
824
+ if (token != null) authProvider = makeOAuthProvider(token);
792
825
  }
793
826
  return Effect5.succeed({
794
827
  transport: "remote",
795
828
  endpoint: config.endpoint,
796
829
  remoteTransport: config.remoteTransport ?? "auto",
797
- queryParams: config.queryParams && Object.keys(config.queryParams).length > 0 ? config.queryParams : void 0,
830
+ queryParams: Object.keys(queryParams).length > 0 ? queryParams : void 0,
798
831
  headers: Object.keys(headers).length > 0 ? headers : void 0,
799
832
  authProvider
800
833
  });
@@ -802,40 +835,19 @@ var buildConnectorInput = (config, value, allowStdio) => {
802
835
  var describeMcpAuthMethods = (record) => {
803
836
  const config = parseMcpIntegrationConfig(record.config);
804
837
  if (!config || config.transport === "stdio") return [];
805
- const auth = config.auth;
806
- if (auth.kind === "none") {
807
- return [
808
- {
809
- id: "none",
810
- label: "No authentication",
811
- kind: "none",
812
- template: "none"
813
- }
814
- ];
815
- }
816
- if (auth.kind === "header") {
817
- return [
818
- {
819
- id: "header",
820
- label: "API key (header)",
821
- kind: "apikey",
822
- template: "header",
823
- placements: [{ carrier: "header", name: auth.headerName, prefix: auth.prefix ?? "" }]
824
- }
825
- ];
826
- }
827
- if (auth.kind === "oauth2") {
828
- return [
829
- {
830
- id: "oauth2",
838
+ return config.authenticationTemplate.map((method) => {
839
+ if (method.kind === "apikey") return describeApiKeyAuthMethod(method);
840
+ if (method.kind === "oauth2") {
841
+ return {
842
+ id: method.slug,
831
843
  label: "OAuth",
832
844
  kind: "oauth",
833
- template: "oauth2",
845
+ template: method.slug,
834
846
  oauth: { discoveryUrl: config.endpoint, supportsDynamicRegistration: true }
835
- }
836
- ];
837
- }
838
- return [];
847
+ };
848
+ }
849
+ return describeNoneAuthMethod(method.slug);
850
+ });
839
851
  };
840
852
  var describeMcpIntegrationDisplay = (record) => {
841
853
  const config = parseMcpIntegrationConfig(record.config);
@@ -1050,12 +1062,34 @@ var mcpPlugin = definePlugin((options) => {
1050
1062
  attributes: { "mcp.integration.slug": slug }
1051
1063
  })
1052
1064
  );
1065
+ const configureAuth = (slug, input) => Effect5.gen(function* () {
1066
+ const record = yield* ctx.core.integrations.get(slugFrom(slug));
1067
+ const current = record ? parseMcpIntegrationConfig(record.config) : null;
1068
+ if (!current || current.transport === "stdio") {
1069
+ return [];
1070
+ }
1071
+ const merged = input.mode === "replace" ? normalizeMcpAuthMethods(input.authenticationTemplate) : mergeAuthTemplates(
1072
+ current.authenticationTemplate,
1073
+ expandMcpAuthMethodInputs(
1074
+ input.authenticationTemplate
1075
+ )
1076
+ );
1077
+ yield* ctx.core.integrations.update(slugFrom(slug), {
1078
+ config: { ...current, authenticationTemplate: merged }
1079
+ });
1080
+ return merged;
1081
+ }).pipe(
1082
+ Effect5.withSpan("mcp.plugin.configure_auth", {
1083
+ attributes: { "mcp.integration.slug": slug }
1084
+ })
1085
+ );
1053
1086
  return {
1054
1087
  probeEndpoint,
1055
1088
  addServer,
1056
1089
  removeServer,
1057
1090
  getServer,
1058
- configureServer
1091
+ configureServer,
1092
+ configureAuth
1059
1093
  };
1060
1094
  },
1061
1095
  // -----------------------------------------------------------------------
@@ -1066,11 +1100,18 @@ var mcpPlugin = definePlugin((options) => {
1066
1100
  // Discovery failures (auth not ready, server down) yield an empty tool set
1067
1101
  // rather than failing — the connection still lands and can be refreshed.
1068
1102
  // -----------------------------------------------------------------------
1069
- resolveTools: ({ config, connection, getValue }) => Effect5.gen(function* () {
1103
+ resolveTools: ({ config, connection, template, getValues }) => Effect5.gen(function* () {
1070
1104
  const parsed = parseMcpIntegrationConfig(config);
1071
1105
  if (!parsed) return { tools: [] };
1072
- const value = yield* getValue().pipe(Effect5.orElseSucceed(() => null));
1073
- const built = yield* buildConnectorInput(parsed, value, allowStdio).pipe(
1106
+ const values = yield* getValues().pipe(
1107
+ Effect5.orElseSucceed(() => ({}))
1108
+ );
1109
+ const built = yield* buildConnectorInput(
1110
+ parsed,
1111
+ values,
1112
+ template === null ? null : String(template),
1113
+ allowStdio
1114
+ ).pipe(
1074
1115
  Effect5.map((ci) => createMcpConnector(ci)),
1075
1116
  Effect5.result
1076
1117
  );
@@ -1104,9 +1145,26 @@ var mcpPlugin = definePlugin((options) => {
1104
1145
  });
1105
1146
  }
1106
1147
  const transport = parsed.transport === "stdio" ? "stdio" : parsed.remoteTransport ?? "auto";
1148
+ if (parsed.transport === "remote") {
1149
+ const method = selectAuthMethod(parsed, String(credential.template));
1150
+ if (method?.kind === "apikey") {
1151
+ const missing = requiredPlacementVariables(method.placements).filter(
1152
+ (variable) => credential.values[variable] == null
1153
+ );
1154
+ if (missing.length > 0) {
1155
+ return authToolFailure({
1156
+ code: "connection_value_missing",
1157
+ message: `Connection has no resolvable credential value for input(s): ${missing.join(", ")}. Re-create the connection with the required value(s).`,
1158
+ source: { id: String(credential.integration) },
1159
+ credential: { kind: "upstream", label: String(credential.connection) }
1160
+ });
1161
+ }
1162
+ }
1163
+ }
1107
1164
  const connector = yield* buildConnectorInput(
1108
1165
  parsed,
1109
- credential.value,
1166
+ credential.values,
1167
+ String(credential.template),
1110
1168
  allowStdio
1111
1169
  ).pipe(Effect5.map((ci) => createMcpConnector(ci)));
1112
1170
  const raw = yield* invokeMcpTool({
@@ -1295,4 +1353,4 @@ export {
1295
1353
  userFacingProbeMessage,
1296
1354
  mcpPlugin
1297
1355
  };
1298
- //# sourceMappingURL=chunk-HSJWIVME.js.map
1356
+ //# sourceMappingURL=chunk-6BJ6MZF7.js.map