import { expect, it } from "@effect/vitest";import { Effect, Schema } from "effect";import { Client } from "@modelcontextprotocol/sdk/client/index.js";import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; import worker from "./worker"; const origin = "https://executor-test-servers.example"; const TokenResponse = Schema.Struct({ access_token: Schema.String,});const decodeTokenResponse = Schema.decodeUnknownEffect(TokenResponse); const OpenApiItemsResponse = Schema.Array( Schema.Struct({ id: Schema.Number, name: Schema.String }),);const decodeOpenApiItemsResponse = Schema.decodeUnknownEffect(OpenApiItemsResponse); const OpenApiSpecResponse = Schema.Struct({ openapi: Schema.String, servers: Schema.Array(Schema.Struct({ url: Schema.String })), paths: Schema.Record(Schema.String, Schema.Unknown), components: Schema.Struct({ securitySchemes: Schema.Struct({ oauth2: Schema.Struct({ type: Schema.Literal("oauth2"), flows: Schema.Struct({ authorizationCode: Schema.Struct({ authorizationUrl: Schema.String, tokenUrl: Schema.String, scopes: Schema.Record(Schema.String, Schema.String), }), }), }), }), }),});const decodeOpenApiSpecResponse = Schema.decodeUnknownEffect(OpenApiSpecResponse); const OAuthMetadataResponse = Schema.Struct({ issuer: Schema.String, authorization_endpoint: Schema.String, token_endpoint: Schema.String, registration_endpoint: Schema.String, code_challenge_methods_supported: Schema.Array(Schema.String),});const decodeOAuthMetadataResponse = Schema.decodeUnknownEffect(OAuthMetadataResponse); const ProtectedResourceMetadataResponse = Schema.Struct({ resource: Schema.String, authorization_servers: Schema.Array(Schema.String), bearer_methods_supported: Schema.Array(Schema.String), scopes_supported: Schema.Array(Schema.String),});const decodeProtectedResourceMetadataResponse = Schema.decodeUnknownEffect( ProtectedResourceMetadataResponse,); const GraphqlResponse = Schema.Struct({ data: Schema.Struct({ hello: Schema.String }),});const decodeGraphqlResponse = Schema.decodeUnknownEffect(GraphqlResponse); const request = (path: string, init?: RequestInit) => new Request(`${origin}${path}`, init); const workerFetch = (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => { const nextRequest = input instanceof Request ? new Request(input, init) : new Request(input, init); return worker.fetch(nextRequest);}; const base64url = (buffer: ArrayBuffer): string => { const bytes = new Uint8Array(buffer); let binary = ""; for (const byte of bytes) binary += String.fromCharCode(byte); return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");}; const codeChallengeForVerifier = (verifier: string): Promise<string> => crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier)).then(base64url); const authorize = Effect.gen(function* () { const redirectUrl = `${origin}/callback`; const verifier = `verifier_${crypto.randomUUID()}`; const authorizationUrl = new URL(`${origin}/authorize`); authorizationUrl.searchParams.set("response_type", "code"); authorizationUrl.searchParams.set("client_id", "test-client"); authorizationUrl.searchParams.set("redirect_uri", redirectUrl); authorizationUrl.searchParams.set("state", "state"); authorizationUrl.searchParams.set("scope", "read"); authorizationUrl.searchParams.set( "code_challenge", yield* Effect.promise(() => codeChallengeForVerifier(verifier)), ); authorizationUrl.searchParams.set("code_challenge_method", "S256"); const loginRedirect = yield* Effect.promise(() => worker.fetch(new Request(authorizationUrl))); const loginUrl = loginRedirect.headers.get("location"); expect(loginRedirect.status).toBe(302); expect(loginUrl).not.toBeNull(); const callbackRedirect = yield* Effect.promise(() => worker.fetch( new Request(new URL(loginUrl ?? "", origin), { method: "POST", headers: { authorization: `Basic ${btoa("alice:password")}` }, }), ), ); const callbackUrl = callbackRedirect.headers.get("location"); expect(callbackRedirect.status).toBe(302); expect(callbackUrl).not.toBeNull(); const code = new URL(callbackUrl ?? "").searchParams.get("code"); expect(code).not.toBeNull(); const tokenResponse = yield* Effect.promise(() => worker.fetch( request("/token", { method: "POST", body: new URLSearchParams({ grant_type: "authorization_code", client_id: "test-client", client_secret: "test-secret", redirect_uri: redirectUrl, code: code ?? "", code_verifier: verifier, }), }), ), ); expect(tokenResponse.status).toBe(200); const tokenBody = yield* Effect.promise(() => tokenResponse.json()).pipe( Effect.flatMap(decodeTokenResponse), ); return tokenBody.access_token;}); it.effect("worker exposes OAuth-protected OpenAPI, GraphQL, and MCP endpoints", () => Effect.gen(function* () { const oauthMetadataResponse = yield* Effect.promise(() => worker.fetch(request("/.well-known/oauth-authorization-server")), ); const oauthMetadata = yield* Effect.promise(() => oauthMetadataResponse.json()).pipe( Effect.flatMap(decodeOAuthMetadataResponse), ); expect(oauthMetadata).toMatchObject({ issuer: origin, authorization_endpoint: `${origin}/authorize`, token_endpoint: `${origin}/token`, registration_endpoint: `${origin}/register`, }); expect(oauthMetadata.code_challenge_methods_supported).toContain("S256"); const resourceMetadataResponse = yield* Effect.promise(() => worker.fetch(request("/.well-known/oauth-protected-resource/openapi/items")), ); const resourceMetadata = yield* Effect.promise(() => resourceMetadataResponse.json()).pipe( Effect.flatMap(decodeProtectedResourceMetadataResponse), ); expect(resourceMetadata).toEqual({ resource: `${origin}/openapi/items`, authorization_servers: [origin], bearer_methods_supported: ["header"], scopes_supported: ["read", "write"], }); const openApiSpecResponse = yield* Effect.promise(() => worker.fetch(request("/openapi/spec.json")), ); const openApiSpec = yield* Effect.promise(() => openApiSpecResponse.json()).pipe( Effect.flatMap(decodeOpenApiSpecResponse), ); expect(openApiSpec.servers).toEqual([{ url: `${origin}/openapi` }]); expect(openApiSpec.paths).toHaveProperty("/items"); expect(openApiSpec.components.securitySchemes.oauth2.flows.authorizationCode).toMatchObject({ authorizationUrl: `${origin}/authorize`, tokenUrl: `${origin}/token`, scopes: { read: "Read test resources" }, }); const accessToken = yield* authorize; const openApiResponse = yield* Effect.promise(() => worker.fetch( request("/openapi/items", { headers: { authorization: `Bearer ${accessToken}` } }), ), ); const items = yield* Effect.promise(() => openApiResponse.json()).pipe( Effect.flatMap(decodeOpenApiItemsResponse), ); expect(items).toEqual([ { id: 1, name: "Widget" }, { id: 2, name: "Gadget" }, ]); const graphqlResponse = yield* Effect.promise(() => worker.fetch( request("/graphql", { method: "POST", headers: { authorization: `Bearer ${accessToken}`, "content-type": "application/json", }, body: JSON.stringify({ query: '{ hello(name: "Ada") }' }), }), ), ); const graphqlBody = yield* Effect.promise(() => graphqlResponse.json()).pipe( Effect.flatMap(decodeGraphqlResponse), ); expect(graphqlBody).toEqual({ data: { hello: "Hello Ada" } }); const client = new Client({ name: "executor-worker-test-client", version: "1.0.0" }); const transport = new StreamableHTTPClientTransport(new URL(`${origin}/mcp`), { fetch: workerFetch, requestInit: { headers: { authorization: `Bearer ${accessToken}` } }, }); yield* Effect.tryPromise(() => client.connect(transport)); const tools = yield* Effect.tryPromise(() => client.listTools()); const result = yield* Effect.tryPromise(() => client.callTool({ name: "hello", arguments: { name: "Ada" } }), ); yield* Effect.promise(() => client.close()); expect(tools.tools.map((tool) => tool.name)).toEqual(["hello"]); expect(result).toMatchObject({ content: [{ type: "text", text: "Hello Ada" }] }); }),);
import { expect, it } from "@effect/vitest";
import { Effect, Schema } from "effect";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import worker from "./worker";
const origin = "https://executor-test-servers.example";
const TokenResponse = Schema.Struct({
access_token: Schema.String,
});
const decodeTokenResponse = Schema.decodeUnknownEffect(TokenResponse);
const OpenApiItemsResponse = Schema.Array(
Schema.Struct({ id: Schema.Number, name: Schema.String }),
);
const decodeOpenApiItemsResponse = Schema.decodeUnknownEffect(OpenApiItemsResponse);
const OpenApiSpecResponse = Schema.Struct({
openapi: Schema.String,
servers: Schema.Array(Schema.Struct({ url: Schema.String })),
paths: Schema.Record(Schema.String, Schema.Unknown),
components: Schema.Struct({
securitySchemes: Schema.Struct({
oauth2: Schema.Struct({
type: Schema.Literal("oauth2"),
flows: Schema.Struct({
authorizationCode: Schema.Struct({
authorizationUrl: Schema.String,
tokenUrl: Schema.String,
scopes: Schema.Record(Schema.String, Schema.String),
}),
}),
}),
}),
}),
});
const decodeOpenApiSpecResponse = Schema.decodeUnknownEffect(OpenApiSpecResponse);
const OAuthMetadataResponse = Schema.Struct({
issuer: Schema.String,
authorization_endpoint: Schema.String,
token_endpoint: Schema.String,
registration_endpoint: Schema.String,
code_challenge_methods_supported: Schema.Array(Schema.String),
});
const decodeOAuthMetadataResponse = Schema.decodeUnknownEffect(OAuthMetadataResponse);
const ProtectedResourceMetadataResponse = Schema.Struct({
resource: Schema.String,
authorization_servers: Schema.Array(Schema.String),
bearer_methods_supported: Schema.Array(Schema.String),
scopes_supported: Schema.Array(Schema.String),
});
const decodeProtectedResourceMetadataResponse = Schema.decodeUnknownEffect(
ProtectedResourceMetadataResponse,
);
const GraphqlResponse = Schema.Struct({
data: Schema.Struct({ hello: Schema.String }),
});
const decodeGraphqlResponse = Schema.decodeUnknownEffect(GraphqlResponse);
const request = (path: string, init?: RequestInit) => new Request(`${origin}${path}`, init);
const workerFetch = (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
const nextRequest =
input instanceof Request ? new Request(input, init) : new Request(input, init);
return worker.fetch(nextRequest);
};
const base64url = (buffer: ArrayBuffer): string => {
const bytes = new Uint8Array(buffer);
let binary = "";
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
};
const codeChallengeForVerifier = (verifier: string): Promise<string> =>
crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier)).then(base64url);
const authorize = Effect.gen(function* () {
const redirectUrl = `${origin}/callback`;
const verifier = `verifier_${crypto.randomUUID()}`;
const authorizationUrl = new URL(`${origin}/authorize`);
authorizationUrl.searchParams.set("response_type", "code");
authorizationUrl.searchParams.set("client_id", "test-client");
authorizationUrl.searchParams.set("redirect_uri", redirectUrl);
authorizationUrl.searchParams.set("state", "state");
authorizationUrl.searchParams.set("scope", "read");
authorizationUrl.searchParams.set(
"code_challenge",
yield* Effect.promise(() => codeChallengeForVerifier(verifier)),
);
authorizationUrl.searchParams.set("code_challenge_method", "S256");
const loginRedirect = yield* Effect.promise(() => worker.fetch(new Request(authorizationUrl)));
const loginUrl = loginRedirect.headers.get("location");
expect(loginRedirect.status).toBe(302);
expect(loginUrl).not.toBeNull();
const callbackRedirect = yield* Effect.promise(() =>
worker.fetch(
new Request(new URL(loginUrl ?? "", origin), {
method: "POST",
headers: { authorization: `Basic ${btoa("alice:password")}` },
}),
),
);
const callbackUrl = callbackRedirect.headers.get("location");
expect(callbackRedirect.status).toBe(302);
expect(callbackUrl).not.toBeNull();
const code = new URL(callbackUrl ?? "").searchParams.get("code");
expect(code).not.toBeNull();
const tokenResponse = yield* Effect.promise(() =>
worker.fetch(
request("/token", {
method: "POST",
body: new URLSearchParams({
grant_type: "authorization_code",
client_id: "test-client",
client_secret: "test-secret",
redirect_uri: redirectUrl,
code: code ?? "",
code_verifier: verifier,
}),
}),
),
);
expect(tokenResponse.status).toBe(200);
const tokenBody = yield* Effect.promise(() => tokenResponse.json()).pipe(
Effect.flatMap(decodeTokenResponse),
);
return tokenBody.access_token;
});
it.effect("worker exposes OAuth-protected OpenAPI, GraphQL, and MCP endpoints", () =>
Effect.gen(function* () {
const oauthMetadataResponse = yield* Effect.promise(() =>
worker.fetch(request("/.well-known/oauth-authorization-server")),
);
const oauthMetadata = yield* Effect.promise(() => oauthMetadataResponse.json()).pipe(
Effect.flatMap(decodeOAuthMetadataResponse),
);
expect(oauthMetadata).toMatchObject({
issuer: origin,
authorization_endpoint: `${origin}/authorize`,
token_endpoint: `${origin}/token`,
registration_endpoint: `${origin}/register`,
});
expect(oauthMetadata.code_challenge_methods_supported).toContain("S256");
const resourceMetadataResponse = yield* Effect.promise(() =>
worker.fetch(request("/.well-known/oauth-protected-resource/openapi/items")),
);
const resourceMetadata = yield* Effect.promise(() => resourceMetadataResponse.json()).pipe(
Effect.flatMap(decodeProtectedResourceMetadataResponse),
);
expect(resourceMetadata).toEqual({
resource: `${origin}/openapi/items`,
authorization_servers: [origin],
bearer_methods_supported: ["header"],
scopes_supported: ["read", "write"],
});
const openApiSpecResponse = yield* Effect.promise(() =>
worker.fetch(request("/openapi/spec.json")),
);
const openApiSpec = yield* Effect.promise(() => openApiSpecResponse.json()).pipe(
Effect.flatMap(decodeOpenApiSpecResponse),
);
expect(openApiSpec.servers).toEqual([{ url: `${origin}/openapi` }]);
expect(openApiSpec.paths).toHaveProperty("/items");
expect(openApiSpec.components.securitySchemes.oauth2.flows.authorizationCode).toMatchObject({
authorizationUrl: `${origin}/authorize`,
tokenUrl: `${origin}/token`,
scopes: { read: "Read test resources" },
});
const accessToken = yield* authorize;
const openApiResponse = yield* Effect.promise(() =>
worker.fetch(
request("/openapi/items", { headers: { authorization: `Bearer ${accessToken}` } }),
),
);
const items = yield* Effect.promise(() => openApiResponse.json()).pipe(
Effect.flatMap(decodeOpenApiItemsResponse),
);
expect(items).toEqual([
{ id: 1, name: "Widget" },
{ id: 2, name: "Gadget" },
]);
const graphqlResponse = yield* Effect.promise(() =>
worker.fetch(
request("/graphql", {
method: "POST",
headers: {
authorization: `Bearer ${accessToken}`,
"content-type": "application/json",
},
body: JSON.stringify({ query: '{ hello(name: "Ada") }' }),
}),
),
);
const graphqlBody = yield* Effect.promise(() => graphqlResponse.json()).pipe(
Effect.flatMap(decodeGraphqlResponse),
);
expect(graphqlBody).toEqual({ data: { hello: "Hello Ada" } });
const client = new Client({ name: "executor-worker-test-client", version: "1.0.0" });
const transport = new StreamableHTTPClientTransport(new URL(`${origin}/mcp`), {
fetch: workerFetch,
requestInit: { headers: { authorization: `Bearer ${accessToken}` } },
});
yield* Effect.tryPromise(() => client.connect(transport));
const tools = yield* Effect.tryPromise(() => client.listTools());
const result = yield* Effect.tryPromise(() =>
client.callTool({ name: "hello", arguments: { name: "Ada" } }),
);
yield* Effect.promise(() => client.close());
expect(tools.tools.map((tool) => tool.name)).toEqual(["hello"]);
expect(result).toMatchObject({ content: [{ type: "text", text: "Hello Ada" }] });
}),
);