rslapp 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. rslapp-1.0.0/.gitignore +52 -0
  2. rslapp-1.0.0/LICENSE +21 -0
  3. rslapp-1.0.0/PKG-INFO +179 -0
  4. rslapp-1.0.0/README.md +150 -0
  5. rslapp-1.0.0/pyproject.toml +62 -0
  6. rslapp-1.0.0/src/rslapp/__init__.py +4 -0
  7. rslapp-1.0.0/src/rslapp/config.py +77 -0
  8. rslapp-1.0.0/src/rslapp/core/__init__.py +16 -0
  9. rslapp-1.0.0/src/rslapp/core/dedup.py +319 -0
  10. rslapp-1.0.0/src/rslapp/core/errors.py +31 -0
  11. rslapp-1.0.0/src/rslapp/core/find.py +213 -0
  12. rslapp-1.0.0/src/rslapp/core/models.py +177 -0
  13. rslapp-1.0.0/src/rslapp/core/references.py +166 -0
  14. rslapp-1.0.0/src/rslapp/core/related.py +438 -0
  15. rslapp-1.0.0/src/rslapp/core/repeat.py +132 -0
  16. rslapp-1.0.0/src/rslapp/core/search.py +200 -0
  17. rslapp-1.0.0/src/rslapp/core/views.py +154 -0
  18. rslapp-1.0.0/src/rslapp/exporters/__init__.py +165 -0
  19. rslapp-1.0.0/src/rslapp/exporters/base.py +43 -0
  20. rslapp-1.0.0/src/rslapp/exporters/csv.py +296 -0
  21. rslapp-1.0.0/src/rslapp/exporters/dois.py +76 -0
  22. rslapp-1.0.0/src/rslapp/exporters/json.py +43 -0
  23. rslapp-1.0.0/src/rslapp/exporters/openalex_url.py +80 -0
  24. rslapp-1.0.0/src/rslapp/exporters/ris.py +115 -0
  25. rslapp-1.0.0/src/rslapp/prompts.py +51 -0
  26. rslapp-1.0.0/src/rslapp/server.py +246 -0
  27. rslapp-1.0.0/src/rslapp/sources/__init__.py +8 -0
  28. rslapp-1.0.0/src/rslapp/sources/base.py +24 -0
  29. rslapp-1.0.0/src/rslapp/sources/crossref.py +529 -0
  30. rslapp-1.0.0/src/rslapp/sources/openalex.py +1054 -0
  31. rslapp-1.0.0/src/rslapp/sources/semantic_scholar.py +774 -0
  32. rslapp-1.0.0/src/rslapp/store/__init__.py +156 -0
  33. rslapp-1.0.0/src/rslapp/store/_atomic.py +173 -0
  34. rslapp-1.0.0/src/rslapp/store/cache.py +86 -0
  35. rslapp-1.0.0/src/rslapp/store/log.py +134 -0
  36. rslapp-1.0.0/tests/core/test_dedup.py +487 -0
  37. rslapp-1.0.0/tests/core/test_find.py +331 -0
  38. rslapp-1.0.0/tests/core/test_models.py +84 -0
  39. rslapp-1.0.0/tests/core/test_references.py +322 -0
  40. rslapp-1.0.0/tests/core/test_related.py +541 -0
  41. rslapp-1.0.0/tests/core/test_repeat.py +390 -0
  42. rslapp-1.0.0/tests/core/test_search.py +695 -0
  43. rslapp-1.0.0/tests/core/test_views.py +411 -0
  44. rslapp-1.0.0/tests/exporters/test_csv.py +370 -0
  45. rslapp-1.0.0/tests/exporters/test_dois.py +79 -0
  46. rslapp-1.0.0/tests/exporters/test_json.py +134 -0
  47. rslapp-1.0.0/tests/exporters/test_openalex_url.py +127 -0
  48. rslapp-1.0.0/tests/exporters/test_ris.py +286 -0
  49. rslapp-1.0.0/tests/sources/test_crossref.py +597 -0
  50. rslapp-1.0.0/tests/sources/test_crossref_find_by_doi.py +184 -0
  51. rslapp-1.0.0/tests/sources/test_openalex.py +621 -0
  52. rslapp-1.0.0/tests/sources/test_openalex_dois.py +282 -0
  53. rslapp-1.0.0/tests/sources/test_openalex_find_by_doi.py +209 -0
  54. rslapp-1.0.0/tests/sources/test_openalex_related.py +366 -0
  55. rslapp-1.0.0/tests/sources/test_semantic_scholar.py +607 -0
  56. rslapp-1.0.0/tests/sources/test_semantic_scholar_find_by_doi.py +251 -0
  57. rslapp-1.0.0/tests/sources/test_semantic_scholar_related.py +343 -0
  58. rslapp-1.0.0/tests/store/test_log_merge.py +174 -0
  59. rslapp-1.0.0/tests/store/test_store.py +425 -0
  60. rslapp-1.0.0/tests/test_config.py +215 -0
  61. rslapp-1.0.0/tests/test_prompts.py +59 -0
  62. rslapp-1.0.0/tests/test_server.py +234 -0
  63. rslapp-1.0.0/tests/test_server_export_list.py +430 -0
  64. rslapp-1.0.0/tests/test_server_find_and_repeat.py +223 -0
  65. rslapp-1.0.0/tests/test_server_get_list.py +276 -0
  66. rslapp-1.0.0/tests/test_server_plan_search.py +162 -0
  67. rslapp-1.0.0/tests/test_server_related.py +187 -0
  68. rslapp-1.0.0/tests/test_server_search_works.py +242 -0
  69. rslapp-1.0.0/tests/test_server_three_sources.py +176 -0
@@ -0,0 +1,52 @@
1
+ # Sistema e editor
2
+ .DS_Store
3
+ Thumbs.db
4
+ *.swp
5
+ .idea/
6
+ .vscode/
7
+
8
+ # Segredos: nunca vão para o git
9
+ .env
10
+ .env.*
11
+ !.env.example
12
+ .pypirc
13
+ *.pem
14
+ *.key
15
+ *.p12
16
+ *.pfx
17
+ secrets.*
18
+ credentials.*
19
+
20
+ # Configuração local de clientes MCP: o bloco "env" costuma trazer chaves de API
21
+ .mcp.json
22
+ claude_desktop_config.json
23
+
24
+ # Configuração local dos agentes: chaves de ferramentas locais ficam aqui, nunca no git
25
+ .claude/settings.local.json
26
+
27
+ # Árvores de trabalho do Playmaker, para agentes em paralelo
28
+ .worktrees/
29
+
30
+ # Python
31
+ __pycache__/
32
+ *.py[cod]
33
+ .venv/
34
+ venv/
35
+ *.egg-info/
36
+ dist/
37
+ build/
38
+ .pytest_cache/
39
+ .ruff_cache/
40
+ .coverage
41
+
42
+ # Dados e exportações de teste feitos na pasta do projeto (os dados reais ficam na pasta do usuário)
43
+ # Trazem nome, ORCID e afiliação de autores (D-004): nunca vão para o git.
44
+ /data/
45
+ /exports/
46
+ /searches/
47
+ /lists/
48
+ /cache/
49
+ /log.md
50
+ /*.ris
51
+ /*.csv
52
+ *.log
rslapp-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Erick Cardoso Mendes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
rslapp-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,179 @@
1
+ Metadata-Version: 2.5
2
+ Name: rslapp
3
+ Version: 1.0.0
4
+ Summary: Servidor MCP em Python para busca acadêmica e exportação para revisão sistemática
5
+ Project-URL: Homepage, https://github.com/Erick-wilding675/RSL-MCP-APP
6
+ Project-URL: Issues, https://github.com/Erick-wilding675/RSL-MCP-APP/issues
7
+ Author: Erick Cardoso Mendes
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: bibliometrics,crossref,mcp,openalex,semantic-scholar,systematic-review,vosviewer
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Natural Language :: Portuguese (Brazilian)
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: httpx
23
+ Requires-Dist: mcp<3,>=2
24
+ Requires-Dist: typing-extensions
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest; extra == 'dev'
27
+ Requires-Dist: ruff; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # RSL.app
31
+
32
+ **Servidor MCP gratuito para revisão sistemática de literatura.** Você pede à sua IA, em linguagem natural, os artigos de um tema. Ela busca no OpenAlex, na Crossref e na Semantic Scholar, junta os resultados sem duplicatas e grava um arquivo pronto para abrir no [VOSviewer](https://www.vosviewer.com/), com autores, afiliações, palavras-chave, referências e citações.
33
+
34
+ > Exemplo: *"Quero os artigos sobre burnout em professores da educação básica e, separado, sobre inteligência artificial na correção de redações. Exporte cada um em RIS."*
35
+ > A IA faz duas buscas, monta duas listas e entrega dois arquivos `.ris`. Cada busca fica registrada num log legível, que você pode anexar à metodologia do seu artigo.
36
+
37
+ O RSL.app roda **na sua máquina** (self-hosted), com as **suas** chaves gratuitas. Ele não tem servidor central, não cobra nada e não manda seus dados para lugar nenhum além das próprias bases consultadas.
38
+
39
+ ## O que ele faz
40
+
41
+ - **Busca por tema, palavra-chave, subtema ou título** nas três bases abertas, ao mesmo tempo.
42
+ - **Tira as duplicatas.** O mesmo artigo vindo de mais de uma base aparece uma vez só, com os ids de cada base.
43
+ - **Avisa quando a lista está incompleta.** Se uma base falha ou um limite corta a busca, a lista sai marcada como incompleta, com o motivo. Nenhuma lista incompleta passa por completa.
44
+ - **Acha um artigo específico** pelo título ou pelo DOI.
45
+ - **Traz as referências de um artigo e quem o cita**, como uma lista própria.
46
+ - **Registra cada busca num log** (`log.md`): o pedido, a string enviada a cada base, a data, quantos artigos cada base achou e se veio do cache.
47
+ - **Repete uma busca do log** com as mesmas strings, para atualizar uma revisão.
48
+ - **Exporta em cinco formatos:** RIS, CSV no padrão do Scopus, JSON completo, lista de DOIs e URL de consulta do OpenAlex. O RIS, o CSV e a lista de DOIs abrem no VOSviewer sem edição.
49
+ - **Guarda tudo na sua máquina:** listas, log, exportações e um cache das respostas, que expira em 7 dias e economiza sua cota.
50
+
51
+ Ele **não** baixa texto completo de artigos, não abre o VOSviewer sozinho e não junta buscas diferentes numa lista só: cada pedido vira a sua própria lista.
52
+
53
+ ## Do que você precisa
54
+
55
+ 1. **Uma IA que fale MCP**, como o Claude Desktop, o Claude Code ou outro cliente compatível.
56
+ 2. **O [uv](https://docs.astral.sh/uv/getting-started/installation/)** instalado. É ele que baixa e roda o RSL.app; você não precisa instalar o Python à mão.
57
+ 3. **Uma chave gratuita do OpenAlex**, obrigatória. Crie em [openalex.org/settings/api](https://openalex.org/settings/api) e **ative pelo link que chega no e-mail**: a chave só funciona depois disso. Ela dá 10.000 créditos por dia, e uma busca gasta cerca de 10.
58
+ 4. **Opcional: uma chave gratuita da [Semantic Scholar](https://www.semanticscholar.org/product/api#api-key-form).** Sem ela a Semantic Scholar funciona, mas recusa pedidos com mais frequência.
59
+
60
+ A Crossref não precisa de chave.
61
+
62
+ ## Instalação no Claude Desktop
63
+
64
+ 1. Feche o Claude Desktop por completo (no Windows, clique com o botão direito no ícone perto do relógio e escolha **Quit**).
65
+ 2. Abra a configuração: **Settings → Developer → Edit Config**. O arquivo é o `claude_desktop_config.json`.
66
+ 3. Acrescente o `rslapp` dentro de `"mcpServers"`:
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "rslapp": {
72
+ "command": "uvx",
73
+ "args": ["rslapp"],
74
+ "env": {
75
+ "OPENALEX_API_KEY": "sua-chave-do-openalex",
76
+ "SEMANTIC_SCHOLAR_API_KEY": "sua-chave-da-semantic-scholar"
77
+ }
78
+ }
79
+ }
80
+ }
81
+ ```
82
+
83
+ 4. Salve e abra o Claude Desktop de novo. O `rslapp` aparece na lista de ferramentas, com oito ferramentas.
84
+ 5. Para conferir, peça: *"Quais fontes do rslapp estão prontas?"*. A IA chama `list_sources` e deve mostrar as três fontes como `ok`.
85
+
86
+ **Se o Claude Desktop não achar o `uvx`:** troque `"uvx"` pelo caminho completo. No Windows, costuma ser `C:\\Users\\<seu-usuário>\\.local\\bin\\uvx.exe`. No macOS e no Linux, rode `which uvx` no terminal para descobrir.
87
+
88
+ **Suas chaves ficam só no arquivo de configuração da sua máquina.** O RSL.app nunca as escreve no log, nas listas nem nas respostas à IA.
89
+
90
+ ### No Claude Code
91
+
92
+ ```bash
93
+ claude mcp add rslapp -e OPENALEX_API_KEY=sua-chave -e SEMANTIC_SCHOLAR_API_KEY=sua-chave -- uvx rslapp
94
+ ```
95
+
96
+ ### Em outros clientes MCP
97
+
98
+ O RSL.app é um servidor MCP por **stdio**. O comando é `uvx rslapp`, e as chaves vão como variáveis de ambiente.
99
+
100
+ ## Como usar
101
+
102
+ Fale com a IA normalmente. Alguns pedidos que funcionam bem:
103
+
104
+ - *"Busque artigos sobre aprendizagem baseada em projetos no ensino de ciências e exporte em RIS."*
105
+ - *"Ache o artigo 'Software survey: VOSviewer, a computer program for bibliometric mapping' e me traga até 200 trabalhos que o citam, de cada base."*
106
+ - *"Me mostre o log das buscas de hoje."*
107
+ - *"Repita a busca s-0003 e exporte em CSV."*
108
+
109
+ A IA planeja antes de buscar: se o pedido tem assuntos diferentes, ela faz uma busca e uma lista para cada um.
110
+
111
+ ### Abrir no VOSviewer
112
+
113
+ | Arquivo | Como abrir no VOSviewer |
114
+ |---|---|
115
+ | `.ris` | Create → *Create a map based on bibliographic data* → *Read data from reference manager files* → RIS |
116
+ | `.csv` | Create → *Create a map based on bibliographic data* → *Read data from bibliographic database files* → aba **Scopus** |
117
+ | `.dois.txt` | Create → *Create a map based on bibliographic data* → *Read data through API* |
118
+ | `.openalex.txt` | A URL da consulta ao OpenAlex (uma por linha, até 100 artigos cada), com os artigos da lista que vieram do OpenAlex |
119
+
120
+ O CSV leva as referências como DOIs, o que permite mapas de citação e de acoplamento bibliográfico.
121
+
122
+ ## Onde ficam os arquivos
123
+
124
+ Por padrão, na pasta `RSL.app` dentro da sua pasta de usuário (no Windows, `C:\Users\<seu-usuário>\RSL.app`):
125
+
126
+ | Pasta ou arquivo | O que tem |
127
+ |---|---|
128
+ | `log.md` | O log legível de todas as buscas |
129
+ | `exports/` | Os arquivos exportados (`l-0001.ris`, `l-0001.csv`…) |
130
+ | `lists/` e `searches/` | As listas e as buscas salvas, para reexportar depois |
131
+ | `cache/` | As respostas das bases, por 7 dias |
132
+
133
+ ## Configuração
134
+
135
+ Tudo por variáveis de ambiente, no bloco `env` da configuração do cliente. Nenhuma exige mexer no código.
136
+
137
+ | Variável | O que faz | Padrão |
138
+ |---|---|---|
139
+ | `OPENALEX_API_KEY` | Chave do OpenAlex (obrigatória para o OpenAlex) | - |
140
+ | `SEMANTIC_SCHOLAR_API_KEY` | Chave da Semantic Scholar (opcional) | - |
141
+ | `RSL_CONTACT_EMAIL` | Seu e-mail, enviado à Crossref, que atende mais rápido quem se identifica (opcional) | - |
142
+ | `RSL_DATA_DIR` | Onde guardar listas, log e cache | `~/RSL.app` |
143
+ | `RSL_EXPORT_DIR` | Onde gravar as exportações | `<RSL_DATA_DIR>/exports` |
144
+ | `RSL_CACHE_DAYS` | Por quantos dias o cache vale | `7` |
145
+
146
+ ## As ferramentas que a IA recebe
147
+
148
+ | Ferramenta | O que faz |
149
+ |---|---|
150
+ | `search_works` | Busca por termos nas três bases e cria uma lista |
151
+ | `find_work` | Acha um artigo específico por título ou DOI |
152
+ | `get_related_works` | Traz as referências ou as citações de um artigo, até um teto por base (padrão 1.000) |
153
+ | `repeat_search` | Repete uma busca do log |
154
+ | `get_list` | Mostra uma lista salva, por páginas |
155
+ | `get_search_log` | Mostra o log e o caminho do `log.md` |
156
+ | `export_list` | Grava a lista em `ris`, `csv`, `json`, `dois` ou `openalex_url` |
157
+ | `list_sources` | Diz quais bases estão prontas |
158
+ | `plan_search` (prompt) | Orienta a IA a planejar e dividir o pedido antes de buscar |
159
+
160
+ O contrato completo, com entradas, respostas e códigos de erro, está em [`docs/interface-contract.md`](docs/interface-contract.md).
161
+
162
+ ## Dados pessoais
163
+
164
+ As listas guardam nome, ORCID e afiliação dos autores, que são dados públicos das próprias bases e formam os nós das redes de coautoria. Eles ficam só na sua máquina, na pasta de dados, e não vão para nenhum outro lugar. Para apagar tudo, apague a pasta.
165
+
166
+ ## Para quem desenvolve
167
+
168
+ ```bash
169
+ git clone https://github.com/Erick-wilding675/RSL-MCP-APP.git
170
+ cd RSL-MCP-APP
171
+ uv run --isolated --no-editable --reinstall-package rslapp --python 3.10 --extra dev ruff check .
172
+ uv run --isolated --no-editable --reinstall-package rslapp --python 3.10 --extra dev pytest -q
173
+ ```
174
+
175
+ A pasta [`docs/`](docs/) tem a descrição do sistema, os requisitos, a arquitetura, as decisões e uma spec por tarefa. Python 3.10 ou mais novo, SDK oficial do MCP (`mcp>=2,<3`).
176
+
177
+ ## Licença
178
+
179
+ [MIT](LICENSE). Uso livre, sem fins comerciais por parte do projeto. Respeite os termos de uso de cada base consultada.
rslapp-1.0.0/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # RSL.app
2
+
3
+ **Servidor MCP gratuito para revisão sistemática de literatura.** Você pede à sua IA, em linguagem natural, os artigos de um tema. Ela busca no OpenAlex, na Crossref e na Semantic Scholar, junta os resultados sem duplicatas e grava um arquivo pronto para abrir no [VOSviewer](https://www.vosviewer.com/), com autores, afiliações, palavras-chave, referências e citações.
4
+
5
+ > Exemplo: *"Quero os artigos sobre burnout em professores da educação básica e, separado, sobre inteligência artificial na correção de redações. Exporte cada um em RIS."*
6
+ > A IA faz duas buscas, monta duas listas e entrega dois arquivos `.ris`. Cada busca fica registrada num log legível, que você pode anexar à metodologia do seu artigo.
7
+
8
+ O RSL.app roda **na sua máquina** (self-hosted), com as **suas** chaves gratuitas. Ele não tem servidor central, não cobra nada e não manda seus dados para lugar nenhum além das próprias bases consultadas.
9
+
10
+ ## O que ele faz
11
+
12
+ - **Busca por tema, palavra-chave, subtema ou título** nas três bases abertas, ao mesmo tempo.
13
+ - **Tira as duplicatas.** O mesmo artigo vindo de mais de uma base aparece uma vez só, com os ids de cada base.
14
+ - **Avisa quando a lista está incompleta.** Se uma base falha ou um limite corta a busca, a lista sai marcada como incompleta, com o motivo. Nenhuma lista incompleta passa por completa.
15
+ - **Acha um artigo específico** pelo título ou pelo DOI.
16
+ - **Traz as referências de um artigo e quem o cita**, como uma lista própria.
17
+ - **Registra cada busca num log** (`log.md`): o pedido, a string enviada a cada base, a data, quantos artigos cada base achou e se veio do cache.
18
+ - **Repete uma busca do log** com as mesmas strings, para atualizar uma revisão.
19
+ - **Exporta em cinco formatos:** RIS, CSV no padrão do Scopus, JSON completo, lista de DOIs e URL de consulta do OpenAlex. O RIS, o CSV e a lista de DOIs abrem no VOSviewer sem edição.
20
+ - **Guarda tudo na sua máquina:** listas, log, exportações e um cache das respostas, que expira em 7 dias e economiza sua cota.
21
+
22
+ Ele **não** baixa texto completo de artigos, não abre o VOSviewer sozinho e não junta buscas diferentes numa lista só: cada pedido vira a sua própria lista.
23
+
24
+ ## Do que você precisa
25
+
26
+ 1. **Uma IA que fale MCP**, como o Claude Desktop, o Claude Code ou outro cliente compatível.
27
+ 2. **O [uv](https://docs.astral.sh/uv/getting-started/installation/)** instalado. É ele que baixa e roda o RSL.app; você não precisa instalar o Python à mão.
28
+ 3. **Uma chave gratuita do OpenAlex**, obrigatória. Crie em [openalex.org/settings/api](https://openalex.org/settings/api) e **ative pelo link que chega no e-mail**: a chave só funciona depois disso. Ela dá 10.000 créditos por dia, e uma busca gasta cerca de 10.
29
+ 4. **Opcional: uma chave gratuita da [Semantic Scholar](https://www.semanticscholar.org/product/api#api-key-form).** Sem ela a Semantic Scholar funciona, mas recusa pedidos com mais frequência.
30
+
31
+ A Crossref não precisa de chave.
32
+
33
+ ## Instalação no Claude Desktop
34
+
35
+ 1. Feche o Claude Desktop por completo (no Windows, clique com o botão direito no ícone perto do relógio e escolha **Quit**).
36
+ 2. Abra a configuração: **Settings → Developer → Edit Config**. O arquivo é o `claude_desktop_config.json`.
37
+ 3. Acrescente o `rslapp` dentro de `"mcpServers"`:
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "rslapp": {
43
+ "command": "uvx",
44
+ "args": ["rslapp"],
45
+ "env": {
46
+ "OPENALEX_API_KEY": "sua-chave-do-openalex",
47
+ "SEMANTIC_SCHOLAR_API_KEY": "sua-chave-da-semantic-scholar"
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ 4. Salve e abra o Claude Desktop de novo. O `rslapp` aparece na lista de ferramentas, com oito ferramentas.
55
+ 5. Para conferir, peça: *"Quais fontes do rslapp estão prontas?"*. A IA chama `list_sources` e deve mostrar as três fontes como `ok`.
56
+
57
+ **Se o Claude Desktop não achar o `uvx`:** troque `"uvx"` pelo caminho completo. No Windows, costuma ser `C:\\Users\\<seu-usuário>\\.local\\bin\\uvx.exe`. No macOS e no Linux, rode `which uvx` no terminal para descobrir.
58
+
59
+ **Suas chaves ficam só no arquivo de configuração da sua máquina.** O RSL.app nunca as escreve no log, nas listas nem nas respostas à IA.
60
+
61
+ ### No Claude Code
62
+
63
+ ```bash
64
+ claude mcp add rslapp -e OPENALEX_API_KEY=sua-chave -e SEMANTIC_SCHOLAR_API_KEY=sua-chave -- uvx rslapp
65
+ ```
66
+
67
+ ### Em outros clientes MCP
68
+
69
+ O RSL.app é um servidor MCP por **stdio**. O comando é `uvx rslapp`, e as chaves vão como variáveis de ambiente.
70
+
71
+ ## Como usar
72
+
73
+ Fale com a IA normalmente. Alguns pedidos que funcionam bem:
74
+
75
+ - *"Busque artigos sobre aprendizagem baseada em projetos no ensino de ciências e exporte em RIS."*
76
+ - *"Ache o artigo 'Software survey: VOSviewer, a computer program for bibliometric mapping' e me traga até 200 trabalhos que o citam, de cada base."*
77
+ - *"Me mostre o log das buscas de hoje."*
78
+ - *"Repita a busca s-0003 e exporte em CSV."*
79
+
80
+ A IA planeja antes de buscar: se o pedido tem assuntos diferentes, ela faz uma busca e uma lista para cada um.
81
+
82
+ ### Abrir no VOSviewer
83
+
84
+ | Arquivo | Como abrir no VOSviewer |
85
+ |---|---|
86
+ | `.ris` | Create → *Create a map based on bibliographic data* → *Read data from reference manager files* → RIS |
87
+ | `.csv` | Create → *Create a map based on bibliographic data* → *Read data from bibliographic database files* → aba **Scopus** |
88
+ | `.dois.txt` | Create → *Create a map based on bibliographic data* → *Read data through API* |
89
+ | `.openalex.txt` | A URL da consulta ao OpenAlex (uma por linha, até 100 artigos cada), com os artigos da lista que vieram do OpenAlex |
90
+
91
+ O CSV leva as referências como DOIs, o que permite mapas de citação e de acoplamento bibliográfico.
92
+
93
+ ## Onde ficam os arquivos
94
+
95
+ Por padrão, na pasta `RSL.app` dentro da sua pasta de usuário (no Windows, `C:\Users\<seu-usuário>\RSL.app`):
96
+
97
+ | Pasta ou arquivo | O que tem |
98
+ |---|---|
99
+ | `log.md` | O log legível de todas as buscas |
100
+ | `exports/` | Os arquivos exportados (`l-0001.ris`, `l-0001.csv`…) |
101
+ | `lists/` e `searches/` | As listas e as buscas salvas, para reexportar depois |
102
+ | `cache/` | As respostas das bases, por 7 dias |
103
+
104
+ ## Configuração
105
+
106
+ Tudo por variáveis de ambiente, no bloco `env` da configuração do cliente. Nenhuma exige mexer no código.
107
+
108
+ | Variável | O que faz | Padrão |
109
+ |---|---|---|
110
+ | `OPENALEX_API_KEY` | Chave do OpenAlex (obrigatória para o OpenAlex) | - |
111
+ | `SEMANTIC_SCHOLAR_API_KEY` | Chave da Semantic Scholar (opcional) | - |
112
+ | `RSL_CONTACT_EMAIL` | Seu e-mail, enviado à Crossref, que atende mais rápido quem se identifica (opcional) | - |
113
+ | `RSL_DATA_DIR` | Onde guardar listas, log e cache | `~/RSL.app` |
114
+ | `RSL_EXPORT_DIR` | Onde gravar as exportações | `<RSL_DATA_DIR>/exports` |
115
+ | `RSL_CACHE_DAYS` | Por quantos dias o cache vale | `7` |
116
+
117
+ ## As ferramentas que a IA recebe
118
+
119
+ | Ferramenta | O que faz |
120
+ |---|---|
121
+ | `search_works` | Busca por termos nas três bases e cria uma lista |
122
+ | `find_work` | Acha um artigo específico por título ou DOI |
123
+ | `get_related_works` | Traz as referências ou as citações de um artigo, até um teto por base (padrão 1.000) |
124
+ | `repeat_search` | Repete uma busca do log |
125
+ | `get_list` | Mostra uma lista salva, por páginas |
126
+ | `get_search_log` | Mostra o log e o caminho do `log.md` |
127
+ | `export_list` | Grava a lista em `ris`, `csv`, `json`, `dois` ou `openalex_url` |
128
+ | `list_sources` | Diz quais bases estão prontas |
129
+ | `plan_search` (prompt) | Orienta a IA a planejar e dividir o pedido antes de buscar |
130
+
131
+ O contrato completo, com entradas, respostas e códigos de erro, está em [`docs/interface-contract.md`](docs/interface-contract.md).
132
+
133
+ ## Dados pessoais
134
+
135
+ As listas guardam nome, ORCID e afiliação dos autores, que são dados públicos das próprias bases e formam os nós das redes de coautoria. Eles ficam só na sua máquina, na pasta de dados, e não vão para nenhum outro lugar. Para apagar tudo, apague a pasta.
136
+
137
+ ## Para quem desenvolve
138
+
139
+ ```bash
140
+ git clone https://github.com/Erick-wilding675/RSL-MCP-APP.git
141
+ cd RSL-MCP-APP
142
+ uv run --isolated --no-editable --reinstall-package rslapp --python 3.10 --extra dev ruff check .
143
+ uv run --isolated --no-editable --reinstall-package rslapp --python 3.10 --extra dev pytest -q
144
+ ```
145
+
146
+ A pasta [`docs/`](docs/) tem a descrição do sistema, os requisitos, a arquitetura, as decisões e uma spec por tarefa. Python 3.10 ou mais novo, SDK oficial do MCP (`mcp>=2,<3`).
147
+
148
+ ## Licença
149
+
150
+ [MIT](LICENSE). Uso livre, sem fins comerciais por parte do projeto. Respeite os termos de uso de cada base consultada.
@@ -0,0 +1,62 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ # D-008: Pacote publicado no PyPI para execução isolada via uvx
7
+ name = "rslapp"
8
+ version = "1.0.0"
9
+ description = "Servidor MCP em Python para busca acadêmica e exportação para revisão sistemática"
10
+ readme = "README.md"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Erick Cardoso Mendes" }]
14
+ keywords = ["mcp", "systematic-review", "bibliometrics", "vosviewer", "openalex", "crossref", "semantic-scholar"]
15
+ classifiers = [
16
+ "Development Status :: 5 - Production/Stable",
17
+ "Intended Audience :: Science/Research",
18
+ "Natural Language :: Portuguese (Brazilian)",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ "Topic :: Scientific/Engineering :: Information Analysis",
26
+ ]
27
+ # D-001: Linguagem do projeto: Python 3.10 ou mais
28
+ requires-python = ">=3.10"
29
+ dependencies = [
30
+ "mcp>=2,<3",
31
+ "httpx",
32
+ "typing_extensions",
33
+ ]
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/Erick-wilding675/RSL-MCP-APP"
37
+ Issues = "https://github.com/Erick-wilding675/RSL-MCP-APP/issues"
38
+
39
+ [project.optional-dependencies]
40
+ dev = [
41
+ "pytest",
42
+ "ruff",
43
+ ]
44
+
45
+ [project.scripts]
46
+ # D-008: Comando de entrada do servidor MCP
47
+ rslapp = "rslapp.server:main"
48
+
49
+ [tool.hatch.build.targets.wheel]
50
+ packages = ["src/rslapp"]
51
+
52
+ # D-008: O pacote de código-fonte leva só o código, os testes, o README e a licença
53
+ [tool.hatch.build.targets.sdist]
54
+ include = ["src/rslapp", "tests", "README.md", "LICENSE", "pyproject.toml"]
55
+ exclude = ["**/__pycache__"]
56
+
57
+ [tool.ruff]
58
+ target-version = "py310"
59
+ line-length = 100
60
+
61
+ [tool.pytest.ini_options]
62
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ """RSL.app — Servidor MCP para revisão sistemática da literatura."""
2
+
3
+ # D-001: Pacote principal em Python
4
+ __version__ = "1.0.0"
@@ -0,0 +1,77 @@
1
+ """Configuração local do servidor RSL.app a partir de variáveis de ambiente."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from dataclasses import dataclass, field
7
+ from pathlib import Path
8
+
9
+ DEFAULT_DATA_DIR_NAME = "RSL.app"
10
+ DEFAULT_EXPORT_DIR_NAME = "exports"
11
+ DEFAULT_CACHE_DAYS = 7
12
+
13
+
14
+ # FR-07: Configuração do servidor e das chaves de API na máquina do usuário via variáveis de ambiente
15
+ # NFR-02: Execução local (self-hosted), usando diretórios locais da máquina do usuário
16
+ # NFR-03: O objeto de configuração guarda apenas se as chaves estão presentes (bool), nunca o valor delas
17
+ @dataclass(frozen=True)
18
+ class Config:
19
+ """Configuração imutável carregada do ambiente local."""
20
+
21
+ data_dir: Path
22
+ export_dir: Path
23
+ cache_days: int = DEFAULT_CACHE_DAYS
24
+ contact_email: str | None = field(default=None, repr=False)
25
+ openalex_key_configured: bool = False
26
+ semantic_scholar_key_configured: bool = False
27
+
28
+
29
+ def _is_key_configured(env_var: str) -> bool:
30
+ """Verifica se uma chave de API está definida e não vazia sem reter seu valor (NFR-03)."""
31
+ raw = os.environ.get(env_var)
32
+ return bool(raw and raw.strip())
33
+
34
+
35
+ def _parse_cache_days(raw_value: str | None) -> int:
36
+ """Valida e converte RSL_CACHE_DAYS para inteiro positivo."""
37
+ if raw_value is None:
38
+ return DEFAULT_CACHE_DAYS
39
+ try:
40
+ days = int(raw_value.strip())
41
+ except ValueError:
42
+ raise ValueError("RSL_CACHE_DAYS deve ser um inteiro positivo") from None
43
+ if days <= 0:
44
+ raise ValueError("RSL_CACHE_DAYS deve ser um inteiro positivo")
45
+ return days
46
+
47
+
48
+ # FR-07: Leitura dinâmica da configuração a cada chamada, sem criar pastas nem reter chaves
49
+ def load() -> Config:
50
+ """Lê as variáveis de ambiente e devolve a configuração atual."""
51
+ # NFR-02: Pastas locais padrão na conta do usuário
52
+ raw_data_dir = os.environ.get("RSL_DATA_DIR")
53
+ if raw_data_dir and raw_data_dir.strip():
54
+ data_dir = Path(raw_data_dir.strip()).expanduser()
55
+ else:
56
+ data_dir = Path.home() / DEFAULT_DATA_DIR_NAME
57
+
58
+ raw_export_dir = os.environ.get("RSL_EXPORT_DIR")
59
+ if raw_export_dir and raw_export_dir.strip():
60
+ export_dir = Path(raw_export_dir.strip()).expanduser()
61
+ else:
62
+ export_dir = data_dir / DEFAULT_EXPORT_DIR_NAME
63
+
64
+ cache_days = _parse_cache_days(os.environ.get("RSL_CACHE_DAYS"))
65
+
66
+ raw_email = os.environ.get("RSL_CONTACT_EMAIL")
67
+ contact_email = raw_email.strip() if raw_email and raw_email.strip() else None
68
+
69
+ # NFR-03: Apenas booleanos indicando presença das chaves são armazenados
70
+ return Config(
71
+ data_dir=data_dir,
72
+ export_dir=export_dir,
73
+ cache_days=cache_days,
74
+ contact_email=contact_email,
75
+ openalex_key_configured=_is_key_configured("OPENALEX_API_KEY"),
76
+ semantic_scholar_key_configured=_is_key_configured("SEMANTIC_SCHOLAR_API_KEY"),
77
+ )
@@ -0,0 +1,16 @@
1
+ """Miolo (core) do RSL.app: modelos e erros independentes do protocolo MCP."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from rslapp.core.errors import ERROR_CODES, ErrorCode, RSLError
6
+ from rslapp.core.models import Affiliation, Author, SourceResult, Work
7
+
8
+ __all__ = [
9
+ "ERROR_CODES",
10
+ "Affiliation",
11
+ "Author",
12
+ "ErrorCode",
13
+ "RSLError",
14
+ "SourceResult",
15
+ "Work",
16
+ ]