FreeApply
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| FREEAPPLY_DB | No | Path to an existing database file to use in place, e.g. C:/path/jobs.db. | |
| FREEAPPLY_DATA | No | Data folder for FreeApply. Defaults to ~/.freeapply. | |
| FREEAPPLY_PORT | No | Dashboard port. Defaults to 7878; the next free port is used if it is taken. | 7878 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| freeapply_statusA | Reports whether FreeApply can work now and returns the signed step-by-step procedure for a task. Unlike freeapply_get_settings (the user's details) and freeapply_job_stats (the job search), it is about FreeApply itself. Use it first in every session and before each task; call it again only to re-check after the user acts. It works while FreeApply is locked or the Terms aren't accepted, so it can tell you why. Behavior: changes no user data. Sets up the data folder on first run, starts the local dashboard if needed and refreshes the résumé copy in the documents folder. Parameters: procedure adds that task's text: freeapply-setup (first run, or Terms or settings missing), freeapply-apply (find jobs and apply) or freeapply-replies (Gmail reply check). Omit it for the status alone. Returns: workflow {ok, problem}, terms {ok}, setup_complete, missing, sites (each chosen job site with ready), autorun, update, dashboard (its URL), data_dir, documents {dir, resume, cover_letters}, stats, procedures, and models {can_delegate, rescan, levels, lanes, unfilled}: each level and lane gives {model, effort, source}, and model current means your own model does it. With procedure also procedure {name, description, text, workflow_version, workflow_hash}, null while locked. Next: workflow.ok false: tell the user why and stop. terms.ok or setup_complete false: follow freeapply-setup. models.rescan true: do its AI models step first. |
| freeapply_open_dashboardA | Opens the user's local FreeApply dashboard in their browser, on one tab. Unlike freeapply_status, which only reports its address, it puts the page in front of the user. Use it when the user has to act there: accept the Terms, fill in settings, answer questions waiting on them, or review applications and replies. Not for reading data; the other tools give you the same information. Behavior: changes no data. Starts the dashboard if needed, on http://127.0.0.1:7878 or the next free port; only this computer can reach it. Parameters: tab picks the page: overview (the Terms show there until accepted), settings (the setup fields), issues (the Needs you list of questions and sign-ups), applications or replies. Default overview. Returns: {url, opened}. url null: the dashboard couldn't start (no free port); tell the user. opened false with a url: no browser could be launched; give the user the url. |
| freeapply_get_settingsA | Reads the user's settings: who they are, what they're looking for and how FreeApply should work. Unlike freeapply_user_answers (answers to single form questions) and freeapply_status (whether FreeApply can run), it holds the facts about the user. Use it once per session, or once per helper, before scoring jobs or filling in a form. With the résumé text and the user's own words it is the only source of facts about the user: never invent what it doesn't contain. To change settings, use freeapply_update_settings. Behavior: read-only; installation secrets are never included. Parameters: sections limits the reply to what a step needs, e.g. ["profile", "eligibility"] for a form; leave out resume, the largest, when you don't need its text. Default all. Returns: {settings, missing}. Sections: profile, targets, eligibility, resume (file paths, text, profile), cover_letter, automation, autorun, gmail, custom_answers, models, model_choices and sharing (choices only). missing lists required fields still empty as {key, label}; while it isn't empty, don't apply anywhere: open the settings tab with freeapply_open_dashboard and ask the user to fill them. Errors: an unknown section name; the message lists the valid ones. |
| freeapply_update_settingsA | Saves what the user told you, what setup reads from their résumé, and the AI models scan. Unlike freeapply_user_answers, which keeps answers to single form questions, it changes the settings themselves. Use it when the user states a fact or preference, in setup to store the résumé's text and profile, and in the AI models step. Don't fill a field the user didn't give you; to read settings, use freeapply_get_settings. Behavior: overwrites the fields you send, with no undo. patch is deep-merged: only its fields change, nested objects merge, lists are replaced whole. Sections only the user changes in the dashboard (legal, sharing, automation, autorun, onboarding, integrity, model_choices) are skipped and listed in ignored. All or nothing: if any field is wrong, nothing is saved. Parameters: patch is nested by section with freeapply_get_settings' field names, e.g. {"targets": {"min_pay": 60000}}. resume takes only text and profile ({headline, skills, titles, education, certifications}, from the résumé text alone). models is the scan {app, current, can_delegate, available, efforts}, read from your own tools; it replaces the last scan. Returns: {changed, ignored, setup_complete, missing}; after a scan also models, the model and effort chosen for each level. Errors: nothing writable, an unknown section or field, a wrong type, a value outside its choices (e.g. cover_letter.length is short, standard or long), résumé files (the user adds those in the dashboard) or a malformed scan. The message names every problem. |
| freeapply_fetch_postingA | Fetches one job posting on the user's computer and returns it trimmed, with its form questions, suggested answers and the skills it asks for. Unlike opening the page in the browser it costs few tokens; you still use the browser to fill in and submit the form. Use it to read each posting before scoring or applying. Not for search-results pages or pages behind a sign-in; read those in the browser. Behavior: read-only; one web request from the user's computer. Greenhouse, Lever and Ashby postings are read through their public APIs, other sites as plain page text. Only public http and https pages are fetched: an address on this computer or a local network, or a redirect to one, is refused. The posting is remembered for this session, so freeapply_claim_job can keep its keywords. Parameters: url is the job page or its application form. max_chars caps the description (default 6000, at least 500); description_chars gives its full length. source, a job site id such as linkedin, picks the saved answers meant for that site. Returns: ats, title, company, location, work_mode, pay, description, description_chars, questions (label, required, type, options), suggested_answers (from settings and saved answers; answer anything else only from the résumé or the user) and keywords {matched, missing, coverage}: use matched skills in the posting's words, never claim missing ones; coverage is the matched share in percent, null when the posting names none. Errors: a bad or local address, or a page that can't be fetched, with the reason; then read it in the browser. Next: freeapply_claim_job. |
| freeapply_claim_jobA | Claims a job before you work on it: runs the duplicate check, applies the user's rules and starts tracking it, returning the job_id every later call needs. Unlike freeapply_list_jobs it adds a job, and unlike freeapply_update_job it makes the job's first record. Use it before opening any application form, and to record a job you reviewed and won't pursue (status skipped, with status_note) so it isn't reviewed again. Not for changing a job you already claimed. Behavior: adds the job unless, in this order: a posting id already tracked returns that job (existing: true; nothing added); a job site the user didn't choose, or one signed out or paused, is refused (refused says why, sites lists the ready ones); the same company and title as a job already applied to is refused as a repost; posted pay below the user's minimum is saved as skipped (rule: pay_floor). Parameters: title and company are required; company is the employer, not a staffing firm, when you can tell. Pass external_id whenever the site shows the posting's id: it catches reposts. url or source tells which job site it came from; the URL just read by freeapply_fetch_posting keeps its keywords. pay_min and pay_max feed the pay floor; fit_score is 0 to 100, as the apply procedure scores it. Returns: {job_id, existing, status, rule, earlier}. earlier lists up to 20 other jobs at the same company as {id, title, company, status, same_title}; if an applied one is clearly the same role under another title, mark this one skipped with freeapply_update_job. Errors: a missing title or company. |
| freeapply_check_textA | Checks a cover letter or free-text answer against what the user really has, and turns a passing cover letter into a PDF to upload. Unlike freeapply_update_job, which only records the result, it is where every piece of prose is checked before you type or attach it. Use it before typing any written answer or attaching any letter, and again after each fix. Not for short fields taken straight from the settings, such as a name, a date or yes/no. Behavior: flags every skill, tool, number or claim that the résumé, settings, highlights and saved answers don't support. Without save it changes nothing. With save a passing letter becomes a PDF in the documents folder, kept with the job; a failing one is never saved, saving again replaces the file, and a job already applied to is refused. Parameters: kind cover_letter also checks the user's chosen length, their sign-off, leftover placeholders and that the company is named; answer, the default, checks facts only. job_id adds the posting's keywords, counts numbers from the posting and the user's answers for that job as facts, and is needed for save. company names the employer when there is no job_id. For a letter, pass save from the first call so a passing letter is checked and saved at once. Returns: {ok, problems}, problems being plain sentences to fix, remove or ask the user about. With job_id also keywords {used, unused}: the posting's supported skills this text uses, and those it could still use. With save also file {path, name, bytes}, or a note why it wasn't saved. Errors: save without kind cover_letter and a job_id, or an unknown job_id. If the résumé was never saved, most claims are reported as unsupported. |
| freeapply_user_answersA | Gets or saves the user's own answers to application questions, so you never guess one. Unlike freeapply_get_settings (the user's general details) it holds answers to specific form questions, and unlike freeapply_update_job status needs_info it asks the user nothing new. Use get before retrying a job the user re-queued from the Needs you tab, and save when the user answers a question in this conversation, so later forms can reuse it. Save only the user's own words: saved answers count as facts in freeapply_check_text. Behavior: get is read-only. save replaces an answer saved under the same question; an empty answer removes it. Parameters: action get needs job_id. action save needs label, the question as forms word it (e.g. "Are you willing to relocate?"), and answer, the user's words. Returns: get {job_id, answers, saved_answers}: answers are the {label, answer} pairs the user gave for that job (empty when none), saved_answers maps questions to reusable answers. save {label, saved, removed, saved_answers}. Errors: get without job_id or with an unknown one, save without label, or another action. |
| freeapply_find_site_accountA | Looks up whether the user already made an account on an employer's careers site, and with which email. Unlike freeapply_report_site_problem, which is for job boards such as LinkedIn that signed the user out, it is about an employer's own site. Use it when an application form asks you to sign in or create an account. Not for signing in or up: FreeApply never stores passwords and you never type one. Behavior: read-only. The user records the accounts they make on the dashboard's Needs you tab. Parameters: site is the site's domain or any web address on it, reduced to the domain without www. and matched exactly, so careers.example.com and example.com are different sites. Returns: {domain, email_used, created_at, job_id, note} for a known account, or {domain, account: null}. Known: ask the user to sign in in the browser, then continue in their session. None: record the job with freeapply_update_job status needs_account and the sign-up page as account_url. Errors: a site that isn't a domain or web address. |
| freeapply_clear_to_submitA | Gives the go-ahead for one submit after checking the pace, the user's limits and, in an unattended run, its budgets. Unlike freeapply_update_job, which records the submit afterwards, it comes right before it; recording applied is refused without its clearance. Use it right before every submit, with the job_id. Not early, and not for a job you won't submit now: each clearance counts toward the per-minute pace at once. Behavior: allows at most 3 submissions a minute (or the user's slower setting), keeps the user's daily cap and, for easy_apply, whether the user allows one-click apply. A clearance is for one job, lasts 15 minutes and is used up when freeapply_update_job records applied; asking again for the same job issues a new one. Clearances last only while FreeApply runs. Parameters: job_id gets the clearance; without it you only see the pace. method (default external) matters only for easy_apply, refused while one-click apply is off. run_id, in an unattended run, first checks that run's time and application budgets and the dashboard's Stop button. Returns: {clear, advice, last_minute, limit_per_minute, today, daily_cap}, plus clearance {job_id, expires_at} when clear. clear false: don't submit; prepare the next job and call again later. refused: one-click apply is off; apply on the employer's site or skip the job. stop_run true, with reason: the run must end now; call freeapply_autorun action finish. |
| freeapply_update_jobA | Records your side of an application by setting a tracked job's status. Unlike freeapply_record_outcome (what the employer did) and freeapply_claim_job (adding a job), it changes a job you already claimed. Use it after a submit (applied), when you give up on a job (skipped or failed), and when the user must act: needs_info with the form's questions, needs_account with the sign-up page, blocked by a check you can't pass. Not for employer replies. Behavior: replaces the job's status. Enforced: applied needs a fresh clearance from freeapply_clear_to_submit for this job; cover_text must pass the truthfulness check; a job already applied to only the user can change. needs_info questions go to the Needs you tab and re-queue the job once answered; if the user already answered them all, the call is refused with the answers to use. Parameters: note is one plain sentence the user reads, with no technical terms. Some fields go with one status and are refused with any other: questions (at least one) with needs_info; account_url with needs_account; method, confirmation, resume_path, cover_path and cover_text with applied. The résumé copy and the letter saved by freeapply_check_text are recorded by default; pass the file and letter fields only when you sent something else. Returns: {job_id, status}, and when relevant: already_waiting; questions (each added, duplicate, grouped or already_answered, with its answer) and questions_added; same_account (needs_account: jobs sharing one sign-up card); same_site (blocked: jobs blocked on the same site). Errors: an unknown job_id or a broken rule, saying what is missing. |
| freeapply_report_site_problemA | Tells FreeApply that one of the user's job sites can't be used right now: it signed the user out, or showed its own daily limit. Unlike freeapply_find_site_account, which is about an employer's own careers site, it is for the job sites the user chose in Settings, such as LinkedIn or Indeed. Use it as soon as a chosen job site shows a sign-in page or a daily limit, then keep applying on the ready sites or on company career sites. Never type a password. Behavior: a signed-out site stays unavailable until the user signs in again and confirms it in the dashboard; a limited site is paused until midnight. Meanwhile freeapply_claim_job refuses new jobs from it. Reporting the same problem again changes nothing, and only the user can mark a site ready. Parameters: site is the job site's id as freeapply_status lists it in sites. status is signed_out (a sign-in page, or the site says you're signed out) or limit_reached (the site's own daily limit, e.g. "You reached today's Easy Apply limit"). Returns: {site, status, sites}, where sites lists each chosen site with ready. Errors: a site the user didn't choose. |
| freeapply_autorunA | Starts and finishes unattended (scheduled) runs, and records the schedule. Unlike freeapply_status, which only shows the run state, it changes it; the schedule itself is a scheduled task in the user's AI app. Use start at the beginning of every scheduled run and finish at its end, also when stopping early. Use schedule_created or schedule_removed after you create or delete the scheduled task, so the dashboard shows it. Not in a session the user runs by hand. Behavior: start opens a run only when one may go now; another start while a run is going, or within 10 minutes of its planned end, gets go false. During the run, freeapply_clear_to_submit with the run_id ends it when a budget runs out or the user presses Stop. finish releases the run; finishing a run that already ended is harmless. Parameters: action picks the step. finish needs the run_id from start and takes summary, one line on the run, e.g. "applied 4, needs you 2" (up to 500 characters). Returns: start {go: true, run_id, minutes, max_applications, sites}, or {go: false, reason} (auto-run off, Terms or setup missing, daily cap reached, or another run going); then stop at once, quietly. finish {finished, applied_this_run}, null for a run no longer active. schedule_created and schedule_removed {schedule_created}. Errors: finish without run_id, or another action. |
| freeapply_list_jobsA | Lists the user's tracked jobs, most recent activity first (submitted, else updated, else found). Unlike freeapply_job_stats, which gives totals and rates, it returns the jobs themselves. Use it to find a job_id or to answer questions about particular jobs. Not for adding or changing jobs; that is freeapply_claim_job and freeapply_update_job. Behavior: read-only. Parameters: filters combine. status and outcome match exactly; search finds text in the title, company or location, ignoring case. limit (default 200, at most 2000) and offset (default 0) page through long lists: fewer jobs than limit means the end. Returns: a list of jobs, each with id, title, company, location, work_mode, pay_text, pay_min, pay_max, url, apply_url, fit_score, status, status_note, outcome, outcome_at, source, found_at, updated_at, method, submitted_at, confirmation, resume_path, cover_path and reply_count; empty when nothing matched. |
| freeapply_job_statsA | Summarizes the user's job search in numbers: applications, replies, interviews, offers and rates. Unlike freeapply_list_jobs (individual jobs) and freeapply_status (whether FreeApply can run), it gives totals. Use it to report progress, for example when wrapping up a session. Not for finding a particular job. Behavior: read-only and cheap: counted fresh from the local database on each call, nothing cached. Takes no parameters. Returns: tracked, applied, applied_today, queued, needs_you (jobs waiting on the user), interviews, offers, rejections, acknowledged, response_rate (percent of applications with a real reply, automatic acknowledgements not counted), avg_fit, last_reply_check (when the last Gmail reply check finished), counts by_status, by_outcome and by_method, daily (applications per day), and top_companies, top_titles and top_jobs. |
| freeapply_reply_checkA | Begins and ends a Gmail reply check (the freeapply-replies procedure). Unlike freeapply_record_outcome, which records each email, it frames the check: start gives the plan, finish marks it done. Use start before searching Gmail and finish once every email you found is recorded. Not for recording an email. Behavior: start is read-only and can be repeated. finish sets the last check to now, so the next check searches only newer email: call it only after recording everything you found. Parameters: action start returns the plan: since (search Gmail from this time), gmail (the user's mail action: none, star, label or star_and_label, plus label_name), applied (the jobs applied to: job_id, company, title, submitted_at) and known_message_ids (already recorded: skip them). action finish marks the check done. Returns: start: the plan above. finish: {last_check}. Errors: another action. |
| freeapply_record_outcomeA | Records what an employer did with an application: acknowledged, replied, assessment, interview, rejected or offer. Unlike freeapply_update_job, which records your side (applied, skipped, ...), it is about the employer's response. Use it for each employer email found during a reply check, between freeapply_reply_check start and finish, and when the user tells you about a call or corrects an outcome. Not for your own steps. Behavior: with an email (gmail_message_id) it stores the email and raises the job's outcome only if this email ranks higher than the current one (an interview outranks an acknowledgement); the same gmail_message_id again stores nothing new. Without an email it sets the outcome exactly, whatever its rank, and an empty outcome clears it. Parameters: outcome is required; "" clears it, without an email only. job_id, from the reply-check plan or freeapply_list_jobs, is required without an email; with an email it is optional, but then no outcome changes. The email fields fill the dashboard's Replies tab: gmail_thread_id, company, sender, subject, received_at (ISO 8601), summary (at most 20 words, no personal data beyond what is needed) and mail_action (starred, labeled:, starred+labeled: or none). Returns: with an email {recorded, kind, job_id, outcome}, where outcome is the job's outcome afterwards and both are null without job_id; without one {job_id, outcome}. Errors: an unknown job_id, no job_id and no email, or an empty outcome with an email. |
| freeapply_shared_dataA | Shows or sends the data the user chose to share with the FreeApply server. Unlike freeapply_get_settings, which shows the sharing choices, it shows the exact data those choices send. Use preview when the user asks what is shared, and sync only when the user asks to send now; it also runs on its own every 12 hours. Not for changing the choices: the user does that in the dashboard (Settings, Data sharing). Behavior: preview is read-only and sends nothing. sync sends over the internet only what the current choices allow and can't be undone from here; the user can delete their shared data in the dashboard. Parameters: action preview is safe to call any time; action sync sends now and is refused moments after the last sync. Returns: preview: the exact requests that would be sent: analytics_request (anonymous usage and job-market data) and the talent-pool request, only if the user joined, secrets hidden. sync: {sent, result}, or {sent: false, reason}: the Terms not accepted, a sync moments ago, or the server unreachable (the automatic sync retries later). Errors: another action. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| freeapply-apply | Find jobs that match the user's FreeApply settings (any role or field) and apply on the employer's site or job board, logging every job and application. |
| freeapply-replies | Check the user's Gmail for employer replies to tracked applications, record each one, and star or label them as the user chose in Settings. |
| freeapply-setup | First-run setup for FreeApply and the check to run at the start of any job-search session. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 18 tools
Every tool carries an explicit 'Unlike X, which does Y' clause that draws sharp boundaries between superficially similar tools (update_job vs record_outcome vs claim_job; report_site_problem vs find_site_account; get_settings vs user_answers vs status). The read-only reporting tools (status, get_settings, job_stats, list_jobs) are clearly separated by what each returns, so an agent can pick correctly without guessing.
All 18 tools share the freeapply_ prefix and most follow a verb_noun pattern (get_settings, fetch_posting, claim_job, report_site_problem, clear_to_submit). A handful are noun-only (status, user_answers, job_stats, autorun, shared_data), which is a minor deviation rather than a different convention, and all remain readable and predictable.
18 tools is slightly heavy but each maps to a distinct step in the apply/check-replies lifecycle (setup, settings, postings, claim, text check, submit clearance, status updates, site issues, replies, sharing). Nothing looks redundant, though a few convenience tools could arguably be folded into larger ones.
The surface covers the full workflow end to end: setup/status, settings read-write, posting fetch, job claim/update/list/stats, truthfulness checking, saved answers, site accounts and problems, submit pacing, unattended runs, reply checks and outcomes, and data sharing. Minor gaps remain — no way to delete or purge a tracked job, and no single-job getter (only paged list_jobs) — but these are workaroundable.