# MCP Tool Active Indicator Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** 在 MCP 工具被真实调用时，让 GUI MCP 页面对应工具短暂高亮，并在调用结束后保留最短可见时间再熄灭。

**Architecture:** GUI IPC server 在已启用 MCP 且 dispatch 已知工具时发出 Tauri 全局事件，事件包含 `requestId`、`toolName` 和 `phase`。前端 MCP 页面监听事件，用每次调用的 `requestId` 跟踪并发，结束事件按最短可见时间延迟清除高亮。

**Tech Stack:** Rust、Tauri 2 event system、React 19、TypeScript、Tailwind CSS、Tauri Specta bindings。

---

### Task 1: Add MCP Tool Call Events In Rust

**Files:**
- Modify: `vrc-get-gui/src/mcp.rs`
- Modify: `vrc-get-gui/src/commands.rs`
- Test: `vrc-get-gui/src/mcp.rs`

- [x] **Step 1: Add event types and constants**

Add a public event name and serializable payload near the existing `MCP_STATUS_CHANGED_EVENT` and status structs:

```rust
pub const MCP_TOOL_CALL_EVENT: &str = "mcp-tool-call";

#[derive(Debug, Clone, Serialize, specta::Type)]
#[serde(rename_all = "camelCase")]
pub struct McpToolCallEvent {
    request_id: String,
    tool_name: String,
    phase: McpToolCallPhase,
}

#[derive(Debug, Clone, Serialize, specta::Type, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub enum McpToolCallPhase {
    Started,
    Finished,
    Failed,
}
```

- [x] **Step 2: Add method-to-tool mapping**

Add a helper that maps internal IPC methods back to the tool names shown in the UI:

```rust
fn mcp_tool_name(method: &str) -> Option<&'static str> {
    match method {
        "list_projects" => Some("alcomd3_list_projects"),
        "get_project_details" => Some("alcomd3_get_project_details"),
        "list_repositories" => Some("alcomd3_list_repositories"),
        "search_packages" => Some("alcomd3_search_packages"),
        _ => None,
    }
}
```

- [x] **Step 3: Emit lifecycle events around dispatch**

In `handle_request`, after MCP enabled validation and before `dispatch_gui_request`, emit `Started` for known tools. After dispatch returns, emit `Finished` on success and `Failed` on business errors. Unknown direct IPC methods should still return `unknown_method` without a UI event.

- [x] **Step 4: Export event payload type to TypeScript**

In `vrc-get-gui/src/commands.rs`, add the new payload type to the dev-time Specta export list:

```rust
.typ::<crate::mcp::McpToolCallEvent>()
```

- [x] **Step 5: Add unit coverage**

Add tests in `vrc-get-gui/src/mcp.rs` for method mapping, finished phase selection, and camelCase event serialization:

```rust
#[test]
fn mcp_tool_name_maps_gui_methods_to_public_tool_names() {
    assert_eq!(mcp_tool_name("list_projects"), Some("alcomd3_list_projects"));
    assert_eq!(
        mcp_tool_name("get_project_details"),
        Some("alcomd3_get_project_details")
    );
    assert_eq!(
        mcp_tool_name("list_repositories"),
        Some("alcomd3_list_repositories")
    );
    assert_eq!(
        mcp_tool_name("search_packages"),
        Some("alcomd3_search_packages")
    );
    assert_eq!(mcp_tool_name("unknown"), None);
}
```

### Task 2: Track Active Tool Calls In The MCP Page

**Files:**
- Modify: `vrc-get-gui/app/_main/mcp/index.tsx`
- Modify: `vrc-get-gui/lib/bindings.ts`

- [x] **Step 1: Import React hooks and event type**

Update imports to use `useCallback`, `useEffect`, `useRef`, and `useState`; import `McpToolCallEvent` from bindings.

- [x] **Step 2: Add frontend timing constants and state helpers**

Add a named minimum visible duration constant and immutable helpers:

```ts
const MCP_TOOL_ACTIVE_MIN_VISIBLE_MS = 800;

type ActiveToolCalls = Record<string, Record<string, number>>;

function addActiveToolCall(
    calls: ActiveToolCalls,
    toolName: string,
    requestId: string,
    startedAt: number,
): ActiveToolCalls {
    return {
        ...calls,
        [toolName]: {
            ...(calls[toolName] ?? {}),
            [requestId]: startedAt,
        },
    };
}
```

- [x] **Step 3: Listen for `mcp-tool-call` events**

In `Page`, maintain active calls in state and a ref, clear old timers by `toolName:requestId`, keep finished or failed calls visible until `MCP_TOOL_ACTIVE_MIN_VISIBLE_MS`, and clear all timers on unmount.

- [x] **Step 4: Render active tool items**

Pass active call state into `ToolsCard`, mark a tool active when it has at least one active `requestId`, and update `CodeValue` to accept an `active` flag that applies theme-based `bg-accent`, `text-accent-foreground`, `ring-primary/70`, `ring-2`, and transitions.

- [x] **Step 5: Sync checked-in bindings**

The project exports `vrc-get-gui/lib/bindings.ts` during dev GUI startup and keeps that generated file checked in. Sync the new Specta event payload shape into the checked-in binding file and confirm `McpToolCallEvent` appears in `vrc-get-gui/lib/bindings.ts`.

### Task 3: Document The User-Visible Behavior

**Files:**
- Modify: `docs/mcp.md`
- Modify: `release-notes/ALCOMD3_2.0.1-beta.1.md`

- [x] **Step 1: Update MCP docs**

Add a short note to the lifecycle/UI section stating that the GUI MCP page highlights a read-only tool while its call is in progress and keeps the highlight visible briefly after completion for fast calls.

- [x] **Step 2: Update release notes in all existing language sections**

Add one bullet to English, Japanese, and Chinese sections describing the MCP page tool-call highlight.

### Task 4: Verify

**Files:**
- No source edits expected.

- [x] **Step 1: Rust targeted tests**

Run:

```powershell
cargo test -p vrc-get-gui mcp
```

Expected: all MCP-related tests in `vrc-get-gui` pass.

- [x] **Step 2: GUI validation**

Run:

```powershell
npm.cmd run lint
```

from `vrc-get-gui`.

Expected: TypeScript and Biome lint pass.

- [x] **Step 3: Build validation**

Run:

```powershell
npm.cmd run build
```

from `vrc-get-gui`.

Expected: Vite build completes and generated bindings remain consistent.
