Inspiration

Every merit cycle, HR managers face two silent risks: blowing the budget and widening the pay gap. Today they manage both in spreadsheets — exported from HRIS, emailed around, filled in manually, and never visible to anyone until it's too late.

The EU Pay Transparency Directive 2026 raises the stakes further. Companies must now justify salary gaps above 5% between peer groups. A missed equity flag isn't just an HR problem — it's a legal and reputational one.

I asked: what if the tool HR managers already live in — Slack — could catch both risks before a single raise is approved?

What it does

Comp Planning Copilot is an AI compensation agent that lives entirely in Slack. HR managers propose, review, and approve merit raises without leaving the conversation — while the agent enforces two guardrails on every submission.

Budget guardrail — each manager has a merit pool. Before any raise goes through, the agent checks remaining budget in real time. If a proposal would exceed the pool, it's automatically escalated to HR for exception approval — with the exact overage surfaced.

Pay equity check — every proposed salary is compared to the peer median (same role, level, location). If it lands more than 5% below median, the agent flags it, shows the gap in dollars and percentage, and recommends a remediation range aligned with the EU Pay Transparency Directive 2026.

Key interactions:

  • /comp give Lily Lopez 5% — instant budget + equity analysis with approve/adjust actions
  • /comp give David Park $200000 — target salary with pay band position
  • /comp status — live cycle pulse: utilization, proposals, escalations
  • App Home tab — equity risk table, manager budget tracker, KPI grid
  • Web dashboard — Chart.js charts, manager breakdown, equity severity table, live auto-refresh

How I built it

Architecture: Slack ↔ MCP ↔ SQLite

Slack (Socket Mode)
    └── Slack Bolt async (Python)
            └── MCP Client (FastMCP 3.x)
                    └── MCP Server (FastMCP HTTP · port 8080)
                            └── SQLAlchemy + SQLite
                                    └── Web Dashboard (FastAPI + Chart.js)

The MCP Server exposes 7 tools over HTTP transport: find_employee, check_budget, check_equity, get_pay_band, submit_proposal, cycle_status, and list_equity_risks. A single /comp give command calls four of these in parallel via asyncio.gather — budget, equity, pay band, and employee lookup all at once.

The Slack agent (Bolt async, socket mode — no public URL required) handles slash commands, App Home publishing, modals, and interactive Block Kit cards with approve / adjust / edit actions. HR alerts post automatically to a dedicated channel on every escalation or equity flag.

The web dashboard (FastAPI + Tailwind CSS + Chart.js) shows real-time budget utilization, manager breakdown charts, equity risk severity table, and a recent proposals feed — publicly accessible via ngrok for judges.

Challenges I ran into

FastMCP version mismatch — FastMCP 3.x changed the transport string ("http" not "streamable-http"), returns CallToolResult instead of list[TextContent], and moved the endpoint to /mcp. Discovering this after 501 errors cost significant debugging time.

Block Kit visual constraints — Slack only supports two button styles (primary and danger). Building communicative cards with ASCII progress bars, emoji severity indicators, and structured field grids required creative workarounds — which ultimately led me to add the web companion dashboard for richer analytics.

Peer median correctness — The equity check must exclude the employee from their own peer group. An off-by-one produced misleading flags. I wrote 22 unit tests covering all edge cases: no peers, single peer, even/odd peer counts, and the boundary condition at exactly 5%.

Python 3.14 + Jinja2 incompatibility — Jinja2's template cache uses function arguments as dict keys, which broke on Python 3.14. Fixed by serving the HTML template directly without Jinja2.

Accomplishments

  • 22/22 tests passing — full coverage of comp math, budget logic, equity flags
  • Real-time MCP tool chaining — four parallel tool calls via asyncio.gather on every proposal
  • EU Pay Transparency Directive 2026 compliance baked in, not bolted on
  • Zero-spreadsheet workflow: propose → review → approve entirely in Slack
  • Budget escalation path fully automated — no manual HR handoff needed
  • Web dashboard with live Chart.js visualizations synced to the same SQLite DB

What I learned

Socket mode is the right choice for enterprise Slack deployments — no public URL required, works behind corporate firewalls, and eliminates webhook maintenance overhead. Pairing it with MCP keeps all business logic in the MCP server — fully testable and portable — while Slack handles only presentation and interaction. That separation made the 22-test suite straightforward to write and fast to run.

What's next

  • HRIS integration — live employee data from BambooHR / Workday / Rippling instead of SQLite
  • Proactive alerts — weekly Slack digest: new equity risks, managers approaching budget limits
  • Manager approval workflow — two-step propose → HR approve with full audit trail
  • Comp benchmarking — integrate Radford / Levels.fyi market data for external peer comparison
  • Multi-cycle tracking — year-over-year equity trend analysis across merit cycles

Built With

Share this project:

Updates