# Metis

> MCP server from chenlomis/metis.

- **Type:** MCP server
- **Install:** `agentstack add mcp-chenlomis-metis`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [chenlomis](https://agentstack.voostack.com/s/chenlomis)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [chenlomis](https://github.com/chenlomis)
- **Source:** https://github.com/chenlomis/metis

## Install

```sh
agentstack add mcp-chenlomis-metis
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# metis

**Spend your time and energy on roles that matter.**

Metis is an AI-powered career agent that automates the first round of job discovery by screening and ranking new opportunities against your profile, experience, career goals, and deal breakers. It consolidates roles from job alerts and company career pages, compares them to your background, and delivers a personalized scored digest on a schedule you control. It can also track applications and recruiter responses in a spreadsheet, then generate summaries that show how your search is progressing over time.

Think of it as a personal decision agent for high-volume opportunity triage: it helps you decide what deserves attention, what can wait, and what is not worth your time.

Under the hood, it is a compact AI platform: source ingestion, semantic extraction, model routing, evaluation traces, feedback memory, and agent-facing tools all share the same local runtime.

[](LICENSE)
[](https://www.python.org/downloads/)
[](#env-configuration)

## See it in 60 seconds

```bash
metis
```

metis reads new job alerts, scores each role against your profile, and emails a ranked digest. A typical card answers the question you actually care about:

> **Solid Match · 91/100**  
> Why it fits: your 0-to-1 ML platform work maps to the role.  
> Watch-out: first 90 days may lean more onsite than your preference.

---

**Jump to:**
[What it does](#what-it-does) •
[How it works](#how-it-works) •
[Prerequisites](#prerequisites) •
[Quick start](#quick-start) •
[Commands](#commands) •
[Project files](#project-files) •
[Roadmap](#roadmap) •
[Changelog](./CHANGELOG.md) •
[Contributing](#contributing)

---

## What it does

**Profile setup (`metis init`).** This interactive wizard builds your profile by reading your resume and LinkedIn profile, then asking about your aspirations, preferences, and deal breakers. The configured LLM provider uses that context to generate `profile.yaml`, which every future scoring run is evaluated against. You can rerun the wizard or edit the file directly at any time.

On first setup, metis prompts you to connect Gmail or Outlook in the browser so it can read job-alert emails and send digests from your own account. You can also add company career-page sources and enable automated delivery during setup, or reconfigure them later with `metis config access`, `metis sources add`, and `metis schedule set`.

**Email digest (`metis`).** Each run ingests new roles from all configured sources, deduplicates across runs, extracts relevant info, and scores each role through a multi-stage LLM pipeline. The end result is an HTML email digest with scored roles. Every JD gets a categorical verdict and a 0-100 score:

- Solid Match (75+): roles worth prioritizing
- Moderate Match (55-74): roles worth a closer look
- Limited Match (below 55): roles that do not clear the bar

Each evaluation surfaces two strengths and one potential friction point, alongside normalized tags for a quick scan. Roles in the Solid Match and Moderate Match tiers are automatically written to `applications.xlsx` to kickstart application tracking.

**Application tracking (`metis track`).** After you apply, this command scans your inbox for confirmation, rejection, and recruiter emails and updates `applications.xlsx`.

**Progress reporting (`metis summary`).** High-level insights across score distribution, verdict trends, and application rates. Useful both for tracking how your search has evolved and for spotting patterns that help calibrate your profile over time.

**Feedback tuning (`metis feedback`).** After reviewing the digest, app tracker, or overall summary, you can provide generic or specific feedback via this command, such as "seed-stage roles keep scoring high but I always skip them." The system parses it, asks you to confirm the signal, and injects it into future scoring runs as a high-priority calibration note.

---

## How it works

Metis is designed as a modular, stateful pipeline composed of loosely coupled subsystems connected through persistent artifacts rather than in-memory state. Instead of a single monolithic prompt, each stage has a focused responsibility—from profile construction and source ingestion to lightweight pre-screening, structured extraction, deep semantic evaluation, reporting, and feedback incorporation. This separation keeps the system observable, debuggable, and easily extensible.

The runtime operates as a closed-loop agentic workflow. New roles are continuously discovered, deduplicated, evaluated against a structured user profile, surfaced through personalized digests, tracked through recruiting outcomes, and refined using explicit user feedback. Every run persists metadata and intermediate artifacts (`profile.yaml`, `email_sources.yaml`, `runs.jsonl`, `feedback.md`, etc.), enabling reproducibility, debugging, and future iteration without relying on opaque prompt state.

The overall architecture prioritizes modularity, cost-aware inference, privacy-first local state, and continuous learning, allowing individual components to evolve independently as better models, data sources, or evaluation strategies become available.

See [ARCHITECTURE.md](./ARCHITECTURE.md) for data flow diagrams and notes on extending each layer.

### Project files

```
metis/
  cli.py           # CLI parsing and command routing
  pipeline.py      # Digest pipeline orchestration
  score.py         # LLM scoring logic
  extract.py       # Structured JD extraction
  profile.py       # Profile loader
  prompts.py       # Canonical prompt templates
  init_cmd.py      # metis init profile setup wizard
  render.py        # HTML digest renderer
  report_cmd.py    # metis summary report
  feedback.py      # Feedback log and calibration parser
  sources_cmd.py   # metis sources command
  track.py         # metis track email parsing
  xlsx.py          # applications.xlsx read/write
  trace.py         # runs.jsonl telemetry
  schedule_cmd.py  # metis schedule wizard
  state.py         # Dedup state
  theme.py         # Rich and InquirerPy theme
  sources/         # Email and career-page ingestion

emails/            # React Email digest templates
tests/             # pytest suite
profile.template.yaml
.env.example
Makefile
```

The CLI surface is listed in [Commands](#commands).

### Local runtime files

metis keeps personal runtime state under `~/.job_pipeline/`:

| File | Purpose |
|------|---------|
| `profile.yaml` | Your active scoring profile. Edit this when your goals, constraints, or resume story changes. |
| `.env` | Your local config. Most users only edit the LLM provider/key and optional recipient email. |
| `applications.xlsx` | Your application tracker. Solid and Moderate matches land here so you can follow up and report on outcomes. |
| `seen_roles.json` | Dedup memory. This keeps the same role from showing up again and again. |
| `runs.jsonl` | Scoring trace. Useful when a score feels off or `metis summary` needs history. |
| `feedback.md` | Calibration notes from `metis feedback`, injected into future scoring runs. |
| `*_token.json` | Local Gmail/Outlook OAuth tokens created after browser login. |

These files are personal and should not be committed.

---

## Prerequisites

Plan for about **5-10 minutes** to get set up, plus up to 24 hours for the first LinkedIn alert email to arrive if you just created a new alert.

| What | Status | Why | How to get it |
|------|--------|-----|---------------|
| Python 3.11+ | **Required** | Runs the CLI. macOS ships with 3.9, which is too old. | [python.org/downloads](https://www.python.org/downloads/) or `brew install python@3.11` |
| LLM API key | **Required, save for [`.env`](#env-configuration)** | Scores roles against your profile. Without this, metis cannot evaluate jobs. | [Anthropic Console](https://console.anthropic.com) or [OpenAI API keys](https://platform.openai.com/api-keys) |
| Gmail or Outlook account | **Required** | Inbox for job alerts and sender for digests. | Connect in the browser during `metis init`. |
| Job alerts | **Recommended** | Fastest way to get useful roles into metis. LinkedIn saved alerts are the best-tested source. | See [Setting up LinkedIn alerts](#linkedin-alerts). |
| Resume | **Required** | The premise for scoring. The richer the resume, the better the profile. | PDF, DOCX, or TXT anywhere on your machine. |

**Notes**

- macOS and Linux are supported. Windows via WSL2 should work but is untested.
- Node.js 18+ is optional. It enables the polished React Email renderer; without it, metis uses a simpler Python HTML fallback.
- Metis uses a provider-neutral LLM boundary. Anthropic and OpenAI are supported today across `metis`, `metis init`, `metis feedback`, and tracker LLM fallback; Gemini and Grok/XAI are adapter extensions.

### Setting up LinkedIn alerts

metis reads emails that LinkedIn sends you. It does not scrape LinkedIn. You need at least one alert email in your inbox before the first run.

1. Go to [LinkedIn Jobs](https://www.linkedin.com/jobs/) and search for your target role and location
2. Click **Set alert** (the bell icon near the search bar)
3. Set frequency to **Daily**
4. Repeat for each search you want to track

LinkedIn sends one email per saved search per day, listing 5-10 new roles. metis reads all of them.

metis reads emails from these three LinkedIn senders:
- `jobalerts-noreply@linkedin.com` - "Your job alert for X" digests
- `jobs-noreply@linkedin.com` - "Company is hiring" / "Jobs similar to X" recommendations
- `jobs-listings@linkedin.com` - "Jobs you might like" (JYMBII) digests

Both multi-job digests and single-role notifications are supported.

### `.env` configuration

Your personal config lives here:

```bash
~/.job_pipeline/.env
```

For normal setup, this file only needs your chosen LLM provider and API key. Use one of:

```bash
METIS_LLM_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
```

```bash
METIS_LLM_PROVIDER=openai
OPENAI_API_KEY=sk-...
```

Optional knobs:

| Value | Use it when |
|-------|-------------|
| `RECIPIENT_EMAIL` | You want digests sent somewhere other than the connected inbox. |
| `MAX_JOBS_PER_RUN` | You want a different per-run scoring cap. Default: `40`; `0` means no cap. |
| `DEFAULT_LOOKBACK` | You want each run to search farther back than `3d`. |
| `METIS_DEFAULT_RESUME` | `metis apply` should use a specific fallback DOCX when no tailored DOCX exists. |

Open the file in Finder with **Go > Go to Folder...** and paste `~/.job_pipeline`. Browser login handles Gmail/Outlook access during `metis init`, so normal users do not need an app password.

### Application assist

Run `metis apply` to choose evaluated, unapplied roles. Metis automatically uses a
tailored resume when one exists and falls back to the default DOCX configured through
`metis config autofill`. Use `metis apply --lookback 7d --top 5` for the best five
recent roles or `metis apply --latest 10` for the ten newest evaluations. Use
`metis tailor` separately when role-specific wording is worth the additional time and
model cost.

Metis opens external Greenhouse, Lever, and Ashby forms in a visible persistent Chrome
profile, fills deterministic contact fields without replacing existing browser autofill,
and attaches the selected resume. You review and click Submit. Metis marks a role applied only after observing
an ATS confirmation page or message; otherwise it remains `prefilled` and is not
written to `applications.xlsx`.

LinkedIn-sourced roles remain selectable even when their external URL was not captured.
After selection, Metis performs at most two exact company/title searches, validates a
matching supported ATS page, and caches the URL only after it opens successfully. LinkedIn
Easy Apply roles and unresolved searches open the original LinkedIn posting instead of
blocking the rest of the batch.

Install browser support once with `pip install 'metis-job[browser]'`. Optional fixed
application values are managed with `metis config autofill`; environment variables remain
available as deployment overrides. Values include contact details, location, work
authorization and sponsorship answers, and optional self-identification fields.
Metis only fills sensitive self-identification answers explicitly supplied by the candidate.
Workflow state is stored owner-only in `~/.job_pipeline/application_state.json`.

---

## Quick start

**Step 1 — Install**

```bash
brew install pipx && pipx ensurepath
pipx install git+https://github.com/chenlomis/metis.git
```

> Already installed? Run `pipx upgrade metis-job` instead.

**Step 2 — Configure credentials**

```bash
mkdir -p ~/.job_pipeline
cat > ~/.job_pipeline/.env  **Optional — Playwright-powered company sourcing:** metis can also pull roles directly from company career pages (Greenhouse, Lever, Ashby). This requires Playwright and is disabled by default. To enable:
> ```bash
> pipx inject metis-job playwright --include-apps
> playwright install chromium
> # Then: metis sources add Stripe
> ```

**Expected output:** metis fetches LinkedIn alert emails from the last 3 days, scores each role, and emails you a ranked digest. On first run this usually takes 30-90 seconds for small batches, and longer if many roles need JD extraction and scoring.

> **No emails found?** LinkedIn alert emails may take up to 24 hours to arrive after setup. Run `metis --lookback 14d` to cast a wider net, or see [Troubleshooting](#troubleshooting).

---

## Commands

### Core workflow

| Command                              | What it does                                                                            |
|--------------------------------------|-----------------------------------------------------------------------------------------|
| `metis`                              | Run full pipeline: ingest, dedupe, score, and email digest. Default: last run or 3d.    |
| `metis --lookback 7d`                | Same pipeline with a wider window. Accepts `7d`, `14d`, or ISO date like `2026-05-10`.  |
| `metis --dry-run`                    | Preview a full fetch + score run without sending email or writing state.                |
| `metis --no-limit`                   | Score everything in the window. The fast pre-screen model runs first.                   |
| `metis --no-limit --lookback 14d`    | Catch up after a gap by scoring everything from a wider window.                         |
| `metis init`                         | Build your scoring profile from your resume and preferences.                            |
| `metis config access`                | Connect, inspect, switch, or reconnect Gmail/Outlook access.                            |

Each digest role gets a 0-100 score, a Solid Match / Moderate Match / Limited Match verdict, two leverage points, one friction point, and scan-friendly tags. Roles are deduplicated across runs, so the same listing should not reappear within 30 days.

`profile.yaml` is the scoring profile used by every future digest. See [profile.template.yaml](./profile.template.yaml) for the full schema with comments.

### Sources and scheduling

| Command                              | What it does                                                                            |
|--------------------------------------|-----------------------------------------------------------------------------------------|
| `metis sources [list]`               | Show active email alerts and company career pages.                                      |
| `metis sources add`                  | Pick an alert source or company source interactively.                                   |
| `metis sources add NAME`             | Add a company for proactive scraping. Auto-detects Greenhouse, Lever, or Ashby.         |
| `metis sources add --all`            | Add every company in the built-in pool.                                                 |
| `metis sources remove`               | Remove company sources interactively.

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [chenlomis](https://github.com/chenlomis)
- **Source:** [chenlomis/metis](https://github.com/chenlomis/metis)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-chenlomis-metis
- Seller: https://agentstack.voostack.com/s/chenlomis
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
