MCP Authentication

MCP agents authenticate using Bearer tokens — long-lived API keys created per agent. Each key is scoped to a specific entity (payroll company or employer) and optionally locked to sandbox mode.


API Key Format #

mcp_<64 hexadecimal characters>

Example:

mcp_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2

Keys are 256-bit random values, SHA-256 hashed before storage. The raw key is shown once at creation and cannot be retrieved again.


Getting Your API Key #

MCP API keys are created by your Audit1 account manager or via the admin REST API. Contact support@audit1.com to request credentials for your agent.

You'll need to provide:

Field Description
Agent name A human-readable label (e.g., "ADP Payroll Agent")
Entity type payroll_company (multi-employer) or employer (single)
Entity ID The Audit1 ObjectId for your payroll company or employer
Sandbox true for testing (forces dry-run on all submissions)

Save your API key immediately

— it's only shown once. If you lose it, request a new key and revoke the old one.


Request Format #

All MCP calls go to a single endpoint using JSON-RPC 2.0:

curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
  -H "Authorization: Bearer mcp_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "initialize",
    "id": 1
  }'

Single endpoint

— Unlike the REST API which has many routes, MCP uses one endpoint (POST /mcp) for all operations. The method field determines the action.


Agent Scoping #

Your API key determines what data you can access:

Agent Type Entity Type Scope
Provider payroll_company All employers where payroll_company_ids includes your company
Employer employer Only this specific employer

Scope is resolved fresh on every request. If an employer is unlinked from your payroll company, your agent loses access immediately — no stale permissions.

Provider Agent Example #

A payroll company with 100 employer clients:

Agent → list_employer_policies(employer_id: "abc") → ✓ (employer linked)
Agent → list_employer_policies(employer_id: "xyz") → ✓ (employer linked)
Agent → list_employer_policies(employer_id: "999") → ✗ SCOPE_ERROR (not linked)

Employer Agent Example #

A single-employer agent:

Agent → list_employer_policies(employer_id: "abc") → ✓ (matches agent scope)
Agent → list_employer_policies(employer_id: "xyz") → ✗ SCOPE_ERROR (wrong employer)

Sandbox Mode #

Sandbox agents work identically to production agents — they can discover fields, list policies, and validate data. The only difference: submit_payroll_data automatically forces dry_run: true, so no data enters the real processing pipeline.

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "submit_payroll_data",
    "arguments": {
      "employer_id": "681abc123def456789012345",
      "policy_id": "680def456ghi789012345678",
      "rows": [{ "employee_first_name": "Test", "gross_wages": 2500 }],
      "dry_run": false
    }
  },
  "id": 5
}

Warning

Even though dry_run: false was set, a sandbox agent's submission will still be dry-run only. The response will indicate "dry_run": true.

Use sandbox mode for: - Development and testing - Onboarding new agents - ✓ Validating data formats before going live


Credential Management #

Create an Agent #

curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/api/v1/agents \
  -H "Content-Type: application/json" \
  -d '{
    "agent_name": "ADP Payroll Agent",
    "entity_type": "payroll_company",
    "entity_id": "68c4c0535d5a5576362a9499",
    "sandbox": false,
    "created_by": "admin@audit1.com"
  }'

Response (201 Created):

{
  "credential_id": "682abc123def456789012345",
  "agent_name": "ADP Payroll Agent",
  "entity_type": "payroll_company",
  "entity_id": "68c4c0535d5a5576362a9499",
  "sandbox": false,
  "api_key": "mcp_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
  "api_key_prefix": "a1b2c3d4",
  "message": "Store this API key securely — it cannot be retrieved again."
}

List Agents #

curl "https://payroll-mcp-server-902057957000.us-central1.run.app/api/v1/agents?entity_type=payroll_company&entity_id=68c4c0535d5a5576362a9499"

Response (200 OK):

{
  "agents": [
    {
      "credential_id": "682abc123def456789012345",
      "agent_name": "ADP Payroll Agent",
      "entity_type": "payroll_company",
      "entity_id": "68c4c0535d5a5576362a9499",
      "api_key_prefix": "mcp_a1b2c3d4...",
      "status": "active",
      "sandbox": false,
      "created_at": "2026-03-15T10:30:00Z",
      "last_used_at": "2026-03-31T14:22:00Z"
    }
  ],
  "count": 1
}

Revoke an Agent #

curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/api/v1/agents/682abc123def456789012345/revoke

Response (200 OK):

{
  "credential_id": "682abc123def456789012345",
  "agent_name": "ADP Payroll Agent",
  "status": "revoked"
}

Key Management Best Practices #

✓ Do ✗ Don't
Store keys in environment variables or secret managers Hardcode keys in source code
Use sandbox agents for development Test with production agents
Revoke unused or compromised keys immediately Share keys across multiple agents
Use one key per agent with descriptive names Reuse keys between environments
Log the key prefix (mcp_a1b2c3d4...) for debugging Log the full API key

Error Responses #

Code Error Meaning
-32001 AUTH_ERROR Missing, invalid, or revoked API key
-32002 SCOPE_ERROR Agent not authorized for this employer
-32003 SANDBOX_ONLY Reserved. Sandbox agents automatically have dry_run forced to true — no error is returned

Example error:

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32001,
    "message": "Invalid or revoked API key"
  },
  "id": 1
}

Need Help? #

Email support@audit1.com to request new agent credentials or report authentication issues.