AI assistants are rapidly becoming the primary interface to modern software. Users no longer want to manually copy-paste data across five different browser tabs; they expect an assistant to search, evaluate options, and execute workflows directly.
For Talon, this creates a major opportunity. An applicant should be able to ask an agent to find relevant roles, a recruiter should be able to query their pipeline, and an employer should be able to manage open requisitions. However, hiring data is inherently sensitive, users cross multiple workspaces, and actions like submitting an application carry real-world consequences.
We built Talon MCP to solve this core tension: exposing public data seamlessly to AI agents while placing private workflows behind the exact same identity, multi-tenancy, authorization, and consent boundaries as our primary web and mobile platforms.
Why Choose MCP?
The Model Context Protocol (MCP) gives AI clients an open standard to discover and execute capabilities. Instead of building bespoke integrations for every assistant on the market, Talon exposes its capabilities through a unified protocol. Compatible agents connect, discover available tools, parse their schemas, and invoke them dynamically based on user intent.
While standardization simplifies connectivity, it does not solve hard application security. The MCP layer still needs to resolve fundamental questions on every call:
- Data Exposure: Is this specific record truly public?
- Identity: Who is the authenticated user behind the agent?
- Context: What Talon persona and workspace are they currently acting within?
- Permissions: Does the user hold explicit permission for this tenant?
- Consent: Does this specific action require a fresh, human-in-the-loop confirmation?
Our architecture started with these security constraints rather than a simple feature list.
Architecture: One Service, Two Trust Boundaries
The Talon MCP server is a dedicated Go service powered by the official MCP Go SDK. It shares Talon’s core domain models, PostgreSQL database, Redis cluster, and authorization engines, but deploys and scales independently from our main API and Next.js frontend.
Network access is split into two distinct Streamable HTTP transports:
https://mcp.talonhr.eu/public/mcp— Anonymous discovery and public data queries.https://mcp.talonhr.eu/mcp— Authenticated, persona-scoped workflows.
AI Client
│
├─► /public/mcp ────► Public Catalog ────► Jobs, Resources, Stories
│
└─► /mcp ───────────► OAuth & PKCE ──────► Role & Workspace Checks
│
└─► Protected Services
This strict separation enforces distinct security models. Public endpoints never accept user credentials, and protected endpoints never treat public context as proof of identity. Furthermore, tools are conditionally exposed: anonymous clients only discover safe endpoints, while authenticated users discover tools explicitly mapped to their active permissions.
Safe Public Discovery
Public endpoints are designed to be useful to conversational agents without exposing sensitive state. Agents can search published jobs, read technical resources, browse company stories, and trigger account creation workflows.
Public Toolset:
search_talon— Multi-entity cross-resource search.search_jobs&get_job— Filtered job discovery and details.list_resources&get_resource— Public documentation access.list_stories&get_story— Case studies and employer branding content.start_registration&start_sign_in— Flow continuation links.
All query results are strictly bounded, paginated, and sanitized before payload delivery.
Authentication handoffs are handled via web and mobile deep links. Passwords, OAuth credentials, MFA tokens, and recovery keys never pass through the MCP payload or chat history. The agent helps the user navigate to the door, but Talon remains the sole environment where credentials are supplied.
User-Bound Authentication & Authorization
An MCP client is software—it is not an applicant, recruiter, or hiring manager. Software alone cannot inherit authority.
Protected endpoints use an OAuth 2.1 authorization code flow with S256 PKCE, dynamic client registration, short-lived access tokens, and rotating refresh tokens. Tokens are stored strictly as cryptographic hashes, tagged with role-restricted scopes, and subject to real-time revocation.
Authentication is merely the entry point. Every protected request runs through a robust authorization pipeline:
Authenticated User
└── Active Account & Session
└── Selected Persona (Applicant / Recruiter / Employer)
└── Valid Workspace ID & Active Tenant Membership
└── Granular Action Permissions
└── Resource Ownership Verification
└── Human Confirmation Guard (if high-impact)
This multi-stage check prevents a common integration vulnerability: treating a valid API token as a blanket pass to read any database record.
Unified Protocol Across Personas
Talon serves multiple user types. The MCP service dynamically maps user roles to targeted tool sets using explicit OAuth scopes:
| Persona | Core Tools |
|---|---|
| Common | get_my_talon_capabilities, list_my_talon_workspaces, get_my_persona_overview |
| Applicant | list_my_applications, list_my_opportunities |
| Recruiter | list_my_recruiter_candidates |
| Employer | list_my_employer_jobs |
| Coach / Trainer | list_my_coach_programmes |
The get_my_talon_capabilities tool acts as an explicit discovery layer. Rather than guessing permissions or brute-forcing calls, the agent queries this endpoint first to learn exactly what roles, scopes, and actions the active user can perform.
Two-Step Confirmation for High-Impact Actions
Submitting a job application is a consequential real-world action. Relying on conversational intent inside a chat window is insufficient: contexts get stale, tool calls get retried, and payload parameters can drift between preview and execution.
We designed application submissions as a stateful, two-step protocol:
1. Agent Calls ───────► prepare_job_application (Validates job, candidate & workspace)
│
2. Talon Issues ──────► Short-Lived Confirmation Token (5-minute TTL)
│
3. Agent Presents ────► Unique Approval Link to User
│
4. User Reviews ──────► Manual Approval on Talon Web Interface
│
5. Agent Invokes ─────► apply_to_job (Executes only if token and payload match)
This out-of-band human confirmation mitigates accidental tool invocation, request replay, duplicate submissions, and payload tampering. High-impact actions require high-assurance UX boundaries.
Operational Readiness & Metrics
Exposing an MCP server opens a new edge interface to domain services. To ensure production resilience, the system includes:
- Rate Limiting: IP-based defaults for anonymous access (120 req/min) and token-based limits for authenticated sessions (600 req/min), backed by Redis.
- Observability: Prometheus metrics, correlation request tracking IDs, and structured JSON logs.
- Privacy Controls: Metrics and logs strictly strip user IDs, Bearer tokens, URL query parameters, and raw request payloads.
- Transport Hardening: Nginx reverse-proxy rules restricting sensitive paths, systemd isolation, and CORS lock-down.
Verification & Lessons Learned
End-to-end integration tests were executed across the Go backend, Next.js frontend, Flutter mobile client, and the agent skill package.
During full-flow integration testing, we identified a JSONB serialization edge-case in PostgreSQL during OAuth state persistence. Catching this prior to deployment highlighted a core lesson: protocol-level unit tests are not enough. Real-world verification requires exercising complete token lifecycles, database migrations, cross-domain redirects, and browser handoffs.
The release artifact was validated across:
- Backend: Go test suites, static analysis (
go vet, linter), and binary compilation. - Web: 323 frontend unit/integration tests and production Next.js builds.
- Mobile: 76 Flutter test suites and static analysis.
- Infrastructure: Reverse proxy verification, CORS handling, rate-limit policies, and token rotation tests.
The Core Takeaway
Building a production-grade MCP service is not simply a matter of wrapping existing REST endpoints with AI tool definitions. The real engineering work lies in defining boundaries: what an agent can read, what it can execute, under whose authority it operates, and when a human must retain direct control.
By combining an open public transport, user-bound OAuth identity, tenant-isolated authorization, and out-of-band approval flows, Talon MCP provides AI agents with deep operational utility—without compromising security or user trust.
