Koskamo

Zovo Resume PDF MCP

Turns resume facts into a clean one-column PDF with selectable text, supporting classic, modern, or compact templates on Letter or A4 paper. It can fit content to one page, provide plain-text and JSON copies, and verify text extraction accuracy.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Zovo Resume PDF MCP logo, by ZovoCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-08Published by Zovo
MCP endpoint (Streamable HTTP)
https://resume-pdf.zovo.one/mcp
Vendor documentation

What its tools do

2 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

2 of 2 have a description · 2 of 2 declare behavior hints · 2 of 2 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Generate a one-column PDF resume from structured facts
  • Fit resume content to one page by adjusting spacing and margins
  • Extract plain-text or JSON data from the generated resume
  • Verify that all resume bullets are present in the PDF text

Source and maintenance

Community listingRegistry 1.0.0

Protocol and capabilities

Server
resume-pdf 1.0.0
MCP protocol negotiated in check
2025-11-25
Tools
2 advertised
Resources
1 advertised
Resource templates
1 advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  },
  "resources": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Zovo Resume PDF lays out resume facts that the user provides into a one-column, text-based PDF plus a plain-text copy and a JSON copy of the data. generate_resume_pdf makes the files; check_resume_text builds the same PDF and reads its text back to show that each heading and bullet is present in order. Pass only facts the user gave; the tools do not write or improve content.

Tools

2 advertised

generate_resume_pdf — Generate resume PDF
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the user wants their resume as a PDF file from facts they provide (name, contact line, summary, jobs with dates and bullets, education, skills, projects, certifications). Returns a one-column PDF with selectable text in reading order, a plain-text copy, a JSON copy of the data, the page count, and whether fit_to_one_page succeeded. Templates: classic, modern, compact; Letter or A4. Lays out only the text given: it does not write, embellish or verify resume content. Does not make cover letters, Word files, two-column designs or photos. Download links expire in about 1 hour.

generate_resume_pdf input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 80,
      "description": "Full name as it should appear, e.g. \"Maria Santos\"."
    },
    "skills": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 120,
        "description": "One skill or a labeled group, e.g. \"SQL\" or \"Languages: English, Spanish\"."
      },
      "maxItems": 60,
      "description": "Up to 60 skills, e.g. [\"SQL\", \"Python\", \"Tableau\"]. Items with a label and a colon print one per line."
    },
    "contact": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 120,
        "description": "One contact item as plain text, e.g. \"maria@example.com\"."
      },
      "maxItems": 6,
      "description": "Up to 6 contact items shown on one line, e.g. [\"maria@example.com\", \"+1 555 0100\", \"Austin, TX\", \"linkedin.com/in/maria\"]."
    },
    "summary": {
      "type": "string",
      "maxLength": 1200,
      "description": "Optional short profile paragraph in the user's own words, e.g. \"Analyst with 6 years in retail pricing.\""
    },
    "headline": {
      "type": "string",
      "maxLength": 140,
      "description": "Optional one-line professional title, e.g. \"Senior Data Analyst\"."
    },
    "projects": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "date": {
            "type": "string",
            "maxLength": 20,
            "description": "Optional date as YYYY-MM, a year, or \"present\", e.g. \"2024\"."
          },
          "link": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional link as plain text, e.g. \"github.com/maria/price-tracker\"."
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Project name, e.g. \"Price tracker\"."
          },
          "bullets": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 400,
              "description": "One line about the project, e.g. \"Scrapes 3 stores daily\"."
            },
            "maxItems": 6,
            "description": "Up to 6 bullet points."
          }
        }
      },
      "maxItems": 8,
      "description": "Up to 8 projects, e.g. [{\"name\":\"Price tracker\",\"bullets\":[\"Scrapes 3 stores daily\"]}]."
    },
    "template": {
      "enum": [
        "classic",
        "modern",
        "compact"
      ],
      "type": "string",
      "description": "Layout: classic (centered header, one column), modern (left header with a blue accent rule) or compact (smaller type). Default classic."
    },
    "education": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "end": {
            "type": "string",
            "maxLength": 20,
            "description": "Optional end as YYYY-MM, a year, or \"present\", e.g. \"2018-05\"."
          },
          "start": {
            "type": "string",
            "maxLength": 20,
            "description": "Optional start as YYYY-MM or a year, e.g. \"2014\"."
          },
          "degree": {
            "type": "string",
            "maxLength": 120,
            "description": "Degree or program, e.g. \"BSc Economics\"."
          },
          "school": {
            "type": "string",
            "maxLength": 120,
            "description": "School, e.g. \"University of Texas\"."
          },
          "details": {
            "type": "string",
            "maxLength": 400,
            "description": "Optional one line such as honors or coursework, e.g. \"Magna cum laude\"."
          },
          "location": {
            "type": "string",
            "maxLength": 80,
            "description": "Optional city, e.g. \"Austin, TX\"."
          }
        }
      },
      "maxItems": 8,
      "description": "Up to 8 education entries, e.g. [{\"degree\":\"BSc Economics\",\"school\":\"UT Austin\",\"end\":\"2018\"}]."
    },
    "page_size": {
      "enum": [
        "letter",
        "a4"
      ],
      "type": "string",
      "description": "Paper size: letter (US, default) or a4."
    },
    "experience": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "end": {
            "type": "string",
            "maxLength": 20,
            "description": "End month as YYYY-MM, a year, or \"present\", e.g. \"present\"."
          },
          "org": {
            "type": "string",
            "maxLength": 120,
            "description": "Employer or organization, e.g. \"Acme Retail\"."
          },
          "start": {
            "type": "string",
            "maxLength": 20,
            "description": "Start month as YYYY-MM (or a year), e.g. \"2021-03\"."
          },
          "title": {
            "type": "string",
            "maxLength": 120,
            "description": "Job title, e.g. \"Data Analyst\"."
          },
          "bullets": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 400,
              "description": "One achievement or duty as written by the user, e.g. \"Cut report time by 40%\"."
            },
            "maxItems": 10,
            "description": "Up to 10 bullet points, e.g. [\"Built the weekly pricing dashboard\"]."
          },
          "location": {
            "type": "string",
            "maxLength": 80,
            "description": "Optional city or \"Remote\", e.g. \"Austin, TX\"."
          }
        }
      },
      "maxItems": 15,
      "description": "Up to 15 jobs in the order to print (usually newest first), e.g. [{\"title\":\"Analyst\",\"org\":\"Acme\",\"start\":\"2021-03\",\"end\":\"present\",\"bullets\":[\"Built dashboards\"]}]."
    },
    "certifications": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "date": {
            "type": "string",
            "maxLength": 20,
            "description": "Optional date as YYYY-MM or a year, e.g. \"2023-06\"."
          },
          "name": {
            "type": "string",
            "maxLength": 160,
            "description": "Certification name, e.g. \"AWS Cloud Practitioner\"."
          },
          "issuer": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional issuer, e.g. \"Amazon Web Services\"."
          }
        }
      },
      "maxItems": 15,
      "description": "Up to 15 certifications, e.g. [{\"name\":\"PMP\",\"issuer\":\"PMI\",\"date\":\"2022\"}]."
    },
    "fit_to_one_page": {
      "type": "boolean",
      "description": "true to tighten spacing, margins (down to 0.5 in) and type size (down to 9 pt) so the resume fits one page. The result says if it still does not fit."
    }
  }
}
generate_resume_pdf output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "name",
    "template",
    "page_size",
    "pages",
    "one_page",
    "fit_to_one_page",
    "counts",
    "replaced_characters",
    "warnings",
    "downloads",
    "file_name",
    "expires_in_hours"
  ],
  "properties": {
    "name": {
      "type": "string"
    },
    "pages": {
      "type": "number"
    },
    "counts": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "one_page": {
      "type": "boolean"
    },
    "template": {
      "type": "string"
    },
    "warnings": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "downloads": {
      "type": "object",
      "required": [
        "pdf",
        "txt",
        "json"
      ],
      "properties": {
        "pdf": {
          "type": "string"
        },
        "txt": {
          "type": "string"
        },
        "json": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "file_name": {
      "type": "string"
    },
    "page_size": {
      "type": "string"
    },
    "fit_to_one_page": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "expires_in_hours": {
      "type": "number"
    },
    "replaced_characters": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "additionalProperties": false
}
generate_resume_pdf annotations
{
  "title": "Generate resume PDF",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
check_resume_text — Check resume PDF text
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the user wants to confirm that a resume PDF made from their facts has machine-readable text: it builds the same PDF as generate_resume_pdf from the same fields, reads the text back with pdf.js, and reports the page count, whether text runs top to bottom, and which headings and bullets are missing or out of order. With an optional uploaded resume PDF it checks that file instead, comparing only the name, summary and bullets given in the fields. Does not score the resume, rewrite it, or predict how a specific applicant tracking system ranks it.

check_resume_text input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "name"
  ],
  "properties": {
    "file": {
      "type": "object",
      "required": [
        "download_url",
        "file_id"
      ],
      "properties": {
        "file_id": {
          "type": "string",
          "description": "ChatGPT file id, e.g. file_abc123."
        },
        "file_name": {
          "type": "string",
          "description": "Original file name if known, e.g. statement.pdf."
        },
        "mime_type": {
          "type": "string",
          "description": "Media type if known, e.g. application/pdf."
        },
        "download_url": {
          "type": "string",
          "description": "Temporary download link for the file, supplied by ChatGPT."
        }
      },
      "description": "Optional: the resume PDF to check, e.g. the Maria-Santos-resume.pdf downloaded from generate_resume_pdf. Without it, the tool builds the PDF from the fields and checks that."
    },
    "name": {
      "type": "string",
      "maxLength": 80,
      "description": "Full name as it should appear, e.g. \"Maria Santos\"."
    },
    "skills": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 120,
        "description": "One skill or a labeled group, e.g. \"SQL\" or \"Languages: English, Spanish\"."
      },
      "maxItems": 60,
      "description": "Up to 60 skills, e.g. [\"SQL\", \"Python\", \"Tableau\"]. Items with a label and a colon print one per line."
    },
    "contact": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 120,
        "description": "One contact item as plain text, e.g. \"maria@example.com\"."
      },
      "maxItems": 6,
      "description": "Up to 6 contact items shown on one line, e.g. [\"maria@example.com\", \"+1 555 0100\", \"Austin, TX\", \"linkedin.com/in/maria\"]."
    },
    "summary": {
      "type": "string",
      "maxLength": 1200,
      "description": "Optional short profile paragraph in the user's own words, e.g. \"Analyst with 6 years in retail pricing.\""
    },
    "headline": {
      "type": "string",
      "maxLength": 140,
      "description": "Optional one-line professional title, e.g. \"Senior Data Analyst\"."
    },
    "projects": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "date": {
            "type": "string",
            "maxLength": 20,
            "description": "Optional date as YYYY-MM, a year, or \"present\", e.g. \"2024\"."
          },
          "link": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional link as plain text, e.g. \"github.com/maria/price-tracker\"."
          },
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Project name, e.g. \"Price tracker\"."
          },
          "bullets": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 400,
              "description": "One line about the project, e.g. \"Scrapes 3 stores daily\"."
            },
            "maxItems": 6,
            "description": "Up to 6 bullet points."
          }
        }
      },
      "maxItems": 8,
      "description": "Up to 8 projects, e.g. [{\"name\":\"Price tracker\",\"bullets\":[\"Scrapes 3 stores daily\"]}]."
    },
    "template": {
      "enum": [
        "classic",
        "modern",
        "compact"
      ],
      "type": "string",
      "description": "Layout: classic (centered header, one column), modern (left header with a blue accent rule) or compact (smaller type). Default classic."
    },
    "education": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "end": {
            "type": "string",
            "maxLength": 20,
            "description": "Optional end as YYYY-MM, a year, or \"present\", e.g. \"2018-05\"."
          },
          "start": {
            "type": "string",
            "maxLength": 20,
            "description": "Optional start as YYYY-MM or a year, e.g. \"2014\"."
          },
          "degree": {
            "type": "string",
            "maxLength": 120,
            "description": "Degree or program, e.g. \"BSc Economics\"."
          },
          "school": {
            "type": "string",
            "maxLength": 120,
            "description": "School, e.g. \"University of Texas\"."
          },
          "details": {
            "type": "string",
            "maxLength": 400,
            "description": "Optional one line such as honors or coursework, e.g. \"Magna cum laude\"."
          },
          "location": {
            "type": "string",
            "maxLength": 80,
            "description": "Optional city, e.g. \"Austin, TX\"."
          }
        }
      },
      "maxItems": 8,
      "description": "Up to 8 education entries, e.g. [{\"degree\":\"BSc Economics\",\"school\":\"UT Austin\",\"end\":\"2018\"}]."
    },
    "page_size": {
      "enum": [
        "letter",
        "a4"
      ],
      "type": "string",
      "description": "Paper size: letter (US, default) or a4."
    },
    "experience": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "end": {
            "type": "string",
            "maxLength": 20,
            "description": "End month as YYYY-MM, a year, or \"present\", e.g. \"present\"."
          },
          "org": {
            "type": "string",
            "maxLength": 120,
            "description": "Employer or organization, e.g. \"Acme Retail\"."
          },
          "start": {
            "type": "string",
            "maxLength": 20,
            "description": "Start month as YYYY-MM (or a year), e.g. \"2021-03\"."
          },
          "title": {
            "type": "string",
            "maxLength": 120,
            "description": "Job title, e.g. \"Data Analyst\"."
          },
          "bullets": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 400,
              "description": "One achievement or duty as written by the user, e.g. \"Cut report time by 40%\"."
            },
            "maxItems": 10,
            "description": "Up to 10 bullet points, e.g. [\"Built the weekly pricing dashboard\"]."
          },
          "location": {
            "type": "string",
            "maxLength": 80,
            "description": "Optional city or \"Remote\", e.g. \"Austin, TX\"."
          }
        }
      },
      "maxItems": 15,
      "description": "Up to 15 jobs in the order to print (usually newest first), e.g. [{\"title\":\"Analyst\",\"org\":\"Acme\",\"start\":\"2021-03\",\"end\":\"present\",\"bullets\":[\"Built dashboards\"]}]."
    },
    "certifications": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "date": {
            "type": "string",
            "maxLength": 20,
            "description": "Optional date as YYYY-MM or a year, e.g. \"2023-06\"."
          },
          "name": {
            "type": "string",
            "maxLength": 160,
            "description": "Certification name, e.g. \"AWS Cloud Practitioner\"."
          },
          "issuer": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional issuer, e.g. \"Amazon Web Services\"."
          }
        }
      },
      "maxItems": 15,
      "description": "Up to 15 certifications, e.g. [{\"name\":\"PMP\",\"issuer\":\"PMI\",\"date\":\"2022\"}]."
    },
    "fit_to_one_page": {
      "type": "boolean",
      "description": "true to tighten spacing, margins (down to 0.5 in) and type size (down to 9 pt) so the resume fits one page. The result says if it still does not fit."
    }
  }
}
check_resume_text output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "result",
    "source",
    "pages",
    "reading_order",
    "text_items",
    "characters",
    "blocks_checked",
    "blocks_found_in_order",
    "bullets_expected",
    "bullets_found",
    "headings_found",
    "missing",
    "out_of_order",
    "replaced_characters",
    "warnings"
  ],
  "properties": {
    "pages": {
      "type": "number"
    },
    "result": {
      "type": "string"
    },
    "source": {
      "type": "string"
    },
    "missing": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {
          "type": "string"
        },
        "additionalProperties": {}
      }
    },
    "warnings": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "characters": {
      "type": "number"
    },
    "text_items": {
      "type": "number"
    },
    "not_checked": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {
          "type": "string"
        },
        "additionalProperties": {}
      }
    },
    "out_of_order": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {
          "type": "string"
        },
        "additionalProperties": {}
      }
    },
    "bullets_found": {
      "type": "number"
    },
    "missing_count": {},
    "reading_order": {
      "type": "string"
    },
    "blocks_checked": {
      "type": "number"
    },
    "headings_found": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "bullets_expected": {
      "type": "number"
    },
    "not_checked_count": {},
    "out_of_order_count": {},
    "replaced_characters": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "blocks_found_in_order": {
      "type": "number"
    }
  },
  "additionalProperties": false
}
check_resume_text annotations
{
  "title": "Check resume PDF text",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

1 advertised

resume-pdf-widget — Zovo Resume PDF view

Advertised by the server during the last successful anonymous check.

Interactive view for Zovo Resume PDF.

resume-pdf-widget URI
ui://widget/resume-pdf-v1-1.0.0-229c29377d879414a6000f2f1a506442eb06a79189f2218a0832a99fb2a81130.html

MIME type: text/html;profile=mcp-app

resume-pdf-widget-legacy — Zovo Resume PDF view (previous versions)

Advertised by the server during the last successful anonymous check.

resume-pdf-widget-legacy URI template
ui://widget/resume-pdf-{version}.html

MIME type: text/html;profile=mcp-app

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1411 ms
95th percentile latency
1411 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1411 ms · metadata changed · 2 tool(s), 1 resource(s), 1 resource template(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http zovo-resume-pdf-mcp https://resume-pdf.zovo.one/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add zovo-resume-pdf-mcp --url https://resume-pdf.zovo.one/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable zovo-resume-pdf-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "zovo-resume-pdf-mcp": {
      "url": "https://resume-pdf.zovo.one/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "zovo-resume-pdf-mcp": {
      "type": "streamableHttp",
      "url": "https://resume-pdf.zovo.one/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start zovo-resume-pdf-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "zovo-resume-pdf-mcp": {
      "type": "http",
      "url": "https://resume-pdf.zovo.one/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http zovo-resume-pdf-mcp https://resume-pdf.zovo.one/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://resume-pdf.zovo.one/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "zovo-resume-pdf-mcp": {
      "serverUrl": "https://resume-pdf.zovo.one/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Zovo Resume PDF MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.