MCP server (read-only)
404 not_found until then. This page describes what it will do.Ahlan Hamad runs a Model Context Protocol server at https://actions.ahlanhamad.com/mcp. An AI assistant that speaks MCP can use it to answer questions about one company — the company the API key belongs to. It uses the sameah_live_ / ah_test_ key as the REST API, the same rate limit, and it appears in the key's request log.
What it can and cannot do
- Read-only. There is no tool that changes anything. It cannot run or finalize payroll, move money, approve leave, or edit an employee.
- A tool is listed only if the key has its scope and the person who created the key still holds the matching role permission. A key with no matching scopes sees no tools.
- Answers are never wider than the REST endpoint behind each tool: payroll is run-level totals only, withheld for runs under 3 employees; no salaries, IBANs or ID numbers.
- Use a test key (
ah_test_, from a sandbox company) while you try it — it can only see generated data.
Tools
| Tool | Scope | Returns |
|---|---|---|
get_headcount | employees:read | Current employees (excluding people who have left), broken down by status, country, employment type and department. |
get_payroll_totals | payroll:read | Finalized and paid payroll runs with their run-level totals in the run's currency, newest first. Totals are withheld for runs under 3 employees. Never per-employee pay. |
get_leave_balances | leave_balances:read | This year's annual leave balance (entitled incl. carry-over, used, remaining days). Pass employee_email or employee_code for one person (needs employees:read too); otherwise up to 50 current employees. |
get_upcoming_deadlines | compliance:read | Payroll cut-off and pay days, and the WPS deadline of each finalized run, in the next days days (overdue WPS items stay listed). Social-insurance dates and document expiries are not included. |
Claude Code
claude mcp add --transport http ahlan-hamad https://actions.ahlanhamad.com/mcp \
--header "Authorization: Bearer ah_test_…"Claude Desktop
Claude Desktop's config file starts local servers, so it reaches a remote server with a header through the mcp-remote bridge. Add toclaude_desktop_config.json and restart Claude Desktop:
{
"mcpServers": {
"ahlan-hamad": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://actions.ahlanhamad.com/mcp",
"--header",
"Authorization:${AHLAN_HAMAD_KEY}"
],
"env": {
"AHLAN_HAMAD_KEY": "Bearer ah_test_…"
}
}
}
}OpenAI (Responses API)
The Responses API's remote MCP tool sends the header on every call:
from openai import OpenAI
client = OpenAI()
resp = client.responses.create(
model="gpt-5",
tools=[{
"type": "mcp",
"server_label": "ahlan_hamad",
"server_url": "https://actions.ahlanhamad.com/mcp",
"headers": {"Authorization": "Bearer ah_test_…"},
"require_approval": "never",
}],
input="How many people do we employ, by department?",
)
print(resp.output_text)claude.ai and ChatGPT connectors
The "add custom connector" screens in claude.ai and ChatGPT sign in with OAuth and do not let you paste an API key header. This server takes API keys only today, so those screens cannot connect to it yet. Use one of the routes above.
Protocol details
- Streamable HTTP transport, stateless: send each JSON-RPC message as a
POST; responses areapplication/json. No sessions and no server-sent events (GETanswers 405). - Protocol versions
2025-06-18,2025-03-26and2024-11-05. Methods:initialize,ping,tools/list,tools/call. One message per request (no batches). - Authentication and rate-limit failures are HTTPproblem+json errors, not JSON-RPC errors.
curl https://actions.ahlanhamad.com/mcp \
-H "Authorization: Bearer ah_test_…" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'