(slug: string, input: McpConfigureAuthInput)
| 1113 | * (returns `[]`) for an unknown slug, a stdio server, or an |
| 1114 | * undecodable config. */ |
| 1115 | const configureAuth = (slug: string, input: McpConfigureAuthInput) => |
| 1116 | Effect.gen(function* () { |
| 1117 | const record = yield* ctx.core.integrations.get(slugFrom(slug)); |
| 1118 | const current = record ? parseMcpIntegrationConfig(record.config) : null; |
| 1119 | if (!current || current.transport === "stdio") { |
| 1120 | return [] as readonly McpAuthMethod[]; |
| 1121 | } |
| 1122 | |
| 1123 | // Replace mode declares the full set — backfill kind-based slugs. |
| 1124 | // Merge mode appends: `mergeAuthTemplates` replaces on slug match and |
| 1125 | // assigns fresh `custom_<id>` slugs to slug-less entries, so a custom |
| 1126 | // method never silently displaces a declared one. |
| 1127 | const merged = |
| 1128 | input.mode === "replace" |
| 1129 | ? normalizeMcpAuthMethods(input.authenticationTemplate) |
| 1130 | : mergeAuthTemplates( |
| 1131 | current.authenticationTemplate, |
| 1132 | expandMcpAuthMethodInputs( |
| 1133 | input.authenticationTemplate, |
| 1134 | ) as readonly McpAuthMethod[], |
| 1135 | ); |
| 1136 | |
| 1137 | yield* ctx.core.integrations.update(slugFrom(slug), { |
| 1138 | config: { ...current, authenticationTemplate: merged }, |
| 1139 | }); |
| 1140 | |
| 1141 | return merged; |
| 1142 | }).pipe( |
| 1143 | Effect.withSpan("mcp.plugin.configure_auth", { |
| 1144 | attributes: { "mcp.integration.slug": slug }, |
| 1145 | }), |
| 1146 | ); |
| 1147 | |
| 1148 | return { |
| 1149 | probeEndpoint, |
nothing calls this directly
no test coverage detected