Previously, I wrote an article titled “Building a Server to Control Cubase via MCP” (source).

Since then, I’ve continued developing cubase_mcp , but it hasn’t progressed as much as I had hoped.

I’ve now managed to handle play/stop and retrieve transport status, so the next step is to obtain a list of the project’s tracks.

If we can retrieve information such as the track name, selection state, mute, and solo status, we could expand what’s possible from MCP. That was the premise, but now I’m still investigating what exactly can be retrieved and how far.

Today I organized the investigation code and merged it into main. This isn’t a report that the track‑list retrieval is finished; it’s a memo of what’s holding us back from getting there.

It wasn’t as simple as just getting the track names

Roughly, the data I’m after would look like this:

TrackSelectedMuteSolo
Pianofalsefalsefalse
Basstruefalsefalse
Vocalfalsefalsetrue

This is just an example for illustration; it isn’t the result the current MCP tool can return.

Even if we can retrieve a few names and states, there’s the question of whether we can simply present that as “the project’s track list.”

Do hidden tracks get included? What about folders? Are the channels that appear in the MixConsole the same as the tracks shown in the project view?

There can be two tracks with the same name, and names can change partway through. Using names as IDs is problematic, and using order as IDs shifts when tracks are added or removed.

The gap between getting a list that looks right once and turning it into a continuously usable API is considerable.

Investigating Mixer Bank and DirectAccess

Currently I’m comparing the Mixer Bank and DirectAccess features of Cubase’s MIDI Remote API.

Mixer Bank

Mixer Bank is a mechanism that assigns a fixed number of channels to slots for manipulation, allowing you to switch between banks as you work.

For example, you could set up eight slots, read the current eight channels, then advance to the next set and read again. I’m considering whether this approach could be used to build a track list.

However, in the type definitions bundled with my Cubase 13.0.30 installation, there’s no direct way to obtain the total number of banks, the current position, or the end point. I also want to distinguish whether a missing name notification means an empty slot or simply that the notification hasn’t arrived yet.

If we assume we’re done just because a page that looks the same is returned, we might confuse channels with the same name or misinterpret delayed notifications.

Therefore, I’ve prepared a procedure that cross‑checks cases with zero entries, a single entry, exactly the bank width, and exceeding the bank width against the actual UI. I haven’t been able to confirm the real‑world behavior solely by reading the type definitions.

DirectAccess

DirectAccess is a low‑level API that lets you traverse the running host objects and retrieve information such as names and IDs. It looks like this could be used to gather the data all at once.

However, being able to traverse objects is different from being able to enumerate every track in the project.

During the August hardware trial, the older implementation that traversed broadly re‑encountered references to the same object, causing a cycle that terminated the traversal. That trial was not counted as a success.

In the current investigative implementation, I’ve limited the observation scope to the root element on the MixConsole side and its immediate children. Repeated references are recorded as references rather than being counted as additional tracks.

Even if we capture that entire scope, it doesn’t mean we’ve captured the whole host or the entire project, including folders. In the code, I’m also careful not to treat this as definitive proof that all tracks have been enumerated.

The details of these checks are compiled in Track API investigation notes . At this point, we haven’t decided which approach to use in production.

Names and states may not arrive at the same time

Another complication is that information arrives via callbacks.

We receive notifications for names, selection state, mute, solo, and so on, and assemble the state from them, but we don’t want to mix the old data with the new data immediately after switching banks.

For example, if the name has already changed to the next track while the mute state still reflects the previous track, the list would look plausible but be incorrect.

Therefore, in the investigative probe we keep track of bank generations and record which generation each piece of information was observed in. Values that have not yet been notified are not arbitrarily filled with placeholders like “false” or empty strings.

Enabling or disabling the script, reloading, or restarting Cubase also changes the boundaries. Today’s changes also include fixes that organize the order of notifications during such switches and the dispatch of any pending notifications.

However, this does not mean we can reliably identify every delayed notification that Cubase actually returns. There are limits to what can be distinguished via the API—for example, when the host hands an old notification to a new handler. Those aspects are also something I want to measure empirically.

The tools for investigation are growing

Just looking at the logs returned by the API doesn’t tell you whether the operation actually occurred on the UI.

If you were clicking a different track, or if human input was interleaved during the test, the interpretation of the logs changes. Since I don’t want to break a regular production project, I’ve set aside a dedicated test project and procedures for verification.

As a result, I’ve ended up creating a Probe that observes values in Cubase, a collector that records data via MIDI, an auditor that inspects the recordings, and additionally an input guard and a screen‑capture utility.

The input guard monitors macOS’s input counter and the pressed state of keyboard and mouse buttons, halting verification if any input interference is detected during an operation. It does not record the actual characters typed.

However, passing the guard does not guarantee that the correct location was clicked. The target and result must be verified separately by comparing the screen before and after the operation and by examining accessibility information.

Even the tools for verification need to be verified, and I’m spending a considerable amount of time on that. Note that this input guard is an independent investigative tool and does not automatically launch during normal MCP operation.

Verification halted when the menu was opened

During the September 13 hardware trial with Cubase 15, we progressed through 30 of the 44 checkpoints.

At that point we were unable to capture an image of the UI with the Project menu open. Although accessibility information confirmed that the menu was open, we could not save a screenshot corresponding to that state.

Since this verification requires matching the screen before and after each operation along with the UI information, we cannot consider the test complete while an image is missing. We can’t simply fill the gap with a screenshot from another screen, so that trial was discarded.

It’s frustrating to be stopped by screen‑capture issues when we’re trying to investigate Cubase’s track information.

This is a problem specific to the current interaction and capture method; it doesn’t mean we have definitively determined that no menu images can be obtained from Cubase at all. We’ve isolated the issue as Problem capturing images while the menu is displayed .

Also, the previously validated input guard cannot be reused without cross‑checking the original conditions from that time against the current execution environment. Based on today’s inspection, I haven’t been able to identify the full set of original assets needed for reuse, so the decision on whether to reuse it is being deferred. I’m not concluding that the records have been lost.

Before embarking on another lengthy hardware verification, I’m first confirming whether we can capture screenshots and gather the necessary recordings.

Changes merged today

Since the investigative code had grown large, I split it into three parts—input guard, track investigation, and I/O investigation—and merged them. I didn’t write everything from scratch today; rather, I organized the code that had been accumulated so far and incorporated it into main.

PRDescription
#46 Input guard, saving screen/UI information, proofreading checks
#31 Track Probe notification handling, acquisition scope, audit and verification procedures for recordings
#47 Integration test with a dedicated probe that reads existing Input/Output
#49 Fix for excessively short wait times in I/O integration tests

The I/O Probe is read‑only, used to inspect existing Input and Output. It does not create or delete buses, nor does it modify routing. Names and internal IDs are also treated as aliases.

Even here, receiving data for eight slots is not considered a full acquisition of all buses. Even if the record structure is correct, it still needs to be separately verified that it matches the actual device’s display.

The final PR addressed a test issue discovered in the Windows CI after merging.

In the integration test that passes responses from the JavaScript mock driver to the Rust collector, the detection timeout was set to 20 ms. This caused a failure by exceeding the limit by about 3 ms.

We stopped using the shortened timeout that was only applied to the test and reverted to the normal default value of 1000 ms. Additionally, we introduced a 50 ms delay on the mock‑driver side, confirmed that the old condition would still fail, and then made the fix. The production code and the success criteria themselves were not altered.

In the latest main branch, CI for Linux, macOS, and Windows all pass. However, passing tests in the mock environment is separate from completing the verification on the actual Cubase.

Track list retrieval has not yet been released

At this point, cubase.get_tracks has not yet been released. tracks.list also remains unavailable in production.

Next, we will align the Conditions for starting real‑device verification and verify the behavior of the Mixer Bank and DirectAccess on Cubase 13 and 15. After deciding on the acquisition scope and how IDs are handled, we plan to proceed with retrieving the full track list in production.

Since playback and stop functions are working, I had thought the next step would be the list, but it has taken much longer than expected.

What we accomplished today isn’t the track‑fetching functionality itself, but rather the part that investigates how much we can trust its results. It’s a low‑key task, but we can’t simply treat a partially retrieved list as if it were complete, so we need to dig a little deeper.