MCP Tool Reference
The toolset is published as Cndctr Terminal, version 1.0. Every tool delegates to the editor
subsystem that owns the real implementation. If the editor is not running (or the subsystem is not
up) every tool returns Failed: Cndctr Terminal subsystem unavailable (is the editor running?).
Addressing a terminal
Section titled “Addressing a terminal”Two different conventions, and mixing them up is the most common mistake:
SplitActivePaneandCloseActivePaneact on the active host — the status-bar panel drawer when it is open, otherwise an open terminal tab. They take no index.- Everything else takes a
TerminalIndex, which is 0-based:0is Conductor Terminal 1,1is Conductor Terminal 2, and so on, up to 3.
Call ListTerminals() first. It is the only reliable way to learn which indices are live and what
the session names actually are.
Return value contract
Section titled “Return value contract”There are two kinds of tool, and they do not share a contract.
Action tools return a status string beginning OK: or Failed:. Check the prefix.
SplitActivePane, CloseActivePane, NotifyUser, CreateSession, SwitchSession, SendKeys,
SetTerminalSetting.
Read tools return their data directly, with no prefix. ListTerminals and
GetTerminalSettingsJson return JSON; GetDebugSummary returns a summary line;
ReadTerminalOutput returns text (possibly empty); GrepTerminalOutput returns matching lines or
No matches for '<pattern>'.
From any tool, a string beginning Failed: is an error.
Layout
Section titled “Layout”SplitActivePane(Orientation)
Section titled “SplitActivePane(Orientation)”Split the focused pane of the active terminal, adding a sibling pane with its own shell. Follows the same code path as the toolbar split buttons and never opens a new window.
| Parameter | Type | Notes |
|---|---|---|
Orientation |
string | "Horizontal" (side by side) or "Vertical" (stacked) |
Returns OK: ..., or Failed: could not split (...) - is a terminal open?. Splitting is not
available inside PSMux or tmux sessions, where the multiplexer owns layout.
CloseActivePane()
Section titled “CloseActivePane()”Close the focused pane of the active terminal — the same action as the close button.
Returns OK: ... or Failed: no split pane to close.
Sessions
Section titled “Sessions”ListTerminals()
Section titled “ListTerminals()”List the open terminal tabs and their sessions. Call this first. It is how you discover valid
TerminalIndex values and the backend session names SwitchSession needs.
{ "maxTerminals": 4, "tabs": [ { "index": 0, "activeSession": "T1_2", "workspaceMode": "PSMuxWorkspace", "workspaceName": "freight", "sessions": ["T1_1", "T1_2"] } ]}workspaceMode is one of PlainShell, PSMuxWorkspace or TmuxWorkspace. Only open tabs are
listed.
CreateSession(TerminalIndex)
Section titled “CreateSession(TerminalIndex)”Start a fresh session in a numbered tab, using that tab’s current shell/workspace profile.
| Parameter | Type | Notes |
|---|---|---|
TerminalIndex |
int32 | 0-based |
SwitchSession(TerminalIndex, SessionName)
Section titled “SwitchSession(TerminalIndex, SessionName)”Point a numbered tab at an already-tracked session, addressed by its internal name.
| Parameter | Type | Notes |
|---|---|---|
TerminalIndex |
int32 | 0-based |
SessionName |
string | Internal name from ListTerminals, e.g. "T1_2" — not the display label |
Input and output
Section titled “Input and output”SendKeys(TerminalIndex, Data)
Section titled “SendKeys(TerminalIndex, Data)”Feed raw input straight to a tab’s PTY.
| Parameter | Type | Notes |
|---|---|---|
TerminalIndex |
int32 | 0-based |
Data |
string | Raw bytes/text sent verbatim |
ReadTerminalOutput(TerminalIndex, MaxLines)
Section titled “ReadTerminalOutput(TerminalIndex, MaxLines)”Read the tail of a tab’s output — visible screen plus scrollback — as plain text. This is how the agent sees.
| Parameter | Type | Notes |
|---|---|---|
TerminalIndex |
int32 | 0-based |
MaxLines |
int32 | Newest last. <= 0 uses the default of 200; capped at 2000 |
Returns the captured text with trailing blank rows trimmed — an empty string when the buffer
has no rows yet — or Failed: ... when there is no readable terminal at that index.
GrepTerminalOutput(TerminalIndex, Pattern)
Section titled “GrepTerminalOutput(TerminalIndex, Pattern)”Return only the lines containing a substring, case-insensitively, each prefixed with its logical row number. Cheaper than pulling the whole buffer when you know what you are looking for.
| Parameter | Type | Notes |
|---|---|---|
TerminalIndex |
int32 | 0-based |
Pattern |
string | Substring, case-insensitive. Not a regular expression. Must not be empty |
Returns matching row: text lines, No matches for '<pattern>', or Failed: ... (including
Failed: empty search pattern). Output is capped at 200 matches, with a final
... (truncated at 200 matches) line when the cap is hit.
Talking to the human
Section titled “Talking to the human”NotifyUser(Title, Body)
Section titled “NotifyUser(Title, Body)”Show a non-intrusive toast in the bottom-right of the Unreal Editor. Use it when you have finished something, or you are blocked and need input.
| Parameter | Type | Notes |
|---|---|---|
Title |
string | Short headline, e.g. "Build finished". Truncated at 120 characters |
Body |
string | Optional detail line, e.g. "12 files compiled, 0 errors". May be empty. Truncated at 600 characters |
It does not raise or focus any window, and it has no click action — it is purely informational.
The toast stays for about six seconds. Identical title-and-body pairs within ten seconds are
de-duplicated — the call still returns OK, nothing new is shown — so call it once per event
rather than polling.
Returns OK: showed an editor notification to the user, or Failed: could not show the notification (editor not running / no Slate UI) in a headless editor.
Settings
Section titled “Settings”GetTerminalSettingsJson()
Section titled “GetTerminalSettingsJson()”Serialise the current terminal settings to a JSON object string. Includes config-only properties
such as ScrollbackLines and the persisted session records.
SetTerminalSetting(PropertyName, Value)
Section titled “SetTerminalSetting(PropertyName, Value)”Assign a value to a setting and persist it to disk.
| Parameter | Type | Notes |
|---|---|---|
PropertyName |
string | A property name from the Settings Reference |
Value |
string | Imported through UE reflection — "14" for an int, "true" for a bool, an enum member name for an enum |
SetTerminalSetting("FontSize", "16")SetTerminalSetting("bShowTopBars", "false")SetTerminalSetting("WorkingDirectoryPolicy", "EngineRoot")Returns OK: ... or Failed: could not set '<name>' (unknown property or unparseable value).
There is no allow-list: any property on the settings object can be set, including config-only
ones. Values are written to the per-user Saved ini; the human’s own edits on the settings page
go to a sibling file and are overridden by yours on the next load, so prefer to ask before changing
a preference the user may have set deliberately.
GetDebugSummary(TerminalIndex)
Section titled “GetDebugSummary(TerminalIndex)”A terse, read-only status snapshot of one tab: shell, workspace mode and name, active session,
native rows and columns, whether the alternate screen is active, the cursor position, the session
list, and psmuxResolved=1|0 — which is how the agent’s skill knows whether PSMux Workspace mode is
available.
A workflow that works
Section titled “A workflow that works”ListTerminals()— discover tabs and session names.GetDebugSummary(0)for a deeper look at one tab.SplitActivePane— lay out the panes you need, e.g. one for a build, one for logs.CreateSession/SwitchSessionto manage shells;SendKeysto type.ReadTerminalOutputorGrepTerminalOutputafter anything you sent —SendKeysalone tells you nothing about the result.CloseActivePaneto tear down when finished.NotifyUserwhen you need the human, once per event.
