Perseus MCP Server: End-User Guide

This guide explains how to install, run, and use the perseus MCP server in tools like Cursor or Claude Desktop.

What You Get

The server provides tools for Greek text research against Perseus CTS and Scaife search. It is designed as a local MCP bridge: your LLM client starts this server, discovers its tools, and can then call those tools with structured arguments instead of relying on ad hoc web browsing or copied URLs.

Use it when you want an LLM to help with tasks such as:

The current implementation exposes twelve text-returning tools:

Raw CTS operations return XML text, search_perseus returns Scaife JSON text, discovery helpers return locally shaped JSON text, and get_passage_plaintext returns readable passage text.

Prerequisites

Install

From the project root:

uv sync

Alternative:

pip install -e .

Run the Server

uv run server.py

Quick Tool Testing (Inspector)

npx @modelcontextprotocol/inspector uv run server.py

Use the inspector UI to call tools and verify responses.

Use with the LLM Client of Your Choice

MCP separates the tool server from the model. This repository does not choose an LLM for you. Instead, it exposes tools that any MCP-capable client can attach to a model from its supported providers. The same local server command is the key piece of configuration:

uv --directory /full/path/to/Perseus-mcp run server.py

When configuring a client, map that command into the client’s MCP-server config. Most clients ask for the same conceptual fields:

Field Value
Server name perseus
Command uv
Arguments --directory, /full/path/to/Perseus-mcp, run, server.py
Environment usually empty
Transport stdio/local process, if the client asks

After connection, ask your client to list MCP tools or inspect the perseus server. You should see tools such as get_author_resources, get_passage_plaintext, get_prev_next_urn, and search_perseus.

Prompting pattern for any LLM

For reliable results, ask the model to use the tools in a research sequence:

  1. Discover: call get_author_resources("urn:cts:greekLit:tlg0012", language="greek") or list_text_groups(language="greek", query="Homer").
  2. Select a URN: choose an edition/work URN from the JSON or XML result.
  3. Fetch or navigate: call get_passage_plaintext(...), get_valid_references(...), or get_prev_next_urn(...).
  4. Verify: when precision matters, call get_passage(...) or get_passage_plus(...) to inspect the raw CTS XML.

If your preferred LLM application does not support MCP natively, you can still use the notebooks or write a small Python adapter with FastMCP’s Client to call these tools and pass the results into that application manually. The optional examples/06_openrouter_llm_mcp_interaction.ipynb notebook demonstrates such a client-side adapter for OpenRouter; it requires an OpenRouter API key, unlike the MCP server and its public Perseus/Scaife upstream calls.

To configure that optional notebook, copy .env.example to .env in the project root and replace the placeholder:

OPENROUTER_API_KEY=sk-or-v1-...

Get your API key at openrouter.ai. See OpenRouter’s API key documentation for authentication details. Notebook 06_ loads the project-root .env file without overriding an existing environment variable. The .env file is ignored by Git and must not be committed.

You may save and commit notebook 06_ with its LLM and tool-call outputs so they render on GitHub. The notebook file does not store Python variables or kernel memory, and the implementation does not print the key. Review visible outputs and run this secret scan before committing:

rg "sk-or-v1-[A-Za-z0-9_-]{20,}" examples/06_openrouter_llm_mcp_interaction.ipynb

The command should produce no output. It does not match the documented sk-or-v1-... placeholder.

Configure Cursor

Edit your mcp.json:

Example:

{
  "mcpServers": {
    "perseus": {
      "command": "uv",
      "args": ["--directory", "/full/path/to/Perseus-mcp", "run", "server.py"],
      "env": {}
    }
  }
}

Restart Cursor, then confirm the perseus server and tools appear.

Configure Claude Desktop

Claude Desktop is an MCP-capable host for local stdio servers. The latest Claude-related project documentation already treats Claude Desktop like Cursor and MCP Inspector: it launches the same local perseus server and then exposes the discovered tools to the selected Claude conversation. The only Claude-specific part is where you place the JSON configuration and how you restart/debug the desktop app.

Open Claude Desktop settings, go to Developer, and choose Edit Config. You can also edit the configuration file directly:

Add or merge the perseus entry under mcpServers:

{
  "mcpServers": {
    "perseus": {
      "command": "uv",
      "args": [
        "--directory",
        "/full/path/to/Perseus-mcp",
        "run",
        "server.py"
      ],
      "env": {}
    }
  }
}

Use an absolute project path. If Claude Desktop cannot find uv, replace "uv" with the full executable path returned by which uv on macOS or where uv on Windows. Save the file and completely quit and reopen Claude Desktop so it reloads the MCP server list.

After restart, open a new Claude conversation and look for the MCP/tool indicator or ask Claude to list available MCP tools. You should see the same perseus tools documented above, including get_author_resources, get_passage_plaintext, get_prev_next_urn, and search_perseus.

Generic MCP JSON Example

Some clients use a JSON structure similar to Cursor’s but with different file locations. If your client supports local stdio MCP servers, adapt this shape:

{
  "mcpServers": {
    "perseus": {
      "command": "uv",
      "args": [
        "--directory",
        "/full/path/to/Perseus-mcp",
        "run",
        "server.py"
      ],
      "env": {}
    }
  }
}

Check your client’s documentation for the exact config-file path and whether it uses mcpServers, servers, or another top-level key. The command and argument values are the important part.

Discovery Tools

The discovery helpers are useful when you do not yet know the exact CTS URN to fetch:

Examples:

URN Tips

Typical CTS URN patterns:

Do not assume that an edition URN returned by Scaife search is also available from Perseus CTS. Discover CTS editions first with get_author_resources(...) or get_work_resources(...). For example, recorded notebook runs have shown a Perseus CTS Iliad edition ending in perseus-grc1 while Scaife search results used perseus-grc2; either inventory may change.

Recommended workflow:

  1. Start with list_text_groups(...), get_author_resources(...), or get_work_resources(...) to discover useful URNs without parsing the full capabilities XML manually.
  2. Use get_label(urn) for human-readable metadata.
  3. Use get_valid_references(urn) and optionally level to discover citations.
  4. Fetch text with get_passage(...), get_passage_plus(...), or get_passage_plaintext(...).
  5. Navigate using get_prev_next_urn(...).

get_first_urn(...) and get_prev_next_urn(...) normally request the corresponding CTS operations. If Perseus returns malformed HTML for those operations, the server derives a well-formed XML result from GetValidReff.

Troubleshooting