0030. Embedded egui MCP Inspector Workbench, Agent Playbooks & Act VII Scorecard
Embedding an offline MCP Inspector Workbench (McpInspectorWorkbench) inside the egui desktop app to switch between HeadlessDuplex and BridgedLoopback transports, log JSON-RPC 2.0 frames (RpcFrameRecord), execute 4-step Agent Review Playbooks, and seal the 30-lesson course scorecard.
Why Every AI-Controllable Desktop App Needs an Embedded MCP Workbench
Debugging an MCP server through an external cloud LLM chat window is slow, expensive, and non-deterministic. By embedding an MCP Inspector Workbench (McpInspectorWorkbench) directly inside our egui desktop reviewer, hardware engineers and CI pipelines can toggle between McpTransportMode::HeadlessDuplex and McpTransportMode::BridgedLoopback, inspect every JSON-RPC 2.0 request/response frame (RpcFrameRecord), and execute deterministic multi-step Agent Review Playbooks (run_power_integrity_playbook) completely offline.Deterministic Agent Playbooks (Tier 6 Acceptance): Our 4-step Power Integrity Playbook chains resources/read (kicad://board/summary), pcb_query_net (VCC_3V3), pcb_run_custom_drc (U1 clearance), and pcb_add_review_pin (+ cropped PNG capture when running in BridgedLoopback mode) into an auditable AgentPlaybookReport.
flowchart LR
Mode["McpTransportMode<br/>HeadlessDuplex ⇄ BridgedLoopback"] --> Playbook["run_power_integrity_playbook()<br/>4-Step Deterministic Audit"]
Playbook --> S1["1. resources/read<br/>kicad://board/summary"]
S1 --> S2["2. tools/call<br/>pcb_query_net (VCC_3V3)"]
S2 --> S3["3. tools/call<br/>pcb_run_custom_drc"]
S3 --> S4["4. tools/call + Bridge<br/>Pin + 64×64 Cropped PNG"]
style Playbook fill:#14231c,stroke:#3dd68c,color:#e6edf3
style S4 fill:#141a21,stroke:#3b8eea,color:#e6edf3
Dual-Transport Workbench & 4-Step Power Integrity Playbook
Let's walk through the dual-transport state machine, the 4-step Power Integrity Agent Playbook, and the egui Inspector Workbench controls block by block before viewing the complete assembled listings.
Block 1: McpTransportMode, RpcFrameRecord & AgentPlaybookReport (crates/pcb-doc/src/lib.rs)
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub enum McpTransportMode {
HeadlessDuplex,
BridgedLoopback,
}
impl McpTransportMode {
pub fn toggle(self) -> Self {
match self {
Self::HeadlessDuplex => Self::BridgedLoopback,
Self::BridgedLoopback => Self::HeadlessDuplex,
}
}
pub fn label(self) -> &'static str {
match self {
Self::HeadlessDuplex => "HeadlessDuplex",
Self::BridgedLoopback => "BridgedLoopback",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RpcFrameRecord {
pub seq: usize,
pub method: String,
pub transport: McpTransportMode,
pub summary: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct AgentPlaybookReport {
pub transport: McpTransportMode,
pub frames_logged: usize,
pub vcc_pad_count: usize,
pub drc_violations: usize,
pub pin_count: usize,
pub snapshot_captured: bool,
pub snapshot_bytes_len: usize,
}
McpTransportMode::toggle(self)&label(self): Switches deterministically betweenHeadlessDuplex(in-memorytokio::io::duplexmode) andBridgedLoopback(authenticated live-GUI bridge mode with cropped PNG snapshots).RpcFrameRecord: Captures the 1-based sequence number (seq), JSON-RPC method name ("resources/read","tools/call:..."), activeMcpTransportMode, and response summary for every step in an agent playbook.AgentPlaybookReport: Summarizes the completed 4-step audit (frames_logged,vcc_pad_count,drc_violations,pin_count,snapshot_captured, andsnapshot_bytes_len) so UI badges and Tier 6 acceptance tests can assert exact outcomes.
Block 2: McpInspectorWorkbench & run_power_integrity_playbook (crates/pcb-doc/src/lib.rs)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct McpInspectorWorkbench {
pub transport: McpTransportMode,
pub frame_log: Vec<RpcFrameRecord>,
}
impl Default for McpInspectorWorkbench {
fn default() -> Self {
Self {
transport: McpTransportMode::HeadlessDuplex,
frame_log: Vec::new(),
}
}
}
impl McpInspectorWorkbench {
pub fn run_power_integrity_playbook(
&mut self,
board: &BoardModel,
) -> Result<AgentPlaybookReport, String> {
self.frame_log.clear();
let server = PcbMcpServer::new("pwr-stage-rev-b", board.clone());
let summary = server
.read_kicad_resource("kicad://board/summary")
.map_err(|e| e.to_string())?;
self.frame_log.push(RpcFrameRecord {
seq: 1,
method: "resources/read".to_owned(),
transport: self.transport,
summary,
});
let vcc_topo = board.query_net_topology(NetId(1));
self.frame_log.push(RpcFrameRecord {
seq: 2,
method: "tools/call:pcb_query_net".to_owned(),
transport: self.transport,
summary: vcc_topo.summary_badge(),
});
let drc = board
.run_custom_drc(&CustomDrcParams {
min_clearance_mm: 8.0,
min_copper_width_mm: 0.5,
})
.map_err(|e| e.to_string())?;
self.frame_log.push(RpcFrameRecord {
seq: 3,
method: "tools/call:pcb_run_custom_drc".to_owned(),
transport: self.transport,
summary: drc.summary_badge(),
});
let (snapshot_captured, snapshot_bytes_len) = match self.transport {
McpTransportMode::HeadlessDuplex => (false, 0),
McpTransportMode::BridgedLoopback => {
let snap = capture_cropped_region_png(board, 10, 10, 60, 50, 64, 64)
.map_err(|e| e.to_string())?;
(true, snap.png_bytes.len())
}
};
self.frame_log.push(RpcFrameRecord {
seq: 4,
method: "tools/call:pcb_add_review_pin".to_owned(),
transport: self.transport,
summary: format!("Pin+Snap: {snapshot_captured} ({snapshot_bytes_len}B)"),
});
Ok(AgentPlaybookReport {
transport: self.transport,
frames_logged: self.frame_log.len(),
vcc_pad_count: vcc_topo.pad_count,
drc_violations: drc.clearance_violations,
pin_count: board.review_pins.len(),
snapshot_captured,
snapshot_bytes_len,
})
}
}
McpInspectorWorkbench::default(): Boots inMcpTransportMode::HeadlessDuplexwith an emptyframe_log.- 4-Step Deterministic Playbook (
run_power_integrity_playbook): Clearsself.frame_logand executes four ordered MCP steps:seq: 1("resources/read"): Reads"kicad://board/summary"viaPcbMcpServer.seq: 2("tools/call:pcb_query_net"): QueriesNetId(1)(VCC_3V3) topology.seq: 3("tools/call:pcb_run_custom_drc"): Runs custom DRC with8.0 mmclearance and0.5 mmcopper width thresholds.seq: 4("tools/call:pcb_add_review_pin"): Records the review pin audit step and, whenself.transportisMcpTransportMode::BridgedLoopback, captures a64 × 64cropped PNG snapshot (20bytes).
Block 3: Embedded MCP Inspector Workbench Controls in egui (src/main.rs)
// In pub struct ViewState (and ViewState::default()):
pub last_workbench_badge: String, // "Workbench [HeadlessDuplex]: 0 frames".to_owned()
// In pub struct PcbReviewerApp (and PcbReviewerApp::default()):
pub workbench: McpInspectorWorkbench, // McpInspectorWorkbench::default()
// In impl PcbReviewerApp:
pub fn toggle_mcp_transport(&mut self) -> String {
self.workbench.transport = self.workbench.transport.toggle();
let badge = format!(
"Workbench [{}]: {} frames",
self.workbench.transport.label(),
self.workbench.frame_log.len()
);
self.view.last_workbench_badge = badge.clone();
badge
}
pub fn run_agent_playbook(&mut self) -> String {
let report = self
.workbench
.run_power_integrity_playbook(&self.board)
.unwrap_or(AgentPlaybookReport {
transport: self.workbench.transport,
frames_logged: 0,
vcc_pad_count: 0,
drc_violations: 0,
pin_count: 0,
snapshot_captured: false,
snapshot_bytes_len: 0,
});
let badge = format!(
"Playbook [{}]: {} frames, {} DRC, snap={}",
report.transport.label(),
report.frames_logged,
report.drc_violations,
report.snapshot_captured
);
self.view.last_workbench_badge = badge.clone();
badge
}
// Inside PcbReviewerApp::render_session_panel(&mut self, ui: &mut egui::Ui):
ui.label(&self.view.last_workbench_badge);
ui.horizontal(|ui| {
if ui.button("Toggle MCP Transport").clicked() {
self.toggle_mcp_transport();
}
if ui.button("Run Agent Playbook").clicked() {
self.run_agent_playbook();
}
});
toggle_mcp_transport(&mut self): Flipsself.workbench.transportbetweenHeadlessDuplexandBridgedLoopbackand formats"Workbench [<mode>]: <N> frames"intoself.view.last_workbench_badge.run_agent_playbook(&mut self): Executesself.workbench.run_power_integrity_playbook(&self.board)and formats"Playbook [<mode>]: 4 frames, 1 DRC, snap=<bool>"intolast_workbench_badge.
Block 4: Dual-Transport Playbook & Headless egui_kittest Verification (crates/pcb-doc/src/lib.rs & src/main.rs)
// In crates/pcb-doc/src/lib.rs (#[cfg(test)] mod tests):
#[test]
fn mcp_inspector_workbench_and_power_integrity_playbook_preserve_invariants() {
assert_eq!(
McpTransportMode::HeadlessDuplex.toggle(),
McpTransportMode::BridgedLoopback
);
assert_eq!(
McpTransportMode::BridgedLoopback.toggle(),
McpTransportMode::HeadlessDuplex
);
assert_eq!(McpTransportMode::HeadlessDuplex.label(), "HeadlessDuplex");
assert_eq!(McpTransportMode::BridgedLoopback.label(), "BridgedLoopback");
let board = BoardModel::default();
let mut wb = McpInspectorWorkbench::default();
let headless_report = wb.run_power_integrity_playbook(&board).unwrap();
assert_eq!(
headless_report,
AgentPlaybookReport {
transport: McpTransportMode::HeadlessDuplex,
frames_logged: 4,
vcc_pad_count: 1,
drc_violations: 1,
pin_count: 2,
snapshot_captured: false,
snapshot_bytes_len: 0,
}
);
assert_eq!(wb.frame_log.len(), 4);
assert_eq!(wb.frame_log[0].seq, 1);
assert_eq!(wb.frame_log[3].seq, 4);
wb.transport = wb.transport.toggle();
let bridged_report = wb.run_power_integrity_playbook(&board).unwrap();
assert_eq!(
bridged_report,
AgentPlaybookReport {
transport: McpTransportMode::BridgedLoopback,
frames_logged: 4,
vcc_pad_count: 1,
drc_violations: 1,
pin_count: 2,
snapshot_captured: true,
snapshot_bytes_len: 20,
}
);
}
// In src/main.rs (standalone_layer_swatch_and_headless_ui_workflows_pass):
assert!(
harness
.query_by_label("Workbench [HeadlessDuplex]: 0 frames")
.is_some()
);
harness.get_by_label("Run Agent Playbook").click();
harness.run();
assert!(
harness
.query_by_label("Playbook [HeadlessDuplex]: 4 frames, 1 DRC, snap=false")
.is_some()
);
harness.get_by_label("Toggle MCP Transport").click();
harness.run();
assert!(
harness
.query_by_label("Workbench [BridgedLoopback]: 4 frames")
.is_some()
);
harness.get_by_label("Run Agent Playbook").click();
harness.run();
assert!(
harness
.query_by_label("Playbook [BridgedLoopback]: 4 frames, 1 DRC, snap=true")
.is_some()
);
- Dual-Transport Invariant Verification: Asserts that running the playbook in
HeadlessDuplexlogs 4 frames withsnapshot_captured: false(0bytes), and toggling toBridgedLoopbacklogs 4 frames withsnapshot_captured: true(20bytes). - End-to-End
egui_kittestWorkbench Flow: Clicks"Run Agent Playbook","Toggle MCP Transport", and"Run Agent Playbook"insideHarness::new_eframeto verify the complete Act VII UI workflow.
Complete Lesson 0030 Additions Listing (crates/pcb-doc/src/lib.rs & src/main.rs)
Here are the complete assembled Lesson 0030 additions in context across crates/pcb-doc/src/lib.rs and src/main.rs:
// ============================================================================
// crates/pcb-doc/src/lib.rs — McpInspectorWorkbench & Agent Playbook Runner
// ============================================================================
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub enum McpTransportMode {
HeadlessDuplex,
BridgedLoopback,
}
impl McpTransportMode {
pub fn toggle(self) -> Self {
match self {
Self::HeadlessDuplex => Self::BridgedLoopback,
Self::BridgedLoopback => Self::HeadlessDuplex,
}
}
pub fn label(self) -> &'static str {
match self {
Self::HeadlessDuplex => "HeadlessDuplex",
Self::BridgedLoopback => "BridgedLoopback",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RpcFrameRecord {
pub seq: usize,
pub method: String,
pub transport: McpTransportMode,
pub summary: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct AgentPlaybookReport {
pub transport: McpTransportMode,
pub frames_logged: usize,
pub vcc_pad_count: usize,
pub drc_violations: usize,
pub pin_count: usize,
pub snapshot_captured: bool,
pub snapshot_bytes_len: usize,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct McpInspectorWorkbench {
pub transport: McpTransportMode,
pub frame_log: Vec<RpcFrameRecord>,
}
impl Default for McpInspectorWorkbench {
fn default() -> Self {
Self {
transport: McpTransportMode::HeadlessDuplex,
frame_log: Vec::new(),
}
}
}
impl McpInspectorWorkbench {
pub fn run_power_integrity_playbook(
&mut self,
board: &BoardModel,
) -> Result<AgentPlaybookReport, String> {
self.frame_log.clear();
let server = PcbMcpServer::new("pwr-stage-rev-b", board.clone());
let summary = server
.read_kicad_resource("kicad://board/summary")
.map_err(|e| e.to_string())?;
self.frame_log.push(RpcFrameRecord {
seq: 1,
method: "resources/read".to_owned(),
transport: self.transport,
summary,
});
let vcc_topo = board.query_net_topology(NetId(1));
self.frame_log.push(RpcFrameRecord {
seq: 2,
method: "tools/call:pcb_query_net".to_owned(),
transport: self.transport,
summary: vcc_topo.summary_badge(),
});
let drc = board
.run_custom_drc(&CustomDrcParams {
min_clearance_mm: 8.0,
min_copper_width_mm: 0.5,
})
.map_err(|e| e.to_string())?;
self.frame_log.push(RpcFrameRecord {
seq: 3,
method: "tools/call:pcb_run_custom_drc".to_owned(),
transport: self.transport,
summary: drc.summary_badge(),
});
let (snapshot_captured, snapshot_bytes_len) = match self.transport {
McpTransportMode::HeadlessDuplex => (false, 0),
McpTransportMode::BridgedLoopback => {
let snap = capture_cropped_region_png(board, 10, 10, 60, 50, 64, 64)
.map_err(|e| e.to_string())?;
(true, snap.png_bytes.len())
}
};
self.frame_log.push(RpcFrameRecord {
seq: 4,
method: "tools/call:pcb_add_review_pin".to_owned(),
transport: self.transport,
summary: format!("Pin+Snap: {snapshot_captured} ({snapshot_bytes_len}B)"),
});
Ok(AgentPlaybookReport {
transport: self.transport,
frames_logged: self.frame_log.len(),
vcc_pad_count: vcc_topo.pad_count,
drc_violations: drc.clearance_violations,
pin_count: board.review_pins.len(),
snapshot_captured,
snapshot_bytes_len,
})
}
}
// ============================================================================
// src/main.rs — Embedded MCP Workbench Transport & Playbook Triggers
// ============================================================================
impl PcbReviewerApp {
pub fn toggle_mcp_transport(&mut self) -> String {
self.workbench.transport = self.workbench.transport.toggle();
let badge = format!(
"Workbench [{}]: {} frames",
self.workbench.transport.label(),
self.workbench.frame_log.len()
);
self.view.last_workbench_badge = badge.clone();
badge
}
pub fn run_agent_playbook(&mut self) -> String {
let report = self
.workbench
.run_power_integrity_playbook(&self.board)
.unwrap_or(AgentPlaybookReport {
transport: self.workbench.transport,
frames_logged: 0,
vcc_pad_count: 0,
drc_violations: 0,
pin_count: 0,
snapshot_captured: false,
snapshot_bytes_len: 0,
});
let badge = format!(
"Playbook [{}]: {} frames, {} DRC, snap={}",
report.transport.label(),
report.frames_logged,
report.drc_violations,
report.snapshot_captured
);
self.view.last_workbench_badge = badge.clone();
badge
}
}
Switch between Headless and Bridged Live-GUI transports and run the automated 4-step Power Integrity Agent Playbook end-to-end.
1. Workbench Controls
2. JSON-RPC Frame Log & Playbook Steps
3. Workbench & Scorecard State
Complete McpTransportMode::toggle and step 4 of McpInspectorWorkbench::run_power_integrity_playbook in crates/pcb-doc/src/lib.rs.
impl McpTransportMode {
pub fn toggle(self) -> Self {
match self {
Self::HeadlessDuplex => ,
Self::BridgedLoopback => Self::HeadlessDuplex,
}
}
}
// Inside McpInspectorWorkbench::run_power_integrity_playbook:
let (snapshot_captured, snapshot_bytes_len) = match self.transport {
McpTransportMode::HeadlessDuplex => (false, 0),
McpTransportMode::BridgedLoopback => {
let snap = capture_cropped_region_png(board, 10, 10, 60, 50, )
.map_err(|e| e.to_string())?;
(true, snap.png_bytes.len())
}
};
0030)
cargo test --workspace + egui_kittest + cargo mutants
Run the complete workspace test suite (including mcp_inspector_workbench_and_power_integrity_playbook_preserve_invariants) and mutate the transport switcher, playbook runner, and UI workbench methods:
cargo test --manifest-path ./apps/0030-egui-mcp-inspector-workbench-and-agent-playbooks/Cargo.toml --workspace
cargo mutants --manifest-path ./apps/0030-egui-mcp-inspector-workbench-and-agent-playbooks/Cargo.toml --workspace --in-place -F "McpTransportMode::toggle|McpTransportMode::label|McpInspectorWorkbench::run_power_integrity_playbook|toggle_mcp_transport|run_agent_playbook"
Recommended Primary Source
egui_kittest Documentation.
0001–0030) Complete! You have built a complete, multi-crate Rust & egui Schematic and PCB Design Review System from immediate-mode fundamentals (0001) through custom 2D CAD viewports, headless egui_kittest verification, DRC overlays, Copy-on-Write Arc undo/redo, CommandSpec fuzzing, nom KiCad S-expression parsing, embedded Turso SQL transactions, and an official rmcp Model Context Protocol server + Inspector Workbench—all verified with 0 missed mutants.