embacle_server/router.rs
1// ABOUTME: Axum router wiring OpenAI-compatible and MCP endpoints
2// ABOUTME: Mounts completions, models, health, and MCP routes with optional auth middleware
3//
4// SPDX-License-Identifier: Apache-2.0
5// Copyright (c) 2026 dravr.ai
6
7use std::sync::Arc;
8
9use axum::middleware;
10use axum::routing::{get, post};
11use axum::Router;
12
13use crate::auth;
14use crate::completions;
15use crate::health;
16use crate::models;
17use crate::state::SharedState;
18
19/// Build the application router with all endpoints
20///
21/// Routes:
22/// - `POST /v1/chat/completions` — Chat completion (streaming and non-streaming)
23/// - `GET /v1/models` — List available models
24/// - `GET /health` — Provider health check
25/// - `POST /mcp` — MCP Streamable HTTP (JSON-RPC 2.0, via embacle-mcp)
26///
27/// The auth middleware is applied to all routes. It only enforces
28/// authentication when `EMBACLE_API_KEY` is set.
29pub fn build(state: SharedState) -> Router {
30 let mcp_server = Arc::new(embacle_mcp::McpServer::new(
31 Arc::clone(&state),
32 embacle_mcp::build_tool_registry(),
33 ));
34
35 let mcp_router = Router::new()
36 .route("/mcp", post(embacle_mcp::transport::http::handle_mcp_post))
37 .with_state(mcp_server);
38
39 Router::new()
40 .route("/v1/chat/completions", post(completions::handle))
41 .route("/v1/models", get(models::handle))
42 .route("/health", get(health::handle))
43 .with_state(state)
44 .merge(mcp_router)
45 .layer(middleware::from_fn(auth::require_auth))
46}