Call the engine from your AI agents.
The placement.solutions matching-reasoning engine is exposed as an MCP server, so an AI agent can match, score, and explain records over the live data index directly. OAuth 2.1 with PKCE, dynamic client registration, and six outcome-oriented tools. The flagship dataset is the legal Hiring Index; the same engine re-points to other markets.
Connect
Point any MCP client at the endpoint. The client discovers the authorization server automatically, registers itself, and walks you through a one-time approval where you paste a placement.solutions API key. There is no client secret to manage by hand: registration and PKCE are automatic.
Claude Desktop / Claude Code
// claude_desktop_config.json -> mcpServers { "placement-solutions": { "url": "https://api.placement.solutions/mcp" } }
Claude.ai (web / Team / Enterprise) - custom connector
Settings → Connectors → Add custom connector → paste https://api.placement.solutions/mcp. Approve, then paste your key on the consent screen.
Cursor / VS Code (and other MCP clients)
// mcp.json -> mcpServers { "placement-solutions": { "url": "https://api.placement.solutions/mcp", "type": "http" } }
MCP Inspector (to test interactively)
npx @modelcontextprotocol/inspector
# Transport: Streamable HTTP URL: https://api.placement.solutions/mcp
How authentication works
The server is both an OAuth 2.1 authorization server and the protected resource. It implements the standards MCP clients expect, so connecting is automatic for compliant clients. Discovery metadata is published at the domain root:
# protected-resource metadata (RFC 9728) - the 401 points clients here GET https://api.placement.solutions/.well-known/oauth-protected-resource/mcp # authorization-server metadata (RFC 8414) GET https://api.placement.solutions/.well-known/oauth-authorization-server GET https://api.placement.solutions/mcp/.well-known/oauth-authorization-server
An unauthenticated request to the MCP endpoint returns 401 with a WWW-Authenticate header carrying the resource_metadata URL, so a client can bootstrap the whole flow on its own. The four steps your client runs for you:
- Register - the client self-registers at /mcp/register (Dynamic Client Registration) and receives a client id. Public client, no secret.
- Authorize - the client opens /mcp/authorize with a PKCE code_challenge (S256). You are redirected to a consent page.
- Consent - you paste your placement.solutions API key. It is validated against your account (/v1/me) and bound to this session, so access stays tied to a real, entitled customer and is tenant-scoped.
- Token - the client exchanges the code plus its PKCE code_verifier at /mcp/token for a bearer access token (1 hour) and a refresh token (30 days).
Don't have a key yet? Email hunter@placement.solutions for access.
Full OAuth flow (for custom clients)
If you are building your own client rather than using a compliant MCP client, this is the exact sequence. It is the flow used in the verified test above.
# 1. Dynamic Client Registration -> returns a client_id curl -X POST https://api.placement.solutions/mcp/register -H 'content-type: application/json' \ -d '{"redirect_uris":["http://localhost:9999/callback"], "token_endpoint_auth_method":"none", "grant_types":["authorization_code","refresh_token"], "response_types":["code"],"scope":"placement.read"}' # 2. PKCE (S256) VERIFIER=$(python -c "import secrets;print(secrets.token_urlsafe(48))") CHALLENGE=$(printf %s "$VERIFIER" | openssl dgst -binary -sha256 | openssl base64 | tr '+/' '-_' | tr -d '=') # 3. Authorize -> 302 to the consent page. Open it in a browser: https://api.placement.solutions/mcp/authorize?response_type=code&client_id=$CID &redirect_uri=http://localhost:9999/callback&code_challenge=$CHALLENGE &code_challenge_method=S256&scope=placement.read&state=$STATE &resource=https%3A%2F%2Fapi.placement.solutions%2Fmcp # paste your pk_live_/sk_live_ key on the consent page # -> you are redirected to http://localhost:9999/callback?code=...&state=... # 4. Exchange the code (with the PKCE verifier) for tokens curl -X POST https://api.placement.solutions/mcp/token \ -d grant_type=authorization_code -d code=$CODE \ -d redirect_uri=http://localhost:9999/callback \ -d client_id=$CID -d code_verifier=$VERIFIER # -> { "access_token":"...", "token_type":"Bearer", "expires_in":3600, "refresh_token":"..." } # 5. Refresh when the access token expires curl -X POST https://api.placement.solutions/mcp/token \ -d grant_type=refresh_token -d refresh_token=$REFRESH -d client_id=$CID
Tools
Six outcome-oriented tools map onto the engine's verbs. Each returns structured JSON from the live REST data API behind it, scoped to your key's entitlements.
Example: an agent asks for litigation associates
# the agent calls the match tool over MCP; the server returns: { "status": 200, "body": { "object": "list", "data": [ { "object": "job", "title": "Employment Litigation Associate", "company": "Ogletree Deakins", "is_law_firm": true, "url": "https://careers.ogletree.com/jobs/6595" } ] } }
Scopes & tokens
The MCP OAuth scope is placement.read. The bound API key carries its own fine-grained scopes that gate the underlying data API:
| Key scope | Grants |
|---|---|
| me:read | account + entitlement lookup (required for consent) |
| jobs:read | match, score_record, explain_match |
| firms:read | get_firm |
| lateral_moves:read | lateral_moves |
| markets:read | list_feeds |
Access tokens live for 1 hour; refresh tokens for 30 days. A tool call without a valid token returns {"error":"unauthenticated"}. Keys are tenant-scoped, so two customers never see each other's data.
Coverage
| Vertical | Record type | Status |
|---|---|---|
| Legal (Hiring Index) | roles, firms, lateral moves | Live |
| Recruiting / staffing | roles, openings | Live |
| CRE, construction, insurance, M&A, freight, MSP | properties, projects, accounts, targets | Roadmap |
The legal Hiring Index is the proven flagship. The same engine and the same tools re-point to other markets by swapping the taxonomy and feeds; those indices are on the roadmap, not live today.
Troubleshooting
- Client says it can't find the auth server. Confirm the URL is exactly https://api.placement.solutions/mcp. The discovery metadata is served at the domain root (the three URLs in "How auth works"); all return 200.
- 401 on every call. The token is missing or expired (1 hour). Re-run the flow or refresh. The 401 body carries a WWW-Authenticate header your client should follow.
- "That key was not accepted" on consent. The key must be a live placement.solutions key (pk_live_ / sk_live_) that resolves at /v1/me with at least me:read.
- A tool returns a 403 about a missing scope. Your key lacks that scope (see the table above). Ask for an upgraded key.
- redirect_uri mismatch. The redirect_uri at the token step must match the one registered and used at authorize, exactly.
Security & honesty
- Access is OAuth-gated and tied to a real placement.solutions API key; the validated key is bound to the session and used only for your calls, scoped to your entitlements.
- The MCP server runs as an isolated service that calls the data API over localhost; it never holds a shared master key.
- No third-party cloud model is called at inference by default; a small fallback model may be used under a strict daily cap. US data residency. We do not train on your data.
- Transport is Streamable HTTP with PKCE-enforced OAuth 2.1 and DNS-rebinding protection.
- SOC 2 Type 1 is targeted for 2026 Q4 (in progress, not yet certified). On-prem deployment is available as a labeled enterprise option; hosted on our infrastructure is the default.