import type { EnvironmentId, ProviderInstanceId, ThreadId } from "@t3tools/contracts"; import { PreviewAutomationUnavailableError } from "@t3tools/contracts"; import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; export type McpCapability = "preview"; export interface McpInvocationScope { readonly environmentId: EnvironmentId; readonly threadId: ThreadId; readonly providerSessionId: string; readonly providerInstanceId: ProviderInstanceId; readonly capabilities: ReadonlySet; readonly issuedAt: number; readonly expiresAt: number; } export class McpInvocationContext extends Context.Service< McpInvocationContext, McpInvocationScope >()("t3/mcp/McpInvocationContext") {} export const requireMcpCapability = Effect.fn("mcp.requireCapability")(function* ( capability: McpCapability, ) { const invocation = yield* McpInvocationContext; if (!invocation.capabilities.has(capability)) { return yield* new PreviewAutomationUnavailableError({ message: `MCP credential does not grant the ${capability} capability.`, }); } return invocation; });