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.