runwayMCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| analyze_jobA | Gather the general resume + scoring guide so Claude can score the match.
The match score and APPLY/CONSIDER/SKIP recommendation are NOT computed by this tool — after calling it, score the candidate's resume against the job (already pasted into this conversation) and apply the scoring_guide's recommendation_rules in your reply. The resume injected here is the GENERAL resume (design D6), not the most recently tailored one: scoring a job against a resume already tailored FOR that job would inflate the match score by scoring the resume against itself. This tool NEVER raises for any documented failure mode — all such failures are encoded in the return envelope. An unexpected keyword argument (e.g. a JD text payload) is a caller programming error and raises normally, exactly as calling any Python function with an unknown keyword does. Args:
title: Job title, Claude-extracted from the pasted posting.
company: Company name, Claude-extracted.
country: Free-text country, Claude-extracted. Compared against
the user's declared work authorization; a mismatch
populates work_authorization with an advisory warning.
url: The job posting URL, if any. Resolved to a job_id
(exact match against the jobs table) so the
general-resume selection can exclude a resume already
tailored to this job. None when the user has no URL to
give (e.g. a referral).
custom_title: The user's handle for a URL-less job. Echoed back, AND
— when Returns: AnalyzeJobResult with extracted/resume/scoring_guide/ work_authorization populated on success, or error/message fields populated on failure ("no_resume" | "corrupt" | "ambiguous_custom_title" | "no_work_authorization"). |
| save_job_analysisA | Persist an analyzed job record. Upserts by Resolution order:
This tool NEVER raises — all failures are encoded in the return envelope. Args:
title: Job title (Claude-extracted). Always required, always
overwrites — no omit-preserve semantics.
company: Company name (Claude-extracted). Same as title.
country: Free-text country (Claude-extracted). Same as title.
id: Existing job id to update. None to create or
upsert-by-url.
url: Job posting URL. Nullable/unique attribute, not the
identity (D1). Omitted (None) preserves the
existing value on an update.
custom_title: User-supplied handle when url is absent. Same
omit-preserve rule as url.
jd_text: Full pasted job description, stored in the
Returns: SaveJobResult with success=True, id, url, custom_title, updated flag on success; success=False with error/message on failure. |
| get_jobA | Retrieve a single job record by id, url, or custom_title (D6, the REQUIRED read path for jd_text — without this tool, jd_text is write-only).
This tool NEVER raises. Args:
id: Job id. Exactly one of id/url/custom_title
must be given.
url: Alternate lookup key (url is UNIQUE).
custom_title: Alternate lookup key for a URL-less job. NOT
unique — see above for the multi-match rule.
include_description: When True and a description was captured,
populates Returns: GetJobResult with success=True, job, description, has_description, resume_versions on success; success=False with error="not_found" | "invalid_input" | "corrupt" | "ambiguous" on failure. |
| list_jobsA | Return stored job records with optional filtering, sorting, and limiting. Pipeline order: FILTER -> SORT -> LIMIT, expressed as WHERE/ORDER BY/ LIMIT (D9). Arguments are validated in Python BEFORE any SQL is built, so an invalid status still produces the "use one of: ..." message rather than a raw SQL error. This tool NEVER raises. Args: since: ISO-8601 string cutoff (inclusive). status: One ApplicationStatus value, or a list to match any member. min_score: Minimum score threshold (inclusive). None scores excluded. company: Substring match against company, case-insensitive (lower() on both sides, ASCII-only — SQLite's lower() does not fold non-ASCII). This is SC-1, the release's headline query ("did I apply to Acme?") — D9. limit: Maximum number of records to return (after sort). sort_by: "analyzed_at" (default, newest first) or "score" (descending, None scores last). Returns: ListJobsResult with success=True and filtered/sorted records on success; success=False with error_message on failure. |
| set_application_statusA | Set the application status of a stored job record, by id or url. Transitions are deliberately UNVALIDATED — any of the 7 status values may transition to any other. This tool NEVER raises.
To edit the analysis itself, call save_job_analysis with an Args: status: One of: not_applied, applied, interviewing, offer, rejected, withdrawn, ghosted. id: Job id (preferred — always resolvable, unlike url). url: Alternate lookup key when id is not known. notes: Optional follow-up note, appended to the timeline as "[YYYY-MM-DD] — ". Omitted, the timeline is left untouched and only the status changes. Returns: SetStatusResult with success=True, id, url, status, previous_status and the resulting status_notes on success; success=False with error="invalid_status" (record unchanged), error="not_found", or error/message on a store failure. |
| delete_jobA | Permanently delete a stored job record, by id or url. For a record that should never have existed: a mistyped entry, a posting
that turned out to be a duplicate, test data. This is NOT the same thing
as the Lookup is by What happens to everything pointing at the job:
There is no confirmation flag and no undo. The returned receipt names the job and every resume version that was unlinked, so the caller can report exactly what disappeared — with no delete_job there is no way back, the receipt is the safety mechanism. This tool NEVER raises. Args: id: Job id (preferred — always resolvable, unlike url). url: Alternate lookup key when id is not known. Returns: DeleteJobResult with success=True and the receipt on success; success=False with error="invalid_input" (neither key given), "not_found", "corrupt", or "write_error". |
| save_resume_versionA | Append a new resume version to the store. Never mutates or deletes. The store enforces a single-root tree: the first saved version's
parent_id MUST be None; every subsequent version's parent_id MUST
reference an existing version id. Args: content: Raw resume text, stored verbatim. label: Caller-supplied human-readable label. parent_id: id of the version this one derives from. None only on the very first save (establishes the base). job_id: Optional job id this version was tailored for. Returns: SaveResumeVersionResult with success=True, id, label, parent_id, job_id on success; success=False with error/message on failure ("invalid_parent", "parent_not_found", "job_not_found", "invalid_input", "corrupt", "write_error"). |
| get_resume_versionA | Retrieve a single resume version by id, or the most recent via "latest". This tool NEVER raises. Args: id: Exact version id, or the literal string "latest" for the most recently created version in the store. Returns: GetResumeVersionResult with success=True and version on success; success=False with error="not_found" or error="corrupt". |
| list_resume_versionsA | Return stored resume versions, newest-first, with optional filtering. Pipeline order: FILTER -> SORT -> LIMIT. This tool NEVER raises. Args: job_id: When provided, only versions linked to this exact job id are returned. limit: Maximum number of records to return (after sort). Returns: ListResumeVersionsResult with success=True and filtered/sorted SUMMARIES (no resume text); success=False with error_message. |
| set_work_authorizationA | Declare the FULL set of countries the user may legally work in. REPLACES the previous declaration in its entirety (SC-26) — this is a
statement about the whole set ("I can work in X and Y"), not an
additive append. An empty list is a valid, distinct declaration
(SC-27): "declared, zero countries" differs from "never declared" —
Countries are canonicalized at write time (tools/_country.py); both the raw text and the canonical form are stored. Two raw spellings that canonicalize to the same country (e.g. "USA" and "United States" in one call) collapse to a single declared row — the first raw spelling encountered wins the echo. This tool NEVER raises. Args: countries: Free-text country names, as the user states them. An empty list explicitly declares zero authorized countries. Entries that canonicalize to nothing ("", " ", "...") are not countries and are dropped. If that leaves nothing, the call is REJECTED rather than silently storing a declaration that means nothing — see the loop below. Returns: SetWorkAuthorizationResult with success=True and the stored raw/ canonical forms on success; success=False with error="invalid_input" when no given name could be understood, "corrupt" on a broken database, or "write_error" when the write itself fails. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 10 tools
Each tool owns a distinct resource-action pair: analyze, save/get/list/delete jobs, status updates, resume version handling, and work authorization. save_job_analysis and set_application_status both target a job, but their descriptions explicitly separate analysis fields from status timeline mechanics, so an agent should not confuse them.
All tool names follow a uniform snake_case verb_noun style (analyze_job, list_jobs, save_resume_version, set_work_authorization). The verbs are specific and the objects are consistently named, with no camelCase or vague action words.
Ten tools is right in the ideal range and every tool earns its place: job CRUD plus analysis, status tracking, resume versioning, and work authorization. There is no apparent redundancy or bloat.
The core job-application lifecycle is well covered: analyze, save, retrieve, list, update status, and delete jobs, plus resume version storage/retrieval and work authorization declaration. The only notable gap is the lack of a direct get_work_authorization tool, though analyze_job returns the live comparison during analysis.