Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Kandev Agent <agent@kandev.dev>
11 KiB
status, system, requirements
| status | system | requirements | ||||
|---|---|---|---|---|---|---|
| current | tasks |
|
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.