MCP Tools Reference
All 6 MCP tools with schemas, examples, and error codes
📖 MCP Tools Reference
Complete reference for all MCP tools available on the Audit1 Payroll MCP Server.
Endpoint: POST /mcp
Protocol: JSON-RPC 2.0
Version: 2025-03-26
JSON-RPC 2.0 Format
Every MCP request follows the same structure:
{
"jsonrpc": "2.0",
"method": "<method_name>",
"params": { ... },
"id": 1
}Every response:
{
"jsonrpc": "2.0",
"result": { ... },
"id": 1
}Protocol Methods
These are the top-level JSON-RPC methods (not tools):
| Method | Purpose |
|---|---|
initialize | Handshake — returns protocol version and server info |
tools/list | Discover all available tools and their input schemas |
tools/call | Execute a tool (see tool sections below) |
ping | Health check |
Initialize
curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
-H "Authorization: Bearer mcp_your_key_here" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","id":1}'{
"jsonrpc": "2.0",
"result": {
"protocolVersion": "2025-03-26",
"capabilities": { "tools": { "listChanged": false } },
"serverInfo": { "name": "audit1-payroll-mcp", "version": "1.0.0" }
},
"id": 1
}Tools/List
curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
-H "Authorization: Bearer mcp_your_key_here" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":2}'Returns all 6 tools with their names, descriptions, and inputSchema.
Tool Call Format
All tools are invoked via tools/call:
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "<tool_name>",
"arguments": { ... }
},
"id": 3
}list_employer_policies
Discover active policies for an employer. Use this to find which policies to report payroll against before submitting data.
Input Schema
| Field | Type | Required | Description |
|---|---|---|---|
employer_id | string | Yes | The employer ObjectId |
include_expired | boolean | No | Include expired policies (default: false) |
Example
curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
-H "Authorization: Bearer mcp_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "list_employer_policies",
"arguments": {
"employer_id": "681abc123def456789012345"
}
},
"id": 3
}'Response
{
"jsonrpc": "2.0",
"result": {
"content": [{
"type": "text",
"text": "{\"employer_id\":\"681abc123def456789012345\",\"policy_count\":2,\"policies\":[{\"policy_id\":\"680def456ghi789012345678\",\"policy_number\":\"WC1025561\",\"carrier_name\":\"CopperPoint\",\"status\":\"active\",\"effective_date\":\"2025-07-01\",\"expiration_date\":\"2026-07-01\",\"fee_count\":3},{\"policy_id\":\"680abc789xyz123456789012\",\"policy_number\":\"WC2038412\",\"carrier_name\":\"CopperPoint\",\"status\":\"active\",\"effective_date\":\"2025-10-01\",\"expiration_date\":\"2026-10-01\",\"fee_count\":5}]}"
}]
},
"id": 3
}
All tool responses are wrapped incontent[].textas JSON strings (MCP standard format). Parse thetextfield to get the structured data.
get_expected_fields
Discover what fields Audit1 expects for a given employer's policy. Returns required and optional fields, valid class codes, valid states, and payroll frequency.
Input Schema
| Field | Type | Required | Description |
|---|---|---|---|
employer_id | string | Yes | The employer ObjectId |
policy_id | string | No | Specific policy. If omitted, returns info for all active policies. |
Example
curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
-H "Authorization: Bearer mcp_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "get_expected_fields",
"arguments": {
"employer_id": "681abc123def456789012345",
"policy_id": "680def456ghi789012345678"
}
},
"id": 4
}'Response (parsed text)
text){
"employer_id": "681abc123def456789012345",
"employer_name": "Smith Industries LLC",
"policies": [
{
"policy_id": "680def456ghi789012345678",
"policy_number": "WC1025561",
"carrier": "CopperPoint",
"status": "active",
"effective_date": "2025-07-01",
"expiration_date": "2026-07-01",
"class_codes": ["8810", "8742"],
"states": ["CA", "NY"],
"locations": [
{ "id": "683aaa111bbb222333444555", "state": "CA" },
{ "id": "683bbb222ccc333444555666", "state": "NY" }
],
"payroll_frequency": "BIWEEKLY",
"fields": {
"required": [
{ "name": "gross_wages", "type": "number", "description": "Gross wages for the pay period in dollars. Alternative: provide hours + rate." }
],
"optional": [
{ "name": "class_code", "type": "string", "description": "WC class code. Policy has 2 codes.", "valid_values": ["8810", "8742"] },
{ "name": "state", "type": "string", "description": "2-letter state. Policy has 2 states.", "valid_values": ["CA", "NY"] },
{ "name": "employee_first_name", "type": "string", "description": "Employee first name" },
{ "name": "employee_last_name", "type": "string", "description": "Employee last name" },
{ "name": "overtime", "type": "number", "description": "Overtime wages in dollars" },
{ "name": "hours", "type": "number", "description": "Hours worked (alternative to gross_wages)" },
{ "name": "rate", "type": "number", "description": "Hourly rate (used with hours)" },
{ "name": "check_date", "type": "string", "description": "Pay date YYYY-MM-DD" },
{ "name": "pay_period_start", "type": "string", "description": "Period start YYYY-MM-DD" },
{ "name": "pay_period_end", "type": "string", "description": "Period end YYYY-MM-DD" }
]
}
}
]
}
Auto-inference: If a policy has exactly 1 class code or 1 state, those fields become optional — the system auto-assigns the value. If a policy has multiple, you must specify.
validate_payroll_submission
Pre-validate payroll data before submitting. Returns field-level feedback on each row without persisting anything. Always runs in dry-run mode.
Input Schema
| Field | Type | Required | Description |
|---|---|---|---|
employer_id | string | Yes | The employer ObjectId |
policy_id | string | Yes | The policy ObjectId |
rows | array | Yes | Payroll data rows (see Row Fields below) |
Example
curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
-H "Authorization: Bearer mcp_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "validate_payroll_submission",
"arguments": {
"employer_id": "681abc123def456789012345",
"policy_id": "680def456ghi789012345678",
"rows": [
{
"employee_first_name": "Jane",
"employee_last_name": "Smith",
"class_code": "8810",
"state": "CA",
"gross_wages": 2500.00,
"check_date": "2026-03-15"
},
{
"employee_first_name": "Bob",
"employee_last_name": "Jones",
"class_code": "9999",
"state": "ZZ",
"gross_wages": 3000.00
}
]
}
},
"id": 5
}'Response (parsed text)
text){
"submission_id": "682xyz789abc123456789012",
"status": "dry_run_complete",
"dry_run": true,
"row_count": 2,
"validation": {
"valid": false,
"error_count": 2,
"warning_count": 0,
"errors": [
{ "row": 2, "field": "class_code", "message": "Class code '9999' not found in policy fees" },
{ "row": 2, "field": "state", "message": "State 'ZZ' is not a valid US state" }
],
"warnings": []
}
}submit_payroll_data
Submit payroll data rows for an employer. Creates a file in Audit1's processing pipeline (Files-creator → Auditor validation → wage calculation → premium calculation). Set dry_run: true to validate without persisting.
Input Schema
| Field | Type | Required | Description |
|---|---|---|---|
employer_id | string | Yes | The employer ObjectId |
policy_id | string | Yes | The policy ObjectId |
rows | array | Yes | Payroll data rows (see Row Fields below) |
dry_run | boolean | No | If true, validate only (default: false) |
Example (Real Submission)
curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
-H "Authorization: Bearer mcp_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "submit_payroll_data",
"arguments": {
"employer_id": "681abc123def456789012345",
"policy_id": "680def456ghi789012345678",
"rows": [
{
"employee_first_name": "Jane",
"employee_last_name": "Smith",
"class_code": "8810",
"state": "CA",
"gross_wages": 2500.00,
"overtime": 375.00,
"check_date": "2026-03-15",
"pay_period_start": "2026-03-01",
"pay_period_end": "2026-03-15"
}
],
"dry_run": false
}
},
"id": 6
}'Response (Real Submission)
{
"jsonrpc": "2.0",
"result": {
"content": [{
"type": "text",
"text": "{\"submission_id\":\"682abc123def456789012345\",\"file_id\":\"683def456ghi789012345678\",\"status\":\"submitted_and_validated\",\"row_count\":1,\"message\":\"Payroll data submitted successfully. File created and validation triggered.\"}"
}]
},
"id": 6
}Response (Dry Run)
{
"submission_id": "682xyz789abc123456789012",
"status": "dry_run_complete",
"dry_run": true,
"row_count": 1,
"validation": {
"valid": true,
"error_count": 0,
"warning_count": 0,
"errors": [],
"warnings": []
}
}Submission Statuses
| Status | Meaning |
|---|---|
dry_run_complete | Validation-only run completed |
submitted_and_validated | Data submitted and validation triggered successfully |
submitted_validation_pending | Data submitted, validation still running |
submission_failed | Submission failed (check error details) |
get_submission_status
Check the processing status of a previously submitted file. Returns Phase 1 (validation), Phase 2 (wage calculation), and Phase 3 (premium calculation) results.
Input Schema
| Field | Type | Required | Description |
|---|---|---|---|
submission_id | string | No* | The submission ID from submit_payroll_data |
file_id | string | No* | The file ObjectId |
*At least one of
submission_idorfile_idis required.
Example
curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
-H "Authorization: Bearer mcp_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "get_submission_status",
"arguments": {
"submission_id": "682abc123def456789012345"
}
},
"id": 7
}'Response (parsed text)
text){
"submission_id": "682abc123def456789012345",
"file_id": "683def456ghi789012345678",
"file_status": "validated",
"phase_1": {
"total_rows": 10,
"green_rows": 9,
"red_rows": 1,
"status": "complete"
},
"phase_2": {
"total_auditable_wages_cents": 2500000,
"rows_processed": 9,
"status": "complete"
},
"phase_3": {
"total_premium_cents": 78122,
"rows_processed": 9,
"status": "complete"
},
"row_breakdown": {
"green": 9,
"red": 1
}
}
Monetary values are in cents.2500000= $25,000.00.78122= $781.22.
File Statuses
Files progress through: pending → uploaded → identified → normalized → validated → completed
get_validation_errors
Get detailed validation errors for a submitted file. Returns RED rows with reasons (invalid class code, missing state, etc.) and suggested corrections.
Input Schema
| Field | Type | Required | Description |
|---|---|---|---|
file_id | string | No* | The file ObjectId |
submission_id | string | No* | The MCP submission ID |
*At least one of
file_idorsubmission_idis required.
Example
curl -X POST https://payroll-mcp-server-902057957000.us-central1.run.app/mcp \
-H "Authorization: Bearer mcp_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "get_validation_errors",
"arguments": {
"file_id": "683def456ghi789012345678"
}
},
"id": 8
}'Response (parsed text)
text){
"file_id": "683def456ghi789012345678",
"total_rows": 10,
"green_rows": 9,
"red_rows": 1,
"errors": [
{
"row_id": "684aaa111bbb222333444555",
"row_number": 7,
"employee_name": "Bob Jones",
"reasons": [
{
"field": "class_code",
"message": "Class code '9999' not found in policy fees",
"suggestion": "Valid class codes for this policy: 8810, 8742"
}
]
}
],
"has_more": false
}
Results are capped at 100 rows. Ifhas_more: true, there are additional errors beyond the returned set.
Row Fields
These fields apply to the rows array in submit_payroll_data and validate_payroll_submission:
| Field | Type | Description |
|---|---|---|
employee_first_name | string | Employee first name |
employee_last_name | string | Employee last name |
class_code | string | WC class code (e.g., "8810") |
state | string | 2-letter state abbreviation (e.g., "CA") |
gross_wages | number | Gross wages for the period in dollars |
overtime | number | Overtime wages in dollars |
hours | number | Hours worked (alternative to gross_wages) |
rate | number | Hourly rate (used with hours) |
check_date | string | Pay date YYYY-MM-DD |
pay_period_start | string | Period start YYYY-MM-DD |
pay_period_end | string | Period end YYYY-MM-DD |
ssn | string | Social Security Number (optional) |
Wage input options (provide one):
gross_wages— Direct dollar amount (most common)hours+rate— Computed as hours x rate- Annual salary fields — Divided by payroll frequency
Error Codes
JSON-RPC Standard Errors
| Code | Name | Meaning |
|---|---|---|
-32700 | Parse Error | Invalid JSON in request body |
-32600 | Invalid Request | Malformed JSON-RPC structure |
-32601 | Method Not Found | Unknown RPC method (typo in method field) |
-32602 | Invalid Params | Missing or invalid tool arguments |
-32603 | Internal Error | Server error during tool execution |
MCP Custom Errors
| Code | Name | Meaning |
|---|---|---|
-32001 | Auth Error | Missing, invalid, or revoked API key |
-32002 | Scope Error | Agent not authorized for this employer/payroll company |
-32003 | Sandbox Only | Sandbox agent attempted non-dry-run (auto-forced to dry-run) |
Error Response Format
{
"jsonrpc": "2.0",
"error": {
"code": -32602,
"message": "Invalid params: employer_id is required",
"data": { "field": "employer_id" }
},
"id": 4
}Full Workflow Example
Python
import requests
import json
MCP_URL = "https://payroll-mcp-server-902057957000.us-central1.run.app/mcp"
API_KEY = "mcp_your_api_key_here"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
def mcp_call(method, params=None, call_id=1):
body = {"jsonrpc": "2.0", "method": method, "id": call_id}
if params:
body["params"] = params
resp = requests.post(MCP_URL, headers=HEADERS, json=body)
result = resp.json()
if "error" in result:
raise Exception(f"MCP Error {result['error']['code']}: {result['error']['message']}")
return result["result"]
def tool_call(name, arguments, call_id=1):
result = mcp_call("tools/call", {"name": name, "arguments": arguments}, call_id)
return json.loads(result["content"][0]["text"])
# Step 1: Initialize
server_info = mcp_call("initialize")
print(f"Connected to {server_info['serverInfo']['name']} v{server_info['serverInfo']['version']}")
# Step 2: Discover policies
policies = tool_call("list_employer_policies", {
"employer_id": "681abc123def456789012345"
}, call_id=2)
policy_id = policies["policies"][0]["policy_id"]
print(f"Using policy: {policies['policies'][0]['policy_number']}")
# Step 3: Get expected fields
fields = tool_call("get_expected_fields", {
"employer_id": "681abc123def456789012345",
"policy_id": policy_id
}, call_id=3)
print(f"Valid class codes: {fields['policies'][0]['class_codes']}")
# Step 4: Validate
validation = tool_call("validate_payroll_submission", {
"employer_id": "681abc123def456789012345",
"policy_id": policy_id,
"rows": [
{
"employee_first_name": "Jane",
"employee_last_name": "Smith",
"class_code": "8810",
"state": "CA",
"gross_wages": 2500.00,
"check_date": "2026-03-15"
}
]
}, call_id=4)
if not validation["validation"]["valid"]:
print(f"Errors: {validation['validation']['errors']}")
exit(1)
# Step 5: Submit for real
result = tool_call("submit_payroll_data", {
"employer_id": "681abc123def456789012345",
"policy_id": policy_id,
"rows": [
{
"employee_first_name": "Jane",
"employee_last_name": "Smith",
"class_code": "8810",
"state": "CA",
"gross_wages": 2500.00,
"check_date": "2026-03-15"
}
],
"dry_run": False
}, call_id=5)
print(f"Submitted! File ID: {result['file_id']}")
# Step 6: Check status
import time
time.sleep(5)
status = tool_call("get_submission_status", {
"submission_id": result["submission_id"]
}, call_id=6)
print(f"Phase 1: {status['phase_1']['green_rows']} green, {status['phase_1']['red_rows']} red")
print(f"Phase 3: ${status['phase_3']['total_premium_cents'] / 100:.2f} premium")JavaScript (Node.js)
const MCP_URL = "https://payroll-mcp-server-902057957000.us-central1.run.app/mcp";
const API_KEY = "mcp_your_api_key_here";
async function mcpCall(method, params, id = 1) {
const body = { jsonrpc: "2.0", method, id };
if (params) body.params = params;
const resp = await fetch(MCP_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
const result = await resp.json();
if (result.error) throw new Error(`MCP Error ${result.error.code}: ${result.error.message}`);
return result.result;
}
async function toolCall(name, arguments_, id = 1) {
const result = await mcpCall("tools/call", { name, arguments: arguments_ }, id);
return JSON.parse(result.content[0].text);
}
// Usage
const policies = await toolCall("list_employer_policies", {
employer_id: "681abc123def456789012345",
});
const result = await toolCall("submit_payroll_data", {
employer_id: "681abc123def456789012345",
policy_id: policies.policies[0].policy_id,
rows: [{
employee_first_name: "Jane",
employee_last_name: "Smith",
class_code: "8810",
state: "CA",
gross_wages: 2500.00,
check_date: "2026-03-15",
}],
dry_run: false,
});
console.log(`Submitted! File ID: ${result.file_id}`);📧 Need Help?
Email [email protected] with:
- Your agent name and API key prefix (first 12 characters)
- The full JSON-RPC request and response
- The tool name and arguments used
Updated 1 day ago
