MCP: stateless job-seeker tools + streamable HTTP transport - #4
Open
miao4ai wants to merge 1 commit into
Open
Conversation
Add search_jobs / recommend_jobs / match_resume_to_job so a chat app (charbit's recruiter skill) can search and recommend jobs for a user from resume text. Nothing is stored or indexed per call, so one shared instance serves many users. RECRUITER_MCP_TRANSPORT=http serves streamable HTTP (stateless, JSON responses) for a server-side caller; stdio stays the default for Claude Desktop / Cursor. The card tools return a JSON string: the SDK splits a list result into one text block per item, and the connector reads the first block as one array. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Lets a chat app (charbit's recruiter skill) use Open Recruiter as its job search / recommendation engine over MCP.
New job-seeker tools — stateless: the resume arrives as text, nothing is stored or indexed, so one shared instance serves many users without their data landing in this database.
search_jobs(query?, location?, top_k=10)"remote"matches remote jobs)recommend_jobs(resume_text, top_k=5)fields.score0–1;[]without a Voyage keymatch_resume_to_job(resume_text, job_id)The existing six recruiter tools are unchanged.
Streamable HTTP transport —
RECRUITER_MCP_TRANSPORT=http(RECRUITER_MCP_HOST/PORT, default127.0.0.1:8765, endpoint/mcp). stdio stays the default, so Claude Desktop / Cursor wiring is untouched.Two interop decisions worth knowing
notifications/initialized, and never opens an SSE stream.stateless_http=Trueis what letstools/callfollowinitializedirectly;json_response=Trueavoids SSE framing.listresult into one text block per item; the connector reads the first text block as one array of{id, title, subtitle, price, detail, url, fields}cards (fieldsvalues are strings — decoded asmap[string]string). Same contract as charbit'smcp-suumopartner service.Also:
Candidate.embed_text()ignoresraw_resume_text, so the transient candidate carries the resume inresume_summary— otherwise the embedding is empty and search returns nothing.Verification
product/tests/harness/test_mcp_jobseeker.py— 6 passed. Full harness: 284 passed.initialize→ plainapplication/json;tools/call search_jobs→ one text block holding the card array,isError: false; string"top_k":"3"coerced to int;recommend_jobswithout a Voyage key →[].uv.lockintentionally not touched (per CLAUDE.md).🤖 Generated with Claude Code