Skip to content

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

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:

  1. Generate a token:

    openssl rand -hex 32
    

  2. Set the MCP_TOKEN environment variable before starting the web server:

    MCP_TOKEN=<your-token> make run
    

On your server, add it to your .env file (e.g., /opt/gogetem/.env if deployed there):

MCP_TOKEN=<your-token>
If using systemd, the unit already loads this file. Restart the service:
sudo systemctl restart gogetem-web

  1. 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:

make build-mcp

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)