mcp-elm 1.0.33__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.
- mcp_elm-1.0.33/.gitignore +8 -0
- mcp_elm-1.0.33/LICENSE +21 -0
- mcp_elm-1.0.33/PKG-INFO +268 -0
- mcp_elm-1.0.33/README.md +253 -0
- mcp_elm-1.0.33/docs/manual-mcp-alm.md +1044 -0
- mcp_elm-1.0.33/mcp_elm/__init__.py +0 -0
- mcp_elm-1.0.33/mcp_elm/bundle.py +158 -0
- mcp_elm-1.0.33/mcp_elm/ccm.py +876 -0
- mcp_elm-1.0.33/mcp_elm/ibm/__init__.py +0 -0
- mcp_elm-1.0.33/mcp_elm/ibm/common.py +362 -0
- mcp_elm-1.0.33/mcp_elm/ibm/requirements.py +167 -0
- mcp_elm-1.0.33/mcp_elm/ibm/test.py +150 -0
- mcp_elm-1.0.33/mcp_elm/ibm/workitems.py +400 -0
- mcp_elm-1.0.33/mcp_elm/infra/__init__.py +0 -0
- mcp_elm-1.0.33/mcp_elm/infra/auth.py +48 -0
- mcp_elm-1.0.33/mcp_elm/infra/config.py +46 -0
- mcp_elm-1.0.33/mcp_elm/infra/document.py +376 -0
- mcp_elm-1.0.33/mcp_elm/infra/http.py +112 -0
- mcp_elm-1.0.33/mcp_elm/infra/oslc.py +520 -0
- mcp_elm-1.0.33/mcp_elm/qm.py +1 -0
- mcp_elm-1.0.33/mcp_elm/rm.py +645 -0
- mcp_elm-1.0.33/mcp_elm/server.py +53 -0
- mcp_elm-1.0.33/pyproject.toml +31 -0
- mcp_elm-1.0.33/tests/conftest.py +72 -0
- mcp_elm-1.0.33/tests/fixtures/allowed_filedagainst.xml +8 -0
- mcp_elm-1.0.33/tests/fixtures/apt_plans.xml +2 -0
- mcp_elm-1.0.33/tests/fixtures/catalog_ccm.xml +18 -0
- mcp_elm-1.0.33/tests/fixtures/category_c1.xml +6 -0
- mcp_elm-1.0.33/tests/fixtures/enum_priority.xml +7 -0
- mcp_elm-1.0.33/tests/fixtures/iteration_it1.xml +6 -0
- mcp_elm-1.0.33/tests/fixtures/query_page1.xml +17 -0
- mcp_elm-1.0.33/tests/fixtures/query_page2.xml +13 -0
- mcp_elm-1.0.33/tests/fixtures/rootservices_ccm.xml +10 -0
- mcp_elm-1.0.33/tests/fixtures/shape_defect.xml +36 -0
- mcp_elm-1.0.33/tests/fixtures/sp_ccm.xml +28 -0
- mcp_elm-1.0.33/tests/fixtures/team_areas.xml +11 -0
- mcp_elm-1.0.33/tests/fixtures/team_iterations.xml +4 -0
- mcp_elm-1.0.33/tests/fixtures/team_iterations_children.xml +3 -0
- mcp_elm-1.0.33/tests/fixtures/team_members.xml +9 -0
- mcp_elm-1.0.33/tests/fixtures/team_roles.xml +3 -0
- mcp_elm-1.0.33/tests/fixtures/user_joao.xml +7 -0
- mcp_elm-1.0.33/tests/fixtures/wf_actions.xml +5 -0
- mcp_elm-1.0.33/tests/fixtures/wf_states.xml +6 -0
- mcp_elm-1.0.33/tests/fixtures/workitem_42.xml +21 -0
- mcp_elm-1.0.33/tests/fixtures/workitem_7.xml +8 -0
- mcp_elm-1.0.33/tests/test_bundle.py +47 -0
- mcp_elm-1.0.33/tests/test_ccm.py +430 -0
- mcp_elm-1.0.33/tests/test_common.py +193 -0
- mcp_elm-1.0.33/tests/test_document.py +206 -0
- mcp_elm-1.0.33/tests/test_infra.py +275 -0
- mcp_elm-1.0.33/tests/test_requirements.py +158 -0
- mcp_elm-1.0.33/tests/test_rm.py +395 -0
- mcp_elm-1.0.33/tests/test_test.py +112 -0
- mcp_elm-1.0.33/tests/test_workitems.py +222 -0
mcp_elm-1.0.33/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Xavier Araújo
|
|
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.
|
mcp_elm-1.0.33/PKG-INFO
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: mcp-elm
|
|
3
|
+
Version: 1.0.33
|
|
4
|
+
Summary: MCP server para IBM ELM (DOORS Next, EWM, ETM) via OSLC
|
|
5
|
+
Project-URL: Repository, https://github.com/dxaraujo/mcp-elm
|
|
6
|
+
Author-email: Daniel Xavier Araújo <danielxaraujo@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Requires-Dist: markdown-it-py>=3
|
|
11
|
+
Requires-Dist: mcp[cli]>=2.2
|
|
12
|
+
Requires-Dist: rdflib>=7.0
|
|
13
|
+
Requires-Dist: requests>=2.31
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# mcp-elm
|
|
17
|
+
|
|
18
|
+
Servidor MCP para o IBM ELM via OSLC: **rm** (DOORS Next), **ccm** (EWM) e **qm** (ETM).
|
|
19
|
+
Ele fornece as capacidades que as skills vão consumir. As tools seguem os nomes e parâmetros do
|
|
20
|
+
[IBM Engineering AI Hub MCP 1.3.0](https://www.ibm.com/docs/en/engineering-lifecycle-management-suite/engineering-ai-hub/1.3.0?topic=tools-mcp-engineering-ai-hub).
|
|
21
|
+
|
|
22
|
+
## Credenciais
|
|
23
|
+
|
|
24
|
+
| SO | Arquivo |
|
|
25
|
+
|---|---|
|
|
26
|
+
| Linux/Mac | `~/.config/mcp-elm/elm.properties` |
|
|
27
|
+
| Windows | `%APPDATA%\mcp-elm\elm.properties` |
|
|
28
|
+
|
|
29
|
+
Para usar outro caminho, defina a variável de ambiente `MCP_ELM_CONFIG`.
|
|
30
|
+
|
|
31
|
+
```ini
|
|
32
|
+
[DEFAULT]
|
|
33
|
+
server = https://elm.SEU-SERVIDOR
|
|
34
|
+
user = SEU_USUARIO
|
|
35
|
+
password = SUA_SENHA
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Certificado com CA próprio: `export REQUESTS_CA_BUNDLE=/caminho/ca.pem`.
|
|
39
|
+
|
|
40
|
+
A autenticação usa o form Jazz (`j_security_check`). Se o servidor responder 401 pedindo Basic, o Basic é usado automaticamente.
|
|
41
|
+
|
|
42
|
+
## Instalação
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv sync
|
|
46
|
+
claude mcp add elm -- uv run --directory /caminho/para/mcp-elm mcp-elm
|
|
47
|
+
# depuração com o MCP Inspector
|
|
48
|
+
uv run mcp dev mcp_elm/server.py
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Contrato de saída
|
|
52
|
+
|
|
53
|
+
- Recursos OSLC: `{url, id, title, types, properties{}, links{}}`, com chaves em qname (`dcterms:title`).
|
|
54
|
+
Cada link é `{url, title?}`. `get_workitem` e `search_workitems` trazem o `title` dos recursos ligados (estado,
|
|
55
|
+
prioridade, iteração...) na mesma requisição (`oslc.properties`/`oslc.select` com `{dcterms:title}`) e completam
|
|
56
|
+
o nome dos usuários do JTS pela lista em cache do Reportable REST.
|
|
57
|
+
- Dados da API de processo e do Reportable REST usam os nomes de campo da doc IBM
|
|
58
|
+
(`get_user` → `userUUID, userId, name, emailAddress, archived`; `get_project_area` → `name, project_area_uuid,
|
|
59
|
+
summary, description, cm_enabled, team_areas, timelines, associations`).
|
|
60
|
+
- Entradas por UUID/URL, como na doc IBM. Descubra-os com `list_project_areas`, `get_project_area`,
|
|
61
|
+
`get_project_components` (rm) e `get_qm_component` (qm).
|
|
62
|
+
- `configuration`/`configuration_url`/`global_configuration_url`/`gc_uri`/`gc_context` vão no header
|
|
63
|
+
`Configuration-Context`. No DOORS Next, sem configuração, é usada a primeira stream do componente.
|
|
64
|
+
|
|
65
|
+
## Tools (IBM Engineering AI Hub 1.3.0)
|
|
66
|
+
|
|
67
|
+
| Conjunto | Tools |
|
|
68
|
+
|---|---|
|
|
69
|
+
| Common | get_user, get_project_area, get_global_configuration, search_global_configuration, list_project_areas, list_linked_requirements, list_linked_workitems, list_linked_testartifacts, link_workitem_and_requirement, link_workitem_and_testartifact, link_testartifact_and_requirement |
|
|
70
|
+
| Requirements | get_project_components, get_rm_component_types, list_rm_component_folders, get_rm_component_configuration, get_requirement, search_requirement, create_requirement |
|
|
71
|
+
| Work Items | create_workitem, get_workitem, get_workitem_schema, list_workitem_categories, list_workitem_releases, search_workitems, add_comment_to_workitem |
|
|
72
|
+
| Test | get_testartifact, get_testartifact_schema, search_testartifact, get_qm_component, get_qm_component_configuration |
|
|
73
|
+
|
|
74
|
+
Aliases da doc (`get_rm_component`, `get_project_component_types`...) não são registrados: vale o primeiro nome.
|
|
75
|
+
|
|
76
|
+
## Skills
|
|
77
|
+
|
|
78
|
+
As skills ficam em `skills/` e documentam, para a IA, as tools, suas entradas e saídas, os fluxos e os erros, para
|
|
79
|
+
evitar consultas desnecessárias ao servidor.
|
|
80
|
+
|
|
81
|
+
| Skill | Assunto |
|
|
82
|
+
|---|---|
|
|
83
|
+
| elm-setup | Cria/atualiza a configuração do projeto em `elm/pa_<project area em snake_case>.json` (um arquivo por project area do CCM) |
|
|
84
|
+
| elm-ccm | Work items: item de trabalho (WI), tarefa, defeito, item de backlog (IB)... |
|
|
85
|
+
| elm-rm | Requisitos: RF, RNF, HU, UC, regra, mensagem, especificação... |
|
|
86
|
+
| elm-qm | Testes (só leitura): caso de teste (CT), plano (PT), execução (TER)... |
|
|
87
|
+
| elm-gc | Comum: usuários, project areas, associações, configuração global e links de rastreabilidade |
|
|
88
|
+
|
|
89
|
+
Instalação por projeto (links relativos, sem cópia):
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
mkdir -p .claude/skills .kiro/skills
|
|
93
|
+
for s in elm-setup elm-ccm elm-rm elm-qm elm-gc; do
|
|
94
|
+
ln -sfn ../../skills/$s .claude/skills/$s # Claude Code
|
|
95
|
+
ln -sfn ../../skills/$s .kiro/skills/$s # Kiro
|
|
96
|
+
done
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Tools das skills
|
|
100
|
+
|
|
101
|
+
Saída com as chaves do elm.json (`elm/pa_*.json`; a skill grava o arquivo, o MCP não o lê). Listas voltam como
|
|
102
|
+
`[{name, identifier, ...}]` e a skill grava o mapa `{name: identifier}`.
|
|
103
|
+
|
|
104
|
+
| Skill | Tools |
|
|
105
|
+
|---|---|
|
|
106
|
+
| elm-setup (ccm) | whoami, list_project_areas("CCM"), ccm_list_team_areas, ccm_list_members, ccm_list_workitem_types, ccm_list_workitem_fields, ccm_list_link_types, ccm_list_iterations, ccm_list_iteration_plans, ccm_create_iteration, ccm_create_iteration_plan |
|
|
107
|
+
| elm-setup (rm) | list_project_areas("RM"), get_project_area(include_associations), rm_get_configuration, rm_list_members, rm_list_folders, rm_list_requirement_types |
|
|
108
|
+
| elm-ccm | ccm_list_workitems, ccm_get_workitem, ccm_list_field_values, ccm_create_workitem, ccm_update_workitem, ccm_list_workitem_states (+ add_comment_to_workitem, link_*) |
|
|
109
|
+
| elm-rm | rm_search_requirements, rm_count_folder, rm_list_folder, rm_list_modified, rm_sync_plan, rm_download_requirements, rm_upload_requirements, rm_get_requirement, rm_create_requirement, rm_update_requirement (+ link_workitem_and_requirement) |
|
|
110
|
+
| elm-qm | search_testartifact, get_testartifact, get_testartifact_schema, get_qm_component, get_qm_component_configuration |
|
|
111
|
+
| elm-gc | whoami, get_user, list_project_areas, get_project_area, get_global_configuration, search_global_configuration, list_linked_*, link_* |
|
|
112
|
+
|
|
113
|
+
### Leitura em Markdown + YAML
|
|
114
|
+
|
|
115
|
+
`ccm_get_workitem` e `rm_get_requirement` devolvem um documento Markdown com cabeçalho YAML. O MCP não traduz
|
|
116
|
+
nomes:
|
|
117
|
+
|
|
118
|
+
- **Work item:** o cabeçalho traz só os campos e links mapeados no elm.json, com o nome de lá. A skill passa
|
|
119
|
+
`fields=workitem-types[tipo].fields` e `link_types=ccm.link-types` e, para gravar, procura a chave no mesmo mapa
|
|
120
|
+
(`fields["Estimativa"]` → `rtc_cm:estimate`).
|
|
121
|
+
- **Requisito:** o cabeçalho traz os links preenchidos, com os nomes do DOORS Next (só leitura: não são gravados), e
|
|
122
|
+
`embedded` (artefatos embutidos no texto). A gravação é só de título e texto. O elm.json do RM guarda só tipos e pastas.
|
|
123
|
+
|
|
124
|
+
O cabeçalho do requisito segue o [Google OKF v0.2](https://okf.md/): primeiro os campos OKF padrão (`type`,
|
|
125
|
+
`title`, `description?`, `resource`, `tags` = [pasta]), depois `sources` (a fonte no DOORS Next: `author` = quem
|
|
126
|
+
criou, `last_modified` = última modificação no ELM e `last_modified_by` = quem modificou por último) e `generated` (quem gerou e **quando o documento foi gerado**), ambos em ISO 8601 UTC, e, por
|
|
127
|
+
fim, as extensões RM. `sources[0].last_modified` > `generated.at` indica cópia desatualizada; `rm_list_modified`
|
|
128
|
+
devolve essa data para um ou vários ids sem ler o conteúdo. Para download/sync de uma pasta, use
|
|
129
|
+
`rm_count_folder` (total pelo servidor) e `rm_list_folder` (todos os `{id, title, modified}`, sem teto) como
|
|
130
|
+
inventário: só a pasta, sem subpastas; `count` diferente do tamanho da lista indica listagem inconsistente. Para o bundle da elm-sync, o MCP cuida de tudo sem passar listas nem conteúdo pela conversa
|
|
131
|
+
(ver [Sincronismo do bundle](#sincronismo-do-bundle-elm-sync)). Extensões RM: `id`, `created` (UTC), `links` e `embedded`, só quando preenchidos. `verified`, `status` e
|
|
132
|
+
`stale_after` só aparecem quando o artefato traz um sinal real (requisitos do DOORS Next não os definem).
|
|
133
|
+
|
|
134
|
+
Exemplo (dados fictícios):
|
|
135
|
+
|
|
136
|
+
```markdown
|
|
137
|
+
---
|
|
138
|
+
type: Caso de Uso
|
|
139
|
+
title: UC - Cadastrar cliente
|
|
140
|
+
resource: "https://elm.example.com/rm/resources/TX_exemplo2010"
|
|
141
|
+
tags:
|
|
142
|
+
- "03-Casos de Uso"
|
|
143
|
+
sources:
|
|
144
|
+
- id: doors-next
|
|
145
|
+
resource: "https://elm.example.com/rm/resources/TX_exemplo2010"
|
|
146
|
+
author: "human:ana.souza"
|
|
147
|
+
last_modified: "2026-01-10T13:05:00Z"
|
|
148
|
+
last_modified_by: "human:bruno.lima"
|
|
149
|
+
generated:
|
|
150
|
+
by: "process:elm-mcp/1.0.14"
|
|
151
|
+
at: "2026-01-11T19:20:00Z"
|
|
152
|
+
id: 2010
|
|
153
|
+
created: "2026-01-05T13:00:00Z"
|
|
154
|
+
links:
|
|
155
|
+
Vincular A:
|
|
156
|
+
- "2002: RN - Cliente deve ser maior de idade"
|
|
157
|
+
embedded:
|
|
158
|
+
- "2001: RN - Validar CPF do cliente"
|
|
159
|
+
---
|
|
160
|
+
## Fluxo Básico
|
|
161
|
+
|
|
162
|
+
1. O usuário informa os dados do cliente.
|
|
163
|
+
2. O sistema valida o documento: [2001 RN - Validar CPF do cliente](https://elm.example.com/rm/resources/TX_exemplo2001)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
O corpo é Markdown nos dois sentidos: `text` (RM) e `description` (WI) aceitam Markdown na gravação. No RM, a
|
|
167
|
+
leitura sai sempre no mesmo padrão: todo artefato, embutido ou hyperlink, é `[<id> <título>](<alvo>)`, com o alvo =
|
|
168
|
+
URL do ELM; o que é embed está na lista `embedded` do cabeçalho (artefato ilegível sai como link e fica fora da
|
|
169
|
+
lista). Na gravação, o link cujo artefato está em `embedded` (parâmetro de
|
|
170
|
+
`rm_create_requirement`/`rm_update_requirement`) vira embed e o resto, hyperlink; alvo por URL (inclusive link da UI
|
|
171
|
+
web com `artifactURI`), id (`2001`) ou arquivo cujo nome começa pelo id. No EWM a descrição só tem texto, `<br/>`, `<b>`, `<i>` e `<a>` (listas viram `• ` / `1. `); para citar outro
|
|
172
|
+
WI, escreva "Tarefa 1002" no texto e o EWM cria o link "Menções". `[texto](url)` é hyperlink comum.
|
|
173
|
+
|
|
174
|
+
### Sincronismo do bundle (elm-sync)
|
|
175
|
+
|
|
176
|
+
O bundle é uma pasta de md, um por requisito (`<pasta>/<id>-<slug>.md`), com `sync.md` (situação de cada artefato),
|
|
177
|
+
`index.md` na raiz e em cada pasta (OKF §8, como o `build_index` do okf-kit) e `log.md` (cada sync registra, sob
|
|
178
|
+
`## AAAA-MM-DD`, o que criou, atualizou, subiu, moveu ou apagou). O sincronismo baixa primeiro e depois sobe o que foi editado no md:
|
|
179
|
+
|
|
180
|
+
1. `rm_sync_plan(folders, dest)`: lista as pastas, regrava `sync.md`, apaga os removidos e devolve um resumo com
|
|
181
|
+
`a_baixar`, `a_subir` e `conflitos`;
|
|
182
|
+
2. `rm_download_requirements(dest)` até `restantes = 0`;
|
|
183
|
+
3. para cada item de `conflitos`, a skill **pergunta ao usuário qual versão fica**. Se for o ELM, chama
|
|
184
|
+
`rm_download_requirements(dest, requirement_ids=[id])`; se for o md, chama `rm_upload_requirements(dest, requirement_ids=[id])`;
|
|
185
|
+
4. `rm_upload_requirements(dest)` até `restantes = 0` (sobe título e corpo e rebaixa o requisito).
|
|
186
|
+
|
|
187
|
+
| Estado | Quando | Ação |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `novo` | id ainda não baixado | download |
|
|
190
|
+
| `sincronizado` | md == ELM | — |
|
|
191
|
+
| `desatualizado` | `modified` do ELM ≠ `Última atualização ELM` | download |
|
|
192
|
+
| `atualizado` | md alterado (sha256 ≠ `Hash`) e ELM sem mudança | upload |
|
|
193
|
+
| `normalizado` | md **não** alterado (hash igual), mas o ELM foge da regra embed/link do bundle (diferença invisível no md) | upload |
|
|
194
|
+
| `conflito` | md alterado **e** ELM mudou | perguntar ao usuário: md ou ELM |
|
|
195
|
+
| `erro: <msg>` | falha no download | download de novo |
|
|
196
|
+
|
|
197
|
+
Mudar de pasta é tratado como remoção na antiga e criação na nova: o arquivo é apagado e a linha volta a `novo`
|
|
198
|
+
(com edição local no md, vira `conflito` e o arquivo fica).
|
|
199
|
+
|
|
200
|
+
```markdown
|
|
201
|
+
---
|
|
202
|
+
type: Relatório de Sincronismo
|
|
203
|
+
title: Sincronismo ELM → OKF
|
|
204
|
+
description: Situação de cada artefato do DOORS Next baixado neste bundle.
|
|
205
|
+
generated:
|
|
206
|
+
by: "process:elm-mcp/1.0.14"
|
|
207
|
+
at: "2026-10-07T12:00:00Z"
|
|
208
|
+
---
|
|
209
|
+
| Artefato | Pasta | Última atualização ELM | Hash | Status |
|
|
210
|
+
|---|---|---|---|---|
|
|
211
|
+
| [123 — Login](</01-Requisitos/123-login.md>) | 01-Requisitos | 2026-10-01T13:45:10Z | 9f2c…e1 | sincronizado |
|
|
212
|
+
| 125 — Sessão | 01-Requisitos | | | novo |
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
`Última atualização ELM` é o `modified` do ELM no último download/upload, e `Hash` é o sha256 completo do arquivo
|
|
216
|
+
gravado (abreviado no exemplo).
|
|
217
|
+
|
|
218
|
+
No corpo do md do bundle vale uma regra fixa: **artefato do bundle (id no `sync.md`) é sempre embed; o resto é
|
|
219
|
+
sempre link**. Por isso o md do bundle não tem `embedded`, e o `links:` do cabeçalho é só de leitura. O download
|
|
220
|
+
grava o artefato do bundle como `[id título](../03-Regras/2001-x.md)` e o de fora como `[id título](URL do ELM)`.
|
|
221
|
+
Se o ELM estiver diferente da regra (um embed de fora ou um hyperlink para o bundle), a linha fica `normalizado` e o
|
|
222
|
+
upload corrige. Formatos sugeridos para escrever no md:
|
|
223
|
+
|
|
224
|
+
| Referência | Formato |
|
|
225
|
+
|---|---|
|
|
226
|
+
| embed (artefato do bundle) | `[<id>](<id>)` |
|
|
227
|
+
| link para artefato de outra PA | `[<id>](<URL do ELM>)` |
|
|
228
|
+
| link externo | `[<texto descritivo>](<url>)` |
|
|
229
|
+
|
|
230
|
+
Um plano do elm.json vira filtro de `ccm_list_workitems` com `iteration=iterations[it].identifier` e
|
|
231
|
+
`team_areas=[iterations[it].plans[nome].team-area]` (plano sem `team-area`: omita `team_areas`).
|
|
232
|
+
|
|
233
|
+
## Limites em relação à doc IBM
|
|
234
|
+
|
|
235
|
+
- `ccm_create_iteration` e `ccm_create_iteration_plan` usam os serviços internos da UI web
|
|
236
|
+
(`IPlanProcessRestService/createIteration` e `IPlanRestService/putItems`), pois o EWM não tem API pública para
|
|
237
|
+
criá-los. Exigem as permissões de processo correspondentes (ex.: "Modify structures of iterations").
|
|
238
|
+
|
|
239
|
+
- Fora do escopo: Models e Source control; `create_requirement_change_set` e `deliver_requirement_change_set`
|
|
240
|
+
(removidos a pedido); `add_comment_to_testartifact` (o ETM não expõe comentários de revisão
|
|
241
|
+
formal numa API pública).
|
|
242
|
+
- `search_workitems`: `filter` só com AND (OR com uma expressão; outras chaves ou lista vazia dão erro), operadores is/equals, is not, in, before/after e
|
|
243
|
+
contains (summary/description). `termExpressions`/`similarityExpressions` não são suportados. Estado e tipo são
|
|
244
|
+
filtrados pelo id (`com.ibm.team.workitem.taskWorkflow.state.s2`, `task`).
|
|
245
|
+
- `get_workitem_schema`: `include=approvals` não é suportado.
|
|
246
|
+
- `search_testartifact`: `customAttributeFilters`, `categoryFilters` e `linkFilters` não são suportados.
|
|
247
|
+
- `rm_update_requirement`: `text` substitui o texto inteiro; atributos e links não são gravados. `ccm_update_workitem`: `description` substitui a descrição inteira.
|
|
248
|
+
- `rm_search_requirements`: exige ao menos um filtro (`text`, `folder` ou `requirement_type`). O DOORS Next
|
|
249
|
+
responde HTTP 400 quando `text` vem junto com `folder`/`requirement_type`: busque só pelo texto e filtre o
|
|
250
|
+
resultado pelo `type`/`folder`.
|
|
251
|
+
- `get_rm_component_types`: `filter_text_only` é redundante. `list_rm_component_folders`: `include_private` é ignorado.
|
|
252
|
+
- `get_qm_component`/`get_qm_component_configuration`: dependem da query de componentes do provider de configuração do
|
|
253
|
+
ETM, que pode exigir permissão de administrador (403) e só faz sentido em project areas opt-in.
|
|
254
|
+
|
|
255
|
+
## Arquitetura
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
mcp_elm/
|
|
259
|
+
server.py instância MCP + @tool (erros esperados viram ToolError com a mensagem)
|
|
260
|
+
infra/ config, auth (login Jazz), http (sessão, XML, Reportable), oslc (RDF, query, descoberta),
|
|
261
|
+
document (leitura em Markdown + YAML)
|
|
262
|
+
ibm/ um módulo por conjunto de tools da doc: common, requirements, workitems, test
|
|
263
|
+
ccm.py rm.py qm.py tools das skills (prefixos ccm_/rm_); compõem ibm/ e infra/
|
|
264
|
+
skills/ SKILL.md de elm-setup, elm-ccm, elm-rm, elm-qm e elm-gc
|
|
265
|
+
elm/ configuração do projeto (pa_<project area>.json), gravada pela elm-setup
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Testes: `uv run pytest` (servidor Jazz falso em `tests/conftest.py`).
|
mcp_elm-1.0.33/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# mcp-elm
|
|
2
|
+
|
|
3
|
+
Servidor MCP para o IBM ELM via OSLC: **rm** (DOORS Next), **ccm** (EWM) e **qm** (ETM).
|
|
4
|
+
Ele fornece as capacidades que as skills vão consumir. As tools seguem os nomes e parâmetros do
|
|
5
|
+
[IBM Engineering AI Hub MCP 1.3.0](https://www.ibm.com/docs/en/engineering-lifecycle-management-suite/engineering-ai-hub/1.3.0?topic=tools-mcp-engineering-ai-hub).
|
|
6
|
+
|
|
7
|
+
## Credenciais
|
|
8
|
+
|
|
9
|
+
| SO | Arquivo |
|
|
10
|
+
|---|---|
|
|
11
|
+
| Linux/Mac | `~/.config/mcp-elm/elm.properties` |
|
|
12
|
+
| Windows | `%APPDATA%\mcp-elm\elm.properties` |
|
|
13
|
+
|
|
14
|
+
Para usar outro caminho, defina a variável de ambiente `MCP_ELM_CONFIG`.
|
|
15
|
+
|
|
16
|
+
```ini
|
|
17
|
+
[DEFAULT]
|
|
18
|
+
server = https://elm.SEU-SERVIDOR
|
|
19
|
+
user = SEU_USUARIO
|
|
20
|
+
password = SUA_SENHA
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Certificado com CA próprio: `export REQUESTS_CA_BUNDLE=/caminho/ca.pem`.
|
|
24
|
+
|
|
25
|
+
A autenticação usa o form Jazz (`j_security_check`). Se o servidor responder 401 pedindo Basic, o Basic é usado automaticamente.
|
|
26
|
+
|
|
27
|
+
## Instalação
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uv sync
|
|
31
|
+
claude mcp add elm -- uv run --directory /caminho/para/mcp-elm mcp-elm
|
|
32
|
+
# depuração com o MCP Inspector
|
|
33
|
+
uv run mcp dev mcp_elm/server.py
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Contrato de saída
|
|
37
|
+
|
|
38
|
+
- Recursos OSLC: `{url, id, title, types, properties{}, links{}}`, com chaves em qname (`dcterms:title`).
|
|
39
|
+
Cada link é `{url, title?}`. `get_workitem` e `search_workitems` trazem o `title` dos recursos ligados (estado,
|
|
40
|
+
prioridade, iteração...) na mesma requisição (`oslc.properties`/`oslc.select` com `{dcterms:title}`) e completam
|
|
41
|
+
o nome dos usuários do JTS pela lista em cache do Reportable REST.
|
|
42
|
+
- Dados da API de processo e do Reportable REST usam os nomes de campo da doc IBM
|
|
43
|
+
(`get_user` → `userUUID, userId, name, emailAddress, archived`; `get_project_area` → `name, project_area_uuid,
|
|
44
|
+
summary, description, cm_enabled, team_areas, timelines, associations`).
|
|
45
|
+
- Entradas por UUID/URL, como na doc IBM. Descubra-os com `list_project_areas`, `get_project_area`,
|
|
46
|
+
`get_project_components` (rm) e `get_qm_component` (qm).
|
|
47
|
+
- `configuration`/`configuration_url`/`global_configuration_url`/`gc_uri`/`gc_context` vão no header
|
|
48
|
+
`Configuration-Context`. No DOORS Next, sem configuração, é usada a primeira stream do componente.
|
|
49
|
+
|
|
50
|
+
## Tools (IBM Engineering AI Hub 1.3.0)
|
|
51
|
+
|
|
52
|
+
| Conjunto | Tools |
|
|
53
|
+
|---|---|
|
|
54
|
+
| Common | get_user, get_project_area, get_global_configuration, search_global_configuration, list_project_areas, list_linked_requirements, list_linked_workitems, list_linked_testartifacts, link_workitem_and_requirement, link_workitem_and_testartifact, link_testartifact_and_requirement |
|
|
55
|
+
| Requirements | get_project_components, get_rm_component_types, list_rm_component_folders, get_rm_component_configuration, get_requirement, search_requirement, create_requirement |
|
|
56
|
+
| Work Items | create_workitem, get_workitem, get_workitem_schema, list_workitem_categories, list_workitem_releases, search_workitems, add_comment_to_workitem |
|
|
57
|
+
| Test | get_testartifact, get_testartifact_schema, search_testartifact, get_qm_component, get_qm_component_configuration |
|
|
58
|
+
|
|
59
|
+
Aliases da doc (`get_rm_component`, `get_project_component_types`...) não são registrados: vale o primeiro nome.
|
|
60
|
+
|
|
61
|
+
## Skills
|
|
62
|
+
|
|
63
|
+
As skills ficam em `skills/` e documentam, para a IA, as tools, suas entradas e saídas, os fluxos e os erros, para
|
|
64
|
+
evitar consultas desnecessárias ao servidor.
|
|
65
|
+
|
|
66
|
+
| Skill | Assunto |
|
|
67
|
+
|---|---|
|
|
68
|
+
| elm-setup | Cria/atualiza a configuração do projeto em `elm/pa_<project area em snake_case>.json` (um arquivo por project area do CCM) |
|
|
69
|
+
| elm-ccm | Work items: item de trabalho (WI), tarefa, defeito, item de backlog (IB)... |
|
|
70
|
+
| elm-rm | Requisitos: RF, RNF, HU, UC, regra, mensagem, especificação... |
|
|
71
|
+
| elm-qm | Testes (só leitura): caso de teste (CT), plano (PT), execução (TER)... |
|
|
72
|
+
| elm-gc | Comum: usuários, project areas, associações, configuração global e links de rastreabilidade |
|
|
73
|
+
|
|
74
|
+
Instalação por projeto (links relativos, sem cópia):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
mkdir -p .claude/skills .kiro/skills
|
|
78
|
+
for s in elm-setup elm-ccm elm-rm elm-qm elm-gc; do
|
|
79
|
+
ln -sfn ../../skills/$s .claude/skills/$s # Claude Code
|
|
80
|
+
ln -sfn ../../skills/$s .kiro/skills/$s # Kiro
|
|
81
|
+
done
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Tools das skills
|
|
85
|
+
|
|
86
|
+
Saída com as chaves do elm.json (`elm/pa_*.json`; a skill grava o arquivo, o MCP não o lê). Listas voltam como
|
|
87
|
+
`[{name, identifier, ...}]` e a skill grava o mapa `{name: identifier}`.
|
|
88
|
+
|
|
89
|
+
| Skill | Tools |
|
|
90
|
+
|---|---|
|
|
91
|
+
| elm-setup (ccm) | whoami, list_project_areas("CCM"), ccm_list_team_areas, ccm_list_members, ccm_list_workitem_types, ccm_list_workitem_fields, ccm_list_link_types, ccm_list_iterations, ccm_list_iteration_plans, ccm_create_iteration, ccm_create_iteration_plan |
|
|
92
|
+
| elm-setup (rm) | list_project_areas("RM"), get_project_area(include_associations), rm_get_configuration, rm_list_members, rm_list_folders, rm_list_requirement_types |
|
|
93
|
+
| elm-ccm | ccm_list_workitems, ccm_get_workitem, ccm_list_field_values, ccm_create_workitem, ccm_update_workitem, ccm_list_workitem_states (+ add_comment_to_workitem, link_*) |
|
|
94
|
+
| elm-rm | rm_search_requirements, rm_count_folder, rm_list_folder, rm_list_modified, rm_sync_plan, rm_download_requirements, rm_upload_requirements, rm_get_requirement, rm_create_requirement, rm_update_requirement (+ link_workitem_and_requirement) |
|
|
95
|
+
| elm-qm | search_testartifact, get_testartifact, get_testartifact_schema, get_qm_component, get_qm_component_configuration |
|
|
96
|
+
| elm-gc | whoami, get_user, list_project_areas, get_project_area, get_global_configuration, search_global_configuration, list_linked_*, link_* |
|
|
97
|
+
|
|
98
|
+
### Leitura em Markdown + YAML
|
|
99
|
+
|
|
100
|
+
`ccm_get_workitem` e `rm_get_requirement` devolvem um documento Markdown com cabeçalho YAML. O MCP não traduz
|
|
101
|
+
nomes:
|
|
102
|
+
|
|
103
|
+
- **Work item:** o cabeçalho traz só os campos e links mapeados no elm.json, com o nome de lá. A skill passa
|
|
104
|
+
`fields=workitem-types[tipo].fields` e `link_types=ccm.link-types` e, para gravar, procura a chave no mesmo mapa
|
|
105
|
+
(`fields["Estimativa"]` → `rtc_cm:estimate`).
|
|
106
|
+
- **Requisito:** o cabeçalho traz os links preenchidos, com os nomes do DOORS Next (só leitura: não são gravados), e
|
|
107
|
+
`embedded` (artefatos embutidos no texto). A gravação é só de título e texto. O elm.json do RM guarda só tipos e pastas.
|
|
108
|
+
|
|
109
|
+
O cabeçalho do requisito segue o [Google OKF v0.2](https://okf.md/): primeiro os campos OKF padrão (`type`,
|
|
110
|
+
`title`, `description?`, `resource`, `tags` = [pasta]), depois `sources` (a fonte no DOORS Next: `author` = quem
|
|
111
|
+
criou, `last_modified` = última modificação no ELM e `last_modified_by` = quem modificou por último) e `generated` (quem gerou e **quando o documento foi gerado**), ambos em ISO 8601 UTC, e, por
|
|
112
|
+
fim, as extensões RM. `sources[0].last_modified` > `generated.at` indica cópia desatualizada; `rm_list_modified`
|
|
113
|
+
devolve essa data para um ou vários ids sem ler o conteúdo. Para download/sync de uma pasta, use
|
|
114
|
+
`rm_count_folder` (total pelo servidor) e `rm_list_folder` (todos os `{id, title, modified}`, sem teto) como
|
|
115
|
+
inventário: só a pasta, sem subpastas; `count` diferente do tamanho da lista indica listagem inconsistente. Para o bundle da elm-sync, o MCP cuida de tudo sem passar listas nem conteúdo pela conversa
|
|
116
|
+
(ver [Sincronismo do bundle](#sincronismo-do-bundle-elm-sync)). Extensões RM: `id`, `created` (UTC), `links` e `embedded`, só quando preenchidos. `verified`, `status` e
|
|
117
|
+
`stale_after` só aparecem quando o artefato traz um sinal real (requisitos do DOORS Next não os definem).
|
|
118
|
+
|
|
119
|
+
Exemplo (dados fictícios):
|
|
120
|
+
|
|
121
|
+
```markdown
|
|
122
|
+
---
|
|
123
|
+
type: Caso de Uso
|
|
124
|
+
title: UC - Cadastrar cliente
|
|
125
|
+
resource: "https://elm.example.com/rm/resources/TX_exemplo2010"
|
|
126
|
+
tags:
|
|
127
|
+
- "03-Casos de Uso"
|
|
128
|
+
sources:
|
|
129
|
+
- id: doors-next
|
|
130
|
+
resource: "https://elm.example.com/rm/resources/TX_exemplo2010"
|
|
131
|
+
author: "human:ana.souza"
|
|
132
|
+
last_modified: "2026-01-10T13:05:00Z"
|
|
133
|
+
last_modified_by: "human:bruno.lima"
|
|
134
|
+
generated:
|
|
135
|
+
by: "process:elm-mcp/1.0.14"
|
|
136
|
+
at: "2026-01-11T19:20:00Z"
|
|
137
|
+
id: 2010
|
|
138
|
+
created: "2026-01-05T13:00:00Z"
|
|
139
|
+
links:
|
|
140
|
+
Vincular A:
|
|
141
|
+
- "2002: RN - Cliente deve ser maior de idade"
|
|
142
|
+
embedded:
|
|
143
|
+
- "2001: RN - Validar CPF do cliente"
|
|
144
|
+
---
|
|
145
|
+
## Fluxo Básico
|
|
146
|
+
|
|
147
|
+
1. O usuário informa os dados do cliente.
|
|
148
|
+
2. O sistema valida o documento: [2001 RN - Validar CPF do cliente](https://elm.example.com/rm/resources/TX_exemplo2001)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
O corpo é Markdown nos dois sentidos: `text` (RM) e `description` (WI) aceitam Markdown na gravação. No RM, a
|
|
152
|
+
leitura sai sempre no mesmo padrão: todo artefato, embutido ou hyperlink, é `[<id> <título>](<alvo>)`, com o alvo =
|
|
153
|
+
URL do ELM; o que é embed está na lista `embedded` do cabeçalho (artefato ilegível sai como link e fica fora da
|
|
154
|
+
lista). Na gravação, o link cujo artefato está em `embedded` (parâmetro de
|
|
155
|
+
`rm_create_requirement`/`rm_update_requirement`) vira embed e o resto, hyperlink; alvo por URL (inclusive link da UI
|
|
156
|
+
web com `artifactURI`), id (`2001`) ou arquivo cujo nome começa pelo id. No EWM a descrição só tem texto, `<br/>`, `<b>`, `<i>` e `<a>` (listas viram `• ` / `1. `); para citar outro
|
|
157
|
+
WI, escreva "Tarefa 1002" no texto e o EWM cria o link "Menções". `[texto](url)` é hyperlink comum.
|
|
158
|
+
|
|
159
|
+
### Sincronismo do bundle (elm-sync)
|
|
160
|
+
|
|
161
|
+
O bundle é uma pasta de md, um por requisito (`<pasta>/<id>-<slug>.md`), com `sync.md` (situação de cada artefato),
|
|
162
|
+
`index.md` na raiz e em cada pasta (OKF §8, como o `build_index` do okf-kit) e `log.md` (cada sync registra, sob
|
|
163
|
+
`## AAAA-MM-DD`, o que criou, atualizou, subiu, moveu ou apagou). O sincronismo baixa primeiro e depois sobe o que foi editado no md:
|
|
164
|
+
|
|
165
|
+
1. `rm_sync_plan(folders, dest)`: lista as pastas, regrava `sync.md`, apaga os removidos e devolve um resumo com
|
|
166
|
+
`a_baixar`, `a_subir` e `conflitos`;
|
|
167
|
+
2. `rm_download_requirements(dest)` até `restantes = 0`;
|
|
168
|
+
3. para cada item de `conflitos`, a skill **pergunta ao usuário qual versão fica**. Se for o ELM, chama
|
|
169
|
+
`rm_download_requirements(dest, requirement_ids=[id])`; se for o md, chama `rm_upload_requirements(dest, requirement_ids=[id])`;
|
|
170
|
+
4. `rm_upload_requirements(dest)` até `restantes = 0` (sobe título e corpo e rebaixa o requisito).
|
|
171
|
+
|
|
172
|
+
| Estado | Quando | Ação |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `novo` | id ainda não baixado | download |
|
|
175
|
+
| `sincronizado` | md == ELM | — |
|
|
176
|
+
| `desatualizado` | `modified` do ELM ≠ `Última atualização ELM` | download |
|
|
177
|
+
| `atualizado` | md alterado (sha256 ≠ `Hash`) e ELM sem mudança | upload |
|
|
178
|
+
| `normalizado` | md **não** alterado (hash igual), mas o ELM foge da regra embed/link do bundle (diferença invisível no md) | upload |
|
|
179
|
+
| `conflito` | md alterado **e** ELM mudou | perguntar ao usuário: md ou ELM |
|
|
180
|
+
| `erro: <msg>` | falha no download | download de novo |
|
|
181
|
+
|
|
182
|
+
Mudar de pasta é tratado como remoção na antiga e criação na nova: o arquivo é apagado e a linha volta a `novo`
|
|
183
|
+
(com edição local no md, vira `conflito` e o arquivo fica).
|
|
184
|
+
|
|
185
|
+
```markdown
|
|
186
|
+
---
|
|
187
|
+
type: Relatório de Sincronismo
|
|
188
|
+
title: Sincronismo ELM → OKF
|
|
189
|
+
description: Situação de cada artefato do DOORS Next baixado neste bundle.
|
|
190
|
+
generated:
|
|
191
|
+
by: "process:elm-mcp/1.0.14"
|
|
192
|
+
at: "2026-10-07T12:00:00Z"
|
|
193
|
+
---
|
|
194
|
+
| Artefato | Pasta | Última atualização ELM | Hash | Status |
|
|
195
|
+
|---|---|---|---|---|
|
|
196
|
+
| [123 — Login](</01-Requisitos/123-login.md>) | 01-Requisitos | 2026-10-01T13:45:10Z | 9f2c…e1 | sincronizado |
|
|
197
|
+
| 125 — Sessão | 01-Requisitos | | | novo |
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`Última atualização ELM` é o `modified` do ELM no último download/upload, e `Hash` é o sha256 completo do arquivo
|
|
201
|
+
gravado (abreviado no exemplo).
|
|
202
|
+
|
|
203
|
+
No corpo do md do bundle vale uma regra fixa: **artefato do bundle (id no `sync.md`) é sempre embed; o resto é
|
|
204
|
+
sempre link**. Por isso o md do bundle não tem `embedded`, e o `links:` do cabeçalho é só de leitura. O download
|
|
205
|
+
grava o artefato do bundle como `[id título](../03-Regras/2001-x.md)` e o de fora como `[id título](URL do ELM)`.
|
|
206
|
+
Se o ELM estiver diferente da regra (um embed de fora ou um hyperlink para o bundle), a linha fica `normalizado` e o
|
|
207
|
+
upload corrige. Formatos sugeridos para escrever no md:
|
|
208
|
+
|
|
209
|
+
| Referência | Formato |
|
|
210
|
+
|---|---|
|
|
211
|
+
| embed (artefato do bundle) | `[<id>](<id>)` |
|
|
212
|
+
| link para artefato de outra PA | `[<id>](<URL do ELM>)` |
|
|
213
|
+
| link externo | `[<texto descritivo>](<url>)` |
|
|
214
|
+
|
|
215
|
+
Um plano do elm.json vira filtro de `ccm_list_workitems` com `iteration=iterations[it].identifier` e
|
|
216
|
+
`team_areas=[iterations[it].plans[nome].team-area]` (plano sem `team-area`: omita `team_areas`).
|
|
217
|
+
|
|
218
|
+
## Limites em relação à doc IBM
|
|
219
|
+
|
|
220
|
+
- `ccm_create_iteration` e `ccm_create_iteration_plan` usam os serviços internos da UI web
|
|
221
|
+
(`IPlanProcessRestService/createIteration` e `IPlanRestService/putItems`), pois o EWM não tem API pública para
|
|
222
|
+
criá-los. Exigem as permissões de processo correspondentes (ex.: "Modify structures of iterations").
|
|
223
|
+
|
|
224
|
+
- Fora do escopo: Models e Source control; `create_requirement_change_set` e `deliver_requirement_change_set`
|
|
225
|
+
(removidos a pedido); `add_comment_to_testartifact` (o ETM não expõe comentários de revisão
|
|
226
|
+
formal numa API pública).
|
|
227
|
+
- `search_workitems`: `filter` só com AND (OR com uma expressão; outras chaves ou lista vazia dão erro), operadores is/equals, is not, in, before/after e
|
|
228
|
+
contains (summary/description). `termExpressions`/`similarityExpressions` não são suportados. Estado e tipo são
|
|
229
|
+
filtrados pelo id (`com.ibm.team.workitem.taskWorkflow.state.s2`, `task`).
|
|
230
|
+
- `get_workitem_schema`: `include=approvals` não é suportado.
|
|
231
|
+
- `search_testartifact`: `customAttributeFilters`, `categoryFilters` e `linkFilters` não são suportados.
|
|
232
|
+
- `rm_update_requirement`: `text` substitui o texto inteiro; atributos e links não são gravados. `ccm_update_workitem`: `description` substitui a descrição inteira.
|
|
233
|
+
- `rm_search_requirements`: exige ao menos um filtro (`text`, `folder` ou `requirement_type`). O DOORS Next
|
|
234
|
+
responde HTTP 400 quando `text` vem junto com `folder`/`requirement_type`: busque só pelo texto e filtre o
|
|
235
|
+
resultado pelo `type`/`folder`.
|
|
236
|
+
- `get_rm_component_types`: `filter_text_only` é redundante. `list_rm_component_folders`: `include_private` é ignorado.
|
|
237
|
+
- `get_qm_component`/`get_qm_component_configuration`: dependem da query de componentes do provider de configuração do
|
|
238
|
+
ETM, que pode exigir permissão de administrador (403) e só faz sentido em project areas opt-in.
|
|
239
|
+
|
|
240
|
+
## Arquitetura
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
mcp_elm/
|
|
244
|
+
server.py instância MCP + @tool (erros esperados viram ToolError com a mensagem)
|
|
245
|
+
infra/ config, auth (login Jazz), http (sessão, XML, Reportable), oslc (RDF, query, descoberta),
|
|
246
|
+
document (leitura em Markdown + YAML)
|
|
247
|
+
ibm/ um módulo por conjunto de tools da doc: common, requirements, workitems, test
|
|
248
|
+
ccm.py rm.py qm.py tools das skills (prefixos ccm_/rm_); compõem ibm/ e infra/
|
|
249
|
+
skills/ SKILL.md de elm-setup, elm-ccm, elm-rm, elm-qm e elm-gc
|
|
250
|
+
elm/ configuração do projeto (pa_<project area>.json), gravada pela elm-setup
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Testes: `uv run pytest` (servidor Jazz falso em `tests/conftest.py`).
|