An AI-native, MCP-first career copilot. Local-first, zero API keys.
Crosswalk has 20 well-named tools with complete input schemas and descriptions. Naming follows verb_noun convention (setup_profile, add_resume, fetch_jobs, score_fit, tailor_resume, draft_application, submit_application, set_status, add_note, list_pipeline, schedule_workflow, run_workflow, list_workflows, delete_workflow, preview_application, apply_application). All tools have descriptions (avg ~100 chars, within baseline 34-392). Input schemas are properly typed with required fields marked. However, output schemas are NOT documented, the code returns JSON.stringify(result) with no schema specification, forcing LLMs to infer structure. Parameter descriptions are minimal (e.g., 'Resume ID to delete' lacks context on format or lifecycle). Error handling is absent, no recovery guidance, no categorization of retryable vs fatal errors. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk levels (WRITE, DESTRUCTIVE, READ_ONLY). Missing dependency hints (e.g., 'Call setup_profile first' or 'Requires resume to exist'). Composition is strong, tools chain well (draft_application uses resumeId, which list_resumes returns). Idempotency unclear for stateful operations like submit_application and set_status.
Append a note to an application (e.g., "recruiter emailed back").
Parse a resume (path or rawText) and store a labeled version.
Open the application's deep link in a headless browser, auto-fill known fields (email/name/phone/resume) from your profile + tailored resume, take a screenshot, and stop. Does NOT submit — review and click Submit yourself. Requires `crosswalk-mcp install-browser` first.
Delete a stored resume by id. Cascades through any applications/events/fit-score cache rows that reference it.
Delete a scheduled workflow by id.
Build a full application "PR" — tailored resume + cover letter + deep link to the form — and persist it. Returns the application id and bundle.
Output schemas not documented. CallToolRequestSchema handler returns JSON.stringify(result) with no schema specification. LLMs cannot infer response structure, forcing them to guess field names and types for downstream tool calls.
No error handling or recovery guidance. Tools return raw errors with no actionable next steps. E.g., 'Resume not found' should suggest 'Call list_resumes() to see available resumes' or 'Call add_resume() to create one.'
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
Produce a markdown narrative explaining fit, strengths, gaps, and positioning.
Fetch live jobs across configured ATSs with filters (title, location, H-1B, etc).
List your application pipeline with company + job context. Filter by status if desired.
List all stored resume versions.
List all scheduled workflows.
Open the application's deep link in a headless browser and return a screenshot + visible form fields. Requires `crosswalk-mcp install-browser` first.
Manually run a previously scheduled workflow now.
Schedule a recurring non-sampling workflow (e.g., refresh job cache every Monday). Run via cron + `crosswalk-mcp run-scheduled`.
Score a job against a stored resume. Returns numeric score + structured strengths/gaps.
Change an application status (draft, submitted, interviewing, rejected, offer).
Store a structured profile from a free-form description of the user.
Mark an application as submitted (after the user clicks "Apply" in their browser).
Tailor your stored resume for a specific job. Returns markdown by default; optional DOCX (base64) or print-ready HTML on request.
Best-fit jobs for a stored resume, from cached fit scores. Optionally scores recent unscored jobs first (one model call each).
No tool annotations despite clear risk levels. Tools marked WRITE, DESTRUCTIVE, READ_ONLY in metadata but not exposed via readOnlyHint, destructiveHint, idempotentHint in schema. LLMs cannot distinguish safe from dangerous operations.
Parameter descriptions lack context and constraints. E.g., 'Resume ID to delete' does not explain format, lifecycle, or cascade behavior. 'Cron expression' lacks validation rules. LLMs cannot validate inputs before calling.
No pagination or result limits documented. fetch_jobs and list_pipeline may return unbounded results. No limit, offset, or cursor parameters visible. Large result sets will exhaust context windows.