import { describe, expect, it } from "@effect/vitest";import { IntegrationSlug, type IntegrationConfig, type IntegrationRecord } from "@executor-js/sdk"; import { describeMcpAuthMethods, describeMcpIntegrationDisplay } from "./plugin"; // ---------------------------------------------------------------------------// `describeMcpAuthMethods` projects the stored MCP config into the catalog's// plugin-agnostic `AuthMethodDescriptor[]`, one per declared method. It is// pure/sync and must tolerate a malformed or foreign config blob by returning// `[]`. Pre-canonical blobs are rewritten by the one-off config migration// (see migrate-config.test.ts), so this projection only ever sees the// canonical placements model.// --------------------------------------------------------------------------- const recordWith = (config: IntegrationConfig): IntegrationRecord => ({ slug: IntegrationSlug.make("server"), name: "Server", description: "Server", kind: "mcp", canRemove: true, canRefresh: true, authMethods: [], config,}); describe("describeMcpAuthMethods", () => { it("projects an oauth2 method carrying the discovery URL", () => { const methods = describeMcpAuthMethods( recordWith({ transport: "remote", endpoint: "https://x.example/oauth/mcp", authenticationTemplate: [{ slug: "oauth2", kind: "oauth2" }], }), ); expect(methods).toEqual([ { id: "oauth2", label: "OAuth", kind: "oauth", template: "oauth2", oauth: { discoveryUrl: "https://x.example/oauth/mcp", supportsDynamicRegistration: true, }, }, ]); }); it("projects an apikey header method carrying the placement", () => { const methods = describeMcpAuthMethods( recordWith({ transport: "remote", endpoint: "https://x.example/mcp", authenticationTemplate: [ { slug: "header", kind: "apikey", placements: [{ carrier: "header", name: "X-Api-Key", prefix: "Bearer " }], }, ], }), ); expect(methods).toEqual([ { id: "header", label: "API key (X-Api-Key)", kind: "apikey", template: "header", placements: [{ carrier: "header", name: "X-Api-Key", prefix: "Bearer " }], }, ]); }); it("projects an apikey query method (the ui.sh '?token=' shape)", () => { const methods = describeMcpAuthMethods( recordWith({ transport: "remote", endpoint: "https://ui.sh/mcp", authenticationTemplate: [ { slug: "query", kind: "apikey", placements: [{ carrier: "query", name: "token" }] }, ], }), ); expect(methods).toEqual([ { id: "query", label: "API key (token)", kind: "apikey", template: "query", placements: [{ carrier: "query", name: "token", prefix: "" }], }, ]); }); it("projects a mixed header+query method with per-placement variables", () => { const methods = describeMcpAuthMethods( recordWith({ transport: "remote", endpoint: "https://x.example/mcp", authenticationTemplate: [ { slug: "custom_mix", kind: "apikey", placements: [ { carrier: "header", name: "Authorization", prefix: "Bearer ", variable: "api_token", }, { carrier: "query", name: "team_id", variable: "team_id" }, ], }, ], }), ); expect(methods[0]?.placements).toEqual([ { carrier: "header", name: "Authorization", prefix: "Bearer ", variable: "api_token" }, { carrier: "query", name: "team_id", prefix: "", variable: "team_id" }, ]); }); it("projects every declared method (multi-method configs)", () => { const methods = describeMcpAuthMethods( recordWith({ transport: "remote", endpoint: "https://x.example/mcp", authenticationTemplate: [ { slug: "oauth2", kind: "oauth2" }, { slug: "custom_abc123", kind: "apikey", placements: [{ carrier: "header", name: "X-Api-Key" }], }, ], }), ); expect(methods.map((m) => ({ id: m.id, kind: m.kind, template: m.template }))).toEqual([ { id: "oauth2", kind: "oauth", template: "oauth2" }, { id: "custom_abc123", kind: "apikey", template: "custom_abc123" }, ]); }); it("projects an open (none) method to a no-auth method", () => { const methods = describeMcpAuthMethods( recordWith({ transport: "remote", endpoint: "https://x.example/mcp", authenticationTemplate: [{ slug: "none", kind: "none" }], }), ); expect(methods).toEqual([ { id: "none", label: "No authentication", kind: "none", template: "none", }, ]); }); it("returns [] for a stdio transport", () => { const methods = describeMcpAuthMethods( recordWith({ transport: "stdio", command: "run-server" }), ); expect(methods).toEqual([]); }); it("returns [] for a malformed / foreign / pre-migration config blob", () => { expect(describeMcpAuthMethods(recordWith({ not: "an mcp config" }))).toEqual([]); expect(describeMcpAuthMethods(recordWith(null))).toEqual([]); expect(describeMcpAuthMethods(recordWith("garbage"))).toEqual([]); // Pre-canonical blobs are the config migration's job, not the projection's. expect( describeMcpAuthMethods( recordWith({ transport: "remote", endpoint: "https://x.example/mcp", authenticationTemplate: [{ slug: "header", kind: "header", headerName: "X" }], }), ), ).toEqual([]); }); it("projects remote endpoint as display metadata", () => { expect( describeMcpIntegrationDisplay( recordWith({ transport: "remote", endpoint: "https://mcp.posthog.com/mcp", authenticationTemplate: [{ slug: "none", kind: "none" }], }), ), ).toEqual({ url: "https://mcp.posthog.com/mcp" }); }); it("does not expose display metadata for stdio or malformed configs", () => { expect( describeMcpIntegrationDisplay(recordWith({ transport: "stdio", command: "run" })), ).toEqual({}); expect(describeMcpIntegrationDisplay(recordWith({ not: "mcp" }))).toEqual({}); });});
import { describe, expect, it } from "@effect/vitest";
import { IntegrationSlug, type IntegrationConfig, type IntegrationRecord } from "@executor-js/sdk";
import { describeMcpAuthMethods, describeMcpIntegrationDisplay } from "./plugin";
// ---------------------------------------------------------------------------
// `describeMcpAuthMethods` projects the stored MCP config into the catalog's
// plugin-agnostic `AuthMethodDescriptor[]`, one per declared method. It is
// pure/sync and must tolerate a malformed or foreign config blob by returning
// `[]`. Pre-canonical blobs are rewritten by the one-off config migration
// (see migrate-config.test.ts), so this projection only ever sees the
// canonical placements model.
// ---------------------------------------------------------------------------
const recordWith = (config: IntegrationConfig): IntegrationRecord => ({
slug: IntegrationSlug.make("server"),
name: "Server",
description: "Server",
kind: "mcp",
canRemove: true,
canRefresh: true,
authMethods: [],
config,
});
describe("describeMcpAuthMethods", () => {
it("projects an oauth2 method carrying the discovery URL", () => {
const methods = describeMcpAuthMethods(
recordWith({
transport: "remote",
endpoint: "https://x.example/oauth/mcp",
authenticationTemplate: [{ slug: "oauth2", kind: "oauth2" }],
}),
);
expect(methods).toEqual([
{
id: "oauth2",
label: "OAuth",
kind: "oauth",
template: "oauth2",
oauth: {
discoveryUrl: "https://x.example/oauth/mcp",
supportsDynamicRegistration: true,
},
},
]);
});
it("projects an apikey header method carrying the placement", () => {
const methods = describeMcpAuthMethods(
recordWith({
transport: "remote",
endpoint: "https://x.example/mcp",
authenticationTemplate: [
{
slug: "header",
kind: "apikey",
placements: [{ carrier: "header", name: "X-Api-Key", prefix: "Bearer " }],
},
],
}),
);
expect(methods).toEqual([
{
id: "header",
label: "API key (X-Api-Key)",
kind: "apikey",
template: "header",
placements: [{ carrier: "header", name: "X-Api-Key", prefix: "Bearer " }],
},
]);
});
it("projects an apikey query method (the ui.sh '?token=' shape)", () => {
const methods = describeMcpAuthMethods(
recordWith({
transport: "remote",
endpoint: "https://ui.sh/mcp",
authenticationTemplate: [
{ slug: "query", kind: "apikey", placements: [{ carrier: "query", name: "token" }] },
],
}),
);
expect(methods).toEqual([
{
id: "query",
label: "API key (token)",
kind: "apikey",
template: "query",
placements: [{ carrier: "query", name: "token", prefix: "" }],
},
]);
});
it("projects a mixed header+query method with per-placement variables", () => {
const methods = describeMcpAuthMethods(
recordWith({
transport: "remote",
endpoint: "https://x.example/mcp",
authenticationTemplate: [
{
slug: "custom_mix",
kind: "apikey",
placements: [
{
carrier: "header",
name: "Authorization",
prefix: "Bearer ",
variable: "api_token",
},
{ carrier: "query", name: "team_id", variable: "team_id" },
],
},
],
}),
);
expect(methods[0]?.placements).toEqual([
{ carrier: "header", name: "Authorization", prefix: "Bearer ", variable: "api_token" },
{ carrier: "query", name: "team_id", prefix: "", variable: "team_id" },
]);
});
it("projects every declared method (multi-method configs)", () => {
const methods = describeMcpAuthMethods(
recordWith({
transport: "remote",
endpoint: "https://x.example/mcp",
authenticationTemplate: [
{ slug: "oauth2", kind: "oauth2" },
{
slug: "custom_abc123",
kind: "apikey",
placements: [{ carrier: "header", name: "X-Api-Key" }],
},
],
}),
);
expect(methods.map((m) => ({ id: m.id, kind: m.kind, template: m.template }))).toEqual([
{ id: "oauth2", kind: "oauth", template: "oauth2" },
{ id: "custom_abc123", kind: "apikey", template: "custom_abc123" },
]);
});
it("projects an open (none) method to a no-auth method", () => {
const methods = describeMcpAuthMethods(
recordWith({
transport: "remote",
endpoint: "https://x.example/mcp",
authenticationTemplate: [{ slug: "none", kind: "none" }],
}),
);
expect(methods).toEqual([
{
id: "none",
label: "No authentication",
kind: "none",
template: "none",
},
]);
});
it("returns [] for a stdio transport", () => {
const methods = describeMcpAuthMethods(
recordWith({ transport: "stdio", command: "run-server" }),
);
expect(methods).toEqual([]);
});
it("returns [] for a malformed / foreign / pre-migration config blob", () => {
expect(describeMcpAuthMethods(recordWith({ not: "an mcp config" }))).toEqual([]);
expect(describeMcpAuthMethods(recordWith(null))).toEqual([]);
expect(describeMcpAuthMethods(recordWith("garbage"))).toEqual([]);
// Pre-canonical blobs are the config migration's job, not the projection's.
expect(
describeMcpAuthMethods(
recordWith({
transport: "remote",
endpoint: "https://x.example/mcp",
authenticationTemplate: [{ slug: "header", kind: "header", headerName: "X" }],
}),
),
).toEqual([]);
});
it("projects remote endpoint as display metadata", () => {
expect(
describeMcpIntegrationDisplay(
recordWith({
transport: "remote",
endpoint: "https://mcp.posthog.com/mcp",
authenticationTemplate: [{ slug: "none", kind: "none" }],
}),
),
).toEqual({ url: "https://mcp.posthog.com/mcp" });
});
it("does not expose display metadata for stdio or malformed configs", () => {
expect(
describeMcpIntegrationDisplay(recordWith({ transport: "stdio", command: "run" })),
).toEqual({});
expect(describeMcpIntegrationDisplay(recordWith({ not: "mcp" }))).toEqual({});
});
});