Relay
An evidence desk: four MCP tools and a React UI share one matcher so each skill hit is a quote, not a hiring score.
MCP · Python · FastAPI · React · TypeScript
The problem
An agent or a UI that cites a skill in a job text still needs the sentence it came from. I wanted that quote from one tested service, not a model deciding whether someone qualifies.
My contribution
I connected a React interface and MCP clients to the same Python review service. I implemented source normalization, token-aware matching, duplicate retention and portable exports. The MCP transport uses the official Python SDK. This is not a job-search product.
Skills this work used
| Skill | Where it was used |
|---|---|
| Python and FastAPI | One evidence service: normalize text, match tokens, keep duplicate wording. |
| MCP | Four read-only tools that call the same matcher as the web UI. Official Python SDK. |
| React and TypeScript | Paste or sample-board review, quoted lines and export. No eligibility score. |
| Tests | pytest in CI for API validation, duplicate wording and MCP transports. |
Try it step by step
- Paste a public job description, or load the sample Arbeitnow page to see the matcher work.
- Add a listing to the review queue. Enter the skills you want to look for.
- Select Review evidence. Read each matching quotation in its original context: a mention is not necessarily a requirement.
- Compare duplicate versions without discarding changed text.
- Export the review or workspace JSON. Saving on this device is optional; do not paste a CV or private correspondence.
What depends on what
| Component | Depends on | Responsibility |
|---|---|---|
| React interface | FastAPI JSON endpoints | Search, review queue, quote display and export. |
| Public-board reader | Arbeitnow public API | A bounded latest-page snapshot, not a search of every employer. |
| Evidence service | Normalized text, explicit aliases and content hashes | Source quotations and duplicate versions; no LLM, eligibility score or application submission. |
| MCP tools | Official Python MCP SDK and the same evidence service | The browser workflow can also be called from an MCP client. |
| Review state | Browser memory; optional device-local storage and JSON files | The job service does not persist reviews in a database. |
| Historical safety lab | Separate SQLite-backed fixture workflow | An older synthetic experiment, not the storage layer for job reviews. |
How the data was organised
There is no job-review database on the public tool. Records live in the HTTP request and in the browser. SQLite belongs only to an older synthetic safety lab, not to these reviews.
| Record | Depends on | Responsibility |
|---|---|---|
| Job listing | Arbeitnow snapshot or pasted public text | The source description kept next to each mention. |
| Review | Chosen skills plus matched quotations | A working set in browser memory; saving on this device is optional. |
| Quoted evidence | Normalized text, aliases and a content hash | Keeps original wording and duplicate versions; not an eligibility score. |
| Export file | JSON written by the visitor | Portable copy. The job service does not persist reviews in PostgreSQL. |
Implementation, step by step
- Define the job, review and quoted-evidence data models.
- Normalize input and validate URLs, sizes and fields before reviewing it.
- Match whole tokens and explicit aliases; keep all changed duplicate descriptions.
- Expose the same functions through HTTP and MCP instead of maintaining two implementations.
- Test API validation, source retention, transport behaviour and search regressions; then exercise the browser workflow.
Run the public code locally
# Backend (inside backend, with a Python virtual environment)
pip install -r requirements.txt
python -m pytest -q
python -m uvicorn app.main:app --host 127.0.0.1 --port 8000
# Frontend (inside frontend, in a second terminal)
npm ci
npm run devUse the repository README for environment setup and supported versions.
Limits and unfinished work
This is not a job-search product and not a recruiter ATS. Arbeitnow is a bounded demo snapshot; paste is the path a reviewer will actually use. Matching is literal, not semantic recall: ordinary English such as “react” or “go” can still hit. An agent that calls these tools can still summarise; Relay does not score eligibility or prove a vacancy is open.