/
alexefan136
/
flowstack
Обзор
Документация
Войти
/
alexefan136
/
flowstack
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
core/gateway/src/proxy/tools.rs
192 строки
6 KB
Alexander Efanov
upd fix
31 июл 2026, 19:17
31 июл 2026, 19:17
d146d86
Код
Авторство
О чём код?
//! Proxy handlers для Tools API и MCP Protocol (Gateway → Engine). //! //! Использует generic [`proxy_to_engine`] из [`super::forward`]: //! - Inject `X-User-ID` / `X-Workspace-ID` из AuthContext //! - Circuit breaker + error handling //! - Прозрачное проксирование (gateway НЕ валидирует — это задача engine) //! //! Endpoints: //! - GET /api/v1/tools — список tools //! - GET /api/v1/tools/names — имена tools (быстрый) //! - GET /api/v1/tools/stats — статистика registry //! - GET /api/v1/tools/{tool_name} — информация о tool //! - POST /api/v1/tools/call — вызвать tool //! - POST /api/v1/tools/mcp — MCP JSON-RPC 2024-11-05 //! - GET /api/v1/tools/bundles — список MCP bundles //! - POST /api/v1/tools/bundles/{n}/enable — включить bundle //! - POST /api/v1/tools/bundles/{n}/disable — отключить bundle //! //! ⚠️ Порядок роутов в main.rs: `/names`, `/stats`, `/call`, `/mcp`, `/bundles` //! ДО `/{tool_name}` (статические пути до динамических). use axum::{ body::Bytes, extract::{Path, State}, http::{HeaderMap, Method}, response::Response, }; use tracing::info; use super::forward::{ProxyState, proxy_to_engine}; use crate::auth::OptionalAuth; // ============================================================================ // TOOL REGISTRY ENDPOINTS // ============================================================================ /// GET /api/v1/tools — список всех доступных tools (builtin + MCP) pub async fn proxy_tools_list( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { proxy_to_engine(&state, Method::GET, "/api/v1/tools", auth, headers, None).await } /// GET /api/v1/tools/names — быстрый список имён tools /// /// ⚠️ Должен быть зарегистрирован ДО `/{tool_name}` в main.rs. pub async fn proxy_tools_names( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { proxy_to_engine( &state, Method::GET, "/api/v1/tools/names", auth, headers, None, ) .await } /// GET /api/v1/tools/stats — статистика Tool Registry /// /// ⚠️ Должен быть зарегистрирован ДО `/{tool_name}` в main.rs. pub async fn proxy_tools_stats( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { proxy_to_engine( &state, Method::GET, "/api/v1/tools/stats", auth, headers, None, ) .await } /// GET /api/v1/tools/bundles — список MCP bundles с их статусами /// /// ⚠️ Должен быть зарегистрирован ДО `/{tool_name}` в main.rs. pub async fn proxy_tools_bundles_list( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { proxy_to_engine( &state, Method::GET, "/api/v1/tools/bundles", auth, headers, None, ) .await } /// GET /api/v1/tools/{tool_name} — детальная информация о конкретном tool pub async fn proxy_tools_get( State(state): State<ProxyState>, Path(tool_name): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { let path = format!("/api/v1/tools/{}", tool_name); proxy_to_engine(&state, Method::GET, &path, auth, headers, None).await } // ============================================================================ // TOOL ACTIONS // ============================================================================ /// POST /api/v1/tools/call — вызвать tool по имени /// /// Body: `{ "name": "...", "arguments": {...}, "confirm": bool }`. /// Валидация (requires_confirmation, existence) — на стороне engine. /// /// ⚠️ Должен быть зарегистрирован ДО `/{tool_name}` в main.rs. pub async fn proxy_tools_call( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, body: Bytes, ) -> Response { info!("proxy_tools_call"); proxy_to_engine( &state, Method::POST, "/api/v1/tools/call", auth, headers, Some(body), ) .await } /// POST /api/v1/tools/mcp — MCP JSON-RPC 2.0 endpoint (spec 2024-11-05) /// /// Body: `{ "jsonrpc": "2.0", "id": ..., "method": "...", "params": {...} }`. /// Валидация JSON-RPC (version, method) — на стороне engine. /// /// ⚠️ Должен быть зарегистрирован ДО `/{tool_name}` в main.rs. pub async fn proxy_tools_mcp( State(state): State<ProxyState>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, body: Bytes, ) -> Response { info!("proxy_tools_mcp"); proxy_to_engine( &state, Method::POST, "/api/v1/tools/mcp", auth, headers, Some(body), ) .await } // ============================================================================ // MCP BUNDLES MANAGEMENT // ============================================================================ /// POST /api/v1/tools/bundles/{name}/enable — включить MCP bundle pub async fn proxy_tools_bundle_enable( State(state): State<ProxyState>, Path(bundle_name): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { info!(bundle_name = %bundle_name, "proxy_tools_bundle_enable"); let path = format!("/api/v1/tools/bundles/{}/enable", bundle_name); proxy_to_engine(&state, Method::POST, &path, auth, headers, None).await } /// POST /api/v1/tools/bundles/{name}/disable — отключить MCP bundle pub async fn proxy_tools_bundle_disable( State(state): State<ProxyState>, Path(bundle_name): Path<String>, OptionalAuth(auth): OptionalAuth, headers: HeaderMap, ) -> Response { info!(bundle_name = %bundle_name, "proxy_tools_bundle_disable"); let path = format!("/api/v1/tools/bundles/{}/disable", bundle_name); proxy_to_engine(&state, Method::POST, &path, auth, headers, None).await }