Files
kandev/docs/specs/tasks/system-design/mcp-workspace-mode.md
T
João Salavisa 10726dfe8e fix: reject incompatible inherited workspace repositories (#3838)
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Kandev Agent <agent@kandev.dev>
2026-09-21 15:08:26 +01:00

11 KiB

status, system, requirements
status system requirements
current tasks
REQ-TASKS-MCP-WORKSPACE-MODE-001
REQ-TASKS-MCP-WORKSPACE-MODE-002
REQ-TASKS-MCP-WORKSPACE-MODE-003
REQ-TASKS-MCP-WORKSPACE-MODE-004

MCP task workspace mode design

Boundary and evidence

This design changes task-creation admission, not Office task creation. server.ModeOffice explicitly excludes Kanban tools because Office agents use CLI commands. server.profileToolGroups exposes generic creation to Kanban and external callers, but not Office sessions.

Office guidance under internal/office/configloader/skills/ directs agents to CLI task creation. office/runtime/handler.go registers POST /runtime/tasks; office/runtime.Actions.CreateTask enforces the run's capabilities and workspace/parent/project checks.

Before this change, internal/mcp/handlers/handlers.go:handleCreateTask accepted a destination workspace without enforcing the session caller's mode. Its assignee-field rejection did not prevent Office targeting. The implemented handler now rejects Office sessions and wrong-mode destinations before repository resolution, and revalidates deduplicated results before exposing them.

Requirement mapping

Requirement Design sections
REQ-TASKS-MCP-WORKSPACE-MODE-001 Trusted admission; Destination resolution
REQ-TASKS-MCP-WORKSPACE-MODE-002 Surface contract
REQ-TASKS-MCP-WORKSPACE-MODE-003 External compatibility; Errors
REQ-TASKS-MCP-WORKSPACE-MODE-004 Materialization schema discoverability

Surface contract

Caller Creation path Destination
Kanban session create_task_kandev Authorized Kanban workspaces
Office session Existing skills and CLI Its Office workspace and run scope
External MCP create_task_kandev Authorized workspaces of either mode

Do not register create_office_task_kandev, add a new backend creation action, or reconstruct an Office run for MCP creation. Preserve the Office catalog, CLI schema, runtime permissions, assignment, and scheduler.

Keep generic MCP arguments and result envelopes intact. workspace_id selects the logical workspace; workspace_mode selects a subtask's materialized-workspace policy. Neither grants authority. In particular, agent_profile_id remains a launch profile, not an Office assignee.

This follows the existing typed MCP profile decision; no amendment adding Office creation is needed.

Trusted admission

Reuse scope.Principal and Resolver.ScopePrincipal, which derive identity from the bound execution's task and session. Reuse origin.IsTrustedExternalTransport, set only by server.NewExternalDispatcherBackendClient, to recognize external calls.

Add a focused guard in MCP creation before repository resolution and other side effects. Keep this caller policy outside generic task/service.Service.CreateTask, which also serves native and internal callers.

  • Verified Office session: reject MCP task creation, regardless of destination.
  • Verified Kanban session: resolve the stored source workspace and enforce Kanban destination/task classification.
  • Trusted external transport: permit either destination mode, subject to existing access controls.
  • Missing identity or conflicting principal/external markers: reject.
  • Automation/configuration: retain their existing explicit policies. Do not accidentally widen or remove the automation creation catalog.

Use Workspace.OfficeWorkflowID for workspace classification and the existing Task.IsFromOffice projection for stored task references. A workspace lookup failure is not a Kanban classification. If a session's surface/task classification disagrees with its workspace, deny creation until the backend context is reconciled.

Preserve trusted source attribution. Reject source IDs conflicting with the principal; external requests cannot fabricate creator-session context. User authentication and workspace authorization remain independent checks. Disabling optional user authentication does not disable this admission policy.

Destination resolution

Resolve explicit input without fallback. Otherwise use the authorized parent, then the principal workspace. External roots may auto-select only a sole authorized workspace across both modes; multiple choices require an explicit ID.

Validate parent, workflow, step, project, and repository associations without registering repositories or mutating state. Parents cannot cross workspaces. Kanban root creation in another permitted Kanban workspace must not inherit source repositories owned by a different workspace. Preserve applicable profile precedence after admission.

Inherited repository compatibility

An explicit repository selection does not change what inherit_parent means: the child must attach to the parent's existing materialized checkout. Before task insertion, the MCP creation handler asks the task service to validate explicit repository inputs against the parent's active task environment when one exists. Each requested repository plus effective branch identity must match exactly one active task_environment_repos row. Deleted, failed, missing, or duplicate matches are unsafe.

The validation runs after repository defaults and workspace policy are resolved but before remote-contribution registration, task insertion, session creation, or launch. It is read-only. A mismatch returns the existing validation envelope with bounded guidance to select workspace_mode=new_workspace; it does not rewrite the repository input, silently change workspace mode, or alter the parent environment. A parent without a materialized environment retains the existing launch-time validation path.

Kanban sessions cannot target Office workspaces, Office parents, or project-linked Office tasks, including inconsistent legacy combinations. External callers retain both modes; selecting an Office workspace must not make the external caller an Office session.

Run admission before remote repository registration, task insertion, idempotency lookups that return task data, and launch. Revalidate the mode and visibility of the task returned on an external-ID retry. A rejected request must not mutate or leak an existing wrong-mode task.

External compatibility

Keep registerCreateTaskTool and registerConfigTaskTools on the external surface. Do not require existing external Office callers to rename their tool. Keep existing creation fields, assignee limitations, launch behavior, and idempotency outcomes. This package does not add external assignment support.

Verify existing external listing, reads, moves, state updates, archive, and delete against both task modes. These operations retain their own authorization and lifecycle checks; the creation gate is not a general management guard.

Use isolated composition tests to prove the transport marker survives external dispatch, foreign targets are denied, and both destination modes remain reachable. Do not create tasks in a developer's live workspace.

Errors, persistence, and documentation

Use existing MCP tool-error and WS validation/not-found envelopes. For an authorized Kanban caller targeting Office, explain that session MCP creation is restricted to Kanban. For an Office session, direct it to its skills/CLI creation path. Do not suggest connecting through external MCP as a way for a session to bypass its scope.

Unknown and inaccessible resources return the same error. Log trusted IDs and a rejection reason using existing logging; do not log submitted prompts or credentials.

No migration, mode column, historical rewrite, new endpoint, or UI is planned. Update public reference documentation when the gate is implemented. The earlier proposal for a separate Office MCP creation tool is withdrawn.

Materialization schema discoverability

The task system owns this addition because the field is a task-creation contract. Workspace lifecycle, transport discovery guidance, and Office admission remain with their existing owners.

In internal/mcp/server/server.go, registerCreateTaskTool adds mcp.Enum("inherit_parent", "new_workspace") to the existing mcp.WithString("workspace_mode", ...) in registerCreateTaskTool. The pinned mcp-go v1.0.0-beta.1 supports this property option; existing delivery_mode and profile-session-policy fields use it. Do not add mcp.Required() or a default. Both ModeTask (through registerKanbanTools) and ModeExternal use this registration.

Field description: "Optional materialized-workspace mode. Omit for subtasks to inherit the parent's workspace/worktree. inherit_parent requires parent_id and reuses the parent's materialized workspace/worktree; new_workspace requests a separate workspace/worktree."

Keep resolveMCPWorkspacePolicy in internal/mcp/handlers/handlers.go unchanged. It trims input, defaults blank with a parent to inherit_parent, leaves blank root policy unspecified, rejects explicit inheritance without a parent, and accepts only the two explicit modes. Do not advertise the broader service's shared_group or an invented shared alias.

Compatibility and schema propagation

compileToolArgumentSchema marshals the registered schema and only adds root additionalProperties: false; it preserves enum metadata. Validation runs before dispatch. normalizeToolArguments only handles the legacy prompt alias, so the enum rejects empty, whitespace-only, and padded strings that previously reached the trimming handler. This is a real MCP input narrowing, not merely a description improvement. Callers should omit the key to request defaulting, or send an exact enum value. Do not introduce normalization or alter the backend to conceal this effect. This follows the existing schema validation decision.

mcpToolInputSchema preserves raw schemas or marshals structured schemas for attachment evidence. cloneValidMCPInputSchema in internal/agentctl/types/streams/mcp_attachment.go copies valid JSON unchanged; size limits can drop a whole schema with a truncation marker, not individual enum keywords. No enum-stripping transform was found in the inspected MCP registration, validator, or attachment paths. Regression tests verify serialized catalog and attachment schemas; this does not prove behavior of arbitrary external clients.

Schema and wrapped-call tests in server/create_task_workspace_mode_test.go cover task/external registration, exact enum order, optionality, absent default, description semantics, both accepted values, omission, and rejected blank/unsupported inputs without dispatch. The direct policy matrix in handlers/workspace_policy_test.go and existing handler tests preserve root, parent, trimming, and rejection behavior. The public MCP reference and coordination guide document omission and blank-input compatibility. No rendered UI changes or browser test are needed.