使用说明
MATCH PDT MCP Server
MCP server for HYDAC PDT .hdb project files. Queries and modifies CAN messages, signals, error definitions, and ECU configuration.
How it works
An .hdb file is a ZIP archive containing XML configuration files and binary .dat files. The server:
- Parses XML files (strips null padding) into indexed lookup dicts
- Deserializes
.datfiles via a .NET helper using the PDT assemblies - Serves read/write queries via MCP stdio transport (lazy-loaded, cached)
- For writes: creates
.hdb.bakbackup, modifies XML in-place, rewrites ZIP
Why use this instead of reading generated code?
The PDT generates C code in AUTO_CEN_* folders — structs, enums, config arrays. For CAN messages, signals, and error definitions, the MCP server is faster and more convenient. For other areas (pins, blocks), the generated code remains the better source.
What this does well:
- CAN signal lookup — scaling formula, bit position, units, and parent message in one query. In generated code this is scattered across
App_CanSigRec.c,Cfg_CRcv.c,Cfg_CSnd.c. - Signal search — find signals by name substring across all messages, optionally filtered by message.
- Message details — CAN ID, DLC, cycle time, direction, and all signals linked together. In generated code you'd cross-reference multiple files.
- Error definitions — SPN, description, severity, debounce times, and thresholds. In generated code this is split between
App_ErrDefine.handCfg_Err.cwithout the PDT metadata. - XML modification — edit CAN messages, signals, databases, and other XML-based config directly.
- Always current — reads the
.hdbdirectly, so it reflects the latest PDT save even if code hasn't been regenerated yet.
What still requires generated code:
- Pin configurations (
project.datuses complex .NET types that can't be loaded outside .NET Framework 4.8) - Software blocks and detailed parameter entries within databases
What can also be modified (binary .dat — via .NET helper):
- Database variables in
project.dat— add, update, delete parameters across NvMem/RAM databases - Custom error definitions — add, list, update and delete custom errors (and their ERR TBlocks) with error templates and detection methods (modifies both
project.datandErrors.datatomically)
What cannot be modified:
- ISOBUS config (
Isobus.dat)
Installation
Prerequisites
Required:
- Python 3.10+ with
mcppackage
Optional (for .dat file tools):
- .NET SDK 8.0+ (builds the helper targeting .NET Framework 4.8)
- HYDAC PDT installed (provides the .NET assemblies for
.datdeserialization)
Without .NET SDK, all tools work except list_errors and get_error — they return an error message instead of crashing the server.
pip install "mcp[cli]"
Build the .NET helper (optional)
Skip this step if you don't need error definition tools (list_errors, get_error).
cd Match_PDT_MCP/dotnet-helper
dotnet build -c Release
Register with Claude Code (per project)
Add a .mcp.json file in the project root directory:
{
"mcpServers": {
"Match_PDT_MCP": {
"type": "stdio",
"command": "python",
"args": [
"C:/Match/Tools/MCP/Match_PDT_MCP/server.py"
]
}
}
}
The server auto-discovers:
- HDB_PATH — first
*.hdbfile in the working directory - PDT_DIR — matched to the project's PDT version (from
info.xml), falling back to the latest installed version inC:\Program Files\Hydac\Project Definition Tool\
If the project has multiple .hdb files or a non-standard location, set environment variables explicitly:
{
"mcpServers": {
"Match_PDT_MCP": {
"type": "stdio",
"command": "python",
"args": ["C:/Match/Tools/MCP/Match_PDT_MCP/server.py"],
"env": {
"HDB_PATH": "C:/Match/Projects/MyProject/SpecificFile.hdb",
"PDT_DIR": "C:/Program Files/Hydac/Project Definition Tool/2.12.100"
}
}
}
}
The same .mcp.json works for any MATCH project — just drop it in the project root and Claude Code will start the server automatically.
Available Tools
CAN Read Tools (from XML)
| Tool | Parameters | Description |
|---|---|---|
list_can_buses |
(none) | List all CAN buses in PDT's own order (from project.dat) with name, bitrate, message counts, ECU IDs, and send/receive buffer IDs. The bus number is what add_can_message expects. Buses only referenced by CanMessages.xml but no longer in the project are flagged [ORPHAN]. |
get_can_message |
name: str, can_id: int |
Look up message by name (case-insensitive, substring match) or CAN ID (decimal). Returns details + all signals + direction. |
list_can_messages |
direction: str, name_filter: str, bus: int |
List all messages. Filter by direction (send/receive), name substring, or bus number. |
get_can_signal |
name: str, message: str |
Look up signal by name (case-insensitive). Returns scaling, bits, units, parent message. Use message to disambiguate duplicates. |
search_can_signals |
query: str, message: str |
Search signals by name substring. Optionally restrict to signals in a specific message. |
CAN Write Tools
| Tool | Parameters | Description |
|---|---|---|
add_can_message |
name, can_id, direction, dlc, cycle_time, signals, bus |
Add a complete CAN message with signals to a specific bus. Creates entries in CanMessages.xml, CanMessageEcuLinks.xml, and CanSignals.xml. Creates .hdb.bak backup before the first write. |
add_can_message details:
name(required): Message name, e.g."VcuSendTestData"can_id(required): CAN ID as decimal. Extended frame if > 0x7FFdirection:"SendCyclically"(default),"SendEventBased", or"Receive"dlc: Data Length Code, 0-8 (default 8)cycle_time: Cycle time in ms (default 100)signals: Comma-separated signal definitions asname:startbit:sizebitsbus: Bus number, 1-indexed (default 1). Uselist_can_busesto see available buses
Bus IDs, ECU IDs, and send/receive buffer IDs are discovered dynamically from the HDB — no hardcoded project-specific constants. This means the server works with any MATCH project, including multi-bus projects.
Example:
add_can_message(
name="VcuSendTestData",
can_id=419365500,
direction="SendCyclically",
dlc=8,
cycle_time=100,
signals="testValue:0:16,status:16:8,mode:24:4",
bus=1
)
This creates:
- The message definition (CAN ID 0x18FF017C, Extended, Intel byte order) on bus 1
- ECU link with the correct send buffer for that bus
- 3 signals:
testValue(16-bit at bit 0),status(8-bit at bit 16),mode(4-bit at bit 24)
Message Block: add_can_message runs through PDT's own services (dotnet-helper-v2), so the ECU link and the CSND/CRCV software block are created in the same save — no manual Usage toggle in PDT is needed any more. Signal widths map to data types the way the GUI does (1 bit → TBOOLEAN, ≤8 → TUINT8, ≤16 → TUINT16, else TUINT32; narrower widths keep the next type up with the requested SizeBits).
Note that add_can_signal still writes CanSignals.xml directly with the project's default data type and VAR_MAX bounds, which PDT flags as a warning (PDT1205) for 8-bit signals; prefer passing all signals to add_can_message. In practice a DBC import in PDT covers most CAN definition work; these tools are for small additions.
Visual walkthrough:
Adding a CAN message from Claude Code:
The resulting message in the PDT:
Database & ECU Tools (from XML + .dat via .NET helper)
| Tool | Parameters | Description |
|---|---|---|
list_databases |
(none) | List NvMem/RAM parameter databases with addresses and settings. |
list_db_variables |
database: str |
List all variables in a database (or all databases if empty) with type, default, range, unit. |
get_db_variable |
database: str, variable: str |
Get detailed info for a single variable including access levels and dataset values. |
add_db_variable |
database, name, type, default, min, max, unit, description |
Add a new variable to a database. Clones from an existing variable of the same type. Creates .hdb.bak backup. |
update_db_variable |
database, variable, default, min, max, unit, description |
Update properties of an existing variable. Only provided fields are changed. |
delete_db_variable |
database: str, variable: str |
Remove a variable from a database. |
get_ecu_config |
(none) | ECU app config: cycle time, watchdog, protocols, protocol parameters, project info. |
Error Tools (from .dat via .NET helper — requires .NET SDK 8.0+ and HYDAC PDT)
These tools are optional. Without .NET SDK, they return an error message; all other tools remain functional.
| Tool | Parameters | Description |
|---|---|---|
list_errors |
spn_filter: int, description_filter: str |
List error definitions with SPN, description, severity, debounce, thresholds. |
get_error |
spn: int |
Look up a specific error by SPN number. Returns full details. |
list_error_templates |
(none) | List custom error block templates. |
list_detection_methods |
filter: str |
List detection methods with bit positions and FMI values. |
list_fmi_definitions |
(none) | List FMI and FMI extension definitions with GUIDs. |
add_custom_error |
template, dm_name, bit, spn, block_name, description, severity, fmi, fmi_extended, debounce/threshold params |
Add a custom error with detection method, error template, and ERR TBlock. Works on projects with or without existing custom errors. |
list_custom_errors |
(none) | Custom errors only, each with its ERR block, bit, detection method, template and FMI names, plus the used/free bits of every ERR block. Start here before adding, updating or deleting. |
update_custom_error |
spn, then any of description, comment, severity, fmi, fmi_extended, set_debounce_ms, release_debounce_ms, set_threshold, release_threshold, new_spn, dm_name |
Change fields of a custom error, rename its detection method, or renumber its SPN. Only the arguments passed change. Refuses built-in errors. |
delete_custom_error |
spn |
Remove a custom error and free its bit in the ERR block (slot name back to DM_ERR_NN, template and custom-DM entries dropped). Block and template stay. Refuses built-in errors. |
delete_error_block |
block_name |
Remove an ERR block with all its custom errors; the template goes too when this was its last linked block. |
repair_error_blocks |
(none) | Fix ERR blocks made by older versions of add_custom_error: registers their parameters in the project's flat parameter list and recomputes ERROR_COUNT. Symptom it cures: empty Block Name / Behavior "- none -" / empty Error Count in PDT's block grid while generated code is fine. Idempotent. |
add_custom_error details:
Creates a complete custom error entry in the PDT project (atomic operation — modifies both project.dat and Errors.dat). Creates .hdb.bak backup before the first write.
template(required): Error template/block name, e.g."Error index us". Creates a new template if not found.dm_name(required): Detection method name, e.g."DM_US_HINDEX_EOB". Must be unique.bit(required): Bit position within the block (0-7).spn(required): SPN number. Must be unique across all errors.block_name: Software error block name, e.g."ERR_INDEX_US". Required when creating a new template (it becomes the ERR TBlock name used for code generation). For an existing template it is derived from the template's linked block; pass it only to disambiguate. The error always points at that block's detection-method slot forbit— PDT only recognizes errors linked to a block DM, a template-only DM is dropped at load.description: Error description text.severity: 1=info, 3=warning (default), 5=critical.fmi: FMI name, default"FMI_31_CONDITION_EXISTS".fmi_extended: FMI extension, default"FMIEX_GLOBAL".- Debounce/threshold:
set_debounce_ms(500),release_debounce_ms(0),set_threshold(500),release_threshold(1000).
Managing existing custom errors: list_custom_errors → update_custom_error / delete_custom_error / delete_error_block. All of them go through the same XML-direct helper as add_custom_error and undo exactly what it registers (Errors.dat entry, block slot CustomName, Custom.DetectionMethods, the template's Error list, LinkedBlockIds, and the repo-level block/section/param/DM lists for a block delete). "Custom" means the error's detection method is a renamed slot of an ERR block; built-in errors are refused.
What gets created:
- Error template in
Custom.ErrorTemplates(if new) - Detection method entries in
Custom.DetectionMethodsand the template'sErrorlist - Error entry in
Errors.datwith SPN, severity, FMI, debounce settings - ERR TBlock with 8 detection method slots (bits 0-7), block parameters (SW_MODULE, BLOCK_NAME, BLOCK_BEHAVIOR, BLOCK_DESCR = template name, ERROR_COUNT = number of used bits, kept in sync on add/delete), registered in
Repo.Blocks,Repo.BlockParamSectionsandRepo.BlockParamslike a GUI-made block, and the Standard library ERR blueprint - Template-to-TBlock link via
LinkedBlockIds
When the project has no existing ERR blocks, the tool auto-discovers a sibling project with ERR blocks (in C:\Match\Projects\) and clones the block structure from there, including TBlockParamSections and TDetectionMethods.
Example:
add_custom_error(
template="Error test dummy",
dm_name="DM_TEST_DUMMY_ALARM",
bit=0,
spn=2000,
block_name="ERR_TEST_DUMMY",
description="Dummy test alarm for validation",
severity=3
)
XML Write Tools
| Tool | Parameters | Description |
|---|---|---|
list_hdb_xml_files |
(none) | List all XML files in the HDB archive with sizes. |
read_hdb_xml |
file: str, xpath: str |
Read raw XML content, optionally filtered by XPath. |
update_hdb_xml |
file, xpath, action, tag, text, attributes |
Modify XML elements: set_text, set_attr, add_child, remove. Creates .hdb.bak backup. |
Utility Tools
| Tool | Parameters | Description |
|---|---|---|
search_hdb |
pattern: str |
Regex search across all XML content in the HDB archive (max 100 results). |
reload_hdb |
(none) | Force re-parse of all data after saving in PDT. |
HDB Archive Structure
XML Files (read/write via Python)
| File | Content |
|---|---|
CanMessages.xml |
CAN message definitions (ID, DLC, cycle time, byte order) |
CanSignals.xml |
Signal definitions (bit position, scaling, units, min/max) |
CanMessageEcuLinks.xml |
Send/receive direction, ECU assignment, and buffer block per message (used for dynamic bus discovery) |
DatabaseLists.xml |
NvMem/RAM database layouts |
EcuApplications.xml |
ECU config (cycle time, watchdog) |
Protocols.xml |
Protocol instances (MST, ISO-Bus) |
ProtocolParameters.xml |
Protocol settings (source addresses, buffer config) |
PinEcuApplicationLinks.xml |
I/O pin mappings (GUIDs only) |
info.xml |
PDT version and file format |
Binary .dat Files (via .NET helper)
| File | Status | Content |
|---|---|---|
Errors.dat |
Read + write | Error definitions (SPN, severity, thresholds, reactions). Custom errors can be added via add_custom_error. |
CompileConfig.dat |
Curated read | Build mode, log level, flags |
Isobus.dat |
Curated read | ISOBUS configuration |
project.dat |
Read + write | Main project data (pins, blocks, FMI definitions). Database variables are read/write. |
| All .dat files | Generic dump | Full JSON dump via dump / dump-all commands |
HDB Diff Tool
Compare two .hdb files semantically:
python hdb_diff.py <hdb_a> <hdb_b> [--output report.md]
Compares all XML files (element-level by ID/Name) and all .dat files (JSON deep-diff). Outputs a markdown report showing added/removed/changed elements.
Limitations
- Most
.datfiles are read-only —project.dat(database variables, custom errors/templates) andErrors.dat(error entries) support write-back. The genericdumpcommand can read all .dat files to JSON for diffing. - PDT version matching — the server auto-matches the PDT installation to the project's version (from
info.xml). A version folder only counts if it still contains the PDT runtime (Hydac.PDT.PdtFramework.dll); an uninstalled version that left an empty folder behind is skipped. If the exact version is not installed, it falls back to the latest available and logs a warning. - One writer at a time —
dotnet-helper-v2keeps the project in memory between calls and saves from that copy. The server restarts it automatically whenever the.hdbchanges on disk (an XML tool, the v1 helper, or a PDT save) and afterreload_hdb, so stale state is never written back. Do not run write tools while the project is open in PDT: PDT holds its own in-memory copy and its next save will overwrite the MCP's changes (and vice-versa). Save and close in PDT first, or callreload_hdbafter a PDT save. - ERR block cloning — when adding custom errors to a project without existing ERR blocks, the tool searches sibling projects for an ERR block to clone structure from. If no reference project is found, the error template and detection method are still created, but without a TBlock.
- Pin name resolution requires cross-referencing GUIDs through
project.dat. Thedump project.datcommand now exposes pin data. - Error GUID fields (Fmi, DetectionMethod, MachineFunction, RestrictedMode) reference objects in
project.datand can't be resolved to names. - Signal name duplicates — many signals share the same name across different messages. Use the
messageparameter inget_can_signalto disambiguate. - CAN Message Blocks — created by
add_can_messagevia PDT'sICanMessageEcuLinkService.SetNewUsage; no manual step in PDT.add_can_signal(XML-direct) cannot touch the block, which is fine for signals but means it never validates bit overlaps.
Dependencies
Required:
- Python 3.10+
mcppackage (pip install "mcp[cli]")
Optional (for .dat file tools and diff):
- .NET SDK 8.0+ (to build the helper)
- HYDAC PDT installation (provides the .NET assemblies for deserialization)
Disclaimers
This project is not associated with or endorsed by HYDAC International GmbH in any way.
This software was not created to compete with the HYDAC Project Definition Tool (PDT) or any other commercial software. It is a utility to help developers working with MATCH controllers interact with their project files programmatically.
HYDAC PDT installation is required for .dat file functionality — this project does not include or redistribute any HYDAC proprietary files.