Files
kandev/apps/backend/internal/task
João Salavisa 0b7bbd93d5 feat(mcp): accept repository_url and local_path on add_branch_to_task_kandev (#1256)
* feat(mcp): accept repository_url and local_path on add_branch_to_task_kandev

Mirror create_task_kandev's repo-locator surface so agents can attach a
branch without first looking up the repository UUID. The MCP tool now
takes repository_id OR repository_url OR local_path; the service
resolves alternatives via the same workspace-scoped find-or-create
path used by create_task.

* fix(mcp): run executor guard before repo resolution on add_branch_to_task

ResolveRepositoryRef may FindOrCreateRepository / CreateRepository
inside the github_url / local_path paths. Running it before
requireWorktreeExecutorForBranchAdd let a rejected add_branch call
on a docker/sprites/SSH task leak an orphan Repository row into
the workspace.

Move the executor check ahead of resolution and add a regression
test that asserts ListRepositories count is unchanged after a
rejected call with a brand-new github_url.

* test(mcp): assert task_id default in add_branch local_path test

* fix(mcp): reject multiple repo locators on add_branch_to_task

resolveRepoInput applies a silent precedence (repository_id >
github_url > local_path), so an agent that accidentally supplies
two of the three locators got a behaviour change with no signal.
Reject at the WS handler with a clear error so the mistake is
surfaced.

Also refresh the AddBranchToTask docstring to document the new
LocalPath / GitHubURL inputs and to correct the workspace-membership
check ownership (now enforced by ResolveRepositoryRef → resolveRepoInput
for the alternative paths).

* fix(mcp): classify resolve_repository errors as validation, not internal

Failures from ResolveRepositoryRef are user-fixable input mistakes
(malformed URL, unknown local_path, cross-workspace repository_id).
Without a matching case the wrapper "resolve repository: ..." message
fell through to ErrorCodeInternalError, so an agent that supplied
e.g. a bitbucket URL saw a server-fault code instead of a validation
error it could correct.

* fix(mcp): narrow add_branch error classification + use wire field name

Two follow-ups to the round-3/4 review feedback:

- Mutual-exclusion error mentioned the MCP tool alias `repository_url`
  but the WS handler sees the wire field `github_url`. A direct WS
  caller would see an error naming a field it never passed.
- The broad `"resolve repository: "` prefix classified ALL wrapped
  errors as Validation, including DB / system failures from
  CreateRepository / ListRepositories inside ResolveRepositoryRef.
  Narrow to specific user-fixable patterns (GitHub URL parse failures,
  cross-workspace repository_id) so genuine internal errors no longer
  masquerade as validation rejections.

* fix(mcp): mutual-exclusion check at MCP tier names agent-facing alias

WS-tier rejection works for direct WS callers but its error mentions
github_url, the wire field — confusing for MCP agents that supplied
repository_url. Move the check up to addBranchToTaskHandler so the
error reads "pass at most one of repository_id, repository_url,
local_path" using the names the agent actually typed. WS handler
still validates as defense-in-depth.

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
2026-06-03 03:04:04 +01:00
..