{
  "markdown": "# grad-agent\n\n<!-- mcp-name: io.github.i-ninte/grad-agent -->\n\nAn autonomous MCP agent that helps you apply to fully funded MS and PhD programs.\n\n**Discover and draft**\n\n- Discovers professors on arXiv in your research areas, or deadline-driven per program (`run_program_batch`)\n- Resolves each professor's identity by anchoring on the trigger paper's canonical Semantic Scholar authorId, not the name string — name collisions like \"Wei Zhang\" are structurally impossible to confuse\n- Refuses to draft when identity cannot be anchored; the specific mismatch (e.g. `identity ambiguous: 2 comparable candidates, h=40 vs h=38`) is persisted to a `skipped` sheet for audit\n- Verifies each candidate is actually faculty (h-index and paper-count gates)\n- Filters by region (`target_regions: [US, Canada]` in your profile; keyword table + homepage TLD + LLM fallback)\n- Scrapes their lab page for a recruiting signal + email address\n- Matches them to your strongest shipped project (tag overlap + TF-IDF semantic layer + learned response-rate bias)\n- Drafts a specific, fact-checked cold email: Claude Haiku writes a hook spanning the prof's recent papers, then a second call verifies every claim against the abstracts and rewrites anything unsupported\n- Scores each draft 1 to 10 for fit, with a one-line reason, so you can triage in seconds\n- **Freshness warnings** on every draft: cross-checks the S2 affiliation against the prof's live homepage (flags `MISMATCH` if they may have moved labs) and flags researchers who have not published in 2+ years\n\n**Learn and follow through**\n\n- Detects professor replies via read-only IMAP and tags the log automatically\n- Learns from outcomes: projects that earn replies rank up in future matching (`outcome_report` shows what works)\n- Drafts follow-up nudges for profs silent 10+ days; never nudges the same prof twice\n- Generates an interview prep one-pager when a prof replies: their papers summarised, likely questions, your talking points\n\n**Track everything**\n\n- Compiles per-school SOPs to PDF (LaTeX), versioned so no draft is ever overwritten\n- Tracks outreach, LOR requests, program deadlines, and external scholarships (Mastercard, Commonwealth, Fulbright, Rhodes, and more) in xlsx/yaml\n- Emails every draft to your inbox for review; nothing is ever sent to a professor without you\n\nRuns as a stdio MCP server for Claude Code / Claude Desktop / any MCP client, or as a plain CLI.\n\nPublished on:\n\n- **PyPI**: [`grad-agent`](https://pypi.org/project/grad-agent/)\n- **MCP Registry**: [`io.github.i-ninte/grad-agent`](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.i-ninte/grad-agent)\n\n## Install\n\nPick one:\n\n```bash\n# Recommended for MCP clients (Claude Desktop, Claude Code, etc.)\nuvx grad-agent server      # single-shot, no persistent install\n\n# Persistent CLI install\npipx install grad-agent\n\n# Or in a venv\npython3 -m venv .venv && source .venv/bin/activate\npip install grad-agent\n```\n\n## Set up in 5 minutes\n\n```bash\ngrad-agent init\n```\n\nThis writes:\n\n- `~/.grad-agent/profile.yaml` — your identity, projects, preferences\n- `~/.grad-agent/programs.yaml` — target programs (seeded)\n- `~/.grad-agent/scholarships.yaml` — external scholarships with deadlines (seeded)\n- `~/.grad-agent/.env` — secrets template\n\nFill in `~/.grad-agent/.env`:\n\n```\nANTHROPIC_API_KEY=sk-ant-...\nSMTP_SERVER=smtp.gmail.com        # presets for Outlook/Yahoo/Zoho in the template\nSMTP_PORT=587\nSMTP_USERNAME=you@gmail.com\nSMTP_PASSWORD=<gmail app password>\nSMTP_FROM=you@gmail.com\n# Optional:\nS2_API_KEY=                       # free Semantic Scholar key, dedicated rate limits\n                                  # (client-side throttle already enforces >=1.1s between requests)\nIMAP_SERVER=imap.gmail.com        # read-only reply detection; defaults to SMTP creds\nGITHUB_USERNAME=your-gh\nGITHUB_TOKEN=github_pat_...\nHF_USERNAME=your-hf\n```\n\nFill in the important bits of `~/.grad-agent/profile.yaml`:\n\n- `name`, `identity_line`, `portfolio`\n- `cv_path`, `transcript_path` (absolute paths)\n- `degree_status: bachelors | masters` (drives PhD eligibility gating)\n- `target_term`, `target_degree`\n- `research_areas: [nlp, ai4health, ...]`\n- `target_regions: [US, Canada]` — only draft for profs in these regions (empty = anywhere)\n- `seed_projects:` 3 to 10 flagship projects with `name`, `pitch`, `link`, `tags`\n\nProfile edits apply immediately, even while a long-running MCP session is open.\n\nThen:\n\n```bash\ngrad-agent sync        # scan projects (GitHub + HF + local)\ngrad-agent run         # one batch, drafts land in your inbox\n```\n\n## Register with Claude Code\n\nThree commands, in order:\n\n```bash\npipx install grad-agent\npipx ensurepath                              # macOS/Linux: opens ~/.local/bin on PATH\n                                             # Windows: opens %USERPROFILE%\\.local\\bin on PATH\nclaude mcp add grad-agent grad-agent server\n```\n\nOn Windows you may need to open a new PowerShell or Terminal window after\n`pipx ensurepath` for the PATH change to take effect.\n\nPrefer a zero-install one-liner? Skip `pipx` and use `uvx`:\n\n```bash\nclaude mcp add grad-agent uvx grad-agent server\n```\n\nThen in a **new** Claude Code session:\n\n```\n/mcp\n```\n\nYou should see `grad-agent` connected with ~36 tools. Before it does anything useful, run `grad-agent init` (or `uvx grad-agent init`) and fill in `~/.grad-agent/.env` and `~/.grad-agent/profile.yaml` as described in the setup section above.\n\nIf you skipped `pipx ensurepath`, `grad-agent register-claude` prints an absolute-path variant of the command that works without PATH changes.\n\n## Register with Claude Desktop\n\nEdit `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"grad-agent\": {\n      \"command\": \"uvx\",\n      \"args\": [\"grad-agent\", \"server\"]\n    }\n  }\n}\n```\n\nThe `uvx` command needs no prior install. If you already ran `pipx install grad-agent`,\nyou can use `\"command\": \"grad-agent\", \"args\": [\"server\"]` instead.\n\nAny other MCP client (Cursor, Zed, Windsurf) uses the same manifest shape; just\npoint them at `uvx grad-agent server`.\n\n## Daily autonomous run\n\nThe package ships scheduler templates for all three OSes. `grad-agent schedule`\nemits the right one for your platform:\n\n```bash\ngrad-agent schedule --dest .\n```\n\nThen follow the install instructions the command prints. In case you want them\nup front:\n\n**macOS (launchd):**\n\n```bash\ncp com.gradagent.daily.plist ~/Library/LaunchAgents/\nlaunchctl load ~/Library/LaunchAgents/com.gradagent.daily.plist\n```\n\n**Linux (systemd user timer, fires at 08:00 local):**\n\n```bash\nmkdir -p ~/.config/systemd/user\ncp grad-agent-daily.service grad-agent-daily.timer ~/.config/systemd/user/\nsystemctl --user daemon-reload\nsystemctl --user enable --now grad-agent-daily.timer\n```\n\n**Windows (Task Scheduler):**\n\n```powershell\n# In an elevated PowerShell prompt:\nschtasks /Create /TN \"grad-agent-daily\" /XML .\\grad-agent-daily.xml\n```\n\nOr import the XML via the Task Scheduler GUI (Action → Import Task).\n\nEvery morning: replies auto-detected via IMAP, follow-up nudges drafted for silent profs, 3 identity-verified faculty leads with fit scores (best fit first), hooks fact-checked against paper abstracts, freshness warnings when a prof's S2 record and live homepage disagree, plus program and scholarship deadline warnings — all in one review email. Skipped leads are persisted with the specific mismatch reason (view with `skipped_log_view` or open the `skipped` sheet).\n\n## What each MCP tool does\n\n| Tool | Purpose |\n|---|---|\n| `run_daily_batch(n, area)` | Full pipeline: verify → recruiting → hook + verify → draft → log |\n| `outreach_log_view(limit)` | Show last N rows of the outreach xlsx |\n| `outreach_mark_sent(prof, uni)` | Flag a row as actually sent to the prof |\n| `sync_catalog(source)` | Pull projects from `github`, `hf`, or `local` |\n| `list_projects_in_catalog()` | Show every project the matcher can see |\n| `list_programs()` | Your target programs |\n| `upcoming_deadlines(days)` | Any program deadline in the next N days |\n| `lor_add / lor_outstanding / lor_mark` | Recommendation-letter tracker |\n| `run_program_batch(program_id, n)` | Deadline-driven batch: draft for one program's faculty |\n| `skipped_log_view(limit)` | Audit trail of skipped leads with the specific stage + mismatch reason |\n| `s2_cache_invalidate(query, all)` | Selectively purge Semantic Scholar cache entries by author name or id |\n| `followups_due(days)` | Drafted nudges for profs silent 10+ days |\n| `outreach_mark_followup(prof)` | Record a sent nudge (never nudged twice) |\n| `outreach_mark_response(prof, outcome)` | Tag replies; feeds the matcher's learning loop |\n| `outcome_report()` | Response rates by area and project |\n| `ingest_replies()` | Read-only IMAP scan; auto-tags replies in the log |\n| `interview_prep(prof)` | One-page brief: their papers, likely questions, your talking points |\n| `list_scholarships(region)` | External scholarships filtered by eligibility region |\n| `upcoming_scholarship_deadlines(days)` | Scholarship deadlines approaching |\n| `draft_cold_email(...)` | Manual per-prof draft |\n| `draft_sop(...)` | Compile a Columbia-style SOP PDF (versioned: sop_v1, v2, ...) |\n| `send_draft_to_me(path)` | Ship any draft file to your review inbox |\n| `discover_profs(area)` | arXiv + OpenReview scan (raw candidates, no verification) |\n\nBlog publishing tools (`publish_article`, `update_article`, ...) are gated behind `blog.enabled: true` in `profile.yaml` and are specific to the author's Turso-backed Next.js portfolio. Most users can ignore them.\n\n## What the agent will not do\n\n- Send any email to a professor. Every send is manual, from your Gmail, after you read the draft.\n- Touch your inbox beyond reading. IMAP access is read-only: it never sends, deletes, or marks messages.\n- Fabricate a paper claim. The hook goes through a second Claude call that rejects any claim not present in the abstracts, and rewrites.\n- Email the same professor twice. Deduplication is keyed on the Semantic Scholar authorId, with a name fallback for legacy rows, and follow-ups are marked so no prof is nudged more than once.\n- Draft for the wrong person when two profs share a name. Identity is resolved from the trigger paper's authorId, not the name string; ambiguous cases are refused and logged.\n- Hide why a lead was rejected. Every skip is persisted to the `skipped` sheet in `outreach_log.xlsx` with the stage (identity, faculty-gate, region, dedup, no-papers) and the exact mismatch — not buried in old review emails.\n- Exceed Semantic Scholar's rate limit. Client-side throttle enforces ≥1.1s between requests, with exponential backoff on any 429 or 5xx.\n- Draft for programs you are ineligible for. If your `degree_status` is `bachelors`, PhD programs that require an MSc first are filtered out. Same gate for scholarships outside your eligibility region.\n\n## Requirements\n\n- Python 3.10+\n- macOS, Linux, or Windows (all three tested in CI on 3.10 / 3.11 / 3.12)\n- `pdflatex` on PATH if you want SOP PDFs\n  (macOS: MacTeX; Ubuntu: `texlive-latex-recommended`; Windows: MiKTeX)\n- Anthropic API key\n- Gmail (or another SMTP) for the review-mailer\n\n## Where your data lives\n\nEverything is under `~/.grad-agent/` by default, or `$GRAD_AGENT_HOME` if set:\n\n```\n~/.grad-agent/\n  profile.yaml         identity + preferences (regions, seed projects, ...)\n  programs.yaml        target programs with eligibility rules + deadlines\n  scholarships.yaml    external scholarships with region eligibility + deadlines\n  .env                 secrets (gitignored)\n  data/\n    outreach_log.xlsx  outreach sheet (drafts + outcomes) + skipped sheet (audit trail)\n    lor_log.xlsx       recommendation-letter tracker\n    catalog.json       synced projects (GitHub + HF + local)\n    s2_cache.json      Semantic Scholar lookups (14 day TTL)\n    region_cache.json  LLM-inferred regions for unusual affiliations\n    db.sqlite          drafts + status\n  drafts/              per-school SOP versions + email drafts\n    prep/              interview prep one-pagers\n```\n\n## Contributing\n\nMIT licensed. PRs welcome for: more program templates, non-Gmail SMTP presets, non-arXiv source adapters, and better prof-verification heuristics.\n\n## Author\n\nKwabena Obeng · [i-ninte.github.io/portfolio/](https://i-ninte.github.io/portfolio/)\n",
  "bytes": 12340,
  "sha": "9e9e1be6e6b9aaed4b0e67e7e32fd460c6a29329e1d119a2efc6d0819cce3a3d",
  "repo_slug": "i-ninte/grad-agent",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_i_ninte_grad_agent_72dbeb8f/readme"
}