# SwiftFit assistant connector SwiftFit provides an authenticated Streamable HTTP MCP endpoint at `https://api.swiftfit.app/mcp` when `ALLOW_ASSISTANT_CONNECTOR=true` and `PUBLIC_API_URL` matches that public HTTPS origin. It is disabled by default. Hosts discover OAuth metadata, register a client, and ask the person to approve access through the SwiftFit consent page. New connections initially have access to all connector tools, not just job search. The person can change each connection's profile, jobs, resume, and application read/write permissions or disconnect it in account settings. Changes apply to already-issued access tokens on their next request; OAuth still uses the `swiftfit` transport scope. This guide is served publicly at `https://api.swiftfit.app/api/connect/assistant/docs`. ## What job search means `get_job_matches` returns a bounded batch for the signed-in person: up to 150 jobs with an AI qualification verdict and 25 additionally retrieved jobs without one. `batch_kind` distinguishes the two; a missing qualification score is not a low score. The `all` view is an alias for this batch, not the full register. `get_job_candidates` still pages through the complete eligible retrieval pool, and `search_jobs` filters that pool, **not the whole web or every employer posting**. `get_job_matches` is always read-only. When `batch_stale` is true, the host may call the separate `refresh_job_batch` tool (requires `jobs:write`): it queues a background retrieval/rerank only if the previous batch is at least 12 hours old or the user's preferences changed, and reuses an existing run. The old batch remains readable while the build runs. Read-only connections can still inspect the stale batch without starting paid work. A first-time account must provide its own resume and complete the role, title, location, and resume-length setup before a ranked list is available. Connector setup guidance describes why those inputs are needed, but does not prescribe an interview script: the assistant may adapt its questions to information the person already volunteered. Role questions and title suggestions are aids, not answers to impose; never invent resume facts or preferences. To redo setup, use `get_setup_review` to show existing choices, `preview_setup_changes` to compare only requested replacements, and `apply_setup_changes` **only after the person confirms** that comparison. Preview tokens are bound to the account, exact changes, and existing values and expire in 15 minutes; a changed/expired preview must be repeated. The update preserves saved jobs and applications and queues at most one background ranking after matching inputs change. Existing setup tools remain available for a single direct change. Ranking is asynchronous; an empty first response can report incomplete setup, pending ranking, or a need to refresh. Job listings are crawled from employer boards; opening a posting in SwiftFit is not an application to that employer. SwiftFit does not promise that a listing remains open or that every job on the web is indexed. The three job list tools return 10 rows by default and accept `limit` from 1 to 25 and a 1-based `page`. `get_job_matches` page 1 returns a one-hour `snapshot_id`: pass it with the **same view and limit** on every later page so a concurrent rebuild cannot skip or duplicate jobs. An expired or missing snapshot requires restarting at page 1; a fresh page 1 creates a new snapshot. `get_job_candidates` and `search_jobs` remain live paginated lists. Rows are arrays keyed by `columns`. Match responses also show the latest build status, stage, progress counts, and last successful completion (when known), separately from the snapshot timestamp; a failed refresh does not erase the older batch. `get_job_details` exposes the longer posting and link. MCP reads do not record impressions or open signals. Account-changing tools can replace a resume, alter search preferences, hide a posting, or use tailoring entitlement. This connector does not initiate checkout or accept API credentials. The account's plan may restrict tailoring, and the app itself handles any billing independently. ## Base resume readiness Before tailoring, the assistant can get the person's base resume into shape. `review_base_resume` (requires `profile:read`) checks it against SwiftFit's readiness rules: standard sections, consistent "Month Year - Month Year" dates, enough bullets on current roles and main projects, projects kept separate from jobs, one accomplishment per bullet, each number stated once with unit, direction, baseline and measurement, skills backed by bullets, clean language, contradictions, work-type coverage, and an email that matches the account. It returns findings with exact `ref` paths and, where only the person knows the answer, the question to ask. The checks are deterministic heuristics; nothing here calls a model, except to read a freshly uploaded resume into the editor once. `preview_base_resume_changes` validates the assistant's drafts (replace, add_bullet, remove, add_skill, move_to_projects). Each draft is labelled new, reworded, removed or moved and shown beside the original wording and its quoted source. A draft that introduces a number or a known tool absent from both the resume and the quoted source is refused. `apply_base_resume_changes` (requires `profile:write`) needs an approve, edit or reject decision for **every** change and a 15-minute preview token bound to the account, the exact drafts and the current resume. It saves only approved or edited changes, and the app's one-step Undo reverses the batch. ## Reviewer walkthrough 1. Connect the MCP endpoint from a host supporting remote MCP OAuth and complete the consent flow with a SwiftFit test account. 2. For an account with completed setup and ranked jobs, ask for job matches, request five results, page with the same limit, filter with `search_jobs`, and open a posting with `get_job_details`. 3. For a fresh account, call `get_account`, supply a test resume, answer the role questions, choose titles/location/length, and inspect the pending-ranking and completed states. A model provider may be needed for setup/ranking; ensure test credentials and data are available. 4. Exercise rejected extra parameters and limits outside 1–25. Test that changes to saved state and the OAuth disconnect are reflected in the app. The integration suite is `./.venv/bin/python -m pytest tests/test_assistant_connector.py -q` from the backend directory. It exercises the OAuth and JSON-RPC HTTP surfaces with local fixtures; it does not certify a production deployment or a real Claude account. ## Connection troubleshooting An unauthenticated `401` from `/mcp` is the expected OAuth discovery challenge, not an outage. A host must follow the advertised protected-resource and authorization-server metadata, register its own redirect URI at `/register` to receive a `client_id`, then use that ID with PKCE at `/authorize`. Public clients can register with `token_endpoint_auth_method: "none"`; confidential clients can use a generated secret. If a host says "missing client ID" before opening consent, check whether its **remote MCP setup** supports dynamic OAuth client registration. A chat instruction to connect to a URL cannot substitute for host-side registration. For a host requiring manual client credentials, obtain its actual OAuth callback URL and register that callback for that host; do not reuse another host's client ID or paste a client secret into chat. The local discovery metadata now advertises the supported public-client method, but production will retain old metadata until this backend change is deployed. ## Restricted directory-review sign-in Normal users continue signing in with Google. Only when **both** `ASSISTANT_REVIEWER_EMAIL` and `ASSISTANT_REVIEWER_PASSWORD_HASH` are configured, the consent page offers a password form to the existing, verified, non-admin account named by the operator. It is not a signup or general account recovery flow. The form requires a live OAuth request, and signing in alone does not approve it. Failed attempts are bounded by shared and per-worker rate limits. Leave both settings empty in production until a populated, authorized demo account and secure reviewer credential delivery are ready. Create a unique high-entropy password, run `from app.auth import hash_password; print(hash_password(password))` locally, store only the hash in the server's secrets, and send the plain password to reviewers privately. Never commit either credential or configure another person's account. Clear both settings and revoke the demo account's sessions when review ends. ## Submission blockers outside the connector code - Verify the deployed public documentation URL, MCP/OAuth/consent flow, and actual Claude and ChatGPT connection end to end. - Publish a legally reviewed privacy policy explaining collection, retention, deletion, and sharing of resumes, preferences, and job information with configured AI/model providers and connected assistant hosts. Do not represent this note as that policy. - Prepare a reviewer account with completed onboarding, realistic resume and preferences, ranked postings, saved application, and a completed tailored resume. Provide access through Anthropic's secure review process, not in this repository. - Confirm current directory eligibility, submitter role, billing restrictions, and review criteria in Anthropic's official submission workflow. Directory acceptance does not guarantee recommendation for generic job-search questions.