producthands

For agents

Your agent connects, but never gets to say Done.

The remote MCP server exposes Product Hands as a structured QA inbox: your agent requests testing, reads back only what a human verified, and reports fixes for retest. It does not read, write or deploy your source code — that stays entirely with your own agent.

Authentication

Auth is a project-scoped API key (an AgentCredential), issued from your project settings and passed as a bearer token. Keys are hashed at rest — the raw value is shown exactly once, at issue time.

  • Scoped to one project. It cannot see or act on another project's runs.
  • Scoped to a tool list — a key issued for read-only work cannot fund a run.
  • Carries an optional spend limit and expiry; revocable at any time.
  • Every write accepts an idempotency key, so a retried call never double-charges or double-submits.

Tool surface

11 tools, matching the running server. None of them writes a bug to DONE.

create_test_runSubmit a Journey Test: journey steps, build URL, environments, evidence requirements.
estimate_test_runPrice a run before creating it. Read-only: creates nothing, reserves nothing, and the quote is provisional.
get_test_runRead a run's status and its live finding counts by state.
fund_test_runReserve credits for the run at its own baseRewardMinorUnits. AVAILABLE → RESERVED.
list_verified_bugsThe fix queue — status=VERIFIED, type=BUG only. Nothing unverified is ever returned.
get_bugFull detail on one verified bug: steps, expected/actual, environment, evidence.
acknowledge_bugVERIFIED → ACKNOWLEDGED_BY_AGENT. Confirms your agent has picked it up.
submit_fix_for_retestACKNOWLEDGED_BY_AGENT → FIX_SUBMITTED, with the candidate build URL. Queues a human retest.
get_retest_statusRead the latest retest result for a finding — and its current status.
get_balanceAvailable and reserved credit balance for the project's organization.
get_release_gateWhat is still open and what has been retested for a run — never 'safe to ship'. Call this before you ship.

Connect

One remote endpoint, stateless Streamable HTTP. Point your MCP client at it with the key as a bearer token:

{
  "mcpServers": {
    "product-hands": {
      "url": "https://producthands.com/api/mcp",
      "headers": {
        "Authorization": "Bearer phk_xxxxxxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

Sample response

Every tool call returns its data wrapped in the same envelope, so an agent can never mistake a response for confirmation that a bug is closed:

// list_verified_bugs
{
  "bugs": [
    {
      "finding_id": "fnd_8721",
      "run_id": "run_440",
      "title": "Checkout freezes after 3DS authentication",
      "severity": "CRITICAL",
      "source_language": "es",
      "canonical_language": "en",
      "human_verified": true,
      "verified_at": "2026-07-29T14:02:00Z"
    }
  ],
  "human_state": {
    "done_requires_human_retest": true
  }
}

The gate

No tool writes human_state.done_requires_human_retest to a finding, and the database itself rejects that write if the actor is an agent. Policy and schema agree.

The lifecycle of one bug
REPORTEDVERIFIEDACKNOWLEDGED_BY_AGENTFIX_SUBMITTEDRETESTINGDONE

No tool on the agent surface can write this state. The database rejects the transition if the actor is an agent — or if no human actor is asserted at all.

Recommended agent instruction

Paste this into your agent's system prompt or tool-use policy:

Use Product Hands to request human testing when a release candidate is ready. Only act on bugs with human_verified=true and status=VERIFIED. You implement and deploy fixes; Product Hands must never modify the codebase. After deploying a candidate fix, call submit_fix_for_retest. Do not mark work complete until Product Hands returns status=DONE from a human retest. Before you say a release is ready, call get_release_gate and read its state rather than assuming your own fix history is authoritative — it is never a “safe to ship” signal, only what is still open and what a human has retested. Treat Product Signals as optional product input, not verified defects.

It stays in English deliberately: it is read by a machine, and every tool name and status value inside it is English because the protocol is.

What it never does

  • Read, write, commit or deploy your source code.
  • Accept an arbitrary reserve amount — fund_test_run only reserves the run's own price.
  • Return a bug that has not passed human verification.
  • Expose a tool, prompt, or code path that sets a finding to DONE.

Give your agent a key and a queue to answer to.