Add application tracker REST and MCP parity

Add comprehensive Application Tracker REST and MCP coverage, document the MCP workflow, add Markdown/ActionLint checks, bump the release version, and fill all extracted translations.
This commit is contained in:
Amruth Pillai
2026-07-07 17:02:39 +02:00
committed by GitHub
parent dfc5559625
commit 46afc65cc6
80 changed files with 9938 additions and 809 deletions
@@ -0,0 +1,215 @@
# Application Tracker REST and MCP Parity
## Status
Approved design for implementation planning. Campaign tracking is out of scope because the current app, database schema, changelog, guides, and tests do not ship a campaign field or campaign endpoint.
## Goal
Make every shipped Application Tracker capability available outside the web UI through:
- the public REST/OpenAPI surface under `/api/openapi`;
- Reactive Resume MCP tools for agent-only workflows;
- the bundled `resume-builder` skill, so agents know the application tracker tools exist.
The result should let a user track applications through an MCP client alone: create records, import existing rows, move stages, log notes, manage contacts and follow-ups, attach sent documents, run AI copilot actions, and inspect pipeline health.
## Current Shipped Capabilities
The current application tracker supports:
- application records with company, role, location, salary, source, source URL, job description, notes, tags, status, archive state, linked resume, sent resume PDF, cover-letter PDF, contacts, follow-up date/note, applied date, and activity timeline;
- fixed stages: `saved`, `applied`, `screening`, `interview`, `offer`, `rejected`;
- create, edit, archive/unarchive, mark rejected, move stage, delete;
- board, table, search, sort, tag filter, archived toggle, and command-palette open/create shortcuts;
- bulk table actions: move stage, add tag, archive, delete;
- CSV import with header mapping and a 500-row cap;
- insights from aggregate stage/source counts plus client-derived weekly application velocity;
- timeline notes and automatic created/stage activity entries;
- contacts embedded on each application;
- Application Copilot actions: job-posting autofill, resume match score, tailored resume copy, cover-letter draft, follow-up draft;
- PDF upload/remove for resume file and cover letter through the generic storage route.
## Existing API Coverage
The app already routes most behavior through `packages/api/src/features/applications`:
- `list`, `getById`, `create`, `import`, `update`, `addNote`, `delete`;
- `bulkUpdate`, `bulkDelete`, `stats`, `tags`;
- `ai.autofill`, `ai.matchScore`, `ai.draftMessage`, `ai.tailorResume`.
These procedures are already authenticated and user-scoped through `protectedProcedure` and `applicationService`. The implementation should reuse them instead of adding a parallel controller or new business layer.
## REST Design
Keep the existing application procedures and improve parity with the public OpenAPI surface.
### Public Application Endpoints
Existing endpoints remain:
- `GET /applications`
- `GET /applications/{id}`
- `POST /applications`
- `POST /applications/import`
- `PUT /applications/{id}`
- `POST /applications/{id}/notes`
- `DELETE /applications/{id}`
- `POST /applications/bulk-update`
- `POST /applications/bulk-delete`
- `GET /applications/stats`
- `GET /applications/tags`
- `POST /applications/ai/autofill`
- `POST /applications/{id}/ai/match-score`
- `POST /applications/{id}/ai/draft-message`
- `POST /applications/{id}/ai/tailor-resume`
Add public document endpoints under the Applications tag:
- `POST /applications/{id}/documents/{kind}` where `kind` is `resume` or `cover-letter`.
- Accept a PDF file via OpenAPI file upload.
- Store through the existing storage service.
- Update only the matching application fields:
- resume: `resumeFileUrl`, `resumeFileName`;
- cover letter: `coverLetterUrl`, `coverLetterName`.
- Return the updated application.
- `DELETE /applications/{id}/documents/{kind}`.
- Delete the owned storage object best-effort.
- Clear only the matching application fields.
- Return the updated application.
This makes the document upload/remove UI available through public REST without exposing the generic storage route, which remains tagged `Internal` because it also serves profile-picture use cases.
### REST Behavior Details
- Use existing ownership checks: every application mutation must be scoped by `userId`.
- Reject non-PDF document uploads, matching the UI.
- Keep file size at the existing storage limit: 10MB.
- Preserve existing delete cleanup for uploaded documents when an application is deleted.
- Do not add server-side search/sort endpoints for board/table parity. The UI derives search and sort from `list`, and external clients can do the same. `list` already exposes status, tags, and archive filtering.
- Do not add campaign fields or endpoints.
- Regenerate or update `docs/spec.json` so the public API reference includes all application endpoints.
## MCP Design
Add application tools to `packages/mcp` using the existing metadata pattern:
- add names to `MCP_TOOL_NAME`;
- add schemas/descriptions to `TOOL_META`;
- add behavior hints to `TOOL_ANNOTATIONS`;
- register handlers in `registerTools`;
- let `buildMcpServerCard` derive tool entries from `TOOL_META`;
- add focused tests so tool registration, annotations, and server card stay synchronized.
All MCP handlers should call the injected in-process oRPC `RouterClient`. They should not import database code or reimplement ownership checks.
### MCP Tools
Read/discovery:
- `list_applications`: list applications, with optional `status`, `tags`, and `includeArchived`.
- `read_application`: read one full application by ID.
- `list_application_tags`: list distinct tags.
- `get_application_stats`: return aggregate stage/source counts.
Write:
- `create_application`: create an application.
- `update_application`: update editable fields, including stage, archive state, contacts, follow-up, tags, linked resume, source URL, job description, notes, and document URLs.
- `add_application_note`: append a timeline note.
- `delete_application`: permanently delete one application.
- `bulk_update_applications`: move, archive/unarchive, or add tags to multiple applications.
- `bulk_delete_applications`: permanently delete multiple applications.
- `import_applications`: bulk-create parsed application rows, matching the REST `import` shape.
- `attach_application_document`: attach a sent resume or cover letter PDF.
- `remove_application_document`: remove a sent resume or cover letter PDF.
AI:
- `autofill_application_from_job`: extract company, role, location, salary, and job description from a job posting URL or pasted job description.
- `score_application_match`: score the linked resume against the job description and persist match metadata.
- `tailor_resume_for_application`: create and link a tailored resume copy.
- `draft_application_message`: draft either a cover letter or follow-up message.
### MCP Attachment Input
`attach_application_document` should support agent-only use. The tool should accept:
- `id`;
- `kind`: `resume` or `cover-letter`;
- `fileName`;
- `contentType`: `application/pdf`;
- `dataBase64`: PDF bytes encoded as base64.
The handler can decode the base64 and call the same shared application-document service used by the public REST file upload. This avoids forcing MCP clients to provide browser `File` objects while still giving agents the same document capability as the UI.
### MCP Output Shape
Prefer JSON text outputs for data-bearing tools. Human-readable success strings are fine for destructive/simple tools only when no structured data is useful. For create/update/read/list/stats/AI tools, return JSON so agents can chain calls reliably.
### Tool Annotations
- Read tools: read-only, idempotent, non-destructive.
- AI generation tools:
- `autofill_application_from_job` is read-only but non-idempotent if it fetches a URL or calls AI.
- `draft_application_message` is read-only but non-idempotent.
- `score_application_match` and `tailor_resume_for_application` are write, non-idempotent.
- Delete tools are destructive.
- `update_application`, `bulk_update_applications`, and document remove are write/idempotent when the same input repeats, except tag append remains effectively idempotent because the service de-duplicates tags.
- `create_application`, `import_applications`, note append, and document attach are write/non-idempotent.
- `openWorldHint` should be `false` for closed account data tools and `true` only for job-posting autofill because it can fetch an external URL.
## Skill Update
Update `skills/resume-builder/SKILL.md` in place.
Add concise guidance that Reactive Resume MCP can manage applications as well as resumes. The skill should tell agents:
- use application tools when the user wants to track job applications, import a spreadsheet, move an opportunity through stages, add notes/contacts/follow-ups, attach sent documents, or use Application Copilot;
- use `list_applications` before acting on existing records;
- use `create_application` or `import_applications` for new records;
- use `tailor_resume_for_application` after a linked resume and job description exist;
- review AI-generated cover letters and follow-ups before sending.
Do not turn the skill into a full API reference. Keep it short and point agents at MCP tools by name.
## Documentation Updates
Update:
- `docs/guides/using-the-mcp-server.mdx`: add Application Tracker tools, examples, and troubleshooting notes.
- `docs/use-cases/api-mcp-resume-automation.mdx`: expand scope from resume-only automation to resume plus application tracking.
- `docs/spec.json`: refresh the public OpenAPI spec so docs show application routes.
The existing job application and CSV guides already describe the UI behavior accurately and should not need broad rewrites.
## Testing Plan
Focused tests:
- API/service tests for attaching/removing resume and cover-letter documents, including ownership and storage cleanup.
- DTO/router tests for application document upload constraints if the route logic is not already covered through service tests.
- MCP tests that:
- every `MCP_TOOL_NAME` has metadata and annotations;
- server card includes the new tools;
- `registerTools` registers application tools;
- one read handler and one write handler call the expected oRPC client procedure;
- base64 document attachment rejects non-PDF input.
Validation commands:
- `pnpm --filter @reactive-resume/api test`
- `pnpm --filter @reactive-resume/mcp test`
- `pnpm --filter @reactive-resume/api typecheck`
- `pnpm --filter @reactive-resume/mcp typecheck`
- `pnpm exec turbo boundaries`
- a focused Biome check on touched files; use a non-mutating check first unless formatting edits are intentionally being applied.
## Non-Goals
- Custom stages.
- Campaign tracking.
- Server-side board/search/sort endpoints.
- A standalone application schema resource in MCP.
- New dependencies.
- Refactoring the application tracker UI.