"""Router /mcp-alpaca/* — DI per env, client e (write) creds. Mappa 1:1 i tool di `cerbero_mcp.exchanges.alpaca.tools` a endpoint `POST /mcp-alpaca/tools/{tool_name}`. L'autenticazione bearer è gestita dal middleware in `cerbero_mcp.auth`; qui leggiamo solo `request.state.environment`. """ from __future__ import annotations from typing import Literal from fastapi import APIRouter, Depends, Request from cerbero_mcp.client_registry import ClientRegistry from cerbero_mcp.exchanges.alpaca import tools as t from cerbero_mcp.exchanges.alpaca.client import AlpacaClient Environment = Literal["testnet", "mainnet"] def get_environment(request: Request) -> Environment: return request.state.environment async def get_alpaca_client( request: Request, env: Environment = Depends(get_environment) ) -> AlpacaClient: registry: ClientRegistry = request.app.state.registry return await registry.get("alpaca", env) def _build_creds(request: Request) -> dict: """Costruisce dict `creds` minimale per leverage cap / metadata.""" settings = request.app.state.settings return { "max_leverage": settings.alpaca.max_leverage, "api_key_id": settings.alpaca.api_key_id, } def make_router() -> APIRouter: r = APIRouter(prefix="/mcp-alpaca", tags=["alpaca"]) # === READ tools === @r.post("/tools/environment_info") async def _environment_info( request: Request, client: AlpacaClient = Depends(get_alpaca_client), ): creds = _build_creds(request) return await t.environment_info(client, creds=creds) @r.post("/tools/get_account") async def _get_account( params: t.GetAccountReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_account(client, params) @r.post("/tools/get_positions") async def _get_positions( params: t.GetPositionsReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_positions(client, params) @r.post("/tools/get_activities") async def _get_activities( params: t.GetActivitiesReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_activities(client, params) @r.post("/tools/get_assets") async def _get_assets( params: t.GetAssetsReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_assets(client, params) @r.post("/tools/get_ticker") async def _get_ticker( params: t.GetTickerReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_ticker(client, params) @r.post("/tools/get_bars") async def _get_bars( params: t.GetBarsReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_bars(client, params) @r.post("/tools/get_snapshot") async def _get_snapshot( params: t.GetSnapshotReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_snapshot(client, params) @r.post("/tools/get_option_chain") async def _get_option_chain( params: t.GetOptionChainReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_option_chain(client, params) @r.post("/tools/get_open_orders") async def _get_open_orders( params: t.GetOpenOrdersReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_open_orders(client, params) @r.post("/tools/get_clock") async def _get_clock( params: t.GetClockReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_clock(client, params) @r.post("/tools/get_calendar") async def _get_calendar( params: t.GetCalendarReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.get_calendar(client, params) # === WRITE tools === @r.post("/tools/place_order") async def _place_order( params: t.PlaceOrderReq, request: Request, client: AlpacaClient = Depends(get_alpaca_client), ): creds = _build_creds(request) return await t.place_order(client, params, creds=creds) @r.post("/tools/amend_order") async def _amend_order( params: t.AmendOrderReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.amend_order(client, params) @r.post("/tools/cancel_order") async def _cancel_order( params: t.CancelOrderReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.cancel_order(client, params) @r.post("/tools/cancel_all_orders") async def _cancel_all_orders( params: t.CancelAllOrdersReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.cancel_all_orders(client, params) @r.post("/tools/close_position") async def _close_position( params: t.ClosePositionReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.close_position(client, params) @r.post("/tools/close_all_positions") async def _close_all_positions( params: t.CloseAllPositionsReq, client: AlpacaClient = Depends(get_alpaca_client), ): return await t.close_all_positions(client, params) return r