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.
- rslapp-1.0.0/.gitignore +52 -0
- rslapp-1.0.0/LICENSE +21 -0
- rslapp-1.0.0/PKG-INFO +179 -0
- rslapp-1.0.0/README.md +150 -0
- rslapp-1.0.0/pyproject.toml +62 -0
- rslapp-1.0.0/src/rslapp/__init__.py +4 -0
- rslapp-1.0.0/src/rslapp/config.py +77 -0
- rslapp-1.0.0/src/rslapp/core/__init__.py +16 -0
- rslapp-1.0.0/src/rslapp/core/dedup.py +319 -0
- rslapp-1.0.0/src/rslapp/core/errors.py +31 -0
- rslapp-1.0.0/src/rslapp/core/find.py +213 -0
- rslapp-1.0.0/src/rslapp/core/models.py +177 -0
- rslapp-1.0.0/src/rslapp/core/references.py +166 -0
- rslapp-1.0.0/src/rslapp/core/related.py +438 -0
- rslapp-1.0.0/src/rslapp/core/repeat.py +132 -0
- rslapp-1.0.0/src/rslapp/core/search.py +200 -0
- rslapp-1.0.0/src/rslapp/core/views.py +154 -0
- rslapp-1.0.0/src/rslapp/exporters/__init__.py +165 -0
- rslapp-1.0.0/src/rslapp/exporters/base.py +43 -0
- rslapp-1.0.0/src/rslapp/exporters/csv.py +296 -0
- rslapp-1.0.0/src/rslapp/exporters/dois.py +76 -0
- rslapp-1.0.0/src/rslapp/exporters/json.py +43 -0
- rslapp-1.0.0/src/rslapp/exporters/openalex_url.py +80 -0
- rslapp-1.0.0/src/rslapp/exporters/ris.py +115 -0
- rslapp-1.0.0/src/rslapp/prompts.py +51 -0
- rslapp-1.0.0/src/rslapp/server.py +246 -0
- rslapp-1.0.0/src/rslapp/sources/__init__.py +8 -0
- rslapp-1.0.0/src/rslapp/sources/base.py +24 -0
- rslapp-1.0.0/src/rslapp/sources/crossref.py +529 -0
- rslapp-1.0.0/src/rslapp/sources/openalex.py +1054 -0
- rslapp-1.0.0/src/rslapp/sources/semantic_scholar.py +774 -0
- rslapp-1.0.0/src/rslapp/store/__init__.py +156 -0
- rslapp-1.0.0/src/rslapp/store/_atomic.py +173 -0
- rslapp-1.0.0/src/rslapp/store/cache.py +86 -0
- rslapp-1.0.0/src/rslapp/store/log.py +134 -0
- rslapp-1.0.0/tests/core/test_dedup.py +487 -0
- rslapp-1.0.0/tests/core/test_find.py +331 -0
- rslapp-1.0.0/tests/core/test_models.py +84 -0
- rslapp-1.0.0/tests/core/test_references.py +322 -0
- rslapp-1.0.0/tests/core/test_related.py +541 -0
- rslapp-1.0.0/tests/core/test_repeat.py +390 -0
- rslapp-1.0.0/tests/core/test_search.py +695 -0
- rslapp-1.0.0/tests/core/test_views.py +411 -0
- rslapp-1.0.0/tests/exporters/test_csv.py +370 -0
- rslapp-1.0.0/tests/exporters/test_dois.py +79 -0
- rslapp-1.0.0/tests/exporters/test_json.py +134 -0
- rslapp-1.0.0/tests/exporters/test_openalex_url.py +127 -0
- rslapp-1.0.0/tests/exporters/test_ris.py +286 -0
- rslapp-1.0.0/tests/sources/test_crossref.py +597 -0
- rslapp-1.0.0/tests/sources/test_crossref_find_by_doi.py +184 -0
- rslapp-1.0.0/tests/sources/test_openalex.py +621 -0
- rslapp-1.0.0/tests/sources/test_openalex_dois.py +282 -0
- rslapp-1.0.0/tests/sources/test_openalex_find_by_doi.py +209 -0
- rslapp-1.0.0/tests/sources/test_openalex_related.py +366 -0
- rslapp-1.0.0/tests/sources/test_semantic_scholar.py +607 -0
- rslapp-1.0.0/tests/sources/test_semantic_scholar_find_by_doi.py +251 -0
- rslapp-1.0.0/tests/sources/test_semantic_scholar_related.py +343 -0
- rslapp-1.0.0/tests/store/test_log_merge.py +174 -0
- rslapp-1.0.0/tests/store/test_store.py +425 -0
- rslapp-1.0.0/tests/test_config.py +215 -0
- rslapp-1.0.0/tests/test_prompts.py +59 -0
- rslapp-1.0.0/tests/test_server.py +234 -0
- rslapp-1.0.0/tests/test_server_export_list.py +430 -0
- rslapp-1.0.0/tests/test_server_find_and_repeat.py +223 -0
- rslapp-1.0.0/tests/test_server_get_list.py +276 -0
- rslapp-1.0.0/tests/test_server_plan_search.py +162 -0
- rslapp-1.0.0/tests/test_server_related.py +187 -0
- rslapp-1.0.0/tests/test_server_search_works.py +242 -0
- rslapp-1.0.0/tests/test_server_three_sources.py +176 -0
rslapp-1.0.0/.gitignore
ADDED
|
@@ -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,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
|
+
]
|