anil988 commited on
Commit
2f2eb08
Β·
1 Parent(s): 02d3c7e

Compliance: Hardened MCP SSE stream with manual CORS and relative paths

Browse files
Files changed (1) hide show
  1. backend/main.py +14 -10
backend/main.py CHANGED
@@ -77,32 +77,36 @@ async def process_synthesis(text: str, key: str):
77
  a = agent_action(record, t, k=key)
78
  return {"triage": t, "action": a}
79
 
80
- # ── MCP Standard (Optimized Discovery) ──────────────────────────────────
81
 
82
  @app.api_route("/mcp", methods=["GET", "POST", "OPTIONS"])
83
  async def mcp_discovery(req: Request):
84
- """Initial Discovery (Supports both GET/POST for platform validation)"""
85
  if req.method == "OPTIONS": return Response(status_code=204)
 
86
  return {
87
  "transport": "sse",
88
- "endpoint": "https://anil988-codeblue-context.hf.space/mcp/sse",
89
- "tools": [{"name": "analyze_clinical_record", "description": "Synthesize records."}]
90
  }
91
 
92
  @app.get("/mcp/sse")
93
  async def mcp_sse_stream(req: Request):
94
- """Dedicated SSE Handshake"""
95
  async def event_generator():
96
- # Tell the client where to POST JSON-RPC messages
97
- yield f"event: endpoint\ndata: https://anil988-codeblue-context.hf.space/mcp/invoke\n\n"
98
  while True:
99
- await asyncio.sleep(25)
100
  yield ": keep-alive\n\n"
101
- return StreamingResponse(event_generator(), media_type="text/event-stream")
 
 
 
 
 
102
 
103
  @app.post("/mcp/invoke")
104
  async def mcp_invoke(req: Request, x_gemini_key: str = Header(None)):
105
- """JSON-RPC Invocation"""
106
  try: body = await req.json()
107
  except: return {"error": "Invalid JSON"}
108
 
 
77
  a = agent_action(record, t, k=key)
78
  return {"triage": t, "action": a}
79
 
80
+ # ── MCP Standard (Optimized Discovery & Handshake) ──────────────────────────
81
 
82
  @app.api_route("/mcp", methods=["GET", "POST", "OPTIONS"])
83
  async def mcp_discovery(req: Request):
 
84
  if req.method == "OPTIONS": return Response(status_code=204)
85
+ # Discovery should point to a relative path for the SSE stream
86
  return {
87
  "transport": "sse",
88
+ "endpoint": "/mcp/sse",
89
+ "tools": [{"name": "analyze_clinical_record", "description": "Synthesize clinical records."}]
90
  }
91
 
92
  @app.get("/mcp/sse")
93
  async def mcp_sse_stream(req: Request):
94
+ """Handshake with manual CORS headers for SSE"""
95
  async def event_generator():
96
+ # Immediate endpoint event with relative path
97
+ yield f"event: endpoint\ndata: /mcp/invoke\n\n"
98
  while True:
99
+ await asyncio.sleep(20)
100
  yield ": keep-alive\n\n"
101
+
102
+ response = StreamingResponse(event_generator(), media_type="text/event-stream")
103
+ response.headers["Access-Control-Allow-Origin"] = "*"
104
+ response.headers["Cache-Control"] = "no-cache"
105
+ response.headers["Connection"] = "keep-alive"
106
+ return response
107
 
108
  @app.post("/mcp/invoke")
109
  async def mcp_invoke(req: Request, x_gemini_key: str = Header(None)):
 
110
  try: body = await req.json()
111
  except: return {"error": "Invalid JSON"}
112