diff --git "a/journals/20260223-0023-MCP\343\203\242\343\202\270\343\203\245\343\203\274\343\203\253\343\201\256\343\203\252\343\203\225\343\202\241\343\202\257\343\202\277\343\203\252\343\203\263\343\202\260\343\201\250\346\251\237\350\203\275\345\210\206\345\211\262.md" "b/journals/20260223-0023-MCP\343\203\242\343\202\270\343\203\245\343\203\274\343\203\253\343\201\256\343\203\252\343\203\225\343\202\241\343\202\257\343\202\277\343\203\252\343\203\263\343\202\260\343\201\250\346\251\237\350\203\275\345\210\206\345\211\262.md" index c33a727..6808c0d 100644 --- "a/journals/20260223-0023-MCP\343\203\242\343\202\270\343\203\245\343\203\274\343\203\253\343\201\256\343\203\252\343\203\225\343\202\241\343\202\257\343\202\277\343\203\252\343\203\263\343\202\260\343\201\250\346\251\237\350\203\275\345\210\206\345\211\262.md" +++ "b/journals/20260223-0023-MCP\343\203\242\343\202\270\343\203\245\343\203\274\343\203\253\343\201\256\343\203\252\343\203\225\343\202\241\343\202\257\343\202\277\343\203\252\343\203\263\343\202\260\343\201\250\346\251\237\350\203\275\345\210\206\345\211\262.md" @@ -33,7 +33,9 @@ - **不一致の修正**: 初期移行時、`JapaneseTokenizer::new()` の戻り値(Result)の処理漏れによりビルドエラーが発生したが、`unwrap()` を追加して修正した。 - **ハンドラの復旧**: リファクタリング時に誤って削除された `initialize` ハンドラを `src/backend/src/mcp/mod.rs` に復旧し、LM Studio 等の外部クライアントからの初期化が失敗する問題を解決した。 -- **プロトコル整合性の修正**: MCP 仕様に従い、セッション ID のパラメータ名を `session_id` から `sessionId` (camelCase) に変更。これにより、SSE 経由のレスポンスが正しくストリームに送信されるよう改善した。 +- **プロトコル整合性の修正**: MCP 仕様に従い、セッション ID のパラメータ名を `session_id` から `sessionId` (camelCase) に変更。 +- **レスポンス方式の改善**: 従来すべてのレスポンスを SSE ストリーム経由で送信していたが、タイムアウト問題を回避するため、HTTP POST のレスポンスボディとして直接返却する方式に変更(MCP 仕様の MAY 規定に基づく)。これにより LM Studio 等での通信安定性が大幅に向上した。 +- **ツール呼び出しロジックの修正**: `tools/call` メソッドにおいて、入れ子になった `arguments` フィールドから正しく引数を抽出できていなかった問題を修正。 - **インポートの欠落**: 各サブモジュールで必要な `log`, `serde_json`, `ndarray`, `sqlx` などのインポートを補完した。 ## 作業詳細 diff --git a/src/backend/src/mcp/mod.rs b/src/backend/src/mcp/mod.rs index 4b19171..d0988e2 100644 --- a/src/backend/src/mcp/mod.rs +++ b/src/backend/src/mcp/mod.rs @@ -75,7 +75,7 @@ pub async fn mcp_messages_handler( State(state): State, - Query(query): Query, + Query(_query): Query, Json(req): Json, ) -> Response { let method = req.method.as_str(); @@ -188,7 +188,14 @@ })), "tools/call" | "get_item_by_id" | "add_item_text" | "search_text" | "lsa_search" | "update_item" | "delete_item" | "lsa_retrain" => { let empty_map = serde_json::Map::new(); - let args = req.params.as_ref().and_then(|p| p.as_object()).unwrap_or(&empty_map); + let mut args = req.params.as_ref().and_then(|p| p.as_object()).unwrap_or(&empty_map); + + // tools/call の場合は、実際の引数は "arguments" フィールドにある + if method == "tools/call" { + if let Some(inner_args) = args.get("arguments").and_then(|a| a.as_object()) { + args = inner_args; + } + } tools::dispatch_tool(&state, method, actual_method, args).await } @@ -212,19 +219,12 @@ id: Some(id_val), }; - if let Some(sid) = query.session_id { - // MCP Client (SSE Mode) - let resp_str = serde_json::to_string(&resp).unwrap(); - log::info!("Sending MCP Response (Session: {}, ID: {:?}): {}", sid, resp.id, resp_str); - let sessions = state.sessions.read().await; - if let Some(tx) = sessions.get(&sid) { - let _ = tx.send(resp_str); - } - axum::http::StatusCode::ACCEPTED.into_response() - } else { - // App UI (Direct Mode) - Json(resp).into_response() - } + // MCP SPEC over SSE: "The server MAY return a response... in the body of the HTTP response." + // SSE 経由での転送だと LM Studio 等でタイムアウトが発生しやすいため、 + // 常に 直接 HTTP レスポンスとして返却するように変更。 + // これを行う場合、SSE ストリームには同じレスポンスを流してはならない。 + log::info!("Sending Direct MCP Response (ID: {:?})", resp.id); + Json(resp).into_response() } else { axum::http::StatusCode::NO_CONTENT.into_response() }