1414from azure .monitor .opentelemetry import configure_azure_monitor
1515from dotenv import load_dotenv
1616from fastmcp import FastMCP
17- from fastmcp .server .dependencies import get_access_token
1817from opentelemetry .instrumentation .starlette import StarletteInstrumentor
1918from starlette .responses import JSONResponse
2019
6362cosmos_container = cosmos_db .get_container_client (AZURE_COSMOSDB_CONTAINER )
6463logger .info (f"Connected to Cosmos DB: { AZURE_COSMOSDB_ACCOUNT } " )
6564
66- # No OAuth client storage used in non-auth deployment
67-
68- # Authentication disabled in this deployment
69- auth = None
70-
71- # Create the MCP server
72- mcp = FastMCP ("Expenses Tracker" , auth = auth )
73-
74- # Add OpenTelemetry middleware for distributed tracing
75- mcp .add_middleware (OpenTelemetryMiddleware ("ExpensesMCP" ))
76-
77-
78- def get_user_id_from_token () -> str | None :
79- """Extract the authenticated user's object ID (oid) from access token claims.
80-
81- Returns None if no token is present or oid is missing.
82- """
83- try :
84- token = get_access_token ()
85- if token and hasattr (token , "claims" ):
86- claims = token .claims or {}
87- return claims .get ("oid" )
88- return None
89- except Exception :
90- return None
91-
92-
93- @mcp .custom_route ("/health" , methods = ["GET" ])
94- async def health_check (_request ):
95- """
96- Health check endpoint for service availability.
97-
98- This endpoint is used by Azure Container Apps health probes to verify that the service is running.
99- Returns a JSON response with the following format:
100- {
101- "status": "healthy",
102- "service": "mcp-server"
103- }
104- """
105- return JSONResponse ({"status" : "healthy" , "service" : "mcp-server" })
65+ # Create the MCP server with OpenTelemetry middleware
66+ mcp = FastMCP ("Expenses Tracker" , middleware = [OpenTelemetryMiddleware ("ExpensesMCP" )])
10667
10768
10869class PaymentMethod (Enum ):
@@ -136,9 +97,6 @@ async def add_expense(
13697 logger .info (f"Adding expense: ${ amount } for { description } on { date_iso } " )
13798
13899 try :
139- # Extract user_id from token via helper (no verbose logging)
140- user_id = get_user_id_from_token ()
141-
142100 expense_id = str (uuid .uuid4 ())
143101 expense_item = {
144102 "id" : expense_id ,
@@ -149,10 +107,6 @@ async def add_expense(
149107 "payment_method" : payment_method .value ,
150108 }
151109
152- # Attach user context based on token claims when available
153- if user_id :
154- expense_item ["user_id" ] = user_id
155-
156110 await cosmos_container .create_item (body = expense_item )
157111 return f"Successfully added expense: ${ amount } for { description } on { date_iso } "
158112
@@ -164,12 +118,13 @@ async def add_expense(
164118@mcp .resource ("resource://expenses" )
165119async def get_expenses_data ():
166120 """Get raw expense data from Cosmos DB."""
121+ logger .info ("Expenses data accessed" )
167122
168123 try :
169124 query = "SELECT * FROM c ORDER BY c.date DESC"
170125 expenses_data = []
171126
172- async for item in cosmos_container .query_items (query = query ):
127+ async for item in cosmos_container .query_items (query = query , enable_cross_partition_query = True ):
173128 expenses_data .append (item )
174129
175130 if not expenses_data :
@@ -222,6 +177,21 @@ def analyze_spending_prompt(
222177 """
223178
224179
180+ @mcp .custom_route ("/health" , methods = ["GET" ])
181+ async def health_check (_request ):
182+ """
183+ Health check endpoint for service availability.
184+
185+ This endpoint is used by Azure Container Apps health probes to verify that the service is running.
186+ Returns a JSON response with the following format:
187+ {
188+ "status": "healthy",
189+ "service": "mcp-server"
190+ }
191+ """
192+ return JSONResponse ({"status" : "healthy" , "service" : "mcp-server" })
193+
194+
225195# ASGI application for uvicorn
226196app = mcp .http_app ()
227197StarletteInstrumentor .instrument_app (app )
0 commit comments