An assistant will happily write you a cover letter. The problem is not the prose, it is that the prose contains claims. Ask for a letter for a payments role and you get a sentence about scaling a platform to a throughput figure that appears nowhere in your career, because the figure was in the job posting. MCP Resume and Cover Letter exists to make that impossible: you store your facts once, and every output is assembled from those facts and nothing else.
claude mcp add resume -- npx -y @theluckystrike/mcp-resume
Cursor and Claude Desktop take the same server as a config block:
{
"mcpServers": {
"resume": {
"command": "npx",
"args": ["-y", "@theluckystrike/mcp-resume"]
}
}
}
The npm publish is pending, so until it lands use the .mcpb bundle from the latest
release or a clone and build. Per client paths are on the
setup pages. The document engine is shared with
MCP Docx rather than duplicated, so a clone build lists both.
profile_set takes name, email, phone, location, links, a summary, skills, roles with
their bullets, education, certifications and languages. You can dictate it in one message, or point
resume_read at a .docx you already have and let it read the sections back into
the profile shape. Nothing is saved from a read unless you pass save: true, and a role it
could not parse lands in unparsed rather than being dropped quietly.
The obvious worry about a resume generator is that it will not fit. It was probed from both ends. With 300 experience bullets stored, a one-page request kept 78 and dropped 222, filling 390 words against a 392-word budget, in 27 ms. That is the case everybody designs for.
The case that actually happens looked different. Driving the server with the real Claude CLI against a realistic profile, a one-page modern resume targeting a senior backend role used 134 of a 361-word budget and dropped zero bullets. The trimmer never engaged. Against the posting in the same session, coverage came back at 75%, with a required keyword missing entirely.
So the constraint on a real application is not space, it is evidence. The tool that earns its place
is tailor_to_job, which returns the keywords the posting asks for, the ones your profile
already supports, the ones it does not, and a coverage figure. Missing keywords never become skills,
and the response says so in plain words. The right response to 75% is to add a true fact to your
profile, not to let something add a false one to your resume.
This is enforced in code rather than asked for in a prompt, and it has five parts.
Every proof line is a verbatim bullet. The letter quotes what you wrote. It never paraphrases a bullet into a stronger claim.
A highlight you pass is checked first. If your profile does not support it, it is printed as a bracketed prompt saying so, not as a claim.
Every digit run is checked before the file is written. A number that traces neither
to your profile nor to the arguments you passed is a refusal: the tool returns an error and writes
nothing. The job description is deliberately not an allowed source, because the employer's revenue and
headcount are theirs, not yours. Comparison is on whole numbers, so a profile holding
2012 does not license a letter claiming 12. Ten letters were generated against
ten postings stuffed with figures: zero posting numbers reached a letter.
Proof lines are printed under the role that holds them. An audit caught the opposite behaviour and it was the worst defect found in this server: every ranked bullet was printed under the most recent employer's heading, so work done at a previous job read as work done at the current one. That is a fabricated fact from the one tool whose entire promise is that it fabricates none. The letter now emits one heading per employer it quotes.
A bullet with no figure asks you for one. It gets [add: metric]
appended rather than a guessed result. The response lists every bracketed prompt in
fills_required, so the letter tells you what it is short of instead of covering it.
There is no page-layout engine in pure JavaScript and this server does not pretend to have one. It
uses a word budget: a full A4 page at 11pt with 2cm margins holds about 520 words of body text, and a
resume spends roughly a seventh of the page on headings, blank lines and the contact block, which gives
450 words per page, or 540 in the compact style. Contact block, summary, skills, role
headers, education, certifications and languages are counted first; the remainder goes to experience
bullets, highest score first. Every role keeps its first bullet before any role gets a second, so
trimming never leaves a job on the page with nothing under it. The response reports the budget, the
words used, the estimated pages and every bullet dropped, so you see the decision rather than discover
it in Word.
The keyword extractor used to delete every token under three characters as noise, which is correct
until the token is Go, R, C#, ML or UI.
Ties used to break by length, so everywhere outranked kafka. Both are fixed:
short skills are kept, a known skill outranks a longer word of the same frequency, and matching is on
word boundaries, so go does not match Google.
Every pure JavaScript route from Word to PDF needs a native dependency, a headless browser or a cloud
API, and this collection ships none of them. resume_to_html writes semantic HTML with a
print stylesheet: open it and print to PDF. resume_to_markdown covers the application form
that wants plain text in a box.
Free covers the profile, the modern style, markdown and HTML export without limit, three
cover letters per calendar month, and tailoring against postings up to 2,000 characters. Pro ($19 once)
adds all three styles, unlimited letters and tailoring, named profile variants and your own accent
colour. Product page: MCP Resume and Cover Letter. Side by side with the
alternatives: resume comparison. Everything runs locally: your employment
history makes no network request, including for licence checks.
No, and it fails loudly rather than quietly. Every digit run in the letter is checked against your profile and the arguments you passed before the file is written; a number that traces to neither returns an error and writes nothing. A highlight the profile does not support is printed as a bracketed prompt, not as a claim.
Deliberately not. The employer's revenue, headcount and throughput figures are theirs. Ten letters were generated against ten postings full of numbers and none of those numbers reached a letter.
Bullets are ranked by keyword hits and recency and trimmed against a word budget of 450 words per page, 540 in compact style. Every role keeps its first bullet before any role gets a second, and the response names every bullet it dropped. With 300 bullets stored, a one-page request kept 78.
No. Every pure JavaScript route from Word to PDF needs a native dependency or a cloud API, and this collection ships neither. resume_to_html writes HTML with a print stylesheet, so you open it and print to PDF, and resume_to_markdown covers plain-text application boxes.
No. The server reads and writes files on your computer, stores the profile under your data directory, and makes no network request of any kind. Pro keys are Ed25519 signatures verified locally, so even activation is offline.