Skip to content

MCP Server Guide

The @humanauth/mcp package is an MCP (Model Context Protocol) server that exposes three HARP tools to any MCP-compatible agent. No code changes required — just add 3 lines to your MCP client config.

  • human_authorize — Request binary authorization (approve/deny). Blocks until the human responds or the request expires.
  • human_collect — Request structured data input via a bounded form. Blocks until the human submits or the request expires.
  • human_inform — Send a fire-and-forget notification. Returns immediately without waiting for a response.
  1. A HARP pairing already created (see Getting Started)
  2. An MCP-compatible agent (Claude Code, Cursor, Windsurf, or any MCP client)

Edit ~/.claude/settings.json:

{
"mcpServers": {
"harp": {
"command": "npx",
"args": ["@humanauth/mcp"]
}
}
}

Edit .cursor/mcp.json in your project root:

{
"mcpServers": {
"harp": {
"command": "npx",
"args": ["@humanauth/mcp"]
}
}
}

Any MCP client that supports the stdio transport can use the HARP server:

Terminal window
npx @humanauth/mcp

The server communicates via stdin/stdout using the MCP JSON-RPC protocol.

Request binary authorization from a human. The call blocks until the human approves, denies, or the TTL expires.

ParameterTypeRequiredDefaultDescription
pair_idstringYesPairing ID for the human to ask
actionstringYesAction name (e.g., deploy_production)
descriptionstringYesHuman-readable description of the action
severity"low" | "medium" | "high" | "critical"No"medium"How dangerous is this action
parametersobjectNoAction parameters for context
reasoningstringNoYour reasoning for requesting this
ttlnumberNo300Timeout in seconds (1–86400)
{
"name": "human_authorize",
"arguments": {
"pair_id": "pair_a1b2c3d4e5f6",
"action": "deploy_production",
"description": "Deploy v2.4.1 to the production environment",
"severity": "high",
"parameters": {
"version": "v2.4.1",
"environment": "production",
"region": "us-east-1"
},
"reasoning": "All staging checks passed. Release window is now open.",
"ttl": 300
}
}

On authorization:

{
"content": [
{
"type": "text",
"text": "APPROVED: Human approved the action 'deploy_production'."
}
]
}

On denial:

{
"content": [
{
"type": "text",
"text": "DENIED: Human denied the action 'deploy_production'. Reason: Wait for the on-call engineer to be online before deploying."
}
],
"isError": true
}

Request structured data input from a human. The call blocks until the human submits the form or the TTL expires. All fields use bounded inputs — no free text — to keep responses predictable and safe.

ParameterTypeRequiredDefaultDescription
pair_idstringYesPairing ID
actionstringYesAction name
descriptionstringYesWhat data you need and why
schemaobjectYesForm schema with a fields array (max 20 fields)
severity"low" | "medium" | "high" | "critical"No"medium"How sensitive is this data
reasoningstringNoWhy you need this data
ttlnumberNo600Timeout in seconds

Each entry in schema.fields must have a type from the following list:

TypeDescriptionoptions Required
selectSingle-selection dropdownYes
multiselectMultiple-selection listYes
checkboxBoolean toggleNo
numberNumeric input with optional min/maxNo
datetimeDate/time pickerNo
{
"name": "human_collect",
"arguments": {
"pair_id": "pair_a1b2c3d4e5f6",
"action": "configure_deployment",
"description": "Please confirm the deployment configuration before I proceed.",
"severity": "high",
"reasoning": "I need the target environment and replica count to proceed with the rollout.",
"ttl": 600,
"schema": {
"fields": [
{
"id": "environment",
"label": "Target Environment",
"type": "select",
"options": ["staging", "production", "canary"],
"required": true
},
{
"id": "replica_count",
"label": "Replica Count",
"type": "number",
"min": 1,
"max": 20,
"required": true
},
{
"id": "notify_team",
"label": "Notify team on Slack after deploy",
"type": "checkbox",
"required": false
}
]
}
}
}
{
"content": [
{
"type": "text",
"text": "SUBMITTED: Human provided data for 'configure_deployment'."
}
],
"form_data": {
"environment": "production",
"replica_count": 3,
"notify_team": true
}
}

Send a notification to a human. Returns immediately without waiting for a response (fire-and-forget).

ParameterTypeRequiredDefaultDescription
pair_idstringYesPairing ID
actionstringYesAction name or context identifier
descriptionstringYesThe notification message
severity"low" | "medium" | "high" | "critical"No"low"Notification urgency
category"escalation" | "result" | "status" | "error" | "general"No"general"Notification type
CategoryWhen to Use
escalationSomething requires human attention but not an authorization gate
resultReporting the outcome of a completed action
statusProgress update mid-task
errorReporting an error or failure
generalEverything else
{
"name": "human_inform",
"arguments": {
"pair_id": "pair_a1b2c3d4e5f6",
"action": "deploy_complete",
"description": "Deployment of v2.4.1 to production completed successfully. All health checks passed.",
"severity": "low",
"category": "result"
}
}
{
"content": [
{
"type": "text",
"text": "NOTIFIED: Notification 'deploy_complete' sent successfully."
}
],
"ok": true
}

LevelDescriptionWhen to Use
lowRoutine, low-riskRead-only operations, status checks, informational notifications
mediumStandard operationsMost actions; the default when severity is not specified
highPotentially dangerousProduction changes, data modifications, configuration updates
criticalIrreversible, high-impactDeletions, financial transactions, security-sensitive actions
VariableDefaultDescription
HARP_PAIRINGS_DIR~/.harp/pairingsDirectory containing pairing JSON files
  1. Agent calls one of the three HARP tools with the required parameters
  2. The MCP server loads the pairing file for the given pair_id
  3. Encrypts the request context with XChaCha20-Poly1305
  4. Sends the encrypted envelope to the relay
  5. For human_authorize and human_collect: blocks until the human responds or the TTL expires, then returns the result to the agent
  6. For human_inform: delivers the notification and returns immediately without waiting

The MCP server is stateless — it reads pairings from disk on each call. No background processes, no persistent connections.

If you have multiple pairings (e.g., personal and work), the agent selects which pair_id to use. You can guide this by naming pairings descriptively:

Terminal window
humanauth pair --name "personal-deploy-approver"
humanauth pair --name "work-infra-approver"

The MCP server discovers all pairings in ~/.harp/pairings/ automatically.

Verify the pairing exists:

Terminal window
humanauth list

Ensure the pair_id in the tool call matches a saved pairing file.

The human did not respond within the TTL. This only applies to human_authorize and human_collect. Consider:

  • Increasing the ttl parameter
  • Verifying push notifications are enabled on the HARP app
  • Checking that the phone has network connectivity

Verify the MCP config path is correct for your client. Run the server manually to test:

Terminal window
npx @humanauth/mcp

If it starts without errors, the issue is in the client configuration.

The tool names in HARP v1 are human_authorize, human_collect, and human_inform. If your agent config or prompts reference the old authorize tool name, update them to use the new names.