Skip to content

feat(mcp): add loopover-mcp agent start CLI subcommand mirroring the existing loopover_agent_start_run MCP tool #8314

Description

@JSONbored

Context

packages/loopover-mcp exposes the base-agent's run lifecycle two ways: as MCP tools for an AI-harness caller (src/mcp/server.ts's loopover_agent_start_run/loopover_agent_get_run, plus this package's own local-stdio mirrors at packages/loopover-mcp/bin/loopover-mcp.ts:2850-2879), and as human-typable loopover-mcp agent <subcommand> CLI commands (runAgentCli, packages/loopover-mcp/bin/loopover-mcp.ts:4898-4946).

runAgentCli only implements plan, status, explain, and packet:

// packages/loopover-mcp/bin/loopover-mcp.ts:4898-4946
async function runAgentCli(args: any) {
  const subcommand = args[0] ?? "help";
  if (subcommand === "--help" || subcommand === "help") return printAgentHelp();
  const options = parseOptions(args.slice(1));
  if (subcommand === "plan") { ... }
  if (subcommand === "status") { ... }
  if (subcommand === "explain") { ... }
  if (subcommand === "packet") { ... }
  throw new Error(`Unknown agent command: ${subcommand}`);
}

status/explain both read an existing run via GET /v1/agent/runs/:id, but nothing in the CLI creates one via POST /v1/agent/runs — the local-stdio MCP tool loopover_agent_start_run (lines 2850-2870) already does exactly this:

// packages/loopover-mcp/bin/loopover-mcp.ts:2856-2869
async (input: any) =>
  toolResult(
    `Queued LoopOver base-agent run for ${input.actorLogin}.`,
    await apiPost("/v1/agent/runs", {
      objective: input.objective,
      actorLogin: input.actorLogin,
      surface: "mcp",
      target: stripUndefined({
        repoFullName: input.targetRepoFullName,
        pullNumber: input.targetPullNumber,
        issueNumber: input.targetIssueNumber,
      }),
    }),
  ),

So the capability exists as an MCP tool (reachable by an AI-harness client connected over stdio) but has no CLI-typable counterpart — a human running loopover-mcp agent start ... from a terminal gets Unknown agent command: start, and printAgentHelp() (line 5363) never mentions it either. This is the one asymmetry found in an otherwise-complete audit of all ~110 loopover_* MCP tools against the CLI's command surface — every other agent-category tool traces cleanly to a CLI command.

Note: printAgentHelp()'s own description ("The agent is copilot-only: it ranks, explains, and drafts public-safe packets. It does not edit code, open PRs, or post comments from the local MCP wrapper.") is still accurate for this addition — queuing a run only enqueues work for later; it is not itself a code/PR/comment write, matching the existing plan/packet commands' own non-mutating nature.

Requirements

  • Add an agent start CLI subcommand to runAgentCli that POSTs to /v1/agent/runs with the same request shape the existing stdio MCP tool (loopover_agent_start_run, lines 2856-2869) already sends: { objective, actorLogin, surface, target: { repoFullName?, pullNumber?, issueNumber? } }. Use surface: "cli" (not "mcp") so the two entry points remain distinguishable server-side, mirroring how plan/packet already set surface: "mcp" only from their stdio-tool registrations, not from runAgentCli (check: confirm whether plan/packet's apiPost calls from runAgentCli already set a surface field at all — if they don't, match that existing convention exactly rather than inventing a new one for start; if they do, use the same value those established CLI-side calls use).
  • objective and actorLogin are required by the existing MCP tool's agentRunShape (src/mcp/server.ts:856-862, both non-optional) — the CLI subcommand must enforce the same requirement (--objective "..." and --login <github-login> / LOOPOVER_LOGIN env fallback, matching the existing plan/packet subcommands' own --login resolution pattern at lines 4903-4904/4922-4923) and throw a clear usage error when either is missing, mirroring those subcommands' if (!login) throw new Error(...) pattern.
  • --repo owner/repo, --pull <number>, --issue <number> map to target.repoFullName/target.pullNumber/target.issueNumber respectively (all optional).
  • Output must go through the existing outputAgentPayload(payload, options, summary) helper (line 4948), matching every other agent subcommand's output handling (--json passthrough vs. the markdown/summary path).
  • Add agent start to printAgentHelp()'s usage listing (line 5363-5373).

Deliverables

  • packages/loopover-mcp/bin/loopover-mcp.ts: add the subcommand === "start" branch to runAgentCli.
  • packages/loopover-mcp/bin/loopover-mcp.ts: update printAgentHelp() to document the new subcommand.
  • A CLI test alongside the existing agent plan/agent status/agent packet coverage (check test/unit/mcp-cli-*.ts for the existing agent-run test file(s), e.g. covering loopover-mcp agent plan/status, and add an equivalent agent start case) asserting: (a) the correct request body reaches POST /v1/agent/runs, (b) a missing --login/--objective throws the expected usage error, (c) --json output matches the raw API payload.

Test Coverage Requirements

99%+ Codecov patch coverage, branch-counted: both the missing---login/missing---objective error branches and the success path (with and without --repo/--pull/--issue) must be exercised.

Expected Outcome

loopover-mcp agent start --login <login> --objective "..." [--repo owner/repo] queues a base-agent run from the terminal, the same capability an AI-harness client already gets via the loopover_agent_start_run MCP tool — closing the one CLI/MCP parity gap found in this audit.

Links & Resources

  • packages/loopover-mcp/bin/loopover-mcp.ts:4898-4946 (runAgentCli, the file to extend)
  • packages/loopover-mcp/bin/loopover-mcp.ts:2850-2870 (the existing stdio MCP tool to mirror the request shape from)
  • packages/loopover-mcp/bin/loopover-mcp.ts:5363-5373 (printAgentHelp, to update)
  • src/mcp/server.ts:856-862 (agentRunShape, the authoritative input contract)
  • src/mcp/server.ts (loopover_agent_start_run tool registration, the remote-MCP counterpart)

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:featureGittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions