embacle_server/state.rs
1// ABOUTME: Shared server state plus the axum AppState carrying the optional MCP tool executor
2// ABOUTME: SharedState (Arc<ServerState>) is reused from embacle-mcp; AppState adds tools
3//
4// SPDX-License-Identifier: Apache-2.0
5// Copyright (c) 2026 dravr.ai
6
7use std::sync::Arc;
8
9use axum::extract::FromRef;
10use embacle::{FunctionDeclaration, McpToolExecutor};
11
12pub use embacle_mcp::state::{ServerState, SharedState};
13
14/// Server-side tools available for autonomous execution.
15///
16/// Bundles the [`McpToolExecutor`] that runs tool calls with the tool
17/// declarations used to build the catalog injected into the conversation.
18#[derive(Clone)]
19pub struct ServerTools {
20 /// Executor that dispatches tool calls (e.g. an MCP client pool)
21 pub executor: Arc<dyn McpToolExecutor>,
22 /// Declarations of the tools the executor can run
23 pub declarations: Vec<FunctionDeclaration>,
24}
25
26/// Application state shared across all axum handlers.
27///
28/// Wraps the provider [`SharedState`] together with optional server-side tools.
29/// They are present only when the server was started with configured
30/// `[[mcp_servers]]` and the `mcp-tools` feature; handlers that do not need them
31/// continue to extract [`SharedState`] directly via [`FromRef`].
32#[derive(Clone)]
33pub struct AppState {
34 /// Provider/runner state shared with the MCP endpoints
35 pub shared: SharedState,
36 /// Server-side tools backing autonomous tool execution, if configured
37 pub server_tools: Option<ServerTools>,
38}
39
40impl AppState {
41 /// Build application state with no server-side tools.
42 pub fn new(shared: SharedState) -> Self {
43 Self {
44 shared,
45 server_tools: None,
46 }
47 }
48
49 /// Attach server-side tools (e.g. from an MCP client pool).
50 pub fn with_server_tools(mut self, tools: Option<ServerTools>) -> Self {
51 self.server_tools = tools;
52 self
53 }
54}
55
56impl FromRef<AppState> for SharedState {
57 fn from_ref(app: &AppState) -> Self {
58 app.shared.clone()
59 }
60}