Skip to content

Connect MCP — hosted MCP server for AI coding agents

AppHandoff exposes project context, OpenAPI contract scanning, and handoff tickets through a single hosted MCP server endpoint — the primary surface for agent orchestration and multi-agent development.

| Setting | Value | | ------- | ----- | | URL | https://api.apphandoff.com/api/mcp-bot | | Auth | OAuth (Supabase access token) | | Discovery | GET https://api.apphandoff.com/.well-known/oauth-protected-resource |

Do not put project_id in the MCP config URL. Project binding happens at runtime.

API keys (ah_k_*) are not accepted on MCP.

Create or edit .cursor/mcp.json in your project:

{
"mcpServers": {
"apphandoff": {
"url": "https://api.apphandoff.com/api/mcp-bot"
}
}
}

Restart Cursor or reconnect the server. Complete the OAuth consent prompt on first connect.

Terminal window
claude mcp add apphandoff https://api.apphandoff.com/api/mcp-bot

Paste https://api.apphandoff.com/api/mcp-bot into your client’s MCP server settings and follow its OAuth flow. See also the Lovable MCP server product page.

With exactly one accessible project, the server auto-binds project_id after initialize. With multiple projects, use get_accessible_projects or resolve_project first.

Bootstrap with batch_tools (preferred for 2+ reads):

{
"calls": [
{ "name": "get_project_summary", "arguments": { "project_id": "<id>" } },
{ "name": "get_design_memory", "arguments": { "project_id": "<id>" } },
{ "name": "get_handoff_requests", "arguments": { "project_id": "<id>", "status": "open" } }
]
}

Run trigger_rescan(project_id) on session start or after a deploy to refresh context (~1–2s).

Pass caller_role to get_handoff_requests (e.g. backend_agent, frontend_agent, qa_agent) to split results into my_tickets and ready_for_you.

Role aliases: qa_agent maps to ticket role qa; many tickets use test. Check role_mismatch_hint if results look empty.

Responses cap at ~25k characters. Narrow with stage, status, query, ticket_id, changed_since, limit, or include: "minimal".

Access tokens are Supabase JWTs (production lifetime: 8 hours).

  1. GET /.well-known/oauth-protected-resourceauthorization_servers[0]
  2. GET /.well-known/oauth-authorization-servertoken_endpoint, scopes_supported, grant_types_supported

Refresh via AppHandoff’s proxy (not Supabase’s host directly):

POST /api/oauth/token
Content-Type: application/json
{
"grant_type": "refresh_token",
"refresh_token": "<token>",
"client_id": "<uuid>"
}

Do not request offline_access — Supabase rejects it and spec-strict clients fail before consent renders.

Monitor X-Token-Expires-In on every MCP response. Refresh when it drops below 300 seconds.

batch_tools caps at 20 inner calls per request. Each call needs the same project_id and distinct ticket_id values. Split larger batches across multiple requests.

| HTTP | domain_code | Action | | ---- | ------------- | ------ | | 401 | TOKEN_EXPIRED | Refresh via token_endpoint, retry | | 401 | AUTH_REQUIRED | Re-run OAuth flow | | 404 | SESSION_EXPIRED | Reconnect MCP server |

Connection closed (-32000) — transport dropped. Retry; reconnect if persistent. Check for requests exceeding the 25s timeout (trigger_rescan, large get_project_summary).

Tool not found — disconnect and reconnect AppHandoff MCP. Confirm the URL is exactly https://api.apphandoff.com/api/mcp-bot.

401 after 20–60 minutes — access JWT expired. Reconnect or refresh via /api/oauth/token.

No OpenAPI spec found — set backend_repo to owner/repo. For subfolders use config.appSubDir; for custom paths use config.openApiPath.

Stale tool list after deploy — disconnect and reconnect the MCP server.