movidesk-mcp-server 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.
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.pyc
3
+ dist/
4
+ build/
5
+ *.egg-info/
6
+ .venv/
7
+ .env
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 João Pedro Rodrigues
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.
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.5
2
+ Name: movidesk-mcp-server
3
+ Version: 1.0.0
4
+ Summary: MCP server somente leitura para a API pública do Movidesk
5
+ Author-email: João Pedro Rodrigues <jpedrocrc@hotmail.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: claude,helpdesk,mcp,movidesk
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: httpx>=0.27
13
+ Requires-Dist: mcp[cli]>=1.2.0
14
+ Description-Content-Type: text/markdown
15
+
16
+ # Movidesk MCP (somente leitura)
17
+
18
+ Servidor MCP em Python (FastMCP, transporte stdio) para a API pública do Movidesk
19
+ (`https://api.movidesk.com/public/v1`). Ele lê qualquer dado que a API expõe, com
20
+ todos os parâmetros OData (`$select`, `$filter`, `$expand` aninhado, `$orderby`,
21
+ `$top`, `$skip`) e os parâmetros próprios de cada rota. Nunca cria, altera ou exclui nada.
22
+
23
+ ## Início rápido
24
+
25
+ 1. Instalar
26
+
27
+ ```bash
28
+ pip install movidesk-mcp-server
29
+ ```
30
+
31
+ 2. Configurar o Claude Desktop
32
+
33
+ Adicione ao `claude_desktop_config.json`:
34
+
35
+ ```json
36
+ {
37
+ "mcpServers": {
38
+ "movidesk": {
39
+ "command": "movidesk-mcp-server",
40
+ "env": {
41
+ "MOVIDESK_TOKEN": "seu-token-aqui"
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ 3. Ou registrar no Claude Code
49
+
50
+ ```bash
51
+ claude mcp add movidesk -e MOVIDESK_TOKEN=seu-token-aqui -- movidesk-mcp-server
52
+ ```
53
+
54
+ O token é gerado no Movidesk em **Configurações > Conta > Parâmetros > aba Ambiente > Gerar nova chave**.
55
+ Gerar uma chave nova invalida a anterior.
56
+
57
+ ## Estrutura
58
+
59
+ | Arquivo | Conteúdo |
60
+ |---|---|
61
+ | `pyproject.toml` | Pacote e comando `movidesk-mcp-server` |
62
+ | `src/movidesk_mcp/server.py` | Servidor MCP e ferramentas |
63
+ | `src/movidesk_mcp/ENDPOINTS.md` | Mapeamento da API (endpoints, parâmetros, campos, expansões e limites). O bloco JSON no fim é lido pelo servidor. |
64
+ | `test_server.py` | Teste de cobertura contra a API real (`$top=1` em cada endpoint) e teste offline |
65
+
66
+ ## Ferramentas
67
+
68
+ | Ferramenta | O que faz |
69
+ |---|---|
70
+ | `movidesk_get(endpoint, params, paginar, max_registros, permitir_nao_listados, arquivo_saida)` | Chama qualquer GET e repassa os parâmetros sem restrição. Com `paginar=True` percorre as páginas sozinho (OData, cursor ou `page`, conforme a rota) até `max_registros`. |
71
+ | `listar_endpoints(endpoint, completo)` | Devolve o mapeamento para o modelo saber o que pode pedir |
72
+ | `listar_tickets(...)` | Lista tickets com filtro, campos, expansões e período; `incluir_antigos=True` junta `tickets/past` |
73
+ | `buscar_ticket(id)` | Ticket completo (todas as coleções) por número ou protocolo; procura em `tickets/past` se precisar; `incluir_html=True` traz o HTML das ações |
74
+ | `listar_pessoas(...)` | Pessoas, empresas e departamentos, com busca por nome |
75
+ | `resumo_tickets(data_inicio, data_fim)` | Contagens por status, equipe, responsável, categoria, urgência, serviço, origem e dia, mais tempo de resolução e cumprimento de SLA |
76
+
77
+ Também há o recurso `movidesk://endpoints` com o conteúdo do `ENDPOINTS.md`.
78
+
79
+ Exemplo de chamada genérica:
80
+
81
+ ```json
82
+ {
83
+ "endpoint": "tickets",
84
+ "params": {
85
+ "$select": "id,subject,status,createdDate",
86
+ "$filter": "createdDate ge 2026-09-01T00:00:00.00z and ownerTeam eq 'Suporte'",
87
+ "$expand": "owner,actions($select=id,origin;$expand=timeAppointments($expand=createdBy)),customFieldValues($expand=items)",
88
+ "$orderby": "id desc"
89
+ },
90
+ "paginar": true,
91
+ "max_registros": 500
92
+ }
93
+ ```
94
+
95
+ ## Instalação: detalhes
96
+
97
+ Requer Python 3.10 ou superior.
98
+
99
+ | Forma | Comando |
100
+ |---|---|
101
+ | PyPI | `pip install movidesk-mcp-server` |
102
+ | Sem instalar, com uv | `uvx movidesk-mcp-server` |
103
+ | GitHub | `pip install git+https://github.com/jpedrocrc/movidesk-mcp` |
104
+ | Código local | `pip install -e .` na pasta do projeto (para editar o código sem reinstalar) |
105
+
106
+ **Windows:** o `pip` coloca o executável em `...\Python3xx\Scripts`. Se essa pasta
107
+ não estiver no PATH, o Claude Desktop não encontra `movidesk-mcp-server`. Nesse caso,
108
+ use o caminho completo do `.exe` em `"command"`, ou `"command": "python"` com
109
+ `"args": ["-m", "movidesk_mcp"]`.
110
+
111
+ Para publicar no PyPI (é preciso ter conta em pypi.org):
112
+
113
+ ```bash
114
+ uv build
115
+ uv publish
116
+ ```
117
+
118
+ ### Testar com o MCP Inspector
119
+
120
+ `mcp dev` usa o `uv` e o `npx` (Node.js).
121
+
122
+ ```bash
123
+ mcp dev src/movidesk_mcp/server.py
124
+ ```
125
+
126
+ No Inspector, defina a variável `MOVIDESK_TOKEN` na seção *Environment Variables* antes de conectar.
127
+
128
+ ## Teste de cobertura
129
+
130
+ ```bash
131
+ python test_server.py --offline
132
+ ```
133
+
134
+ Esse modo não usa rede: valida o mapeamento, o registro das ferramentas e as travas (escrita bloqueada, `$select` obrigatório, token ocultado).
135
+
136
+ ```bash
137
+ python test_server.py
138
+ ```
139
+
140
+ Esse modo precisa de `MOVIDESK_TOKEN` no ambiente. Ele chama cada endpoint mapeado com `$top=1` (ou `limit=1`/`pageSize=1`) e usa os IDs que encontra para testar as rotas que pedem um id (HTML das ações, pergunta da pesquisa, artigo, anexo, consumo do contrato). No horário limitado leva cerca de 2 minutos.
141
+
142
+ ## Limites e comportamento
143
+
144
+ - **Rate limit:** 10 req/min das 07:01 às 18:59 (Brasília); livre das 19:00 às 07:00. O servidor segura as chamadas localmente nesse horário para não estourar o limite.
145
+ - **Bloqueio por erro:** 3 requisições com erro bloqueiam a API por 60 s, depois 120 s, depois 300 s. Por isso o servidor valida localmente o que consegue antes de chamar a API (por exemplo, `$select` obrigatório nas listas de tickets) e, num 429, espera o tempo do header `retry-after` e tenta de novo.
146
+ - **Erros:** 401 (token), 404, 400 (com a mensagem da API) e timeout voltam como JSON `{"erro": ..., "mensagem": ...}`. Timeout e 5xx são repetidos com backoff.
147
+ - **Respostas grandes:** acima de `MOVIDESK_MAX_CHARS` a resposta é cortada, com um aviso que sugere `$select`/`$filter`. Use `arquivo_saida` para gravar o resultado completo em disco.
148
+ - **Tickets antigos:** `/tickets` só traz tickets com `lastUpdate` nos últimos 90 dias. Os demais estão em `/tickets/past`.
149
+ - **Segurança:** só GET. As rotas de telefonia que usam GET mas registram chamadas (`asterisk_*`) estão bloqueadas, mesmo com `permitir_nao_listados=True`. O token só é lido do ambiente, nunca vai para o log, e qualquer ocorrência dele é removida das respostas.
150
+
151
+ ### Variáveis de ambiente opcionais
152
+
153
+ | Variável | Padrão | Uso |
154
+ |---|---|---|
155
+ | `MOVIDESK_RATE_LIMIT` | `10` | Requisições por minuto (0 desliga o limitador local) |
156
+ | `MOVIDESK_RATE_LIMIT_MODO` | `horario` | `horario` limita só das 07:01 às 18:59; `sempre` limita 24 h |
157
+ | `MOVIDESK_PAGE_SIZE` | `100` | Tamanho da página na paginação automática |
158
+ | `MOVIDESK_MAX_RETRIES` | `3` | Novas tentativas em 429/5xx/timeout |
159
+ | `MOVIDESK_MAX_ESPERA` | `320` | Maior espera (s) aceita num retry de 429 |
160
+ | `MOVIDESK_TIMEOUT` | `60` | Timeout por requisição (s) |
161
+ | `MOVIDESK_MAX_CHARS` | `60000` | Tamanho máximo da resposta antes de cortar |
162
+ | `MOVIDESK_LOG_LEVEL` | `WARNING` | Nível de log (sempre em stderr) |
163
+
164
+ ## Licença
165
+
166
+ MIT. Veja [LICENSE](LICENSE).
@@ -0,0 +1,151 @@
1
+ # Movidesk MCP (somente leitura)
2
+
3
+ Servidor MCP em Python (FastMCP, transporte stdio) para a API pública do Movidesk
4
+ (`https://api.movidesk.com/public/v1`). Ele lê qualquer dado que a API expõe, com
5
+ todos os parâmetros OData (`$select`, `$filter`, `$expand` aninhado, `$orderby`,
6
+ `$top`, `$skip`) e os parâmetros próprios de cada rota. Nunca cria, altera ou exclui nada.
7
+
8
+ ## Início rápido
9
+
10
+ 1. Instalar
11
+
12
+ ```bash
13
+ pip install movidesk-mcp-server
14
+ ```
15
+
16
+ 2. Configurar o Claude Desktop
17
+
18
+ Adicione ao `claude_desktop_config.json`:
19
+
20
+ ```json
21
+ {
22
+ "mcpServers": {
23
+ "movidesk": {
24
+ "command": "movidesk-mcp-server",
25
+ "env": {
26
+ "MOVIDESK_TOKEN": "seu-token-aqui"
27
+ }
28
+ }
29
+ }
30
+ }
31
+ ```
32
+
33
+ 3. Ou registrar no Claude Code
34
+
35
+ ```bash
36
+ claude mcp add movidesk -e MOVIDESK_TOKEN=seu-token-aqui -- movidesk-mcp-server
37
+ ```
38
+
39
+ O token é gerado no Movidesk em **Configurações > Conta > Parâmetros > aba Ambiente > Gerar nova chave**.
40
+ Gerar uma chave nova invalida a anterior.
41
+
42
+ ## Estrutura
43
+
44
+ | Arquivo | Conteúdo |
45
+ |---|---|
46
+ | `pyproject.toml` | Pacote e comando `movidesk-mcp-server` |
47
+ | `src/movidesk_mcp/server.py` | Servidor MCP e ferramentas |
48
+ | `src/movidesk_mcp/ENDPOINTS.md` | Mapeamento da API (endpoints, parâmetros, campos, expansões e limites). O bloco JSON no fim é lido pelo servidor. |
49
+ | `test_server.py` | Teste de cobertura contra a API real (`$top=1` em cada endpoint) e teste offline |
50
+
51
+ ## Ferramentas
52
+
53
+ | Ferramenta | O que faz |
54
+ |---|---|
55
+ | `movidesk_get(endpoint, params, paginar, max_registros, permitir_nao_listados, arquivo_saida)` | Chama qualquer GET e repassa os parâmetros sem restrição. Com `paginar=True` percorre as páginas sozinho (OData, cursor ou `page`, conforme a rota) até `max_registros`. |
56
+ | `listar_endpoints(endpoint, completo)` | Devolve o mapeamento para o modelo saber o que pode pedir |
57
+ | `listar_tickets(...)` | Lista tickets com filtro, campos, expansões e período; `incluir_antigos=True` junta `tickets/past` |
58
+ | `buscar_ticket(id)` | Ticket completo (todas as coleções) por número ou protocolo; procura em `tickets/past` se precisar; `incluir_html=True` traz o HTML das ações |
59
+ | `listar_pessoas(...)` | Pessoas, empresas e departamentos, com busca por nome |
60
+ | `resumo_tickets(data_inicio, data_fim)` | Contagens por status, equipe, responsável, categoria, urgência, serviço, origem e dia, mais tempo de resolução e cumprimento de SLA |
61
+
62
+ Também há o recurso `movidesk://endpoints` com o conteúdo do `ENDPOINTS.md`.
63
+
64
+ Exemplo de chamada genérica:
65
+
66
+ ```json
67
+ {
68
+ "endpoint": "tickets",
69
+ "params": {
70
+ "$select": "id,subject,status,createdDate",
71
+ "$filter": "createdDate ge 2026-09-01T00:00:00.00z and ownerTeam eq 'Suporte'",
72
+ "$expand": "owner,actions($select=id,origin;$expand=timeAppointments($expand=createdBy)),customFieldValues($expand=items)",
73
+ "$orderby": "id desc"
74
+ },
75
+ "paginar": true,
76
+ "max_registros": 500
77
+ }
78
+ ```
79
+
80
+ ## Instalação: detalhes
81
+
82
+ Requer Python 3.10 ou superior.
83
+
84
+ | Forma | Comando |
85
+ |---|---|
86
+ | PyPI | `pip install movidesk-mcp-server` |
87
+ | Sem instalar, com uv | `uvx movidesk-mcp-server` |
88
+ | GitHub | `pip install git+https://github.com/jpedrocrc/movidesk-mcp` |
89
+ | Código local | `pip install -e .` na pasta do projeto (para editar o código sem reinstalar) |
90
+
91
+ **Windows:** o `pip` coloca o executável em `...\Python3xx\Scripts`. Se essa pasta
92
+ não estiver no PATH, o Claude Desktop não encontra `movidesk-mcp-server`. Nesse caso,
93
+ use o caminho completo do `.exe` em `"command"`, ou `"command": "python"` com
94
+ `"args": ["-m", "movidesk_mcp"]`.
95
+
96
+ Para publicar no PyPI (é preciso ter conta em pypi.org):
97
+
98
+ ```bash
99
+ uv build
100
+ uv publish
101
+ ```
102
+
103
+ ### Testar com o MCP Inspector
104
+
105
+ `mcp dev` usa o `uv` e o `npx` (Node.js).
106
+
107
+ ```bash
108
+ mcp dev src/movidesk_mcp/server.py
109
+ ```
110
+
111
+ No Inspector, defina a variável `MOVIDESK_TOKEN` na seção *Environment Variables* antes de conectar.
112
+
113
+ ## Teste de cobertura
114
+
115
+ ```bash
116
+ python test_server.py --offline
117
+ ```
118
+
119
+ Esse modo não usa rede: valida o mapeamento, o registro das ferramentas e as travas (escrita bloqueada, `$select` obrigatório, token ocultado).
120
+
121
+ ```bash
122
+ python test_server.py
123
+ ```
124
+
125
+ Esse modo precisa de `MOVIDESK_TOKEN` no ambiente. Ele chama cada endpoint mapeado com `$top=1` (ou `limit=1`/`pageSize=1`) e usa os IDs que encontra para testar as rotas que pedem um id (HTML das ações, pergunta da pesquisa, artigo, anexo, consumo do contrato). No horário limitado leva cerca de 2 minutos.
126
+
127
+ ## Limites e comportamento
128
+
129
+ - **Rate limit:** 10 req/min das 07:01 às 18:59 (Brasília); livre das 19:00 às 07:00. O servidor segura as chamadas localmente nesse horário para não estourar o limite.
130
+ - **Bloqueio por erro:** 3 requisições com erro bloqueiam a API por 60 s, depois 120 s, depois 300 s. Por isso o servidor valida localmente o que consegue antes de chamar a API (por exemplo, `$select` obrigatório nas listas de tickets) e, num 429, espera o tempo do header `retry-after` e tenta de novo.
131
+ - **Erros:** 401 (token), 404, 400 (com a mensagem da API) e timeout voltam como JSON `{"erro": ..., "mensagem": ...}`. Timeout e 5xx são repetidos com backoff.
132
+ - **Respostas grandes:** acima de `MOVIDESK_MAX_CHARS` a resposta é cortada, com um aviso que sugere `$select`/`$filter`. Use `arquivo_saida` para gravar o resultado completo em disco.
133
+ - **Tickets antigos:** `/tickets` só traz tickets com `lastUpdate` nos últimos 90 dias. Os demais estão em `/tickets/past`.
134
+ - **Segurança:** só GET. As rotas de telefonia que usam GET mas registram chamadas (`asterisk_*`) estão bloqueadas, mesmo com `permitir_nao_listados=True`. O token só é lido do ambiente, nunca vai para o log, e qualquer ocorrência dele é removida das respostas.
135
+
136
+ ### Variáveis de ambiente opcionais
137
+
138
+ | Variável | Padrão | Uso |
139
+ |---|---|---|
140
+ | `MOVIDESK_RATE_LIMIT` | `10` | Requisições por minuto (0 desliga o limitador local) |
141
+ | `MOVIDESK_RATE_LIMIT_MODO` | `horario` | `horario` limita só das 07:01 às 18:59; `sempre` limita 24 h |
142
+ | `MOVIDESK_PAGE_SIZE` | `100` | Tamanho da página na paginação automática |
143
+ | `MOVIDESK_MAX_RETRIES` | `3` | Novas tentativas em 429/5xx/timeout |
144
+ | `MOVIDESK_MAX_ESPERA` | `320` | Maior espera (s) aceita num retry de 429 |
145
+ | `MOVIDESK_TIMEOUT` | `60` | Timeout por requisição (s) |
146
+ | `MOVIDESK_MAX_CHARS` | `60000` | Tamanho máximo da resposta antes de cortar |
147
+ | `MOVIDESK_LOG_LEVEL` | `WARNING` | Nível de log (sempre em stderr) |
148
+
149
+ ## Licença
150
+
151
+ MIT. Veja [LICENSE](LICENSE).
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "movidesk-mcp-server"
3
+ version = "1.0.0"
4
+ description = "MCP server somente leitura para a API pública do Movidesk"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ authors = [{ name = "João Pedro Rodrigues", email = "jpedrocrc@hotmail.com" }]
9
+ requires-python = ">=3.10"
10
+ dependencies = [
11
+ "mcp[cli]>=1.2.0",
12
+ "httpx>=0.27",
13
+ ]
14
+ keywords = ["mcp", "movidesk", "helpdesk", "claude"]
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ ]
19
+
20
+ [project.scripts]
21
+ movidesk-mcp-server = "movidesk_mcp.server:main"
22
+
23
+ [build-system]
24
+ requires = ["hatchling"]
25
+ build-backend = "hatchling.build"
26
+
27
+ [tool.hatch.build.targets.wheel]
28
+ packages = ["src/movidesk_mcp"]
29
+
30
+ [tool.hatch.build.targets.sdist]
31
+ include = ["src/movidesk_mcp", "test_server.py", "README.md", "LICENSE"]