MCP server for the YC Work at a Startup (WAAS) API. Lets Claude Code list applicants, view candidate profiles, send messages, update pipeline state, and manage notes — all from the command line.
claude mcp add waas -- uvx --from git+https://github.com/yc-software/waas-mcp waasOr install locally with uv:
uv tool install git+https://github.com/yc-software/waas-mcp
claude mcp add waas -- waaswaas loginYour browser opens to the YC authorization page. Click Authorize and you're done. Tokens are saved to ~/.yc/waas-credentials.json and auto-refresh on expiry.
Restart Claude Code, then run health_check. You should see:
WAAS_API: ok (api.ycombinator.com)
waas login # Authenticate (opens browser)
waas logout # Clear stored credentials
waas status # Check token statusAll env vars are optional — the default setup requires no configuration beyond waas login.
| Env var | Default | Description |
|---|---|---|
WAAS_CLIENT_ID |
built-in | Override the OAuth2 client ID |
WAAS_ACCESS_TOKEN |
— | OAuth2 access token (overrides stored credentials) |
WAAS_REFRESH_TOKEN |
— | OAuth2 refresh token (overrides stored credentials) |
WAAS_CLIENT_SECRET |
— | OAuth2 client secret (only for confidential apps) |
WAAS_API_HOST |
https://api.ycombinator.com |
API host |
WAAS_API_HOST_HEADER |
— | Custom Host header (for local dev routing) |
WAAS_TOKEN_HOST |
derived from API host | Token endpoint host (for refresh) |
Credentials are stored in ~/.yc/waas-credentials.json and auto-refreshed. Env vars take priority over stored credentials.
| Tool | Description |
|---|---|
applicant_list |
List candidates who applied to your jobs. Filter by state, needs_response, job_id, since. Supports compact=true for triage (see below). |
applicant_list(compact: true) returns ~60% smaller payloads optimized for first-pass scanning. Use this for triage, pipeline views, and applicant review. Use full mode (no compact) only when you need email addresses, full work history, or complete looking_for text.
What compact trims:
- Positions: top 2 only (full mode returns up to 12)
- Educations: top 1 only (full mode returns up to 6)
looking_for: truncated to 200 chars (full mode can be 1.2KB+)- Dropped fields:
email,remote,github_url,last_active_at,role_type,applicant_messaged_at,last_messaged_at - Kept:
short_id,name,location,role,experience,us_authorized,us_visa_sponsorship,short_phrase,linkedin_url,profile_url,positions(top 2),educations(top 1),state,applied_at,applied_jobs,company_messaged_at
The compact transformation is client-side only — the WAAS API returns the same data, and the MCP server trims it before passing to Claude.
| Tool | Description |
|---|---|
candidate_show |
Get a single candidate profile by short_id. Full profile with all positions, educations, work auth. |
candidate_batch |
Batch lookup up to 25 candidates by comma-separated short_ids. |
| Tool | Description |
|---|---|
candidate_status_show |
Get pipeline state — stage, archive reason, messaging timestamps. |
candidate_status_update |
Update state (reviewing, shortlisted, screen, interviewing, offer, archived). |
States: reviewing · shortlisted · screen · interviewing · offer · archived
Archive reasons: not_qualified · team_fit · might_consider_later · turned_down_offer · hired · other
| Tool | Description |
|---|---|
candidate_messages_list |
List all messages between you and a candidate. |
candidate_message_send |
Send a message to a candidate via WAAS. Messages appear as emails to the candidate. |
| Tool | Description |
|---|---|
candidate_notes_list |
List internal notes on a candidate. |
candidate_note_create |
Add an internal note. |
| Tool | Description |
|---|---|
health_check |
Validate the API connection. Returns ok/expired/error with the host. |
Once registered, you can use natural language in Claude Code:
- "Show me applicants who need a response" →
applicant_list(needs_response: true, compact: true) - "Just PE applicants" →
applicant_list(job_id: 41302, compact: true) - "Who applied this week?" →
applicant_list(since: "2026-03-17T00:00:00Z", compact: true) - "Tell me about this candidate" →
candidate_show(short_id: "KhNCmzEZ") - "Archive candidates 1-5" → loops
candidate_status_update(short_id, state: "archived", archive_reason: "not_qualified") - "Message this candidate" →
candidate_message_send(short_id: "KhNCmzEZ", message: "Hi! Thanks for applying...") - "Check if WAAS is connected" →
health_check()
# Clone
git clone [email protected]:yc-software/waas-mcp.git
cd waas-mcp
# Install locally
uv tool install --from . waas-mcp
# After making changes, reinstall
uv tool install --force --from . waas-mcp
# Then restart Claude CodeFor testing against local bookface (http://bookface.yclocal.com):
- Create an OAuth app at
http://account.yclocal.com/oauth/applications/new(non-confidential, redirect URIhttp://localhost:19877/callback, scopescandidates:read candidates:manage) - Register with host overrides:
claude mcp add waas \
-e WAAS_CLIENT_ID=your_local_client_id \
-e WAAS_API_HOST=http://bookface.yclocal.com \
-e WAAS_API_HOST_HEADER=public-api.yclocal.com:3002 \
-e WAAS_TOKEN_HOST=http://account.yclocal.com \
-- uvx --from /path/to/waas-mcp waas- Run
waas login— browser opens to local auth page
"Not authenticated" — Run waas login to authenticate via browser.
"Client authentication failed" — The OAuth app must be non-confidential. Confidential apps hash secrets, making the PKCE token exchange fail.
Token expired — Tokens auto-refresh. If refresh fails, run waas login to re-authenticate.
Wrong environment — Run health_check to see which host you're hitting. Check ~/.claude.json for duplicate MCP entries if it's pointing to the wrong environment.
Local dev 404 — The API routes require Host: public-api.yclocal.com:3002. Set WAAS_API_HOST_HEADER in your env config.
Rate limiting — The WAAS API rate-limits write operations. When batch-archiving candidates, space out calls or retry on 429 responses.