Perseus-mcp
Servidor MCP para a Biblioteca Digital Perseus — fornecendo acesso direto a textos gregos antigos, passagens CTS e pesquisa Scaife para modelos de IA.
Documentação
Perseus-mcp
Dê ao Claude / Cursor / Windsurf acesso direto à Biblioteca Digital Perseus — textos em grego antigo e latim, navegação CTS precisa, texto simples, busca e muito mais.
Um servidor MCP de alta qualidade para literatura grega e latina clássica. Ele roda como um servidor FastMCP local para que aplicativos compatíveis com MCP possam anexar essas ferramentas Perseus ao provedor de LLM/modelo de sua escolha.
Recursos
Este servidor expõe vinte e três ferramentas MCP. Cada ferramenta retorna um payload de texto: algumas são XML CTS bruto do Perseus ou JSON do Scaife, enquanto os auxiliares de descoberta e texto simples retornam JSON formatado localmente ou texto legível.
get_passage(urn)— busca uma passagem CTS por URN.get_passage_plus(urn)— busca o texto da passagem mais metadados contextuais.get_passage_plaintext(urn)— busca uma passagem CTS como texto simples legível.get_valid_references(urn, level=None)— recupera referências de citação navegáveis para uma obra ou edição.get_valid_references_json(urn, level=None, limit=100, offset=0)— recupera referências de citação paginadas como JSON (limit: 1–500).count_valid_references(urn, level=None)— conta referências válidas sem retornar a lista completa.get_capabilities()— lista textos/edições disponíveis do CTS Perseus.get_cache_status()— inspeciona o estado do cache de metadados local.refresh_metadata_cache()— atualiza os metadados em cache do CTS e da biblioteca Scaife.clear_metadata_cache()— limpa entradas de cache de metadados em memória e em disco.list_text_groups(language=None, query=None, limit=100, offset=0)— lista autores/grupos de texto e obras correspondentes com metadados de paginação (limit: 1–500).get_author_resources(author, language=None)— lista obras, edições e traduções para um nome de autor correspondente ou URN de grupo de texto CTS.find_author_names(query, language=None, limit=100, offset=0)— encontra nomes de autores/grupos de texto por correspondência parcial de nome com metadados de paginação (limit: 1–500).get_work_resources(urn_or_title, language=None)— lista edições, traduções e recursos para uma obra, opcionalmente filtrados por idioma original.get_label(urn)— busca rótulos de metadados legíveis para uma URN.get_first_urn(urn)— obtém a primeira URN navegável sob uma obra/edição.get_prev_next_urn(urn)— obtém URNs de passagens vizinhas para navegação.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")— busca textos via API de busca Scaife. Consultas em grego podem ser inseridas como grego Unicode (por exemplo,μῆνιν) ou Beta Code (por exemplo,mh=nin).search_within_text(query, text_urn, ..., size=10, offset=0)— busca dentro de uma URN de texto/edição Scaife (size: 1–500).get_passage_highlights(query, passage_urn, ...)— obtém posições de destaque de token Scaife para uma passagem.get_scaife_library_metadata(urn)— obtém metadados JSON Scaife para uma URN de biblioteca.get_scaife_passage_json(urn)— obtém JSON Scaife para uma URN de passagem.get_scaife_passage_text(urn)— obtém texto simples Scaife para uma URN de passagem.
Entrada de Busca em Grego
search_perseus normaliza os termos de busca antes de enviá-los à rota de busca JSON do Scaife.
As consultas devem conter pelo menos um caractere não-branco. A
ferramenta retorna a resposta JSON do Scaife como texto.
| Entrada | Valores aceitos | Comportamento |
|---|---|---|
query | Grego Unicode, como μῆνιν, ou Beta Code, como mh=nin a)/eide | Normalizado para grego Unicode composto (NFC) antes da busca. |
query_format | "auto" (padrão), "betacode" ou "unicode" | auto reconhece marcas Beta Code como =, /, (, ) e *, e termos curtos sem acento com aparência grega como logos. Use um formato explícito para entrada ASCII ambígua. |
language | Aliases gregos: greek, grc, gr; aliases latinos: latin, lat, la | Controla a normalização da consulta, não a filtragem do corpus Scaife. Entrada em branco assume grego; valores não reconhecidos geram erro. |
search_kind | "form" (padrão) ou "lemma" | Busca formas flexionadas ou lemas de dicionário. |
preserve_operators | False (padrão) ou True | Defina como True para frases entre aspas ou operadores como -, |, * e ~, evitando que a detecção de Beta Code os consuma. |
author | Nome do autor/grupo de texto CTS ou URN | Uma correspondência única torna-se um filtro text_group no lado do servidor. Correspondências ambíguas usam filtragem local por prefixo de URN CTS na página retornada. |
text_group, work | URNs de escopo Scaife | Aplica filtros de escopo no lado do servidor diretamente. |
page_num | Número da página | Seleciona a página de resultados. |
Exemplos de consultas com operadores:
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,
)
Para descoberta de inventário, list_text_groups, find_author_names,
get_author_resources e get_work_resources tratam language como um filtro
real de idioma da obra. find_author_names mescla o inventário CTS legado com
o catálogo da biblioteca Scaife, para que autores exclusivos do Scaife, como Philo Judaeus, permaneçam
descobríveis. As ferramentas de passagem e navegação usam URNs CTS, cujo
namespace greekLit/latinLit e identificador de edição já selecionam o texto.
Cache de Metadados Local
As ferramentas de descoberta e navegação armazenam em cache metadados CTS estáveis localmente para evitar
requisições repetidas de vários megabytes a GetCapabilities e GetValidReff. O
cache em disco padrão fica em .cache/perseus-mcp sob o diretório de trabalho atual
e também usa um cache em memória para o processo do servidor em execução.
Configure-o com:
PERSEUS_MCP_CACHE_DIR— substitui o diretório de cache em disco.PERSEUS_MCP_CACHE_TTL_SECONDS— define o TTL do cache; o padrão é 86400 segundos.PERSEUS_MCP_DISABLE_CACHE=1— desativa leituras/gravações de cache em memória e em disco.
O diretório de trabalho atual é o diretório a partir do qual o processo Python é
iniciado. Executar o servidor MCP a partir da raiz do repositório usa
.cache/perseus-mcp; executar um notebook a partir de examples/ usaria
examples/.cache/perseus-mcp. Isso não é uma segunda instância do servidor, apenas um
segundo local de cache para um processo Python separado. Para manter um único local de cache
entre notebooks e clientes MCP, defina PERSEUS_MCP_CACHE_DIR para um caminho
absoluto como /path/to/Perseus-mcp/.cache/perseus-mcp.
As entradas em disco são gravadas em arquivos temporários irmãos exclusivos e substituídas
atomicamente, para que vários processos locais possam compartilhar esse diretório com segurança sem
expor arquivos de cache parcialmente gravados. Falhas de gravação do cache em disco emitem um
MetadataCacheWarning, mas não descartam uma resposta upstream buscada com sucesso.
Descoberta de URN
As URNs de edição disponíveis podem diferir entre o CTS Perseus e os resultados de busca Scaife,
e o inventário ativo pode mudar. Use get_author_resources,
get_work_resources ou list_text_groups antes de construir
URNs de passagem CTS específicas de edição. Os notebooks selecionam edições CTS anunciadas
a partir dos resultados de descoberta em vez de assumir que uma URN de edição Scaife é válida
para o CTS Perseus.
A implementação ativa do CTS Perseus pode retornar HTML malformado para
GetFirstUrn e GetPrevNextUrn. As ferramentas MCP detectam essa resposta e
derivam resultados XML válidos de GetValidReff.
O Perseus também pode retornar 429 Too Many Requests quando um fluxo de trabalho envia muitas
requisições CTS em um curto período. Pause antes de tentar novamente, reduza a concorrência e adicione
atrasos aos loops de processamento de passagens. O servidor atualmente expõe o
erro HTTP upstream em vez de tentar novamente automaticamente.
Configuração
1) Instalar dependências
Usando uv:
uv sync
Ou com pip:
pip install -e .
Quando uma versão for publicada no PyPI, os usuários poderão instalá-la sem clonar o repositório:
pip install perseus-mcp
Para desenvolvimento e testes:
pip install -e ".[dev]"
2) Executar testes
pytest
Com uv, use:
uv run --extra dev pytest
3) Executar localmente
uv run perseus-mcp
O comando de console instalado e o ponto de entrada do módulo são equivalentes:
perseus-mcp
python -m perseus_mcp
4) Inspecionar ferramentas (opcional)
npx @modelcontextprotocol/inspector uv run perseus-mcp
Estratégia de teste e automação
O Perseus MCP usa verificações em camadas em vez de depender de um único teste ponta a ponta. A maior parte do comportamento é coberta por testes pytest determinísticos com fixtures XML/JSON locais e chamadas HTTP assíncronas simuladas. O GitHub Actions verifica separadamente a matriz suportada de Python e sistemas operacionais, artefatos de pacote, segredos, tags de versão e publicação.
Os arquivos de fluxo de trabalho sob .github/workflows/ são a fonte executável da
verdade.
Organização do conjunto de testes
O Pytest é configurado em pyproject.toml para importar de src/ e descobrir
testes sob tests/.
| Módulo de teste | Responsabilidade principal |
|---|---|
test_author_resources.py | Análise de autor, obra e recurso CTS; comportamento de autor mesclado |
test_disk_cache.py | Gravações atômicas de cache, desativação de cache, limpeza e gravadores concorrentes |
test_exploration_tools.py | Descoberta, navegação, ferramentas de cache, escopo de autor e respostas estruturadas |
test_greek_query_normalization.py | Grego Unicode, Beta Code, parâmetros Scaife e operadores de busca |
test_limits_and_language.py | Limites de resultados, limites de paginação e aliases de idioma |
test_packaging.py | Metadados, dependências, ativos de documentação, notebooks e expectativas de fluxo de trabalho |
test_scaife_urls.py | Construção segura de URLs e codificação percentual de URN CTS |
test_shared_http_client.py | Reutilização de conexão, mudanças de event-loop, desligamento e erros HTTP |
test_xml_hardening.py | Análise XML segura e rejeição de ataques XML baseados em entidades |
Uma correção de regressão deve incluir um teste focado que falhe para o problema original. Os testes devem afirmar o comportamento observável e cobrir caminhos de falha e valores de limite, bem como chamadas bem-sucedidas.
Isolamento do Perseus e Scaife
Os testes de rotina não dependem de serviços upstream ativos. Os auxiliares HTTP são monkeypatched com duplos de teste assíncronos, enquanto XML CTS representativo e JSON Scaife são armazenados em fixtures de teste. Isso mantém o CI determinístico quando catálogos mudam ou um serviço upstream está indisponível, evita tráfego desnecessário para infraestrutura acadêmica pública e torna os testes de resposta malformada seguros.
Sondas ativas somente leitura podem ser usadas durante revisão manual para compatibilidade de endpoint ou mudanças no ciclo de vida da conexão, mas elas complementam em vez de substituir o conjunto automatizado.
Limpeza de teste assíncrono
Vários testes invocam ferramentas com asyncio.run(), o que cria um novo event loop
para cada chamada. O servidor usa um httpx.AsyncClient compartilhado em todo o processo, então a
fixture autouse em tests/conftest.py fecha e redefine esse cliente após cada
teste. Testes que manipulam o estado compartilhado do cliente também devem deixá-lo redefinido.
Comandos de teste locais
Execute o conjunto completo:
python -m pytest
Execute um módulo ou um teste:
python -m pytest tests/test_disk_cache.py
python -m pytest tests/test_disk_cache.py::test_disk_cache_set_writes_readable_content
Mostre testes ignorados, os testes mais lentos e variáveis locais em caso de falha:
python -m pytest -ra --durations=10 -l
Desative leituras e gravações do cache de metadados durante uma execução de teste:
PERSEUS_MCP_DISABLE_CACHE=1 python -m pytest
Equivalente no PowerShell:
$env:PERSEUS_MCP_DISABLE_CACHE = "1"
python -m pytest
Matriz de teste do GitHub Actions
.github/workflows/tests.yml instala o projeto editável com dependências de
desenvolvimento e executa python -m pytest em:
- Ubuntu e Windows;
- Python 3.11, 3.12 e 3.13.
A matriz usa fail-fast: false, para que cada trabalho de plataforma/versão termine mesmo
quando um falha. Isso torna regressões específicas de versão e específicas do Windows
visíveis em uma única execução. Mudanças somente de documentação sob docs/** são excluídas
do fluxo de trabalho de teste Python; filtros exatos de evento e branch permanecem definidos no
arquivo de fluxo de trabalho.
Validação de pacote
.github/workflows/package.yml verifica se o repositório produz uma distribuição de
código-fonte válida e uma wheel universal. Ele instala Python 3.12, executa:
python -m build
python -m twine check dist/*
e envia dist/ como o artefato do fluxo de trabalho python-package. O fluxo de trabalho é
filtrado por caminho para arquivos relevantes ao pacote e suporta despacho manual.
tests/test_packaging.py complementa essa compilação verificando expectativas no nível do repositório,
como metadados, dependências, arquivos de documentação, JSON de notebook
e configuração de fluxo de trabalho. Ambas as camadas importam: testes de metadados podem passar
enquanto uma compilação isolada falha, e um pacote pode compilar enquanto ativos
obrigatórios do repositório estão ausentes.
Varredura de segredos
.github/workflows/secret-scan.yml rejeita chaves OpenRouter rastreadas que correspondem a:
sk-or-v1-[A-Za-z0-9_-]{20,}
O fluxo de trabalho relata os arquivos afetados sem imprimir o segredo correspondente. Uma
chave detectada deve ser removida e rotacionada; a verificação nunca deve ser ignorada.
Esta varredura focada não substitui a higiene normal de credenciais: não faça commit de
arquivos .env, tokens, configuração MCP privada ou saídas de notebook contendo
credenciais.
Segurança de código e dependências
.github/workflows/codeql.yml analisa tanto o código-fonte Python quanto os fluxos de trabalho do GitHub
Actions em pushes para main e development, em pull requests, e
semanalmente. A análise Python usa o conjunto de consultas security-and-quality do CodeQL, enquanto
a análise de fluxos de trabalho usa o conjunto security-extended. O fluxo de trabalho também suporta
execução manual para verificações de configuração.
.github/workflows/dependency-review.yml é executado em todo pull request e falha
quando uma dependência alterada introduz uma vulnerabilidade conhecida de gravidade moderada ou
superior. O Dependabot verifica dependências Python e GitHub Actions
semanalmente. Seus rótulos padrão são usados intencionalmente para que pull requests de atualização
não dependam de rótulos específicos do repositório pré-criados.
Portões de liberação e publicação
.github/workflows/release.yml é executado para tags v* ou execução manual. Para execuções
de tag, ele verifica se a tag é igual a v<project.version>, compila o wheel e o
arquivo fonte, valida ambos com Twine, anexa-os a uma release do GitHub gerada
e despacha o fluxo de trabalho do PyPI usando a mesma tag.
.github/workflows/publish.yml requer uma referência de tag, repete a
verificação de tag/versão, recompila e revalida os artefatos, e publica através
da publicação confiável do PyPI. O ambiente GitHub protegido pypi usa OIDC
(id-token: write), portanto nenhum token de API PyPI de longa duração é armazenado.
Recompilar durante a publicação evita confiar em um artefato de fluxo de trabalho não relacionado, enquanto a verificação repetida de tag impede a publicação a partir de um branch ou tag de release incompatível.
Implantação de documentação
.github/workflows/pages.yml compila docs/ com Jekyll e implanta o
artefato gerado no GitHub Pages após alterações na documentação chegarem a main ou
master. Este site Pages é destinado principalmente a usuários finais; documentação de
desenvolvimento e estratégia de teste vive no README deste repositório. Pull requests que
alteram a documentação ou o fluxo de trabalho Pages também compilam o site para validação,
sem implantá-lo. Visualize o site gerado em vez de abrir
docs/index.html diretamente: a página inicial agora compartilha o layout Jekyll usado pelas
outras páginas.
Interpretando falhas
- Falhas em todos os jobs da matriz geralmente indicam uma regressão geral.
- Uma falha em uma única versão Python sugere sintaxe, dependências ou comportamento da biblioteca padrão específicos da versão.
- Falhas apenas no Windows geralmente envolvem caminhos, permissões, atributos somente leitura ou ciclo de vida do event loop.
- Uma falha de pacote com jobs pytest verdes geralmente diz respeito a metadados, manifests, renderização do README ou isolamento de build.
- Uma falha na varredura de segredos requer remoção e rotação de credenciais.
- Uma falha de release antes da publicação geralmente significa que a tag e
project.versionnão correspondem.
Entenda a falha antes de reexecutar um job e preserve logs de fluxo de trabalho úteis ou tracebacks no pull request quando a causa não for óbvia.
Convenções de nível de mantenedor para estender o conjunto também são mantidas ao lado dos
testes em tests/testing.md.
Exemplos de notebooks
O diretório examples/ inclui notebooks Jupyter que demonstram tanto chamadas diretas de endpoint quanto uso de cliente MCP com dados reais em grego e latim:
examples/00_install_and_run_perseus_mcp.ipynb— guia de instalação e inicialização cobrindo PyPI, pip, uv, desenvolvimento local do repositório, configuração de cliente MCP, verificação, atualizações e solução de problemas.examples/01_basic_cts_workflow.ipynb— solicitações CTS diretas mínimas.examples/02_search_and_navigation.ipynb— busca JSON Scaife direta e navegação CTS a partir de referências válidas.examples/03_mcp_connection_homer_iliad.ipynb— conexão de cliente FastMCP, descoberta de recursos de Homero e análise de passagens gregas da Ilíada.examples/04_mcp_greek_search_and_navigation.ipynb— busca grega MCP com Unicode/Beta Code, referências válidas e navegação de passagens.examples/05_mcp_all_tools.ipynb— catálogo completo de ferramentas MCP com descrições e esquemas de entrada.examples/06_openrouter_llm_mcp_interaction.ipynb— loop opcional de chamada de ferramentas LLM OpenRouter sobre as ferramentas MCP locais, usando o Free Models Router do OpenRouter por padrão.examples/07_mcp_advanced_search_options.ipynb— busca de forma/lema MCP, consultas de operador Scaife e exemplos de busca com escopo de autor.examples/08_mcp_cache_and_search_tools.ipynb— demonstração avançada de ferramentas de cache, referências paginadas, busca com escopo, busca de leitor, destaques e recuperação de metadados/texto Scaife.examples/09_openrouter_philo_politeia_analysis.ipynb— análise assistida por OpenRouter, primeiro as evidências, deπολιτείαem Fílon de Alexandria usando resultados de busca MCP com escopo e passagens citadas.examples/10_mcp_latin_augustine_workflow.ipynb— descoberta em língua latina, navegação CTS, recuperação de passagens e uma pequena análise de texto usando seleções das Epistulae de Agostinho.
Execute-os após instalar as dependências do projeto. Os notebooks MCP usam
o transporte de cliente em processo do FastMCP e chamam as mesmas ferramentas expostas a
clientes MCP externos. O notebook OpenRouter opcional também requer uma
chave de API OpenRouter; o próprio servidor MCP não.
Células de configuração do notebook instalam helpers exclusivos do notebook, como python-dotenv
diretamente. Esses helpers não são dependências de runtime principais de perseus-mcp.
Configurar a chave de API OpenRouter
Para examples/06_openrouter_llm_mcp_interaction.ipynb e
examples/09_openrouter_philo_politeia_analysis.ipynb, copie .env.example para
.env na raiz do projeto e substitua o espaço reservado:
OPENROUTER_API_KEY=sk-or-v1-...
Obtenha sua chave de API em openrouter.ai. Veja
a documentação da chave de API do OpenRouter para
detalhes de autenticação.
O arquivo .env é ignorado pelo Git. Você também pode definir OPENROUTER_API_KEY no seu
ambiente ou inseri-la com segurança quando o notebook solicitar.
Ambos os notebooks OpenRouter usam openrouter/free por padrão. Este roteador seleciona
entre modelos gratuitos atualmente disponíveis no OpenRouter e filtra por capacidades
exigidas pela solicitação, como chamada de ferramentas ou saída estruturada. Ele evita
vincular os exemplos a um único modelo gratuito que pode ser removido posteriormente ou ficar
temporariamente indisponível. A compensação é reprodutibilidade reduzida: execuções separadas podem usar
modelos concretos diferentes, então os notebooks registram o modelo resolvido retornado
pelo OpenRouter. Defina OPENROUTER_MODEL para um slug de modelo fixo quando a seleção
exata do modelo for importante.
O notebook 06_ pode ser salvo e commitado com suas saídas de LLM e chamadas de ferramentas para que
renderizem no GitHub. Variáveis Python e memória do kernel não são armazenadas em um
arquivo .ipynb, e o notebook não imprime a chave de API. Antes de commitar uma
execução com credenciais, revise as saídas visíveis e verifique se há uma chave OpenRouter completa:
rg "sk-or-v1-[A-Za-z0-9_-]{20,}" examples/06_openrouter_llm_mcp_interaction.ipynb
O comando não deve produzir saída. Ele não corresponde ao espaço reservado
sk-or-v1-... documentado.
Usando com qualquer cliente LLM compatível com MCP
Este projeto não requer um LLM específico. Configure seu cliente para iniciar o servidor MCP local com:
uv --directory /full/path/to/Perseus-mcp run perseus-mcp
A maioria dos clientes MCP precisa das mesmas partes: nome do servidor perseus, comando uv, args --directory /full/path/to/Perseus-mcp run perseus-mcp e um ambiente vazio, a menos que você tenha personalizações locais. Veja docs/enduser.md para orientação genérica de clientes e docs/architecture.md para as escolhas de arquitetura, incluindo por que o FastMCP é usado.
Claude Desktop e Claude Code
O servidor roda com Claude via stdio, sem exigir OpenRouter ou chave de API (OpenRouter só é necessário para o cliente de demonstração opcional).
Claude Desktop — adicione a claude_desktop_config.json:
{
"mcpServers": {
"perseus": {
"command": "uv",
"args": ["--directory", "/full/path/to/Perseus-mcp", "run", "perseus-mcp"]
}
}
}
Reinicie o Claude Desktop; as ferramentas Perseus aparecem na lista de ferramentas.
Claude Code — uma linha:
claude mcp add perseus -- uv --directory /full/path/to/Perseus-mcp run perseus-mcp
Verificado contra um handshake MCP stdio: todas as 23 ferramentas registram e chamadas ao vivo retornam (testado com search_perseus e list_text_groups).
Compilar uma distribuição PyPI
Instale as dependências de desenvolvimento, depois compile e valide ambos os formatos de distribuição:
python -m pip install -e ".[dev]"
python -m build
python -m twine check dist/*
A compilação cria um wheel e um arquivo fonte em dist/. Teste o wheel em um
ambiente virtual limpo antes de publicar. Envie para o TestPyPI primeiro:
python -m twine upload --repository testpypi dist/*
Após verificar a instalação a partir do TestPyPI, envie os mesmos artefatos para o PyPI:
python -m twine upload dist/*
O PyPI não permite substituir uma release existente. Atualize project.version em
pyproject.toml, recompile a partir de um diretório dist/ limpo e publique cada
versão apenas uma vez. O fluxo de trabalho de compilação do pacote também compila e verifica artefatos
no CI sem publicá-los.
Release automatizada do GitHub e publicação no PyPI
A automação de release segue o mesmo padrão de publicação confiável do MorphKit:
- Defina a versão da release em
pyproject.toml, por exemplo1.2.3. - Mescle a alteração de versão no commit que deve ser lançado.
- Crie e envie a tag correspondente, por exemplo
v1.2.3. - O fluxo de trabalho
Build release artifactsverifica a correspondência tag/versão, compila e valida ambas as distribuições e as anexa a uma release gerada no GitHub. - Esse fluxo de trabalho despacha
Publish to PyPI, que recompila e valida o pacote antes de publicar através da publicação confiável do PyPI.
Configure o repositório uma vez antes do primeiro upload automatizado:
- Crie um ambiente GitHub Actions chamado
pypi. - Nas configurações existentes do projeto PyPI, ou como um publicador pendente antes do
primeiro upload, adicione um publicador confiável para o proprietário
tonyjurg, repositórioPerseus-mcp, fluxo de trabalhopublish.ymle ambientepypi. - Não adicione um token de API PyPI; o fluxo de trabalho usa GitHub OIDC com
id-token: write.
Os fluxos de trabalho rejeitam uma tag como v1.2.4 quando project.version ainda é
1.2.3. As versões do PyPI são imutáveis, então incremente a versão antes de tentar novamente
uma release que já foi enviada.
Contribuindo e relatando problemas
Relatórios de bugs, correções de documentação, solicitações de recursos focadas e pull requests são bem-vindos. Por favor, relate problemas através do rastreador de issues do GitHub e inclua o comando, a versão Python, o cliente MCP, os argumentos da ferramenta, o traceback e qualquer URN CTS relevante ou consulta de busca grega quando possível.
Veja docs/contributing.md para orientação de contribuição.
Divulgação responsável
Este projeto foi criado com assistência do OpenAI Codex. O mantenedor humano permanece responsável por revisar, testar e aceitar todas as alterações de código e documentação.
Licença
Este projeto é lançado sob a Licença MIT. Veja LICENSE para detalhes.