Edit SSRS reports using AI - MCP server for RDL files
Project description
RDL MCP Server
mcp-name: io.github.bethmaloney/rdl-mcp
Edit SSRS reports using AI assistants instead of wrestling with 2000+ lines of XML. This Model Context Protocol (MCP) server gives Claude, Copilot, and other AI tools simple commands to read and modify RDL files.
What It Does
Read reports:
describe_rdl_report- Get report structure overviewget_rdl_datasets- View datasets, fields, and stored procedures (supports field limiting and filtering)get_rdl_parameters- List all report parametersget_rdl_columns- See column headers, widths, and bindings
Modify reports:
update_column_header/update_column_width- Change columnsadd_column/remove_column- Add or remove columnsupdate_column_format- Change number/date formattingupdate_stored_procedure- Swap stored proceduresadd_dataset_field/remove_dataset_field- Manage dataset fieldsadd_parameter/update_parameter- Manage parametersvalidate_rdl- Validate XML after changes
Why it's better than editing XML:
- AI sees clean JSON instead of verbose XML namespaces
- One-line commands instead of error-prone string manipulation
- Automatic validation catches errors before they break reports
- No dependencies - just Python 3.8+ standard library
Installation
1. Get the server:
git clone https://github.com/yourusername/rdl-mcp.git
cd rdl-mcp
2. Configure your MCP client:
Claude Desktop
Edit config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows, ~/.config/Claude/claude_desktop_config.json on Linux):
{
"mcpServers": {
"rdl-mcp": {
"command": "python3",
"args": ["/absolute/path/to/rdl_mcp_server.py"]
}
}
}
GitHub Copilot (VSCode)
Add to VSCode settings (.vscode/settings.json in your workspace or user settings):
{
"github.copilot.chat.mcp.servers": {
"rdl-mcp": {
"command": "python3",
"args": ["/absolute/path/to/rdl_mcp_server.py"]
}
}
}
Note: MCP support in GitHub Copilot requires VSCode with Copilot Chat extension installed.
3. Restart your AI assistant and try: "Describe the structure of my report.rdl file"
Requirements: Python 3.8+ (no other dependencies)
Optional: Enable debug logging
Set environment variables:
RDL_MCP_LOG_LEVEL:DEBUG,INFO,WARNING, orERRORRDL_MCP_LOG_FILE: Path to log file
Usage
Just ask your AI assistant in natural language:
- "What datasets does this report use?"
- "Make the Account Number column 2 inches wide"
- "Format the Amount column as currency with 2 decimals"
- "Add a new Amount column that shows the sum in the footer"
- "Add a Status column but leave the footer blank"
- "Update the main dataset to use the V2 stored procedure and add the TaxAmount field"
- "Remove the obsolete Status column"
- "Add a Year parameter to filter the report"
The AI assistant will use the appropriate MCP tools automatically.
Example: Editing vs. XML
Without MCP (manually editing XML):
<!-- Find this in 2000+ lines -->
<TablixCell><CellContents><Textbox><Paragraphs>
<Paragraph><TextRuns><TextRun>
<Value>Old Header</Value>
</TextRun></TextRuns></Paragraph>
</Paragraphs></Textbox></CellContents></TablixCell>
With MCP (one command):
update_column_header(filepath="report.rdl",
old_header="Old Header",
new_header="New Header")
API Reference
View all available tools
Reading Tools
describe_rdl_report(filepath)- Report structure summaryget_rdl_datasets(filepath, field_limit?, field_pattern?)- Datasets with fields and stored proceduresfield_limit: 0 = counts only (default), -1 = all fields, N = limit to N fieldsfield_pattern: Optional regex to filter field names
get_rdl_parameters(filepath)- All parameters with configurationsget_rdl_columns(filepath)- Column headers, widths, bindings
Editing Tools
update_column_header(filepath, old_header, new_header)- Change column textupdate_column_width(filepath, column_index, new_width)- Modify width (e.g. "2.5in")update_column_format(filepath, column_index, format_string)- Change format (e.g. "#,0.00", "dd/MM/yyyy", "C2")add_column(filepath, column_index, header_text, field_binding, width?, format_string?, footer_expression?)- Add columnfooter_expression: Optional expression for footer/total row - e.g. "=Sum(Fields!Amount.Value)", "=Count(Fields!ID.Value)", "Total:", or leave empty
remove_column(filepath, column_index)- Remove columnupdate_stored_procedure(filepath, dataset_name, new_sproc)- Change dataset sprocadd_dataset_field(filepath, dataset_name, field_name, data_field, type_name)- Add field to datasetremove_dataset_field(filepath, dataset_name, field_name)- Remove field from datasetadd_parameter(filepath, name, data_type, prompt)- Add new parameterupdate_parameter(filepath, name, prompt?, default_value?)- Update parametervalidate_rdl(filepath)- Validate XML structure
All tools return {success: bool, message?: string, error?: string} or structured data.
Limitations & Roadmap
Current limitations:
- Tablix (table) controls only - no Matrix or Chart support yet
- Works best with standard report layouts
- Some complex RDL features may still need manual XML editing
Planned features:
- Column reordering, grouping, and sorting configuration
- Expression builder helpers
- Dataset field management
Troubleshooting
Server not appearing?
- Check absolute path in config is correct
- Verify Python 3.8+:
python3 --version - Restart your MCP client
Permission errors?
- Make script executable:
chmod +x rdl_mcp_server.py - Check RDL file read/write permissions
Releasing a New Version
This server is published to the MCP Registry. To release a new version:
-
Update version number in
server.json:{ "version": "0.2.0" }
-
Commit your changes:
git add . git commit -m "Release v0.2.0: Add feature description"
-
Create and push a git tag:
git tag v0.2.0 git push origin main --tags
-
Automated publishing: The GitHub Actions workflow automatically:
- Validates
server.jsonagainst the MCP schema - Authenticates with GitHub
- Publishes to the MCP Registry
- Updates downstream registries (like GitHub's)
- Validates
Contributing
PRs welcome! Priority areas:
- Better column detection for complex layouts
- More editing operations (reordering, grouping, etc.)
Requirements: Python standard library only
- Fork repo
- Create feature branch
- Make changes + tests
- Submit PR
License
MIT License - see LICENSE file for details.
This means you're free to use, modify, and distribute this software for any purpose, commercial or non-commercial.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rdl_mcp-0.1.0.tar.gz.
File metadata
- Download URL: rdl_mcp-0.1.0.tar.gz
- Upload date:
- Size: 17.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f05c781b6c26a704a3d41595feba1c09c042780d0306c5d94d3e8d37cb888b71
|
|
| MD5 |
daea2d70c2aabcb025d5b8ea3119a0cc
|
|
| BLAKE2b-256 |
abc9a44cf2f148518debd792e4b449acec3c5a454cab5959d0deb1ba7cfe6130
|
Provenance
The following attestation bundles were made for rdl_mcp-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on bethmaloney/rdl-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rdl_mcp-0.1.0.tar.gz -
Subject digest:
f05c781b6c26a704a3d41595feba1c09c042780d0306c5d94d3e8d37cb888b71 - Sigstore transparency entry: 715301155
- Sigstore integration time:
-
Permalink:
bethmaloney/rdl-mcp@a11d3d83b67d8a119d2969e7b19f81eca9b6638b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bethmaloney
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a11d3d83b67d8a119d2969e7b19f81eca9b6638b -
Trigger Event:
push
-
Statement type:
File details
Details for the file rdl_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: rdl_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ec3e862938515d5734ba79fcbea2d728b99f62d62e873455d737da937b68b19
|
|
| MD5 |
ff72790f7694cc3dbf9243f942e6e56d
|
|
| BLAKE2b-256 |
d0a62858d9c510fd5de2b56bdd93bf85f2715a7d614be8a89b756f6e55fd6cd3
|
Provenance
The following attestation bundles were made for rdl_mcp-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on bethmaloney/rdl-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rdl_mcp-0.1.0-py3-none-any.whl -
Subject digest:
8ec3e862938515d5734ba79fcbea2d728b99f62d62e873455d737da937b68b19 - Sigstore transparency entry: 715301183
- Sigstore integration time:
-
Permalink:
bethmaloney/rdl-mcp@a11d3d83b67d8a119d2969e7b19f81eca9b6638b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bethmaloney
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a11d3d83b67d8a119d2969e7b19f81eca9b6638b -
Trigger Event:
push
-
Statement type: