import { type EnvironmentId, PreviewAutomationUnavailableError, type ProviderInstanceId, type ThreadId, } from "@t3tools/contracts"; import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; export const ALL_MCP_CAPABILITIES = ["preview", "orchestration", "worktree"] as const; export type McpCapability = (typeof ALL_MCP_CAPABILITIES)[number]; export interface McpInvocationScope { readonly environmentId: EnvironmentId; readonly threadId: ThreadId; readonly providerSessionId: string; readonly providerInstanceId: ProviderInstanceId; readonly capabilities: ReadonlySet; readonly issuedAt: number; } export class McpInvocationContext extends Context.Service< McpInvocationContext, McpInvocationScope >()("t3/mcp/McpInvocationContext") {} export const requireMcpCapability = Effect.fn("mcp.requireCapability")(function* ( capability: "preview", ) { const invocation = yield* McpInvocationContext; if (!invocation.capabilities.has(capability)) { return yield* new PreviewAutomationUnavailableError({ capability, environmentId: invocation.environmentId, threadId: invocation.threadId, providerSessionId: invocation.providerSessionId, providerInstanceId: invocation.providerInstanceId, }); } return invocation; });