import { controllerMcpWorkspaceMethods, type TControllerMcpWorkspaceTypedRequest } from './mcpworkspacerequests.js'; import * as plugins from './plugins.js'; import type { IReq_ControllerMcpAuthSwitch } from './authswitch.js'; import type { IReq_ControllerSettingsGet, IReq_ControllerSettingsUpdate } from './requests.js'; import type { IControllerProject, IControllerSession, IControllerSessionDetail, IControllerSessionScratchpad, IControllerStatus, IControllerRuntimeId, TControllerSessionId, TControllerModelChoice, } from './interfaces.js'; export const controllerMcpTypedRequestPath = '/mcp/typedrequest' as const; export const controllerMcpTypedRequestMaximumBodyBytes = 256 * 1024; export const controllerMcpTypedResponseMaximumBytes = 1024 * 1024; export const controllerMcpToolMaximumOutputBytes = 512 * 1024; export const controllerMcpMethods = [ 'agl.mcp.controller.status', 'agl.mcp.projects.list', 'agl.mcp.sessions.list', 'agl.mcp.session.read', 'agl.mcp.session.send', 'agl.mcp.session.scratchpad.read', 'agl.mcp.session.scratchpad.update', ...controllerMcpWorkspaceMethods, 'agl.mcp.authswitch.request', 'agl.mcp.controller.settings.get', 'agl.mcp.controller.settings.update', ] as const; export type TControllerMcpMethod = (typeof controllerMcpMethods)[number]; export type TControllerOperationPrincipal = 'browser' | 'mcp'; /** * Environment variable through which the controller hands a freshly minted caller credential to a * harness process it spawns. Every `agl mcp` server that process launches inherits it and presents * it on the private endpoint, so the controller authorizes the calling chat instead of trusting a * caller-supplied task id. It is never allowlisted for inheritance: only explicit per-spawn writes * may set it. */ export const controllerMcpCallerCredentialEnvironmentVariable = 'AGL_MCP_CALLER_CREDENTIAL'; /** Wire shape of the optional credential envelope field. */ export interface IControllerMcpWireCaller { credential: string; } /** * What an MCP call is authorized as. `runtime` is deliberately coarse: OpenCode runs one shared * server per controller and addresses MCP servers per directory, never per session, so an * OpenCode-launched caller can only be identified as "this OpenCode runtime" until upstream grows * per-session MCP servers. Its reach is scoped to the project named in each request. */ export type TControllerMcpSubject = | { kind: 'session'; projectId: string; sessionId: TControllerSessionId; sessionIdentityId: string; } | { kind: 'terminal'; projectId: string; resourceId: string; agentSessionId?: string } | { kind: 'runtime'; harnessId: 'opencode'; runtimeGeneration: string } | { kind: 'anonymous' }; export interface IControllerMcpCaller { subject: TControllerMcpSubject; /** Stable, non-reversible operation budget and audit key. Never the credential. */ auditPeerId: string; } export interface IReq_ControllerMcpSettingsGet extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpSettingsGet > { method: 'agl.mcp.controller.settings.get'; request: Record; response: IReq_ControllerSettingsGet['response']; } export interface IReq_ControllerMcpSettingsUpdate extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpSettingsUpdate > { method: 'agl.mcp.controller.settings.update'; /** * The settings the CLI administers. Every key is optional and absent leaves it unchanged, so * `agl settings` can edit the standard project directories without touching video capture. */ request: { browserVideoBackend?: 'chromium' | 'native'; standardProjectDirectories?: string[]; }; response: IReq_ControllerSettingsUpdate['response']; } export interface IControllerMcpStatusResponse { status: IControllerStatus; controllerPort: number; lifecycleGeneration: string; } export interface IReq_ControllerMcpStatus extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpStatus > { method: 'agl.mcp.controller.status'; request: Record; response: IControllerMcpStatusResponse; } export interface IReq_ControllerMcpProjectsList extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpProjectsList > { method: 'agl.mcp.projects.list'; request: Record; response: { projects: IControllerProject[] }; } export interface IReq_ControllerMcpSessionsList extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpSessionsList > { method: 'agl.mcp.sessions.list'; request: { projectId: string }; response: { sessions: IControllerSession[] }; } export interface IReq_ControllerMcpSessionRead extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpSessionRead > { method: 'agl.mcp.session.read'; request: { projectId: string; sessionId: IControllerRuntimeId; }; response: IControllerSessionDetail; } export interface IReq_ControllerMcpSessionSend extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpSessionSend > { method: 'agl.mcp.session.send'; request: { projectId: string; sessionId: IControllerRuntimeId; text: string; model?: TControllerModelChoice; /** Exact Flex provider account paired with the model override. */ providerConnectionId?: string; }; response: { accepted: true }; } export interface IReq_ControllerMcpSessionScratchpadRead extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpSessionScratchpadRead > { method: 'agl.mcp.session.scratchpad.read'; request: { projectId: string; sessionId: IControllerRuntimeId; }; response: { scratchpad: IControllerSessionScratchpad }; } export interface IReq_ControllerMcpSessionScratchpadUpdate extends plugins.typedrequestInterfaces.implementsTR< plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerMcpSessionScratchpadUpdate > { method: 'agl.mcp.session.scratchpad.update'; request: { projectId: string; sessionId: IControllerRuntimeId; text: string; expectedRevision: number; }; response: { scratchpad: IControllerSessionScratchpad }; } export type TControllerMcpTypedRequest = | IReq_ControllerMcpSettingsGet | IReq_ControllerMcpSettingsUpdate | IReq_ControllerMcpAuthSwitch | TControllerMcpWorkspaceTypedRequest | IReq_ControllerMcpStatus | IReq_ControllerMcpProjectsList | IReq_ControllerMcpSessionsList | IReq_ControllerMcpSessionRead | IReq_ControllerMcpSessionSend | IReq_ControllerMcpSessionScratchpadRead | IReq_ControllerMcpSessionScratchpadUpdate;