Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 - use add_processing_unit_application / generate_bus_containers instead.",
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def bus_manager_restbus_simulation(
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`.
A processing unit application must exist. For real hardware, register a platform with
`add_hardware_platform`; for a VEOS/no-hardware build, call `add_processing_unit_application`.
Then `create_application_process` (auto-assigned to "{bus_config_name}").

## Step 7 — Connect the ports
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ def create_application_process(

## Prerequisite
A ProcessingUnitApplication must exist: register a hardware platform
(`add_hardware_platform`) or, for VEOS/no-hardware, call `add_application_processing_unit`.
(`add_hardware_platform`) or, for VEOS/no-hardware, 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 @@ -386,7 +386,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 a SCALEXIO/MicroAutoBox III/MicroLabBox II platform, import an .htfx file, or add a processing unit application for VEOS",
)
def register_hardware(
platform_type: str = "SCALEXIO",
Expand All @@ -410,7 +410,8 @@ def register_hardware(
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
Call `add_processing_unit_application`. VEOS is not a registered real-time hardware
platform — do NOT call
`add_hardware_platform` for it. The deliverable is the generated BSC.

## Verify / maintain
Expand Down Expand Up @@ -477,7 +478,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
4 changes: 2 additions & 2 deletions ConfigurationDeskMCP/sources/resources/domain_resources.py
Original file line number Diff line number Diff line change
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 registered real-time hardware platform — use `add_processing_unit_application`.
"""

_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 registered real-time hardware platform — use `add_processing_unit_application`.)

## `bus_type` (create_io_function_block)
- `CAN`
Expand Down
4 changes: 2 additions & 2 deletions ConfigurationDeskMCP/sources/server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ async def _lifespan(server: FastMCP) -> Any: # type: ignore[type-arg]
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 registered 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
31 changes: 31 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,34 @@ 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.

A processing unit application hosts one or more application processes. Add one
explicitly when no registered hardware or imported topology already provides
one — typically a no-hardware or VEOS build.
"""
try:
conn = await _get_live_connection()
result = await dispatch(app_management_com.add_processing_unit_application, 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 processing unit application")
return error_response(str(e), transient=False)
6 changes: 3 additions & 3 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), or add a processing unit application (add_processing_unit_application) for a no-hardware build."
),
)
return error_response(detail, transient=False)
Expand Down Expand Up @@ -390,7 +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`). "
"is available (registered hardware or `add_processing_unit_application`). "
"Do NOT retry with the same parameters."
),
)
Expand All @@ -406,7 +406,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
31 changes: 1 addition & 30 deletions ConfigurationDeskMCP/sources/services/hardware_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ 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: "
"VEOS is not a registered real-time hardware platform. 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."
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
23 changes: 23 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,25 @@ 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. "
"A processing unit application is a component of every executable application "
"that hosts one or more application processes. Add one explicitly when no "
"registered hardware or imported topology already provides one — typically a "
"no-hardware or VEOS build. VEOS is not a registered real-time hardware platform; "
"it consumes generated Bus Simulation Containers (BSC)."
),
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()
2 changes: 1 addition & 1 deletion ConfigurationDeskMCP/sources/tools/bus_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ 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). "
"(VEOS workflows: ensure `add_processing_unit_application` was called first). "
"For all-models behavior, prefer create_application_process or pass `model_names` to it."
),
annotations={
Expand Down
26 changes: 2 additions & 24 deletions ConfigurationDeskMCP/sources/tools/hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
"BEFORE calling this tool, ASK the user which hardware approach they want: "
"1) Provide address of SCALEXIO, MicroAutoBox III, or MicroLabBox II hardware → use this tool, "
"2) Import an .htfx topology file → use import_hardware_topology, "
"3) Create empty topology (VEOS/no hardware) → use add_application_processing_unit. "
"VEOS is NOT a platform - never call this for VEOS. "
"VEOS is not a registered real-time hardware platform - never call this for VEOS. "
"Returns the unique platform name for subsequent hardware operations."
),
annotations={
Expand All @@ -38,7 +37,7 @@ async def add_hardware_platform(
platform_type: Annotated[
str,
Field(
description="Platform type: 'SCALEXIO', 'MicroAutoBox III', or 'MicroLabBox II'. VEOS is not a platform.",
description="Platform type: 'SCALEXIO', 'MicroAutoBox III', or 'MicroLabBox II'. VEOS is not a real-time hardware platform.",
),
] = "SCALEXIO",
) -> str:
Expand Down Expand Up @@ -167,24 +166,3 @@ async def add_hardware_element(
],
) -> str:
return await svc.add_hardware_element(element_type)


@mcp.tool(
name="add_application_processing_unit",
description=(
"Add a ProcessingUnitApplication to the application configuration. "
"Use this for VEOS-targeted or no-hardware workflows where the project needs "
"an application processing unit to host I/O function blocks and application processes. "
"VEOS does NOT use registered hardware platforms; it consumes generated Bus "
"Simulation Containers (BSC)."
),
annotations={
"readOnlyHint": False,
"destructiveHint": False,
"idempotentHint": True,
"openWorldHint": False,
},
)
@with_preconditions("connection", "project", "application")
async def add_application_processing_unit() -> str:
return await svc.add_application_processing_unit()
2 changes: 1 addition & 1 deletion ConfigurationDeskMCP/sources/tools/model_topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ async def analyze_models() -> str:
"Pass `bus_config_names` to scope the assignment to specific configurations, or pass an "
"empty list `[]` to skip assignment entirely. "
"PRECONDITION: a ProcessingUnitApplication must exist (register a hardware platform or call "
"`add_application_processing_unit` for VEOS workflows)."
"`add_processing_unit_application` for VEOS workflows)."
),
annotations={
"readOnlyHint": False,
Expand Down
2 changes: 1 addition & 1 deletion ConfigurationDeskMCP/tests/_fake_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def _create_preconfigured_application_process(model_name, *args):
"hardware_items": [etype or "Element"],
"verified": True,
},
"add_application_processing_unit": {
"add_processing_unit_application": {
"processing_unit_created": True,
"processing_unit_detail": "created",
},
Expand Down
5 changes: 5 additions & 0 deletions ConfigurationDeskMCP/tests/domains/test_app_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"activate_application",
"remove_application",
"list_applications",
"add_processing_unit_application",
)


Expand All @@ -28,3 +29,7 @@ def test_remove_application(fake_bridge):

def test_list_applications(fake_bridge):
run_ok(appmgmt_svc.list_applications())


def test_add_processing_unit_application(fake_bridge):
run_ok(appmgmt_svc.add_processing_unit_application())
5 changes: 0 additions & 5 deletions ConfigurationDeskMCP/tests/domains/test_hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
COVERS = (
"add_hardware_platform",
"add_hardware_element",
"add_application_processing_unit",
"import_hardware_topology",
"scan_hardware",
"remove_hardware",
Expand All @@ -27,10 +26,6 @@ def test_add_hardware_element(fake_bridge):
assert payload["element_name"] == "DS1513"


def test_add_application_processing_unit(fake_bridge):
run_ok(hw_svc.add_application_processing_unit())


def test_import_hardware_topology(fake_bridge):
run_ok(hw_svc.import_hardware_topology("D:/topology.htfx"))

Expand Down
2 changes: 1 addition & 1 deletion ConfigurationDeskMCP/tests/mcp_inventory.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"tools": [
"activate_application",
"add_application",
"add_application_processing_unit",
"add_communication_matrix",
"add_feature_to_bus_element",
"add_hardware_element",
Expand All @@ -11,6 +10,7 @@
"add_model",
"add_model_port_to_signal_chain",
"add_model_to_signal_chain",
"add_processing_unit_application",
"analyze_models",
"assign_bus_access",
"assign_bus_config_to_application_process",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"`set_io_function_block_property`",
"`add_hardware_platform`",
"`import_hardware_topology`",
"`add_application_processing_unit`",
"`add_processing_unit_application`",
"`add_model_to_signal_chain`",
"`add_model_port_to_signal_chain`",
"`create_preconfigured_application_process`",
Expand Down
Loading