elm-alm-py
MCP server for IBM Engineering Lifecycle Management (ELM) — read and write access to DOORS Next (RM), RTC/EWM (CCM), and ETM (QM) via OSLC REST APIs.
Tested against ELM 7.0.3 (alm.dataprev.gov.br).
Install
uv pip install -e .
Configuration
Option 1: Credentials file (recommended)
elm-alm-py login
Saves to ~/.elm_creds.json:
{"url": "https://your-elm-server.example.com", "username": "user", "password": "base64encoded"}
Option 2: Environment variables
export ELM_URL=https://your-elm-server.example.com
export ELM_USER=your_username
export ELM_PASSWORD=secret
Usage
# As MCP server (stdio)
elm-alm-py
MCP client configuration
{
"mcpServers": {
"elm-alm": {
"command": "/path/to/.venv/bin/elm-alm-py"
}
}
}
Tools
Read Operations
| Tool | Description |
|---|---|
list_projects(domain) |
List projects for RM/CCM/QM |
search_requirements(project, query?) |
OSLC query on RM requirements |
get_requirement(uri) |
Get single requirement by URI |
list_workitems(project, query?) |
OSLC query on CCM work items |
get_workitem(id) |
Get single work item by ID |
search_testcases(project, query?) |
OSLC query on QM test cases |
Write Operations
| Tool | Description |
|---|---|
create_workitem(project, title, type?, ...) |
Create a work item (task/story/defect) |
update_workitem(id, title?, description?) |
Update work item fields (ETag-based) |
add_child_workitem(parent_id, title, ...) |
Create a child work item |
create_workitem parameters
| Parameter | Required | Description |
|---|---|---|
project |
✅ | Project name (e.g., "MEU IMOVEL RURAL (MIR)") |
title |
✅ | Work item title |
type |
"task" (default), "story", or "defect" | |
description |
HTML description | |
parent_id |
Parent work item ID (creates child link) | |
owner |
Username (e.g., "claudio.filho") | |
filed_against |
Category URI. Auto-discovered if not provided | |
custom_fields |
Dict of extra RDF fields (see below) |
custom_fields for project-specific attributes
Some RTC projects require custom fields. Pass them as a dict:
custom_fields={
"rtc_ext:com.dataprev.team.workitem.attribute.categoriatarefa": {
"rdf:resource": "https://server/ccm/oslc/enumerations/{projectAreaId}/..."
}
}
Values can be:
{"rdf:resource": "uri"}— for URI/enumeration fields"text"— for literal text fields
OSLC API Details
Work Item Types (CCM)
| Type | RTC type ID | calm:id in services.xml |
|---|---|---|
| task | task |
requirementChangeRequest |
| story | com.ibm.team.apt.workItemType.story |
planItem |
| defect | defect |
defect |
Key Fields
| Field | Namespace | Format |
|---|---|---|
| Title | dcterms:title |
Text |
| Type | rtc_cm:type |
rdf:resource URI |
| Category | rtc_cm:filedAgainst |
rdf:resource (itemOid format) |
| Iteration | rtc_cm:plannedFor |
rdf:resource URI |
| Owner | dcterms:contributor |
rdf:resource /jts/users/{login} |
| Estimate | rtc_cm:estimate |
Integer (milliseconds) |
| State | rtc_cm:state |
rdf:resource URI |
Content Types
- Create (POST):
application/rdf+xml - Read (GET):
application/json(Accept header) - Update (PUT):
application/jsonwithIf-Match: {ETag}
Development
uv sync --group dev
uv run pytest tests/ -v --cov=elm_alm_py
uv run ruff check src/ tests/
Known Limitations
_find_default_categoryreturns first category from list (may not be correct for your project). Usefiled_againstparameter explicitly.update_workitemsupports title, description, owner, estimate_hours, planned_for, and custom_fields.- OSLC CM 1.0 services.xml parsing is bypassed — creation URL is constructed directly.
License
MIT
Metadata
Release files for elm-alm-py 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| elm_alm_py-0.3.0.tar.gz | 23.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| elm_alm_py-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.2 kB
Release files / elm_alm_py-0.3.0.tar.gz
| Download URL | elm_alm_py-0.3.0.tar.gz |
|---|---|
| Size | 23.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1a410c08d406e3d57cda1090bcefa6a6c1347f8ed57a9a90473f9a2295cf8f31
|
|
BLAKE2b-256 checksum How to use checksums |
042040c79e8efdbd5a2bdcb487db20980d187a24db28b3e7ef7400712501ba5c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency logRelease files / elm_alm_py-0.3.0-py3-none-any.whl
| Download URL | elm_alm_py-0.3.0-py3-none-any.whl |
|---|---|
| Size | 14.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7b8404112b21c67b8da4f52593f37fdb28ef3a1f4ca6f6279089d22a57005696
|
|
BLAKE2b-256 checksum How to use checksums |
ffd1ef2c86ea903a31816dda25f3de28962d8c987bb38088e6841fdde5a42119
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency log