# ApplyWise (pypi · applywise)

Job search and form filling; dry run by default, real submits need your approval or consent.

- Trust score: 77/100 (medium)
- Change this week: 0
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- pypi · `applywise`: 77/100 (this document), [markdown](https://verifymcp.io/servers/tanmayagrawal21-applywise/applywise.md), [page](https://verifymcp.io/servers/tanmayagrawal21-applywise/applywise)

## Channel facts

- Registry: `pypi`
- Package: `applywise`
- Version: `0.1.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Supply Chain Security**: 100/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - Runs hatchling.build at install time, a recognised build step with no custom scripting around it.
  - 0 of 28 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 100/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to tanmayagrawal21/job-apply-mcp).
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 12 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 62/100
  - AI-judged instruction clarity (fair).
  - Tool/resource definitions use about 2885 tokens (~87/item across 33 items; 33 tools + 0 resources), lean.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 71/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 0% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 33 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 33 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the ApplyWise MCP server?

ApplyWise runs locally as a PyPI package, launched with uvx applywise. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add tanmayagrawal21-applywise -- uvx applywise
```

### Cursor

```json
{
  "mcpServers": {
    "tanmayagrawal21-applywise": {
      "command": "uvx",
      "args": [
        "applywise"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "tanmayagrawal21-applywise": {
      "command": "uvx",
      "args": [
        "applywise"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add tanmayagrawal21-applywise -- uvx applywise
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "tanmayagrawal21-applywise": {
      "type": "local",
      "command": [
        "uvx",
        "applywise"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add tanmayagrawal21-applywise --command uvx --arg applywise
```

### Hermes

```yaml
mcp_servers:
  tanmayagrawal21-applywise:
    command: "uvx"
    args: ["applywise"]
```

### Netclaw

```json
{
  "McpServers": {
    "tanmayagrawal21-applywise": {
      "Transport": "stdio",
      "Command": "uvx",
      "Arguments": [
        "applywise"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add tanmayagrawal21-applywise -t stdio -c uvx -a applywise
```

### Other

```json
{
  "mcpServers": {
    "tanmayagrawal21-applywise": {
      "command": "uvx",
      "args": [
        "applywise"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-10-24 (score 77, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-10-23 (score 62)

First indexed and scored.

## MCP tools (33)

### `search_jobs` (~111 tokens)

Search postings across enabled platforms in parallel. Returns compact rows: ref, co, title, loc, pay, flags.
The first call runs the whole search once; pass the returned `next` as `cursor` for more pages (instant).

Input parameters:

- `apply_policy` (boolean)
- `boards`
- `cursor` (string)
- `limit` (integer)
- `location` (string)
- `platforms`
- `query` (string)
- `since_days` (integer)

Output parameters:

- `result` (string)

### `search_status` (~42 tokens)

Progress of a search_jobs session: status, boards done/total, rows, elapsed. Accepts a session id or cursor.

Input parameters:

- `session_id` (string, required)

Output parameters:

- `result` (string)

### `get_job` (~41 tokens)

Fetch one posting. Add 'description' to fields to include the (trimmed) description.

Input parameters:

- `fields`
- `ref_or_url` (string, required)

Output parameters:

- `result` (string)

### `get_form` (~33 tokens)

Return the application form schema (keys, labels, kinds, required, options).

Input parameters:

- `ref_or_url` (string, required)

Output parameters:

- `result` (string)

### `plan_application` (~174 tokens)

Run policy gates + duplicate check, fill answers from the profile and local LLMs, and list unresolved fields.
Unresolved free-text fields come back as `client_tasks` for the calling agent to write. `src` names the source
of every answer that is not "profile". A result too large for one response is paged: it carries `next` and
\`total`; call again with `cursor=next` to get the next page of the SAME plan (from memory, no re-plan) until
\`next` is null. Pages keep the shape (answers/src stay dicts) so they merge. The first call of a session may
ask the user the top open profile questions (elicitation) before planning.

Input parameters:

- `cursor` (integer)
- `ref_or_url` (string, required)

Output parameters:

- `result` (string)

### `draft_answers` (~86 tokens)

Draft the prose fields a plan left open (writing.mode="deferred", or ones that timed out): local writer +
reviewer under writing.timeout_s. Returns the same shape as plan_application with a fresh approval_id, paged
the same way (`cursor=next` pages the last draft from memory).

Input parameters:

- `cursor` (integer)
- `ref_or_url` (string, required)

Output parameters:

- `result` (string)

### `submit_application` (~108 tokens)

Submit using the best available path (platform API, else browser driver). Honors global dry_run; a per-call
dry_run can only make it safer. `approval_id` is the server-issued id from plan_application. With
approval_mode=human a person must approve (dialog, or `job-apply-mcp approve <id>`).

Input parameters:

- `answers`
- `approval_id`
- `dry_run`
- `ref_or_url` (string, required)
- `token`

Output parameters:

- `result` (string)

### `provide_verification_code` (~121 tokens)

The user types the code they received (email/SMS) for a submission in status `awaiting_code`. Ask the USER;
never try to read their mail or guess. Only the format is checked; the code is typed into the open page, the
page's verify button is clicked once, then the normal confirmation check runs. One attempt per code; the
application is never resubmitted; after `verification.code_ttl_s` it becomes a `handoff`.

Input parameters:

- `code` (string, required)
- `pending_id` (string, required)

Output parameters:

- `result` (string)

### `apply_batch` (~60 tokens)

Plan + submit many applications concurrently. Returns one compact status row per ref. Open profile questions
are asked once, before the batch starts (never mid-batch).

Input parameters:

- `dry_run`
- `max_parallel`
- `refs` (array, required)

Output parameters:

- `result` (string)

### `list_applications` (~38 tokens)

List recorded applications from the local store.

Input parameters:

- `cursor` (integer)
- `limit` (integer)
- `status` (string)

Output parameters:

- `result` (string)

### `request_feature` (~66 tokens)

Propose (and, if a coder backend is configured, implement as a PR for human review) a change to this tool.
kind: platform_adapter | control | config | new_tool | bug (auto-detected if omitted).

Input parameters:

- `description` (string, required)
- `kind`

Output parameters:

- `result` (string)

### `improvement_report` (~43 tokens)

Ranked improvement proposals learned from recent run failures (compact). Page with `cursor` (= `next`).

Input parameters:

- `cursor` (integer)
- `limit` (integer)

Output parameters:

- `result` (string)

### `record_text` (~96 tokens)

Record provenance for a text artifact (kind: resume_bullet|cover_letter|answer|profile_fact).
origin: user_written | llm_generated (llm_generated needs `model`). `context` = job/question the text answers.

Input parameters:

- `context`
- `kind` (string, required)
- `model`
- `origin` (string, required)
- `parent`
- `prompt`
- `text` (string, required)

Output parameters:

- `result` (string)

### `verify_text` (~52 tokens)

User approves LLM text. Without edited_text -> user_verified; with it -> user_edited child plus diff.

Input parameters:

- `edited_text`
- `id` (string, required)
- `verified_by` (string)

Output parameters:

- `result` (string)

### `provenance` (~36 tokens)

Origin, model, prompt hash and ancestor chain for a text id.

Input parameters:

- `id` (string, required)
- `include_text` (boolean)

Output parameters:

- `result` (string)

### `health` (~21 tokens)

Report enabled platforms, LLM providers and which local models are reachable.

Output parameters:

- `result` (string)

### `control_check` (~87 tokens)

Check a side-effecting action against the control layer. action: apply|submit|send_message|
write_prose|merge. payload: ref, platform, company, dry_run, text, recipient, page_text, form_labels,
attestations. Returns {decision: pass|block|needs_human, violations, warnings}.

Input parameters:

- `action` (string, required)
- `payload`

Output parameters:

- `result` (string)

### `control_status` (~22 tokens)

Active mode, quotas used/remaining, enabled controls and recent blocks.

Output parameters:

- `result` (string)

### `tune_status` (~30 tokens)

Local style-tuning state: backend, promoted/previous adapter, new user texts vs threshold, last run.

Output parameters:

- `result` (string)

### `tune_run` (~75 tokens)

Train a LoRA on the user's own texts, gate it against the incumbent, promote only if better.
trigger: manual | new_data (skips below the configured threshold) | rollback (restore previous adapter).
wait=False starts in the background; poll tune_status.

Input parameters:

- `trigger` (string)
- `wait` (boolean)

Output parameters:

- `result` (string)

### `facts_report` (~47 tokens)

Resume-first fact precedence: counts, profile/resume conflicts, and user-letter facts excluded
because they conflict with or are outdated relative to the resume (with the reason and the resume's version).

Output parameters:

- `result` (string)

### `grants_status` (~49 tokens)

Active human-issued grants (scope, seconds left, uses left). Read-only: only a human can create or
revoke a grant, via `job-apply-mcp grant` in a terminal.

Output parameters:

- `result` (string)

### `consent_status` (~56 tokens)

Active consent windows (mode, scopes, seconds left, submissions left). Read-only: only a human can
consent, in a terminal: `job-apply-mcp consent --for 24h` or `--per-run`.

Output parameters:

- `result` (string)

### `vault_status` (~76 tokens)

Which ATS hosts have a stored login (host and count only, never a username's password), whether the
credentials consent window is open, accounts awaiting email verification, and this run's login flags
(lockout, wrong_password, captcha). Read-only: logins are added by a human with `job-apply-mcp vault add`.

Output parameters:

- `result` (string)

### `ingest_confirmations` (~102 tokens)

Record the user's own application-confirmation emails so those jobs are never re-applied to.
Pass message summaries from the user's mail tool: [{sender, subject, date, snippet}] (snippet = first
\~500 chars, optional). Read-only on mail; the server stores only company, title and date. Returns
counts plus up to a few new matches. preview=true parses without writing.

Input parameters:

- `messages` (array, required)
- `preview` (boolean)

Output parameters:

- `result` (string)

### `sync_confirmations` (~73 tokens)

Pull confirmation emails from the configured read-only source (ingest.source: mbox or imap) for the
last `since_days` days and record them as already applied. Never sends, moves, flags or deletes mail.

Input parameters:

- `preview` (boolean)
- `since_days`
- `source`

Output parameters:

- `result` (string)

### `reconcile_submissions` (~137 tokens)

Match open submissions (submitted/unknown/submitting/handoff) to confirmation emails and mark confident
matches `confirmed` (evidence = email subject/date; never bodies). Checks run at ingest.reconcile_delays_min
after each submit; force=true checks now. With the default client mail source and no `messages`, returns a
\`client_task`: fetch recent confirmation-email summaries and pass them here or to ingest_confirmations.
An unknown with no match after the last window stays unknown and is listed under `unresolved`. Read-only
on mail; never resubmits.

Input parameters:

- `force` (boolean)
- `messages`

Output parameters:

- `result` (string)

### `seed_from_confirmations` (~91 tokens)

Seed dedupe from confirmation-email history (default ingest.seed_since_days=180) before a run, so no
side files are needed. mbox/imap sources are read directly; with the client source and no `messages`
this returns a `client_task` to fetch summaries and call it again with them.

Input parameters:

- `messages`
- `preview` (boolean)
- `since_days`

Output parameters:

- `result` (string)

### `run_applications` (~382 tokens)

Apply from any mix of sources in one run: explicit `links` (or `links_file`, one URL per line), job links
the user emailed to themselves (read-only mail; sender, recipient and label come from config only; `mail`
may only narrow with {query, since, since_days}), and discovery (`discovery` = search_jobs arguments). Priority: links,
then mail, then discovery. `sources` subsets ["links","mail","discovery"]. `max_applications` (whole number
\>= 1; default intake.max_applications or run_size feedback, capped at intake.max_applications_cap) caps the
eligible postings handled, the same in dry and live mode; skipped and ineligible ones do not count. Every URL
goes through adapter detection, plan, gates, dedupe and submit. Prose is deferred: jobs needing unapproved
prose are skipped, not blocking. With the client mail source pass `messages` [{id, from, to, subject, date,
body}]. Pending feedback is applied first (see plan_context). Returns the run report: one status per posting,
each with `why`: submitted, confirmed, dry_run_ok (a live run would submit it), needs_human (the owner must
act: unresolved fields, review gate, awaiting approval), quota_blocked (a live quota refused it), skipped
(policy, duplicate, prose not approved, max_applications reached), unsupported_site, unknown (verify by
hand), failed. A dry run adds `live_preview` (would_submit, quota_blocked, warning) from the live quotas.

Input parameters:

- `discovery`
- `dry_run`
- `links`
- `links_file`
- `mail`
- `max_applications`
- `messages`
- `sources`

Output parameters:

- `result` (string)

### `run_report` (~100 tokens)

Report of a run (default: the latest): counts plus rows per status (submitted, confirmed, dry_run_ok,
needs_human, quota_blocked, skipped, unsupported_site, unknown, failed; see run_applications), each with
\`why`. `category` shows one only (the old names handed_off and dry_run still work).

Input parameters:

- `category` (string)
- `limit` (integer)
- `run_id` (string)

Output parameters:

- `result` (string)

### `give_feedback` (~247 tokens)

Feedback on a run (optionally on one `ref` of it), applied at the start of the next run. Structured:
{"kind":"deny_company"|"deny_title", "pattern"?} (no pattern + ref = that item's company/title),
{"kind":"answer","pattern","value"} for plain questions only; any authorization, demographic, consent,
attestation, legal or AI-use question (or {"kind":"profile_answer","key"|"question","value","scope":
"global|company|role_family","scope_value"}) goes to the profile builder's answer_profile_question.
{"kind":"salary","salary_floor"|"base_salary"|"default_ask"|"expected"|"delta"|"percent"}: never below the
configured floor, capped at intake.salary_max_multiple. {"kind":"run_size","value"|"delta"}. Free text is
shown in the next run's plan_context. Answers given here (and pay changes in human approval mode) apply only
after the USER confirms them on a terminal: `job-apply-mcp feedback --confirm <id>`.

Input parameters:

- `feedback` (required)
- `ref`
- `run_id` (string, required)

Output parameters:

- `result` (string)

### `profile_questions` (~56 tokens)

Top open profile gaps (questions the tool could not answer, or answered with a default), ranked by
frequency x impact (blocked applications weigh most). Ask the user these, then call answer_profile_question.

Input parameters:

- `limit` (integer)

Output parameters:

- `result` (string)

### `answer_profile_question` (~127 tokens)

Ask the USER (MCP elicitation) to type the answer for a gap key from profile_questions. This tool takes
no value: the answer comes only from the user's own input and is stored as user_written. If the client
cannot elicit, nothing is stored; tell the user to run `job-apply-mcp profile ask`. Scope: global | company |
role_family (+ scope_value, or 'company:Acme'). Demographics are never stored here.

Input parameters:

- `key` (string, required)
- `scope` (string)
- `scope_value` (string)

Output parameters:

- `result` (string)

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Dependencies. The full working is on the page: https://verifymcp.io/servers/tanmayagrawal21-applywise/applywise#diagnostics

## Score history

- 2026-11-05: 77
- 2026-11-04: 77
- 2026-11-03: 77
- 2026-11-02: 77
- 2026-11-01: 77
- 2026-10-31: 77
- 2026-10-30: 77
- 2026-10-29: 77
- 2026-10-28: 77
- 2026-10-27: 77
- 2026-10-26: 77
- 2026-10-25: 77
- 2026-10-24: 77
- 2026-10-23: 62

## Common questions

### What is the ApplyWise MCP server?

ApplyWise is an MCP server listed in the public MCP registry as io.github.tanmayagrawal21/applywise. Job search and form filling; dry run by default, real submits need your approval or consent. This page covers its PyPI package (applywise).

### Is the ApplyWise MCP server safe to use?

ApplyWise scores 77 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the ApplyWise MCP server expose?

ApplyWise exposes 33 tools: search_jobs, search_status, get_job, get_form, plan_application, and 28 more. Their descriptions and schemas cost roughly 2,885 tokens of context every time the server is loaded.

### Is the ApplyWise MCP server still maintained?

ApplyWise is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the ApplyWise MCP server under?

ApplyWise declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- PyPI project: https://pypi.org/project/applywise/
- Socket report: https://socket.dev/pypi/package/applywise
- Repository: https://github.com/tanmayagrawal21/job-apply-mcp
- Changelog RSS feed: https://verifymcp.io/servers/tanmayagrawal21-applywise/applywise.xml
- Changelog JSON feed: https://verifymcp.io/servers/tanmayagrawal21-applywise/applywise.json
- HTML version of this page: https://verifymcp.io/servers/tanmayagrawal21-applywise/applywise
