Engineering

MCP Contract#

Agents use MCP tools to log work and receive feedback. The server must enforce rules. Agent prompts are not enough.

Install Paths#

Co-Vibe exposes two agent paths:

  • stdio MCP bridge: npm exec -- covibe-mcp in customer repos, or npm run mcp:stdio in this repo
  • direct JSON endpoint: /api/mcp
  • local companion setup/status, watch, and inbox flush: npm exec -- covibe-local setup --base-url <origin>, npm exec -- covibe-local doctor --base-url <origin>, npm exec -- covibe-local watch --base-url <origin>, then npm exec -- covibe-local telemetry --base-url <origin> --inbox .covibe/telemetry

Both paths expose the same task lifecycle tools, including plan, start planned, and cancel.

Claude Code uses the same stdio bridge through .mcp.json; .claude/settings.json starts/ends Co-Vibe sessions and forwards usage counters to covibe_ingest_agent_telemetry. When Cursor is installed, setup also writes a repo-local .cursor/mcp.json server entry and .cursor/hooks.json lifecycle hooks (see cursor-integration.md). The local companion installs those repo files, creates a .covibe/telemetry inbox for Codex/Cursor/provider usage JSON, syncs Codex Desktop split usage counters from local response.completed logs plus Cursor local usage, and verifies token, server, and hook readiness without storing the raw MCP token. Hosted customers point COVIBE_BASE_URL at the hosted app origin, install the companion package, and run covibe-local setup per repo for the agent config writes — there is no per-repo watch registration: agent activity registers each repo in ~/.covibe/repos.json for the machine-level watcher. Setup rejects credential-bearing URLs, callback URLs, queries, hashes, and other paths. covibe-local doctor is a status alias for rechecking the installed repo without rewriting config.

Set these env vars for the stdio bridge:

  • COVIBE_BASE_URL
  • COVIBE_MCP_TOKEN

The stdio bridge injects the token into tool calls when the agent does not pass one. When COVIBE_MCP_TOKEN is unset, the bridge and hooks fall back to the typed per-agent token in ~/.covibe/credentials.json, selected by the non-secret COVIBE_AGENT config marker (see device-setup.md).

The Settings → Agent setup config includes the repo cwd so copied stdio configs run outside the repository shell. The copied local setup block is finite (install companion, prompt for COVIBE_MCP_TOKEN, run setup, run covibe-local doctor, exit); setup installs the machine-level watch service by default (--no-service opts out), and the separate copyable covibe-local watch command runs the same loop in the foreground. Watch reads only numeric usage counters from local Codex and Cursor stores (codex-integration.md, cursor-integration.md); without split counters no usage event is submitted. Prompts, responses, transcripts, logs, and file contents stay local.

Agents should call covibe_session with operation: "start" at the start of a long run (include agent_name, provider, and model when available), pass the returned session_id into task/scope/blocker/decision/summary/usage tools, heartbeat with operation: "heartbeat", submit local repo state with operation: "snapshot" for dirty files, unpushed files, diff hashes, recent commits, and worktree/branch state (which feeds the per-repo local graph), and end with operation: "end". Snapshot overlap returns warnings to agents; tools reject a session_id not owned by the developer attached to the token.

Required Tools#

The public MCP surface is compact and operation-based:

  • covibe_task: check, plan, start, start_planned, update, complete, cancel
  • covibe_workstream: check, plan, start, start_planned, update, complete, cancel
  • covibe_session: start, heartbeat, snapshot, activity, publish_context, get_context, revoke_context, end
  • covibe_note: kind: "decision" or kind: "blocker"
  • covibe_team: state, feedback, audit_parallel_work, generate_weekly_summary
  • covibe_coordination: announcements, code claims, peer asks/replies, handoffs, releases, conflict checks, and summaries
  • covibe_warning: dismiss
  • covibe_ingest_agent_telemetry

covibe_team with operation: "generate_weekly_summary" renders sections for completed, planned, and active work, blockers, decisions, overlap warnings, parallel audits, and agent sessions. The UI weekly summary route creates summaries directly for the current developer and must not mint MCP tokens. covibe_team with operation: "feedback" returns recent stored feedback events for the calling developer.

covibe_session also carries the session context exchange (see session-context.md): operation: "publish_context" upserts the caller's working context, superseding their previous active context for the same repo/branch; operation: "get_context" returns a teammate's latest active context by handle/id or lists all active workspace contexts (never revoked, superseded, or expired rows; private developers redacted like team state); operation: "revoke_context" withdraws an owned context. Contexts expire after 24 hours by default (ttl_hours 1-168). A coordination operation: "handoff" attaches the giver's active context reference so the receiver can fetch it with get_context.

covibe_team with operation: "state" returns active team work, planned work, recent completions, active workstreams, recent risks and decisions, recent sessions, stale sessions, overlap warnings, published session contexts, and next actions for the calling developer — planned_work, risks_decisions, and recent_completions give agents context without opening the dashboard. If stale sessions exist it returns warning and writes an agent_feedback_event so agents review stale work before taking it over. If the latest persisted parallel audit conflicts with active or blocked work it also returns warning with latest_parallel_audits and parallel_audit_conflicts; completed-vs-completed historical conflicts stay visible but do not block agents.

covibe_team with operation: "audit_parallel_work" compares existing active, blocked, and recently completed work. It returns warning when already-running work appears duplicated or when active work repeats recently completed work.

The dashboard can run the same audit through /api/audit for the current signed-in developer without creating an MCP token.

The dashboard can also plan work directly: /api/tasks and /api/workstreams are cookie-authenticated POST routes running the same overlap-checked planning core as the MCP plan operations (developer-scoped, no MCP token). When the check escalates candidates the route returns them with requires_confirm and the console requires an explicit confirm — the same duplicate handling agents get.

Audit and coordination work events store bounded details in payload_json so agents and humans do not lose results after refresh.

Task and workstream operation: "update" only allows active or blocked status updates on started work. On a PLANNED task, operation: "update" lets the owner edit title, description, scope, action, component, priority, and task_type before start; status stays planned, the edit writes a task.planned_updated work event, and title/scope/description changes re-embed the task. Field edits on started work return a warning.

Planned tasks are created with covibe_task operation: "plan", shown in the dashboard, and activated with operation: "start_planned".

Planned workstreams mirror that lifecycle: covibe_workstream operation: "plan" creates a planned workstream (auto_created = 0) through the same overlap-checked path as a task plan; operation: "start_planned" activates it after a recent check with the same title; operation: "cancel" abandons an owned PLANNED workstream with a reason (started workstreams still require operation: "complete"). They appear in /api/state (plannedWorkstreams) and covibe_team state (planned_workstreams), and are overlap candidates for other developers' checks.

Starting planned work requires a recent covibe_task operation: "check" call with the same title and planned_task_id (workstreams: a recent covibe_workstream operation: "check" with the same title). Both start_planned operations then re-run overlap detection at activation time — see the activation re-check section in mcp-overlap-contract.md.

Completed tasks and workstreams cannot be updated or reopened through update tools.

Agents must use task/workstream operation: "complete" to finish work because completion requires a result summary. On covibe_task operation: "complete" the summary field is optional — result_summary is the canonical completion text and doubles as the summary.

covibe_workstream operation: "complete" refuses to silently close a workstream with open (planned/active/blocked) tasks: it returns a warning listing open_task_ids and requires a confirm_open_tasks: true retry. The confirmed workstream.completed event records those ids in its payload.

Agents can use covibe_task operation: "cancel" with a reason to abandon owned planned, active, or blocked work. covibe_workstream operation: "cancel" is planned-only. Repeated completion calls are idempotent: they return warning and create no duplicate completion events.

Optional inputs: feedback_type (warning|block|error|info) and limit (1-100 rows).

covibe_session operation: "heartbeat" updates last_seen_at for an active session owned by the calling developer. session_id is optional — the machine companion heartbeats session-lessly to sync registered repos and report liveness, and passes one only to touch its own session. The optional companion_version drives the self-update handshake: with a hosted-companion manifest the response data carries companion: { latest_version, tarball_sha256, update_available }, where update_available is latest_version !== companion_version — convergence, so a machine ahead of its server updates back down (the companion self-updates from this answer, see device-setup.md). companion_version is server-untrusted input and is length-bounded (capped at 64 characters); an over-long value is rejected by the handler, the same way registered_repos is bounded. operation: "end" may only end an owned session; peer tokens get an error and no session.ended event. Sessions idle for more than 30 minutes render as stale in the dashboard and weekly summary.

covibe_ingest_agent_telemetry is the only usage-metric path. It accepts structured Claude/Codex/OpenAI harness, provider, proxy, or OTel payloads, parses model and token counters server-side, stores only counters plus a SHA-256 payload hash, flags submitted-cost mismatches, and marks the span verified = 1.

Response Shape#

Every tool returns:

json
{
  "status": "ok",
  "message": "Short human-readable result.",
  "feedback": {
    "type": "info",
    "required_action": null
  },
  "data": {}
}

Malformed HTTP envelopes (invalid JSON, a non-object body, a missing tool string) return 400 with the same structured error shape. Malformed envelopes, unknown tools, and schema failures still write usage events.

The stdio bridge preserves structured API errors and converts unreachable, hung, or non-JSON API failures into structured MCP text responses instead of crashing or hanging the client process.

Blocked tools return:

json
{
  "status": "blocked",
  "message": "Possible duplicate work found.",
  "feedback": {
    "type": "block",
    "required_action": "Ask the developer for confirmation and a reason before starting."
  },
  "data": {
    "warning_id": "warn_123",
    "matches": []
  }
}

Check Before Start#

covibe_task operation: "start" requires a recent successful operation: "check".

covibe_task operation: "plan" logs future work without marking it active. If it overlaps existing work, the agent gets a warning and the warning is stored.

covibe_task operation: "start_planned" starts an owned planned task after operation: "check" confirms it is still safe to begin.

Task checks compare against planned, active, blocked, and recently completed work. Completed work older than the 14-day recent window is still visible in history but does not block a new start.

Task check/plan/start REQUIRE task_type (feature|bug|refactor|chore|docs|test|spike) — no default; a missing or unknown value fails schema validation in both the internal and public tool schemas. start_planned takes no task_type (the planned row already stores it), and a PLANNED task's owner can change it via operation: "update". Escalated candidates carry the candidate's task_type as informational context; it never affects scoring, escalation, or blocking.

Task check/plan/start accept optional target_files (max 50 repo-relative paths), stored on the task as a SUPPORT signal: data.file_conflicts lists intersections with other open tasks' targets and recent snapshot dirty/unpushed files (source, owner, same_developer, shared files, the other task's action); matching candidates carry file_overlap, opposed work carries action_divergent: true. File conflicts inform — never escalate or block; private developers redact to @private.

Task operation: "plan" and operation: "start" may include workstream_id to attach a task to an owned active or blocked workstream. Tasks cannot be attached to another developer's workstream or a completed workstream.

If a task omits workstream_id, the server assigns one: best matching owned open workstream in the workspace, else a new active auto-created workstream from the task title and scope/description. It writes workstream.auto_created, stores the id on tasks.workstream_id, and backfills older orphan tasks during schema initialization. Auto-created workstreams are containers: overlap and audit logic scores their tasks, not the generated container, and the server completes the container when no planned/active/blocked tasks remain inside it.

Starting overlapping planned work resolves its warning the same way as a direct task start: a v2 scope verdict writes scope.judged, a legacy confirmation writes warning.confirmed.

covibe_workstream operation: "start" requires a recent successful operation: "check". Recent means within 10 minutes.

If the check found overlap with still-live work, start requires the exact warning_id returned by the latest check plus a confirmation_reason; without those the tool returns blocked (carrying the warning's matches). Matches whose work is all done/cancelled by start time never block: the warning auto-dismisses and the start proceeds.

Overlap Detection v2#

The stage-2 agent-judge protocol lives in mcp-overlap-contract.md. In short, escalated checks return check_id, requires_verdict, and candidates (with score and reason); starts then require the matching check_id plus a scope_verdict, and confirmed duplicates still need confirmation_reason. Weak warn-floor warnings are disclosed on the check (warning_id + data.matches) but never block a start — blocking is reserved for escalated and agent-confirmed paths.

Agent Feedback#

Warnings and blocks must be returned to the agent in the MCP response — it is not enough to show the warning in the UI — and the response must tell the agent what to do next.

Logging#

Every MCP call writes a usage_event; every successful state change writes a work_event.

These Activity events are written so work is visible before and after it changes state: task.checked / workstream.checked (preflight and activation re-checks), task.planned / workstream.planned (future work), task.planned_updated (planned-task edits), workstream.start_planned (planned workstream activation), task.cancelled / workstream.cancelled (abandoned work), weekly_summary.generated, and parallel_work.audit (duplicate-work reviews).

When session_id is provided, usage and work events link to that agent session.

Rejected foreign-session attempts write an error usage event without linking that usage or work to the foreign session.

Blocked calls also write a usage_event; warnings and blocks also write an agent_feedback_event.

A resolved agent scope verdict writes a scope.judged work event (payload.duplicate true when a duplicate was confirmed). A legacy confirmation override writes a warning.confirmed event.

Agents can later retrieve stored feedback with covibe_team operation: "feedback".

Authentication#

Every MCP call must include a developer token; the server maps it to a developer. Store only token hashes. Revoked tokens must fail.

Tokens may carry a typed agent_type (claude-code, codex, cursor). A typed token's type overrides the agent's self-reported agent_type at covibe_session start; an explicit conflicting report writes a session.agent_mismatch work event. The device-flow setup mints one typed token per agent (device-setup.md).

The UI can create and revoke MCP tokens for the current developer. UI-created tokens receive distinct default labels for safer inventory management. Token creation and revocation write Activity work events without raw token values.

Every mutating tool is owner-scoped to the developer attached to the MCP token: task update/complete, decision/blocker attach, workstream update/complete, and session heartbeat/end all reject ids owned by another developer.

View as .md