GoGetEm MCP Server¶
The MCP server exposes your job search database over the Model Context Protocol — browsing, searching, saving, scoring, and managing your match profile through any MCP-compatible client.
Compatible clients¶
Any application that speaks MCP can connect. Tested with:
- Claude Code (CLI) — used during development, setup examples below
- Claude Desktop — Anthropic's desktop app, supports both stdio and HTTP MCP servers
- Cursor, Windsurf, VS Code + Copilot — IDE-based clients with MCP support
- Any MCP client — the server implements the standard MCP protocol over HTTP (JSON-RPC) or stdio transport. See the MCP client directory for more options.
The setup examples below use Claude Code, but the connection details (URL, token, env vars) apply to any client — adapt the config format to match your client's MCP configuration.
Two ways to connect¶
1. HTTP endpoint (recommended for remote access)¶
The web server embeds the MCP server at /api/mcp. This is the best option when the database lives on a different machine from where you run your MCP client.
Server setup:
-
Generate a token:
-
Set the
MCP_TOKENenvironment variable before starting the web server:
On your server, add it to your .env file (e.g., /opt/gogetem/.env if deployed there):
- Verify it's working:
# Should return 401 curl -s -o /dev/null -w "%{http_code}" -X POST http://localhost:8080/api/mcp # Should return 200 with MCP initialize response curl -X POST http://localhost:8080/api/mcp \ -H "Authorization: Bearer <your-token>" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
Client setup (Claude Code example):
The project's .mcp.json uses environment variable interpolation so you never put secrets in the file. Other MCP clients use a similar config — adapt the URL, token, and transport type to your client's format.
{
"mcpServers": {
"gogetem": {
"type": "http",
"url": "${GOGETEM_MCP_URL}/api/mcp",
"headers": {
"Authorization": "Bearer ${GOGETEM_MCP_TOKEN}"
}
}
}
}
Set the two env vars before launching your MCP client:
# In your shell profile (~/.zshrc, ~/.bashrc, etc.)
export GOGETEM_MCP_URL="http://<host>:8080"
export GOGETEM_MCP_TOKEN="<your-token>"
Replace <host> with:
- localhost if running locally
- The Pi's Tailscale IP (e.g., 100.x.y.z) for remote access
- A hostname if you've configured DNS
The .mcp.json file is checked into the repo — it contains no secrets because it uses ${...} env var references. Claude Code resolves these at startup. Other clients may need the URL and token configured differently — refer to your client's MCP documentation.
2. Stdio transport (local only)¶
If your MCP client runs on the same machine as the database, use the standalone MCP binary directly:
Configure in your MCP client. For Claude Code (.claude/settings.json):
{
"mcpServers": {
"gogetem": {
"type": "stdio",
"command": "/path/to/bin/gogetem-mcp",
"env": {
"DB_PATH": "/path/to/db/jobs.sqlite3",
"PROFILE_PATH": "/path/to/personal/profile.yaml"
}
}
}
}
Note: PROFILE_PATH is only used for first-boot migration. Once the profile is imported to the DB, it's loaded from there. You can still set it to point at a YAML for the migration path.
Available tools¶
Browsing¶
| Tool | Description | Key parameters |
|---|---|---|
list_jobs |
Browse jobs with filters and pagination | query, site, remote, work_model, page, page_size |
get_job |
Get full details for a single job | id |
search_jobs |
Full-text search across title, company, location, description, search terms | query, limit |
Scrape history¶
| Tool | Description | Key parameters |
|---|---|---|
list_scrape_runs |
List recent scrape runs | limit (default 10) |
get_scrape_run |
Get details for a single run | run_id |
get_dashboard |
Aggregate stats: totals, last scrape, recent runs, data quality metrics | none |
Data quality¶
| Tool | Description | Key parameters |
|---|---|---|
list_duplicate_groups |
Groups of near-duplicate jobs (same company + title) | limit (default 20) |
Saving¶
| Tool | Description | Key parameters |
|---|---|---|
save_job |
Save/shortlist a job | id, notes (optional) |
unsave_job |
Remove a job from saved list | id |
Scoring¶
| Tool | Description | Key parameters |
|---|---|---|
get_match_profile |
View the active match profile | none |
auto_score_jobs |
Heuristic-score all unscored jobs in bulk (see CLAUDE.md for algorithm) | batch_size (default 50, max 200) |
score_job |
Persist a manual score (0-100) with reasoning — overrides auto-scores | job_id, score, reasoning |
list_unscored_jobs |
Jobs not yet scored against the current profile version | limit (default 20) |
list_top_matches |
Highest-scored jobs with reasoning | limit (default 20) |
Profile management¶
| Tool | Description | Key parameters |
|---|---|---|
update_match_profile |
Update the match profile with new JSON. Saves a new version, triggers re-scoring. | profile (full profile JSON object) |
get_profile_history |
List past profile versions with timestamps | limit (default 10) |
Auto-scoring: The web server automatically scores all unscored jobs on startup. Use auto_score_jobs to re-run scoring after new jobs arrive. Auto-scored jobs have reasoning prefixed with [auto-v2]. Use score_job to override any auto-score with Claude's assessment — the upsert replaces the previous score.
Profile updates: When you call update_match_profile, the server saves a new version to the DB, swaps in the new profile/scorer at runtime (no restart needed), and kicks off re-scoring in the background. Use get_match_profile to see the current profile and get_profile_history to see past versions.
Example prompts¶
Once connected, try asking your AI assistant:
- "Show me the latest remote Go jobs"
- "List hybrid jobs in Hannover"
- "Search for backend engineering roles at startups"
- "Auto-score all unscored jobs"
- "Score the top 10 unscored jobs against my profile"
- "Save job 42 with a note about the interesting tech stack"
- "How did the last scrape run go?"
- "Give me a dashboard summary"
- "Show me duplicate job listings"
- "Show me my current match profile"
- "Update my profile to add Rust to my strong skills"
- "Show me my profile version history"
Troubleshooting¶
"No tools available" in your MCP client
- Check that your MCP config has the correct URL/token
- Restart your client after modifying the MCP configuration
- For Claude Code specifically: check .mcp.json exists and restart
401 Unauthorized
- Verify the token in your client config matches the MCP_TOKEN on the server
- Check the Authorization header format: Bearer <token> (capital B, one space)
Connection refused
- Confirm the web server is running: sudo systemctl status gogetem-web
- Check the IP/port — default is 0.0.0.0:8080
- If using Tailscale, verify both machines are connected: tailscale status
Scoring tools return "no profile loaded"
- The profile is now stored in the SQLite database. On first boot, it's auto-imported from the YAML file at PROFILE_PATH.
- If you see this error, no profile has been imported yet. Either:
- Place a profile.yaml at the PROFILE_PATH location and restart the server
- Use update_match_profile to save a profile directly to the DB
- Use the /settings web page to paste in profile JSON
- Check web server logs for the "profile loaded from DB" or "profile not loaded" message at startup
Timeout errors
- The web server has a 10-second write timeout — this is fine for all MCP tools since they're simple DB queries
- If using SSE mode (non-JSON), switch to JSON responses by ensuring the server uses JSONResponse: true (this is the default)