Perseus-mcp
MCP server for the Perseus Digital Library — giving AI models direct access to ancient Greek texts, CTS passages, and Scaife search.
Install / Use
claude mcp add tonyjurg -- npx -y github:tonyjurg/Perseus-mcpIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of Perseus-mcp
Perseus-mcp scores 83/100 on our quality scale, 3038th of 4,658 Development & Engineering skills we index.
Its MCP Server is 25 KB long, well organised into 31 sections with 25 code examples: a thorough specification that gives an agent plenty to work with.
It has 3 GitHub stars, so there is little community track record yet; judge it on its content.
Maintenance, license and trust
- The repository was last updated 2 days ago, so Perseus-mcp is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 92/100, with 1 caution from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Perseus-mcp compared with similar skills
All 4 of these similar skills score higher than Perseus-mcp; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| Perseus-mcp (this skill)by tonyjurg | 83 | 3 | 2d ago | MCP Server |
| Agent-Reachby Panniantong | 100 | 106.6k | 5d ago | CLAUDE.md |
| taste-skillby Leonxlnx | 100 | 106.0k | today | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 78.3k | today | CLAUDE.md |
| ai-job-searchby ai-job-search-dev | 100 | 67.6k | 3d ago | CLAUDE.md |
Frequently asked questions
- How do I install Perseus-mcp?
- Run
claude mcp add tonyjurg -- npx -y github:tonyjurg/Perseus-mcp. The install tabs above show the steps for each supported agent. - Which AI agents does Perseus-mcp work with?
- It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
- Is Perseus-mcp safe to use?
- It is MIT-licensed and scores 92/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is Perseus-mcp still maintained?
- The repository was last updated 2 days ago, so Perseus-mcp is actively maintained.
Skill content
View source on GitHubPerseus-mcp
Give Claude / Cursor / Windsurf direct access to the Perseus Digital Library — ancient Greek and Latin texts, precise CTS navigation, plaintext, search, and more.
A high-quality MCP server for Classical Greek and Latin literature. It runs as a local FastMCP server so MCP-capable applications can attach these Perseus tools to the LLM/model provider of your choice.
Features
This server exposes twenty-three MCP tools. Every tool returns a text payload: some are raw Perseus CTS XML or Scaife JSON, while the discovery and plaintext helpers return locally shaped JSON or readable text.
get_passage(urn)— fetch a CTS passage by URN.get_passage_plus(urn)— fetch passage text plus contextual metadata.get_passage_plaintext(urn)— fetch a CTS passage as plain readable text.get_valid_references(urn, level=None)— retrieve navigable citation references for a work or edition.get_valid_references_json(urn, level=None, limit=100, offset=0)— retrieve paged citation references as JSON (limit: 1–500).count_valid_references(urn, level=None)— count valid references without returning the full list.get_capabilities()— list available texts/editions from Perseus CTS.get_cache_status()— inspect local metadata cache state.refresh_metadata_cache()— refresh cached CTS and Scaife library metadata.clear_metadata_cache()— clear in-memory and disk metadata cache entries.list_text_groups(language=None, query=None, limit=100, offset=0)— list matching authors/textgroups and works with pagination metadata (limit: 1–500).get_author_resources(author, language=None)— list works, editions, and translations for a matching author name or CTS textgroup URN.find_author_names(query, language=None, limit=100, offset=0)— find author/textgroup names by partial name match with pagination metadata (limit: 1–500).get_work_resources(urn_or_title, language=None)— list editions, translations, and resources for a work, optionally filtered by original language.get_label(urn)— fetch human-readable metadata labels for a URN.get_first_urn(urn)— get the first navigable URN under a work/edition.get_prev_next_urn(urn)— get neighboring passage URNs for navigation.search_perseus(query, language="greek", query_format="auto", author=None, search_kind="form", preserve_operators=False, page_num=1, text_group=None, work=None, result_format="instances")— search texts via Scaife search API. Greek queries may be entered as Unicode Greek (for exampleμῆνιν) or Beta Code (for examplemh=nin).search_within_text(query, text_urn, ..., size=10, offset=0)— search within one Scaife text/edition URN (size: 1–500).get_passage_highlights(query, passage_urn, ...)— get Scaife token highlight positions for one passage.get_scaife_library_metadata(urn)— get Scaife JSON metadata for a library URN.get_scaife_passage_json(urn)— get Scaife JSON for a passage URN.get_scaife_passage_text(urn)— get Scaife plaintext for a passage URN.
Greek Search Input
search_perseus normalizes search terms before sending them to Scaife's JSON
search route. Queries must contain at least one non-whitespace character. The
tool returns Scaife's JSON response as text.
| Input | Accepted values | Behavior |
| --- | --- | --- |
| query | Unicode Greek, such as μῆνιν, or Beta Code, such as mh=nin a)/eide | Normalized to composed Greek Unicode (NFC) before searching. |
| query_format | "auto" (default), "betacode", or "unicode" | auto recognizes Beta Code marks such as =, /, (, ), and *, and short unaccented Greek-looking terms such as logos. Use an explicit format for ambiguous ASCII input. |
| language | Greek aliases: greek, grc, gr; Latin aliases: latin, lat, la | Controls query normalization, not Scaife corpus filtering. Blank input defaults to Greek; unrecognized values raise an error. |
| search_kind | "form" (default) or "lemma" | Searches inflected forms or dictionary lemmas. |
| preserve_operators | False (default) or True | Set to True for quoted phrases or operators such as -, \|, *, and ~, preventing Beta Code detection from consuming them. |
| author | CTS author/textgroup name or URN | A unique match becomes a server-side text_group filter. Ambiguous matches use local CTS URN-prefix filtering on the returned page. |
| text_group, work | Scaife scope URNs | Apply server-side scope filters directly. |
| page_num | Page number | Selects the result page. |
Operator-query examples:
search_perseus(
'"μῆνιν ἄειδε"',
query_format="unicode",
preserve_operators=True,
)
search_perseus(
"μῆνιν -ἄειδε",
query_format="unicode",
preserve_operators=True,
)
search_perseus(
"λόγος | ἀνήρ",
search_kind="lemma",
query_format="unicode",
preserve_operators=True,
)
For inventory discovery, list_text_groups, find_author_names,
get_author_resources, and get_work_resources treat language as an actual
work-language filter. find_author_names merges the legacy CTS inventory with
the Scaife library catalog, so Scaife-only authors such as Philo Judaeus remain
discoverable. Passage and navigation tools use CTS URNs, whose
greekLit/latinLit namespace and edition identifier already select the text.
Local Metadata Cache
Discovery and navigation tools cache stable CTS metadata locally to avoid
repeated multi-megabyte GetCapabilities and GetValidReff requests. The
default disk cache lives in .cache/perseus-mcp under the current working
directory and also uses an in-memory cache for the running server process.
Configure it with:
PERSEUS_MCP_CACHE_DIR— override the disk cache directory.PERSEUS_MCP_CACHE_TTL_SECONDS— set cache TTL; default is 86400 seconds.PERSEUS_MCP_DISABLE_CACHE=1— disable both memory and disk cache reads/writes.
The current working directory is the directory from which the Python process is
started. Running the MCP server from the repository root uses
.cache/perseus-mcp; running a notebook from examples/ would otherwise use
examples/.cache/perseus-mcp. That is not a second server instance, only a
second cache location for a separate Python process. To keep one cache location
across notebooks and MCP clients, set PERSEUS_MCP_CACHE_DIR to an absolute
path such as /path/to/Perseus-mcp/.cache/perseus-mcp.
Disk entries are written to unique sibling temporary files and atomically
replaced, so multiple local processes can safely share that directory without
exposing partially written cache files. Disk-cache write failures emit a
MetadataCacheWarning but do not discard a successfully fetched upstream
response.
URN Discovery
Available edition URNs can differ between Perseus CTS and Scaife search results,
and the live inventory can change. Use get_author_resources,
get_work_resources, or list_text_groups before constructing
edition-specific CTS passage URNs. The notebooks select advertised CTS editions
from discovery results instead of assuming that a Scaife edition URN is valid
for Perseus CTS.
The live Perseus CTS implementation may return malformed HTML for
GetFirstUrn and GetPrevNextUrn. The MCP tools detect that response and
derive valid XML results from GetValidReff.
Perseus may also return 429 Too Many Requests when a workflow sends many CTS
requests in a short period. Pause before retrying, reduce concurrency, and add
delays to passage-processing loops. The server currently exposes the upstream
HTTP error instead of retrying automatically.
Setup
1) Install dependencies
Using uv:
uv sync
Or with pip:
pip install -e .
Once a release is published to PyPI, users can install it without cloning the repository:
pip install perseus-mcp
For development and tests:
pip install -e ".[dev]"
2) Run tests
pytest
With uv, use:
uv run --extra dev pytest
3) Run locally
uv run perseus-mcp
The installed console command and module entry point are equivalent:
perseus-mcp
python -m perseus_mcp
4) Inspect tools (optional)
npx @modelcontextprotocol/inspector uv run perseus-mcp
Test strategy and automation
Perseus MCP uses layered checks rather than relying on one end-to-end test. Most behavior is covered by deterministic pytest tests with local XML/JSON fixtures and mocked asynchronous HTTP calls. GitHub Actions separately verifies the supported Python and operating-system matrix, package artifacts, secrets, release tags, and publication.
The workflow files under .github/workflows/ are the executable source of
truth.
Test suite organization
Pytest is configured in pyproject.toml to import from src/ and discover
tests under tests/.
| Test module | Main responsibility |
| --- | --- |
| test_author_resources.py | CTS author, work, and resource parsing; merged-author behavior |
| test_disk_cache.py | Atomic cache writes, cache disabling, cleanup, and concurrent writers |
| test_exploration_tools.py | Discovery, navigation, cache tools, author scope, and structured responses |
| test_greek_query_normalization.py | Unicode Greek, Beta Code, Scaife parameters, and search operators |
| test_limits_and_language.py | Result limits, paging bounds, and language aliases |
| test_packaging.py | Metadata, dependencies, documentation assets, notebooks, and workflow expectations |
| test_scaife_urls.py | Safe URL construction and CTS URN percent encoding |
| test_shared_http_client.py | Connection reuse, event-loop changes, shutdown, and HTTP errors |
| test_xml_hardening.py | Safe XML parsing and rejection of entity-based XML attacks |
A regression fix should include a focused test that fails for the original problem. Tests should assert observable behavior and cover failure paths and boundary values as well as successful calls.
Isolation from Perseus and Scaife
Routine tests do not depend on live upstream services. HTTP helpers are monkeypatched with asynchronous test doubles, while representative CTS XML and Scaife JSON are stored in test fixtures. This keeps CI deterministic when catalogs change or an upstream service is unavailable, avoids unnecessary traffic to public scholarly infrastructure, and makes malformed-response tests safe.
Live read-only probes may be used during manual review for endpoint compatibility or connection-lifecycle changes, but they supplement rather than replace the automated suite.
Async test cleanup
Several tests invoke tools with asyncio.run(), which creates a new event loop
for each call. The server uses a process-wide shared httpx.AsyncClient, so the
autouse fixture in tests/conftest.py closes and resets that client after every
test. Tests that manipulate shared client state must also leave it reset.
Local test commands
Run the complete suite:
python -m pytest
Run a module or one te
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
106.6kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
taste-skill
106.0kAgent skills that give coding agents taste: art direction, reference images and a browser check instead of generic AI pages
headroom
78.3kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
ai-job-search
67.6kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
