Skip to content
4 changes: 2 additions & 2 deletions ConfigurationDeskMCP/sources/models/hardware_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

class AddHardwarePlatformInput(BaseModel):
ip_addresses: List[str] = Field(
description="Address(es) of the platform to register, e.g. ['192.0.2.10']. VEOS is NOT a platform - do not use this for VEOS."
description="Address(es) of the platform to register, e.g. ['192.0.2.10']. VEOS is not a real-time hardware platform - do not use this for VEOS."
)
platform_type: str = Field(
default="SCALEXIO",
description="Platform type: 'SCALEXIO', 'MicroAutoBox III', or 'MicroLabBox II'. VEOS is NOT a platform - use add_application_processing_unit / generate_bus_containers instead.",
description="Platform type: 'SCALEXIO', 'MicroAutoBox III', or 'MicroLabBox II'. VEOS is not a real-time hardware platform.",
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

class AddModelInput(BaseModel):
path: str = Field(
description="Path to the model file (.slx, .mdl, .sic, or .bsc), e.g. 'C:/Models/Restbus_Model_64-bit.sic'"
description="Path to the model file (.slx, .mdl, .sic, .bsc, or .fmu), e.g. 'C:/Models/Restbus_Model_64-bit.sic'"
)
analyze: bool = Field(
default=True,
description="Analyze model after adding. Set false for .sic/.bsc files, e.g. true",
description="Analyze model after adding. Set false for .sic/.bsc/.fmu files, e.g. true",
)
create_preconfigured: bool = Field(
default=True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,22 @@ def bus_manager_restbus_simulation(
For .slx/.mdl also call `analyze_models`; .sic/.bsc are already analyzed.
Then `add_model_to_signal_chain` to expose the model ports.

## Step 6 — Provide scheduling
A processing unit must exist. For real hardware, register it with
`add_hardware_platform`; for VEOS/offline, call `add_application_processing_unit`.
Then `create_application_process` (auto-assigned to "{bus_config_name}").
## Step 6 — Create the application process and assign the model
When creating an application process, a Processing Unit Application should be
automatically created if one does not already exist. If exactly one Processing Unit
Application exists, the Application Process should be added to it.

Assign the behavior model from Step 5 by calling
`create_preconfigured_application_process` with the model's name (use `list_models` to
get the exact name of "{model_path}"). This creates an application process pre-configured
for that model. Tasks that match the requirements of the model are created and/or
configured appropriately.

Then assign the bus configuration to that application process with
`assign_bus_config_to_application_process` (bus_config_name="{bus_config_name}").

For a model-less restbus process instead, call `create_application_process` — it
auto-assigns to "{bus_config_name}".

## Step 7 — Connect the ports
Call `auto_connect_matching_io_function_blocks_to_model_ports` to wire matching
Expand Down
30 changes: 18 additions & 12 deletions ConfigurationDeskMCP/sources/prompts/individual_setup_prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def add_feature_to_bus_element(

@mcp.prompt(
name="add_behavior_model",
description="Single task: add a behavior model (.slx/.mdl/.sic/.bsc), analyze it, and expose its ports in the signal chain",
description="Single task: add a behavior model (.slx/.mdl/.sic/.bsc/.fmu), analyze it, and expose its ports in the signal chain",
)
def add_behavior_model(
model_path: str = "D:/Models/plant_model.slx",
Expand All @@ -226,6 +226,7 @@ def add_behavior_model(
- .slx / .mdl — Simulink model (model analysis required).
- .sic — Simulink implementation container.
- .bsc — Bus Simulation Container.
- .fmu — Functional Mock-up Unit (FMI-based model implementation).

## Step 2 — Analyze (Simulink model only)
Call `analyze_models` to detect input/output ports and create model port blocks.
Expand Down Expand Up @@ -258,8 +259,8 @@ def create_application_process(
{_ENSURE_RUNNING}

## Prerequisite
A ProcessingUnitApplication must exist: register a hardware platform
(`add_hardware_platform`) or, for VEOS/no-hardware, call `add_application_processing_unit`.
A ProcessingUnitApplication is mandatory regardless of the target (real-time
hardware or BSC/VEOS). If none exists yet, call `add_processing_unit_application`.

## Step 1 — Create the process (default periodic task)
Call `create_application_process` with name="{process_name}". This sets
Expand Down Expand Up @@ -387,7 +388,7 @@ def build_application(

@mcp.prompt(
name="register_hardware",
description="Single task: provide the hardware topology — register a SCALEXIO/MicroAutoBox III/MicroLabBox II platform, import an .htfx file, or add a VEOS processing unit",
description="Single task: provide the hardware topology — register and scan a SCALEXIO/MicroAutoBox III/MicroLabBox II platform or import an .htfx file for a real-time application. A non-empty hardware topology is NOT necessary to generate bus simulation containers (BSC)",
)
def register_hardware(
platform_type: str = "SCALEXIO",
Expand All @@ -397,23 +398,28 @@ def register_hardware(
# Register Hardware

Goal: provide the hardware topology that bus and I/O function blocks are assigned to.
NOTE: a hardware topology is required to build and download a real-time application
for SCALEXIO, MicroAutoBox III, or MicroLabBox II. It describes the components of a
specific hardware system, such as channel types and slot numbers.

GENERAL REMARK: a non-empty hardware topology — created for example by registering
and scanning hardware — is NOT necessary to generate bus simulation containers (BSC).
When BSC output is the only deliverable, skip this prompt entirely and use
`generate_bus_containers`.

{_ENSURE_RUNNING}

## Choose an approach (ASK the user which applies)

### Option A — Physical platform
### Option A — Register and scan a physical platform
Call `add_hardware_platform` with ip_addresses=["{platform_ip}"], platform_type="{platform_type}".
Valid types: "SCALEXIO", "MicroAutoBox III", "MicroLabBox II".
Returns the unique platform name used by later hardware operations.
Returns the unique platform name used by later hardware operations. Scanning the
registered platform creates a matching hardware topology.

### Option B — Import a topology file
Call `import_hardware_topology` with path="C:/HW/topology.htfx".

### Option C — VEOS / no hardware
Call `add_application_processing_unit`. VEOS is NOT a platform — do NOT call
`add_hardware_platform` for it. The deliverable is the generated BSC.

## Verify / maintain
- `list_platforms` — confirm the registered hardware and its I/O boards.
- `refresh_platforms` — refresh platform information.
Expand Down Expand Up @@ -478,7 +484,7 @@ def assign_bus_hardware(
## Prerequisite
- A bus configuration with assigned ECUs (see `create_bus_configuration`).
- Hardware present: `add_hardware_platform` / `import_hardware_topology`, or
`add_application_processing_unit` for VEOS (then skip channel assignment).
`add_processing_unit_application` for VEOS (then skip channel assignment).

## Step 1 — Inspect what needs hardware
Call `list_bus_access_requests` — each cluster/part generates one request to assign.
Expand Down Expand Up @@ -572,7 +578,7 @@ def inspect_configuration() -> str:
Call `get_application_status` — project name, project root, and active application.

## Configuration tree
Call `list_configuration` — executable applications, processing units, tasks, events.
Call `list_configuration` — executable applications, processing unit applications, application processes, tasks, events.

## Inventory
- `list_applications` — applications in the project.
Expand Down
10 changes: 7 additions & 3 deletions ConfigurationDeskMCP/sources/resources/domain_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
2. **Set Project Root** — Use `set_project_root` to configure where projects are stored
3. **Create/Open Project** — Use `create_project` or `open_project`
4. **Add Application** — Use `add_application` within the project
5. **Add Model** — Use `add_model` to import Simulink (.slx/.mdl), SIC, or BSC files
5. **Add Model** — Use `add_model` to import Simulink (.slx/.mdl), SIC, BSC, or FMU files
6. **Analyze Models** — Use `analyze_models` to detect ports and interfaces
7. **Add Communication Matrix** — Use `add_communication_matrix` for ARXML/DBC/LDF files
8. **Configure Bus** — Use `create_bus_configuration` and `assign_matrix_to_bus_config`
Expand Down Expand Up @@ -91,7 +91,7 @@
## Hardware Platforms
SCALEXIO, MicroAutoBox III, and MicroLabBox II platforms are registered by
address and scanned to create the hardware topology. Use `list_platforms` to see
registered hardware. VEOS is NOT a platform — use `add_application_processing_unit`.
registered hardware. VEOS is not a real-time hardware platform.
"""

_TOOL_CATEGORIES = """\
Expand Down Expand Up @@ -597,7 +597,7 @@
- `SCALEXIO`
- `MicroAutoBox III`
- `MicroLabBox II`
(VEOS is NOT a platform — use `add_application_processing_unit`.)
(VEOS is not a real-time hardware platform.)

## `bus_type` (create_io_function_block)
- `CAN`
Expand All @@ -620,6 +620,10 @@
- `.slx` / `.mdl` — Simulink (require `analyze_models`).
- `.sic` — Simulink implementation container (pre-analyzed).
- `.bsc` — Bus Simulation Container.
- `.fmu` — Functional Mock-up Unit (pre-analyzed).

`generate_bus_containers` supports only SIC model implementations; FMU and
Simulink models cannot be used to generate BSC files.

## Communication matrix file extensions (add_communication_matrix)
- `.arxml` (AUTOSAR), `.dbc` (CAN), `.ldf` (LIN).
Expand Down
6 changes: 3 additions & 3 deletions ConfigurationDeskMCP/sources/server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ async def _lifespan(server: FastMCP) -> Any: # type: ignore[type-arg]
8. `add_feature_to_bus_element` → add signal/PDU/controller features
8b. `set_bus_config_element_property` → set feature-node or bus-element properties like countdown, overwrite, offset, or frame-length values
8c. `set_matrix_element_property` → set communication-matrix element properties like PDU/signal Length or Initial value
9. `add_model` → load behavior model (.slx/.sic/.bsc)
9. `add_model` → load behavior model (.slx/.mdl/.sic/.bsc/.fmu)
10. `create_application_process` → set up execution scheduling
11. `auto_connect_matching_io_function_blocks_to_model_ports` → wire bus ports to model
12. `generate_bus_containers` → OPTIONAL: generate BSC/container output only when the user explicitly asks for it
13. Hardware topology → ASK USER which approach:
- `add_hardware_platform` → register SCALEXIO, MicroAutoBox III, or MicroLabBox II hardware (needs address from user)
- `import_hardware_topology` → import .htfx file (needs file path from user)
- `add_application_processing_unit` → no physical hardware / VEOS workflow
- VEOS does NOT need platform registration. Use generate_bus_containers for BSC files.
- `add_processing_unit_application` → no physical hardware / VEOS workflow
- VEOS is not a real-time hardware platform; use generate_bus_containers to produce the BSC files it consumes.
14. `create_io_function_block` → create CAN/LIN/Ethernet I/O block
15. `set_io_function_block_property` → set BaudRate
16. `assign_bus_access` → link bus access requests to function block
Expand Down
32 changes: 32 additions & 0 deletions ConfigurationDeskMCP/sources/services/app_management_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,35 @@ async def list_applications() -> str:
except Exception as e:
logger.exception("Error listing applications")
return error_response(str(e), transient=False)


async def add_processing_unit_application() -> str:
"""Add a processing unit application to the executable application.

An executable application has one or more processing unit applications (PUA);
each PUA is executed on one processing unit (PU) and hosts one or more
application processes (AP).
"""
try:
conn = await _get_live_connection()
result = await dispatch(app_management_com.add_processing_unit_application, conn)
pua_created = result.get("processing_unit_application_created", False)
if not pua_created:
return error_response(
f"ProcessingUnitApplication could not be added: "
f"{result.get('processing_unit_application_detail', '')}. "
"You may need to add it manually in ConfigurationDesk.",
transient=False,
)
return success_response(
message=(
"ProcessingUnitApplication added. "
"For VEOS: use generate_bus_containers to produce BSC files."
),
verified=True,
)
except BridgeError as exc:
return tool_error_result(exc)
except Exception as e:
logger.exception("Error adding processing unit application")
return error_response(str(e), transient=False)
7 changes: 3 additions & 4 deletions ConfigurationDeskMCP/sources/services/bus_access_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ async def auto_assign_channel_set(function_block_name: str, bus_type: str = "CAN
f"Function block '{function_block_name}' not found. "
f"Verify it exists with list_io_function_block_properties. "
f"If the block is LIN, pass bus_type='LIN'. "
f"Also ensure a hardware topology exists via add_application_processing_unit or add_hardware_platform."
f"Also ensure a hardware topology exists (add_hardware_platform or import_hardware_topology)."
),
)
return error_response(detail, transient=False)
Expand Down Expand Up @@ -390,8 +390,7 @@ async def create_preconfigured_application_process(model_name: str) -> str:
next_action=(
"Pre-configured application process creation failed. "
"Verify the model exists in the topology and a ProcessingUnitApplication "
"is available (registered hardware or `add_application_processing_unit`). "
"Do NOT retry with the same parameters."
"is available. Do NOT retry with the same parameters."
),
)
if result.get("verified"):
Expand All @@ -406,7 +405,7 @@ async def create_preconfigured_application_process(model_name: str) -> str:
"No new application process became observable after the pre-configured creation call.",
transient=False,
next_action=(
"Verify a ProcessingUnitApplication exists (use `add_application_processing_unit` "
"Verify a ProcessingUnitApplication exists (use `add_processing_unit_application` "
"for VEOS workflows, or register hardware). Then call `create_application_process` "
"as the manual fallback."
),
Expand Down
33 changes: 2 additions & 31 deletions ConfigurationDeskMCP/sources/services/hardware_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ async def add_hardware_platform(ip_addresses: list[str], platform_type: str = "S
transient=False,
retryable=False,
next_action=(
"VEOS is not a hardware platform. For VEOS workflows: "
"For real-time hardware platforms (SCALEXIO, MicroAutoBox III, and MicroLabBox II): ensure hardware is powered on and reachable."
"VEOS is not a real-time hardware platform and cannot be registered in ConfigurationDesk. For VEOS workflows: "
"1) Use generate_bus_containers to create BSC files, "
"2) Import BSC files into VEOS. "
"For SCALEXIO: ensure hardware is powered on and reachable."
)
if platform_type.upper() == "VEOS"
else (
Expand Down Expand Up @@ -160,32 +160,3 @@ async def add_hardware_element(element_type: str) -> str:
except Exception as e:
logger.exception("Error adding hardware element")
return error_response(str(e), transient=False)


async def add_application_processing_unit() -> str:
"""Add a ProcessingUnitApplication to the application configuration.

Used for VEOS-targeted or no-hardware workflows.
"""
try:
conn = get_connection()
result = await dispatch(hardware_com.add_application_processing_unit, conn)
pu_created = result.get("processing_unit_created", False)
if not pu_created:
return error_response(
f"ProcessingUnitApplication could not be added: {result.get('processing_unit_detail', '')}. "
"You may need to add it manually in ConfigurationDesk.",
transient=False,
)
return success_response(
message=(
"ProcessingUnitApplication added. "
"For VEOS: use generate_bus_containers to produce BSC files."
),
verified=True,
)
except BridgeError as exc:
return tool_error_result(exc)
except Exception as e:
logger.exception("Error adding application processing unit")
return error_response(str(e), transient=False)
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ async def create_application_process(
"No new application process became observable after the creation call.",
transient=False,
next_action=(
"Verify a ProcessingUnitApplication exists (use `add_application_processing_unit` "
"Verify a ProcessingUnitApplication exists (use `add_processing_unit_application` "
"for VEOS workflows or register a hardware platform), then retry."
),
)
Expand Down
21 changes: 21 additions & 0 deletions ConfigurationDeskMCP/sources/tools/app_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
RemoveApplicationInput,
)
from sources.server.app import mcp
from sources.server.preconditions import with_preconditions
from sources.services import app_management_service as svc


Expand Down Expand Up @@ -69,3 +70,23 @@ async def remove_application(input: RemoveApplicationInput) -> str:
)
async def list_applications() -> str:
return await svc.list_applications()


@mcp.tool(
name="add_processing_unit_application",
description=(
"Add a processing unit application to the executable application. "
"An executable application has one or more processing unit applications (PUA); "
"each PUA is executed on one processing unit (PU) and hosts one or more "
"application processes (AP)."
),
annotations={
"readOnlyHint": False,
"destructiveHint": False,
"idempotentHint": True,
"openWorldHint": False,
},
)
@with_preconditions("connection", "project", "application")
async def add_processing_unit_application() -> str:
return await svc.add_processing_unit_application()
1 change: 0 additions & 1 deletion ConfigurationDeskMCP/sources/tools/bus_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,6 @@ async def auto_connect_matching_io_function_blocks_to_model_ports() -> str:
"Create a pre-configured application process for one specific model. "
"Calls Algorithms.CreatePreConfiguredApplicationProcessAutomatically([model], None). "
"A new ProcessingUnitApplication is created automatically when no Parent is supplied "
"(VEOS workflows: ensure `add_application_processing_unit` was called first). "
"For all-models behavior, prefer create_application_process or pass `model_names` to it."
),
annotations={
Expand Down
3 changes: 2 additions & 1 deletion ConfigurationDeskMCP/sources/tools/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
name="list_configuration",
description=(
"List the application configuration tree "
+ "(executable applications, processing units, tasks, events). "
+ "(executable applications, processing unit applications, application processes, "
+ "tasks, events). "
+ "Results are paginated; call again with next_offset to retrieve later pages."
),
annotations={
Expand Down
Loading