A comprehensive Model Context Protocol (MCP) server for Siemens Polarion ALM integration, with full support for test case management, test runs, and result reporting.
- Create test cases with full details (all Polarion fields supported)
- Update test case attributes
- Search and query test cases
- Add/update test steps (REST API + SOAP API fallback)
- Blank Slate Strategy - Add test steps immediately upon creation
- SOAP API Integration - Override existing test steps with username/password auth
- Link test cases to bugs or requirements (e.g.
verifiesrelationship) - Full field support - automation status, setup, teardown, test type, importance, level, version, and more
- Create test runs
- Add test cases to test runs
- Update test run status
- Record test results (passed/failed/blocked)
- Add attachments and comments
- JUnit XML import - Import test results from JUnit reports
- Spreadsheet export - Export test cases/results to Excel/CSV
- Spreadsheet import - Bulk import test cases from spreadsheets
- Webhook support for CI/CD integration
pip install fastmcp requests openpyxl xmltodict- Clone or copy this project:
cd ~/Documents/GitHub
git clone <repo-url> polarion-mcp-server
cd polarion-mcp-server- Install dependencies:
pip install -r requirements.txt- Configure environment variables:
export POLARION_TOKEN="your-personal-access-token"
export POLARION_URL="https://polarion.engineering.redhat.com"
export POLARION_PROJECT="OSE"
# Optional: For SOAP API support (updating existing test steps)
export POLARION_USERNAME="your-username"
export POLARION_PASSWORD="your-password"Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"polarion": {
"command": "python3",
"args": [
"/path/to/polarion-mcp-server/server.py"
],
"env": {
"POLARION_TOKEN": "${POLARION_TOKEN}",
"POLARION_URL": "https://polarion.engineering.redhat.com",
"POLARION_PROJECT": "OSE"
}
}
}
}python3 server.pycreate_polarion_test_case(
title="Verify certificate validation",
description="Test that certificates are read from controllerConfig",
test_steps="1. Check config\n2. Verify certs\n3. Validate",
severity="should_have",
status="draft"
)create_polarion_test_case(
title="Duplicate BIOS UUID: verify correct VM disks after migration",
description="Bug verification for MTV-5091/MTV-5326.",
severity="should_have",
status="draft",
caseautomation="manualonly",
automation_script="Manual only - behavioral E2E test has ~33% false negative rate",
setup="Source Provider: vmware-8 (vSphere 8).\nTarget Provider: host (OpenShift).",
teardown="Delete migration plan and migrated VM from OpenShift.",
testtype="functional",
caseposneg="positive",
caseimportance="high",
caselevel="system",
version=["2.12."],
customerscenario=False
)link_polarion_work_item(
test_case_id="MTV-694",
target_id="MTV-5091",
role="verifies"
)add_test_steps_to_testcase(
test_case_id="PROJECT-123",
test_steps=[
{
"step": "Run command: oc get nodes",
"expectedResult": "All nodes are Ready"
},
{
"step": "Check certificate: Get-Item C:\\k\\cert.crt",
"expectedResult": "File exists"
}
]
)create_test_run(
title="Sprint 123 - Certificate Tests",
template="Release Test",
test_case_ids=["PROJECT-123", "PROJECT-456"],
query="type:testcase AND title:certificate"
)update_test_run_result(
test_run_id="OSE-TR-12345",
test_case_id="PROJECT-123",
result="passed",
comment="All certificates validated successfully",
executed_by="user@example.com",
duration=120 # seconds
)import_junit_results(
junit_file="/tmp/junit-results.xml",
test_run_id="OSE-TR-12345",
map_test_ids={
"com.example.CertTest.testKubeletCA": "PROJECT-123",
"com.example.CertTest.testCloudCA": "PROJECT-456"
}
)export_test_cases_to_spreadsheet(
query="type:testcase AND author:username",
output_file="/tmp/my-tests.xlsx",
include_test_steps=True
)import_test_cases_from_spreadsheet(
spreadsheet_file="/tmp/test-cases.xlsx",
project_id="OSE"
)The server uses a delete-then-create strategy via the REST API to add or replace test steps on any test case, whether new or existing.
# Works for both new and existing test cases
add_test_steps_to_testcase(
test_case_id="PROJECT-123",
test_steps=[
{"step": "Run command: oc get nodes", "expectedResult": "All nodes Ready"},
{"step": "Verify certificate", "expectedResult": "Certificate valid"}
]
)When a test case already has steps, the server automatically deletes the existing steps and creates the new ones. No manual cleanup or SOAP credentials are needed.
For environments where the REST delete endpoint is unavailable, the SOAP API can be used as a fallback with force_soap=True. This requires username/password credentials:
export POLARION_USERNAME="your-username"
export POLARION_PASSWORD="your-password"add_test_steps_to_testcase(
test_case_id="PROJECT-123",
test_steps=[...],
force_soap=True
)Create a new test case in Polarion.
Parameters:
title(str): Test case titledescription(str): Detailed descriptionproject_id(str): Project ID (default: from env)test_steps(str, optional): Test steps (newline-separated)severity(str): must_have, should_have, nice_to_have, will_not_havestatus(str): draft, approved, etc.caseautomation(str, optional):notautomated,automated, ormanualonlyautomation_script(str, optional): Script path or explanation why manual onlysetup(str, optional): Preconditions / environment setupteardown(str, optional): Cleanup instructionstesttype(str, optional):functional,nonfunctional,structuralcaseposneg(str, optional):positiveornegativecaseimportance(str, optional):critical,high,medium,lowcaselevel(str, optional):component,integration,system,acceptanceversion(list, optional): Version strings, e.g.["2.12."]customerscenario(bool, optional): Whether this is a customer scenario
Returns: JSON with test case ID and URL
Link a test case to a bug or requirement.
Parameters:
test_case_id(str): Source test case ID (e.g., "MTV-694")target_id(str): Target work item ID (e.g., "MTV-5091")role(str): Link role —verifies,parent,relates_to,duplicatesproject_id(str): Project ID of the sourcetarget_project_id(str, optional): Project ID of the target (defaults to same)
Returns: JSON with link status
Add or replace test steps for a test case.
Parameters:
test_case_id(str): Test case ID (e.g., "PROJECT-123")test_steps(List[Dict]): List of {"step": "...", "expectedResult": "..."}project_id(str): Project ID
Returns: JSON with success status and steps count
Search for test cases using Polarion query language.
Parameters:
query(str): Polarion query (e.g., "type:testcase AND title:Windows")project_id(str): Project IDlimit(int): Max results to return
Returns: JSON with matching test cases
Create a new test run.
Parameters:
title(str): Test run titletemplate(str): Template name (e.g., "Release Test")project_id(str): Project IDtest_case_ids(List[str], optional): Test case IDs to includequery(str, optional): Query to select test cases
Returns: JSON with test run ID and URL
Update the result of a test case within a test run.
Parameters:
test_run_id(str): Test run IDtest_case_id(str): Test case IDresult(str): passed, failed, blockedcomment(str, optional): Comment about the resultexecuted_by(str, optional): Who executed the testduration(int, optional): Duration in seconds
Returns: JSON with update status
Import test results from JUnit XML file.
Parameters:
junit_file(str): Path to JUnit XML filetest_run_id(str): Test run ID to updatemap_test_ids(Dict[str, str]): Map JUnit test names to Polarion IDsauto_create_test_run(bool): Create test run if it doesn't exist
Returns: JSON with import summary
Export test cases to Excel/CSV.
Parameters:
query(str): Query to select test casesoutput_file(str): Output file path (.xlsx or .csv)include_test_steps(bool): Include test stepsformat(str): xlsx or csv
Returns: JSON with export summary
Bulk import test cases from spreadsheet.
Parameters:
spreadsheet_file(str): Input spreadsheet pathproject_id(str): Project IDupdate_existing(bool): Update if test case exists
Returns: JSON with import summary
| Title | Description | Severity | Status | Test Steps | Expected Results |
|---|---|---|---|---|---|
| Test case 1 | Description here | should_have | draft | Step 1\nStep 2 | Result 1\nResult 2 |
| Test case 2 | Description here | must_have | approved | Step 1\nStep 2 | Result 1\nResult 2 |
| Test Case ID | Result | Comment | Executed By | Duration (s) |
|---|---|---|---|---|
| PROJECT-123 | passed | All checks OK | user@example.com | 120 |
| PROJECT-456 | failed | Certificate mismatch | user@example.com | 45 |
The server automatically maps JUnit test results to Polarion test cases:
<testsuite name="Certificate Tests">
<testcase classname="com.example.CertTest" name="testKubeletCA" time="1.234">
<system-out>Test output here</system-out>
</testcase>
<testcase classname="com.example.CertTest" name="testCloudCA" time="0.567">
<failure message="Certificate not found">Stack trace...</failure>
</testcase>
</testsuite>Maps to Polarion test cases via map_test_ids parameter.
polarion-mcp-server/
├── server.py # Main MCP server
├── polarion_client.py # Polarion REST API client
├── test_runs.py # Test run management
├── integrations/
│ ├── junit_import.py # JUnit XML parser
│ ├── spreadsheet.py # Excel/CSV integration
│ └── webhooks.py # CI/CD webhooks
├── examples/
│ ├── create_test_case.py
│ ├── create_test_run.py
│ ├── import_junit.py
│ └── export_to_excel.py
├── tests/
│ ├── test_client.py
│ └── test_integrations.py
├── requirements.txt
├── .env.example
└── README.md
This server uses several Polarion REST API endpoints, including some undocumented ones:
| Endpoint | Method | Purpose | Documented? |
|---|---|---|---|
/projects/{id}/workitems |
POST | Create workitem | Yes |
/projects/{id}/workitems/{id} |
PATCH | Update workitem | Yes |
/projects/{id}/workitems/{id}/teststeps |
POST | Add test steps | No - Discovered! |
/projects/{id}/workitems/{id}/teststeps |
DELETE | Bulk delete test steps | No - Discovered! |
/projects/{id}/workitems/{id}/teststeps/{index} |
GET | Get test step | No - Discovered! |
/projects/{id}/workitems/{id}/teststeps/{index} |
DELETE | Delete test step | No - Discovered! |
/projects/{id}/testruns |
POST | Create test run | Yes |
/projects/{id}/testruns/{id}/records |
PATCH | Update test result | Yes |
The server uses Personal Access Tokens (PAT) for authentication. Get your token from:
- Log into Polarion
- Go to your profile settings
- Click "Personal Access Token"
- Create a new token (max 90 days)
- Copy the token and set
POLARION_TOKENenvironment variable
- Never commit
POLARION_TOKENto version control - Use environment variables or secure vaults
- SSL verification is enabled by default for secure connections
- Limit token permissions to minimum required
SSL verification is enabled by default for security. If you encounter certificate errors with self-signed certificates or internal servers:
Option 1: Install the CA certificate (recommended)
export POLARION_CA_CERT="/path/to/ca-cert.pem"Option 2: Disable SSL verification (development only)
export POLARION_VERIFY_SSL="false"Note: Disabling SSL verification should only be used in trusted development environments, never in production.
- Check token is valid (not expired)
- Verify token has correct permissions
- Check Polarion URL is correct
- Test with curl:
curl -H "Authorization: Bearer $POLARION_TOKEN" \
"https://polarion.engineering.redhat.com/polarion/rest/v1/projects/OSE"- Ensure you're using the
/teststepsendpoint (not/relationships/testSteps) - Check keys are exactly
["step", "expectedResult"] - Verify HTML escaping in values
Contributions welcome! Areas for improvement:
- Additional integration formats (TestRail, Zephyr, etc.)
- Bulk operations optimization
- Advanced query builders
- Test run templates
- Attachment management
Custom field support(done - see v1.1.0)
MIT License - See LICENSE file
Developed for Red Hat OpenShift Windows Container testing.
Discovered and documented undocumented Polarion REST API test steps endpoints.
- GitHub Issues: Create an issue
- Internal: Red Hat WINC team
- Polarion Docs: https://developer.siemens.com/polarion/
- Full test case field support: automation status, setup, teardown, test type, importance, level, version, customer scenario, automation script
- Work item linking (e.g. test case
verifiesa bug) - Rich text fields (setup, teardown, automation_script) use proper Polarion HTML format
- Initial release
- Test case management
- Test steps API discovery
- Test run management
- JUnit integration
- Spreadsheet import/export
- Full MCP server implementation