Skip to main content
Version: 3.0 (next)

Walkthrough: Claude Code

Four prompts in Claude Code built, tested and enabled three pipelines and a sixteen-panel dashboard on the Caliperline demo factory, through MaestroHub MCP alone.

Prerequisites
Digital Factory Simulator easy setup
Client
Claude Code · Claude Opus 5.5
Protocols
Modbus · OPC UA · REST · UNS
Result
3 pipelines · 1 dashboard with 16 panels

This walkthrough records one real session: Claude Code with Claude Opus 5.5, connected to a MaestroHub 3.0 instance running the Digital Factory Simulator. Everything below is what the session did, quoted from its own reports; nothing was built or fixed by hand.

Prerequisites

The Caliperline connections come from the Digital Factory Simulator easy setup. Run it first if you want to follow along; the session works from those connections and the topics their collectors publish.

Setup​

The session used the .mcp.json from the Claude Code page, with a Personal Access Token scoped to the workspace. These are the scopes it needed, and no more:

ScopeWhy
connectors:read, functions:readFind the Caliperline connections and the functions on them
uns:readSample the topics the collectors publish, and read back its own results
pipelines:read, pipelines:writeCreate the pipelines and fix them
pipelines:executeDry-run the pipelines before enabling them, and enable them
dashboards:read, dashboards:write, library_panels:readBuild the dashboard
workspaces:readResolve the workspace the token belongs to

Without pipelines:execute, the assistant can save pipelines but cannot test or enable them: it saves them disabled and says so.

Keep the session on MCP

Claude Code also has local tools: a shell, file editing, background commands. For a session that should only work in MaestroHub, start it with the built-in tools turned off, so the MaestroHub MCP tools are all it has:

claude --tools "" --mcp-config .mcp.json

In this session the assistant used local tools twice: a timer while it waited for scheduled runs, and, while building the dashboard, an attempt to install a charting library to test its panels; that attempt was stopped and the session resumed with built-in tools off (see Part 3).

Part 1: Building the Pipelines​

Prompt:

Can you design and implement some pipelines using the Caliperline connections?

What the assistant did (54 MCP calls, about 5 minutes):

  1. Read pipeline_builder_guide for the node types and the output shape of each.
  2. Listed the Caliperline connections and the functions on each, then sampled the topics the existing collectors publish with query_topic_data, to see real values and ranges.
  3. Listed the pipelines already on the plant and aimed at gaps: collection, OP10 tool wear, OP20 tool life and part tracing were covered already.
  4. Validated each design with manage_pipelines validate_draft, created it, and dry-ran it with dry_run, on a real event and on invented failure cases (a 0.72 cc/min leak, a test at 14.41 bar, a 6.8 °C drop in wash temperature).
  5. Saved all three disabled: they had only been dry-run, so it had not yet seen them talk to the real Modbus, OPC UA and REST endpoints.

It also named the limits it had chosen itself (the OP30 pressure band) as a decision for the reader, and said it could not create new functions with this token, so it used the existing ones.

Pipeline 1: OP40 Leak Test Quality Gate​

Caliperline OP40 Leak Test Quality Gate pipeline in the Pipeline DesignerCaliperline OP40 Leak Test Quality Gate pipeline in the Pipeline Designer

Every OP40 cycle: grade the leak test, publish the verdict, and on a FAIL ask SAP whether the part is already in stock

NodeTypePurpose
On OP40 Cycle Completetrigger.uns.subscribeOne run per part: the test station's cycle-complete event, with its measurements and serial
Grade Leak Testlogic.javascriptPASS, MARGINAL (80 to 100% of the limit), FAIL, or INVALID_TEST when the test pressure was out of tolerance
Publish Verdictsystem.uns.publishdfs/LINE-BC-01/quality/leak_test/verdict
Route By Verdictlogic.switchFAIL to containment, INVALID_TEST to a retest request
Lookup SAP Goods Movementsconnected.rest.requestAsks SAP (idocs_by_serial) whether the part was already received into stock
Build Containment Recordlogic.javascriptQUARANTINE_STOCK when it was, BLOCK_AT_LINE when not
Publish Containment / Publish Retest Requestsystem.uns.publish…/leak_test/containment, …/leak_test/retest_request

The grading reads the event the trigger delivers, $trigger.result, and each part's own tolerance from its measurements. This is the code as it ran after the fix in Part 2:

const e = $trigger.result || {};
const ms = Array.isArray(e.measurements) ? e.measurements : [];
const leak = ms.find(m => m.Feature === 'Leak Rate');
const pres = ms.find(m => m.Feature === 'Test Pressure');
const MARGINAL_FRACTION = 0.8;
// A leak spec is one-sided: only a reading above the limit is a leak. A small negative
// reading is gauge noise around zero; one far below zero means the gauge needs re-zeroing.
const NOISE_FRACTION = 0.1;
// ...
if (!presOk) {
verdict = 'INVALID_TEST';
} else if (leak.Value < noiseFloor) {
verdict = 'INVALID_TEST';
} else if (leak.Value > leak.ToleranceMax) {
verdict = 'FAIL';
} else if (leak.Value >= leak.ToleranceMax * MARGINAL_FRACTION) {
verdict = 'MARGINAL';
} else {
verdict = 'PASS';
}

Pipeline 2: OP30 Wash Process Health​

Caliperline OP30 Wash Process Health pipeline in the Pipeline DesignerCaliperline OP30 Wash Process Health pipeline in the Pipeline Designer

Every 30 seconds: read the washer over Modbus, grade it against its setpoints, and raise an alarm topic only when something is in ALARM

NodeTypePurpose
Every 30 Secondstrigger.schedulePolls every 30 s
Read OP30 Wash Registersconnected.modbus.readgroupSeven registers: temperature, pressure, detergent, their setpoints, state and fault
Evaluate Wash Healthlogic.javascriptScales the raw registers and grades each value; only grades while the station is RUNNING
Publish Wash Healthsystem.uns.publishdfs/LINE-BC-01/equipment/OP30-WASH/health, every cycle
Is Process In Alarmlogic.conditionContinues only when the status is ALARM
Publish Wash Alarmsystem.uns.publish…/OP30-WASH/alarms/process

The bands sit at the top of the JavaScript node, where the assistant pointed the reader to set them from the washer's spec:

const r = $node['Read OP30 Wash Registers'].result || {};
// Bands; tune to the washer's spec.
const TEMP_WARN_C = 2.0, TEMP_ALARM_C = 5.0;
const PRES_WARN = [3.0, 4.2], PRES_ALARM = [2.5, 4.5];
const DET_WARN_REL = 0.10, DET_ALARM_REL = 0.20;

Pipeline 3: Line KPI Rollup​

Caliperline Line KPI Rollup pipeline in the Pipeline DesignerCaliperline Line KPI Rollup pipeline in the Pipeline Designer

Every 5 minutes: read all four stations and the MES order, compute the line KPIs, publish one summary

NodeTypePurpose
Every 5 Minutestrigger.scheduleRolls up every 5 minutes
Read OP10 / OP30 Countersconnected.modbus.readgroupProduction, time, energy and state counters
Read OP20 / OP40 Countersconnected.opcua.readgroupThe same counters over OPC UA
Fetch MES Current Orderconnected.rest.requestThe work order in progress
Compute Line KPIslogic.javascriptPer station: yield, availability, utilisation, kWh per good part. For the line: first-pass yield across all four stations, the bottleneck, the least available station, faulted stations, order progress
Publish Line KPIssystem.uns.publishdfs/LINE-BC-01/kpi/line_summary

The counters are running totals, so the KPIs cover the period since they were last reset, not a shift; the assistant said so in its report.

Part 2: Enabling Them​

It ended Part 1 with a question: "Should I enable all three, or just some, and then check their first real runs?"

Prompt:

Yes, enable all three and check their first real runs.

It enabled the pipelines and watched their first runs with query_executions and query_topic_data, waiting for each scheduled run with a short timer (Claude Code's own sleep, the only thing it ran outside MaestroHub in this part). The real runs found two bugs in what it had built, and it fixed both:

  • A gauge reading of −0.01 cc/min graded FAIL. That is noise around zero, and the station had called the part GOOD, but the pipeline had already published a wrong QUARANTINE_STOCK record for it. The fix is in the code above: only a reading above the limit is a leak; a slightly negative one passes as noise, and one far below zero becomes INVALID_TEST with a "check gauge zero" note. It dry-ran the same event again (now PASS) before moving on.
  • A mistyped function ID in the KPI rollup's OP40 read group left OP40's availability empty. The pipeline saved and ran anyway: the read group records a function it cannot find as a failed read and carries on, so nothing failed. It corrected the ID and checked every other station's values against the live output. (Validation now warns about this: validate_draft reports a read group function that does not exist, or that belongs to another connection.)

After the fixes all three ran clean: the first FAIL after the fix (a 0.557 cc/min leak) matched the station's SCRAP result and produced a BLOCK_AT_LINE record, and the 15:45 rollup put first-pass yield at 92.1%, with OP10 as the bottleneck.

It also flagged that the wrong quarantine record stays in the topic's history and offered to publish a retraction; on a demo plant that was not needed.

Part 3: Building the Dashboard​

Prompt:

No retraction needed, this is a demo plant. Now, I want you to create a comprehensive dashboard using those pipelines you just created.

It listed the panel types, checked how the plant's own dashboards read fields inside object payloads, sampled every topic its pipelines publish, and created the dashboard Caliperline Quality & Process Intelligence with 16 panels.

To test the panels' code it then reached for the local machine: through Claude Code's own tools it started installing a charting library to render the panels outside MaestroHub. That is outside what an MCP session should do, so it was stopped and resumed with the built-in tools turned off:

Please don't run anything on this machine; stick to the MaestroHub MCP tools. Finish the dashboard you created and check every panel against the live data through MaestroHub.

With only MCP tools it checked each panel's logic by hand against the live data (every KPI record, 63 leak verdicts and 41 wash-health records in the hour), made every panel accept fields that arrive flattened or as text, and listed what each panel should show, asking for the dashboard to be opened to confirm it renders. Opened in a browser, all 16 panels drew with the values it predicted.

Dashboard top: six KPI tiles, station performance, energy by station and the production orderDashboard top: six KPI tiles, station performance, energy by station and the production order

Top: first-pass yield, good parts, energy per good part, the bottleneck, leak pass rate and wash status; station performance and energy; the current MES order

Dashboard middle: leak rate per part, verdict counts and the containment tableDashboard middle: leak rate per part, verdict counts and the containment table

Middle: every leak test against the limit and the marginal line, verdict counts, and the containment and retest actions

Dashboard bottom: wash station status timeline and the temperature, pressure and detergent chartsDashboard bottom: wash station status timeline and the temperature, pressure and detergent charts

Bottom: the wash station's status over time, and its temperature, pressure and detergent against their bands

PanelsWhat they show
Six tilesFirst-pass yield, good parts out, energy per good part, the bottleneck station, leak test pass rate, wash station status
Station performance, Energy by stationYield, availability and utilisation per station; kWh per good part per station
Production orderThe current MES order and its progress
Leak rate per part, Leak test verdictsEach test against the 0.5 cc/min limit and the 0.4 marginal line; counts by verdict and how often the station disagreed
Containment & retestEvery FAIL with its SAP check and action, and every retest request
Wash station status, Wash temperature / pressure / detergentThe washer's status over time, and each value against its band and setpoint

Observations​

  • It checked before it acted. Pipelines were validated and dry-run, on invented failures as well as real data, then saved disabled until it was asked to enable them.
  • It found its own bugs in real runs, not in dry runs: the noise reading and the mistyped ID only showed once real parts came through. Watching the first runs is part of the job, and it did it without being asked twice.
  • It named its own assumptions: the OP30 pressure band, counters that cover the time since reset, the wrong record left in history.
  • Validation did not catch the mistyped function ID at the time. A read group naming a function that does not exist saved cleanly and, at run time, recorded a failed read without failing the node. validate_draft now warns about it, and about a function of another connection; it is still worth reading a new read group's output once after saving.
  • It cannot see a dashboard render. It checked the panels' logic against the data, and asked for the dashboard to be opened; that check matters.
  • Scope the session. The token scopes above and --tools "" keep it inside MaestroHub.

Prompts Summary​

  1. "Can you design and implement some pipelines using the Caliperline connections?"
  2. "Yes, enable all three and check their first real runs."
  3. "No retraction needed, this is a demo plant. Now, I want you to create a comprehensive dashboard using those pipelines you just created."
  4. "Please don't run anything on this machine; stick to the MaestroHub MCP tools. Finish the dashboard you created and check every panel against the live data through MaestroHub."