Skip to content

Commit c2ae7de

Browse files
committed
Fix MCP server
- Fix port: use 9224 everywhere (it was a mix before) - Fix MCP tool call names: they contained period characters, which is invalid.
1 parent f6dcf27 commit c2ae7de

8 files changed

Lines changed: 177 additions & 173 deletions

File tree

apps/desktop/src-tauri/src/mcp/executor.rs

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -40,39 +40,39 @@ impl ToolError {
4040
pub fn execute_tool<R: Runtime>(app: &AppHandle<R>, name: &str, params: &Value) -> ToolResult {
4141
match name {
4242
// App commands
43-
n if n.starts_with("app.") => execute_app_command(app, n),
43+
n if n.starts_with("app_") => execute_app_command(app, n),
4444
// View commands
45-
n if n.starts_with("view.") => execute_view_command(app, n),
45+
n if n.starts_with("view_") => execute_view_command(app, n),
4646
// Pane commands
47-
n if n.starts_with("pane.") => execute_pane_command(app, n),
47+
n if n.starts_with("pane_") => execute_pane_command(app, n),
4848
// Navigation commands
49-
n if n.starts_with("nav.") => execute_nav_command(app, n),
49+
n if n.starts_with("nav_") => execute_nav_command(app, n),
5050
// Sort commands
51-
n if n.starts_with("sort.") => execute_sort_command(app, n),
51+
n if n.starts_with("sort_") => execute_sort_command(app, n),
5252
// File commands
53-
n if n.starts_with("file.") => execute_file_command(app, n),
53+
n if n.starts_with("file_") => execute_file_command(app, n),
5454
// Volume commands
55-
n if n.starts_with("volume.") => execute_volume_command(app, n, params),
55+
n if n.starts_with("volume_") => execute_volume_command(app, n, params),
5656
// Context commands
57-
n if n.starts_with("context.") => execute_context_command(app, n),
57+
n if n.starts_with("context_") => execute_context_command(app, n),
5858
_ => Err(ToolError::invalid_params(format!("Unknown tool: {name}"))),
5959
}
6060
}
6161

6262
/// Execute an app command.
6363
fn execute_app_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResult {
6464
match name {
65-
"app.quit" => {
65+
"app_quit" => {
6666
app.emit("mcp-action", json!({"action": "quit"}))
6767
.map_err(|e| ToolError::internal(e.to_string()))?;
6868
Ok(json!({"success": true}))
6969
}
70-
"app.hide" => {
70+
"app_hide" => {
7171
app.emit("mcp-action", json!({"action": "hide"}))
7272
.map_err(|e| ToolError::internal(e.to_string()))?;
7373
Ok(json!({"success": true}))
7474
}
75-
"app.about" => {
75+
"app_about" => {
7676
app.emit("show-about", ())
7777
.map_err(|e| ToolError::internal(e.to_string()))?;
7878
Ok(json!({"success": true}))
@@ -84,15 +84,15 @@ fn execute_app_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResult
8484
/// Execute a view command.
8585
fn execute_view_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResult {
8686
match name {
87-
"view.showHidden" => {
87+
"view_showHidden" => {
8888
let result = toggle_hidden_files(app.clone()).map_err(ToolError::internal)?;
8989
Ok(json!({"success": true, "showHiddenFiles": result}))
9090
}
91-
"view.briefMode" => {
91+
"view_briefMode" => {
9292
set_view_mode(app.clone(), "brief".to_string()).map_err(ToolError::internal)?;
9393
Ok(json!({"success": true, "viewMode": "brief"}))
9494
}
95-
"view.fullMode" => {
95+
"view_fullMode" => {
9696
set_view_mode(app.clone(), "full".to_string()).map_err(ToolError::internal)?;
9797
Ok(json!({"success": true, "viewMode": "full"}))
9898
}
@@ -103,17 +103,17 @@ fn execute_view_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResul
103103
/// Execute a pane command.
104104
fn execute_pane_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResult {
105105
match name {
106-
"pane.switch" => {
106+
"pane_switch" => {
107107
app.emit("switch-pane", ())
108108
.map_err(|e| ToolError::internal(e.to_string()))?;
109109
Ok(json!({"success": true}))
110110
}
111-
"pane.leftVolumeChooser" => {
111+
"pane_leftVolumeChooser" => {
112112
app.emit("mcp-action", json!({"action": "leftVolumeChooser"}))
113113
.map_err(|e| ToolError::internal(e.to_string()))?;
114114
Ok(json!({"success": true}))
115115
}
116-
"pane.rightVolumeChooser" => {
116+
"pane_rightVolumeChooser" => {
117117
app.emit("mcp-action", json!({"action": "rightVolumeChooser"}))
118118
.map_err(|e| ToolError::internal(e.to_string()))?;
119119
Ok(json!({"success": true}))
@@ -126,18 +126,18 @@ fn execute_pane_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResul
126126
/// These emit keyboard-equivalent events to the frontend.
127127
fn execute_nav_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResult {
128128
let key = match name {
129-
"nav.open" => "Enter",
130-
"nav.parent" => "Backspace",
131-
"nav.back" => "GoBack", // Custom event, handled by frontend
132-
"nav.forward" => "GoForward", // Custom event
133-
"nav.up" => "ArrowUp",
134-
"nav.down" => "ArrowDown",
135-
"nav.left" => "ArrowLeft",
136-
"nav.right" => "ArrowRight",
137-
"nav.home" => "Home",
138-
"nav.end" => "End",
139-
"nav.pageUp" => "PageUp",
140-
"nav.pageDown" => "PageDown",
129+
"nav_open" => "Enter",
130+
"nav_parent" => "Backspace",
131+
"nav_back" => "GoBack", // Custom event, handled by frontend
132+
"nav_forward" => "GoForward", // Custom event
133+
"nav_up" => "ArrowUp",
134+
"nav_down" => "ArrowDown",
135+
"nav_left" => "ArrowLeft",
136+
"nav_right" => "ArrowRight",
137+
"nav_home" => "Home",
138+
"nav_end" => "End",
139+
"nav_pageUp" => "PageUp",
140+
"nav_pageDown" => "PageDown",
141141
_ => return Err(ToolError::invalid_params(format!("Unknown nav command: {name}"))),
142142
};
143143

@@ -149,14 +149,14 @@ fn execute_nav_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResult
149149
/// Execute a sort command.
150150
fn execute_sort_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResult {
151151
let (action, value) = match name {
152-
"sort.byName" => ("sortBy", "name"),
153-
"sort.byExtension" => ("sortBy", "extension"),
154-
"sort.bySize" => ("sortBy", "size"),
155-
"sort.byModified" => ("sortBy", "modified"),
156-
"sort.byCreated" => ("sortBy", "created"),
157-
"sort.ascending" => ("sortOrder", "asc"),
158-
"sort.descending" => ("sortOrder", "desc"),
159-
"sort.toggleOrder" => ("sortOrder", "toggle"),
152+
"sort_byName" => ("sortBy", "name"),
153+
"sort_byExtension" => ("sortBy", "extension"),
154+
"sort_bySize" => ("sortBy", "size"),
155+
"sort_byModified" => ("sortBy", "modified"),
156+
"sort_byCreated" => ("sortBy", "created"),
157+
"sort_ascending" => ("sortOrder", "asc"),
158+
"sort_descending" => ("sortOrder", "desc"),
159+
"sort_toggleOrder" => ("sortOrder", "toggle"),
160160
_ => return Err(ToolError::invalid_params(format!("Unknown sort command: {name}"))),
161161
};
162162

@@ -168,11 +168,11 @@ fn execute_sort_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResul
168168
/// Execute a file command.
169169
fn execute_file_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResult {
170170
let action = match name {
171-
"file.showInFinder" => "showInFinder",
172-
"file.copyPath" => "copyPath",
173-
"file.copyFilename" => "copyFilename",
174-
"file.quickLook" => "quickLook",
175-
"file.getInfo" => "getInfo",
171+
"file_showInFinder" => "showInFinder",
172+
"file_copyPath" => "copyPath",
173+
"file_copyFilename" => "copyFilename",
174+
"file_quickLook" => "quickLook",
175+
"file_getInfo" => "getInfo",
176176
_ => return Err(ToolError::invalid_params(format!("Unknown file command: {name}"))),
177177
};
178178

@@ -184,20 +184,20 @@ fn execute_file_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResul
184184
/// Execute a volume command.
185185
fn execute_volume_command<R: Runtime>(app: &AppHandle<R>, name: &str, params: &Value) -> ToolResult {
186186
match name {
187-
"volume.list" => {
187+
"volume_list" => {
188188
// Request volume list from frontend - it will respond via event
189189
app.emit("mcp-volume-list-request", ())
190190
.map_err(|e| ToolError::internal(e.to_string()))?;
191191
// For now, return a placeholder - real implementation needs async response
192192
Ok(json!({"note": "Volume list requested, check mcp-volume-list-response event"}))
193193
}
194-
"volume.selectLeft" | "volume.selectRight" => {
194+
"volume_selectLeft" | "volume_selectRight" => {
195195
let index = params
196196
.get("index")
197197
.and_then(|v| v.as_i64())
198198
.ok_or_else(|| ToolError::invalid_params("Missing 'index' parameter"))?;
199199

200-
let pane = if name == "volume.selectLeft" { "left" } else { "right" };
200+
let pane = if name == "volume_selectLeft" { "left" } else { "right" };
201201

202202
app.emit("mcp-volume-select", json!({"pane": pane, "index": index}))
203203
.map_err(|e| ToolError::internal(e.to_string()))?;
@@ -214,28 +214,28 @@ fn execute_context_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolRe
214214
.ok_or_else(|| ToolError::internal("Pane state not initialized"))?;
215215

216216
match name {
217-
"context.getFocusedPane" => {
217+
"context_getFocusedPane" => {
218218
let focused = store.get_focused_pane();
219219
Ok(json!({"focusedPane": focused}))
220220
}
221221

222-
"context.getLeftPanePath" => {
222+
"context_getLeftPanePath" => {
223223
let left = store.get_left();
224224
Ok(json!({
225225
"path": left.path,
226226
"volumeId": left.volume_id,
227227
}))
228228
}
229229

230-
"context.getRightPanePath" => {
230+
"context_getRightPanePath" => {
231231
let right = store.get_right();
232232
Ok(json!({
233233
"path": right.path,
234234
"volumeId": right.volume_id,
235235
}))
236236
}
237237

238-
"context.getLeftPaneContent" => {
238+
"context_getLeftPaneContent" => {
239239
let left = store.get_left();
240240
Ok(json!({
241241
"path": left.path,
@@ -246,7 +246,7 @@ fn execute_context_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolRe
246246
}))
247247
}
248248

249-
"context.getRightPaneContent" => {
249+
"context_getRightPaneContent" => {
250250
let right = store.get_right();
251251
Ok(json!({
252252
"path": right.path,
@@ -257,7 +257,7 @@ fn execute_context_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolRe
257257
}))
258258
}
259259

260-
"context.getSelectedFileInfo" => {
260+
"context_getSelectedFileInfo" => {
261261
let focused = store.get_focused_pane();
262262
let pane = if focused == "right" {
263263
store.get_right()

apps/desktop/src-tauri/src/mcp/server.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,21 @@ pub fn start_mcp_server<R: Runtime + 'static>(app: AppHandle<R>, config: McpConf
4343
.with_state(state);
4444

4545
let addr = SocketAddr::from(([127, 0, 0, 1], port));
46-
log::info!("MCP server listening on http://{}", addr);
46+
log::info!("MCP server attempting to bind on http://{}", addr);
4747

48-
let listener = tokio::net::TcpListener::bind(addr).await;
49-
match listener {
50-
Ok(listener) => {
51-
if let Err(e) = axum::serve(listener, app).await {
52-
log::error!("MCP server error: {}", e);
53-
}
48+
let listener = match tokio::net::TcpListener::bind(addr).await {
49+
Ok(l) => {
50+
log::info!("MCP server successfully bound to {}", addr);
51+
l
5452
}
5553
Err(e) => {
5654
log::error!("Failed to bind MCP server to {}: {}", addr, e);
55+
return;
5756
}
57+
};
58+
59+
if let Err(e) = axum::serve(listener, app).await {
60+
log::error!("MCP server crashed: {}", e);
5861
}
5962
});
6063
}

0 commit comments

Comments
 (0)