placement.solutions MCP · live REST reference Overview CestoneAI
Model Context Protocol

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.

MCP https://api.placement.solutions/mcp

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
Verified working. The full path (discovery → registration → PKCE → consent → token → authenticated tool call returning live data) is tested end to end against this endpoint.

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:

  1. Register - the client self-registers at /mcp/register (Dynamic Client Registration) and receives a client id. Public client, no secret.
  2. Authorize - the client opens /mcp/authorize with a PKCE code_challenge (S256). You are redirected to a consent page.
  3. 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.
  4. 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.

explain_matchthe differentiator
Explain why a record matched, in plain language with the scoring signals behind it. This is the verb that makes the engine more than a search box: the ranking shows its work.
record_id: string  ·  query: string (optional)
match
Match a free-text query against the live data index for a vertical and return ranked records.
query: string  ·  vertical: string = "legal"  ·  limit: int = 10 (max 50)
score_record
Return the engine's score and signal breakdown for a single record.
record_id: string
get_firm
Return the firm / organization dossier for an entity id.
firm_id: string
lateral_moves
Recent lateral-movement events from the index (flagship: legal partner and counsel moves).
limit: int = 20 (max 100)
list_feeds
List the live data feeds and markets the engine aggregates for a vertical.
vertical: string = "legal"

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 scopeGrants
me:readaccount + entitlement lookup (required for consent)
jobs:readmatch, score_record, explain_match
firms:readget_firm
lateral_moves:readlateral_moves
markets:readlist_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

VerticalRecord typeStatus
Legal (Hiring Index)roles, firms, lateral movesLive
Recruiting / staffingroles, openingsLive
CRE, construction, insurance, M&A, freight, MSPproperties, projects, accounts, targetsRoadmap

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

Security & honesty

placement.solutions is a CestoneAI product · cestoneai.cloud REST reference · hunter@placement.solutions