PD03 commited on
Commit
1ec9387
·
verified ·
1 Parent(s): 75ce927

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -85
app.py CHANGED
@@ -1,105 +1,69 @@
1
  import os
2
- import httpx
3
  from fastapi import FastAPI, HTTPException
4
- from fastapi.middleware.cors import CORSMiddleware
5
- from pydantic import BaseModel
6
 
7
  # -------------------------------------------------
8
- # FastAPI App Configuration
9
  # -------------------------------------------------
 
 
10
  app = FastAPI(
11
- title="SAP Purchase Order API Demo",
12
  description=(
13
- "Backend to fetch purchase order data from SAP Sandbox API.\n\n"
14
- "Designed for integration with OpenAI Agentkit UI — "
15
- "Agentkit automatically discovers endpoints from `/openapi.json`."
16
  ),
17
  version="1.0.0",
18
  )
19
 
20
- # Enable CORS for Agentkit and browser testing
21
- app.add_middleware(
22
- CORSMiddleware,
23
- allow_origins=["*"],
24
- allow_credentials=True,
25
- allow_methods=["*"],
26
- allow_headers=["*"],
27
- )
28
-
29
  # -------------------------------------------------
30
- # Environment Variables
31
- # -------------------------------------------------
32
- SAP_API_KEY = os.getenv("SAP_API_KEY")
33
- SAP_BASE_URL = (
34
- "https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata4/"
35
- "sap/api_purchaseorder_2/srvd_a2x/sap/purchaseorder/0001/PurchaseOrder?$top=50"
36
- )
37
-
38
  # -------------------------------------------------
39
- # Pydantic Models (for OpenAPI schema)
40
- # -------------------------------------------------
41
- class PurchaseOrderItem(BaseModel):
42
- PurchaseOrder: str | None = None
43
- Supplier: str | None = None
44
- CreatedByUser: str | None = None
45
- CreatedDateTime: str | None = None
46
-
47
-
48
- class PurchaseOrderResponse(BaseModel):
49
- source: str
50
- count: int
51
- data: list[PurchaseOrderItem] | dict
 
 
 
 
 
 
 
 
 
52
 
53
 
54
  # -------------------------------------------------
55
- # Routes
56
  # -------------------------------------------------
57
-
58
- @app.get("/", tags=["Root"])
59
- async def root():
60
- """Friendly welcome message for the root URL."""
61
- return {
62
- "message": "👋 Welcome to the SAP Purchase Order API demo!",
63
- "available_endpoints": {
64
- "health": "/health",
65
- "purchase_orders": "/purchase-orders",
66
- "docs": "/docs"
67
- },
68
- "instructions": (
69
- "Use /purchase-orders to fetch SAP Sandbox data, "
70
- "or open /docs for the interactive Swagger UI."
71
- ),
72
- }
73
-
74
-
75
- @app.get("/health", summary="Health check", tags=["System"])
76
- async def health_check():
77
- """Check if the API is running."""
78
- return {"status": "ok", "message": "SAP Purchase Order API backend is running"}
79
-
80
-
81
- @app.get(
82
- "/purchase-orders",
83
- response_model=PurchaseOrderResponse,
84
- summary="Get Purchase Orders",
85
- tags=["Purchase Orders"],
86
- description="Fetches the top 50 purchase orders from the SAP Sandbox API.",
87
- )
88
  async def get_purchase_orders():
89
- """Fetch purchase order data from SAP Sandbox API."""
90
- if not SAP_API_KEY:
91
- raise HTTPException(status_code=500, detail="SAP_API_KEY not found in environment")
 
 
 
 
 
 
 
92
 
93
- headers = {"APIKey": SAP_API_KEY}
94
 
95
- try:
96
- async with httpx.AsyncClient(timeout=30.0) as client:
97
- resp = await client.get(SAP_BASE_URL, headers=headers)
98
- resp.raise_for_status()
99
- data = resp.json()
100
- po_items = data.get("value", [])
101
- return {"source": "SAP Sandbox", "count": len(po_items), "data": po_items}
102
- except httpx.HTTPStatusError as e:
103
- raise HTTPException(status_code=e.response.status_code, detail=f"SAP API error: {e.response.text}")
104
- except Exception as e:
105
- raise HTTPException(status_code=500, detail=str(e))
 
1
  import os
2
+ import requests
3
  from fastapi import FastAPI, HTTPException
4
+ from fastapi.responses import JSONResponse
 
5
 
6
  # -------------------------------------------------
7
+ # CONFIGURATION
8
  # -------------------------------------------------
9
+ HUGGINGFACE_BACKEND = os.getenv("SAP_BACKEND_URL", "https://pd03-agentkit.hf.space/purchase-orders")
10
+
11
  app = FastAPI(
12
+ title="SAP MCP Server",
13
  description=(
14
+ "Minimal MCP-compatible FastAPI server that exposes a tool to fetch SAP "
15
+ "purchase orders from the Hugging Face backend."
 
16
  ),
17
  version="1.0.0",
18
  )
19
 
 
 
 
 
 
 
 
 
 
20
  # -------------------------------------------------
21
+ # MCP Manifest (for AgentKit autodiscovery)
 
 
 
 
 
 
 
22
  # -------------------------------------------------
23
+ @app.get("/.well-known/mcp/manifest.json", include_in_schema=False)
24
+ async def get_manifest():
25
+ """Returns MCP manifest so AgentKit can auto-discover the tool."""
26
+ manifest = {
27
+ "name": "sap_mcp_server",
28
+ "description": "MCP server exposing a tool for retrieving SAP purchase orders.",
29
+ "version": "1.0.0",
30
+ "tools": [
31
+ {
32
+ "name": "get_purchase_orders",
33
+ "description": "Fetches the top 50 purchase orders from the SAP Sandbox API "
34
+ "via the Hugging Face backend.",
35
+ "input_schema": {"type": "object", "properties": {}},
36
+ "output_schema": {"type": "object"},
37
+ "http": {
38
+ "method": "GET",
39
+ "url": "/tools/get_purchase_orders"
40
+ }
41
+ }
42
+ ]
43
+ }
44
+ return JSONResponse(content=manifest)
45
 
46
 
47
  # -------------------------------------------------
48
+ # Tool Endpoint
49
  # -------------------------------------------------
50
+ @app.get("/tools/get_purchase_orders", tags=["MCP Tools"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  async def get_purchase_orders():
52
+ """
53
+ Fetch the top 50 SAP purchase orders from your Hugging Face backend.
54
+ This endpoint is exposed as an MCP tool for AgentKit.
55
+ """
56
+ try:
57
+ resp = requests.get(HUGGINGFACE_BACKEND, timeout=30)
58
+ resp.raise_for_status()
59
+ return resp.json()
60
+ except requests.exceptions.RequestException as e:
61
+ raise HTTPException(status_code=500, detail=f"Failed to call backend: {e}")
62
 
 
63
 
64
+ # -------------------------------------------------
65
+ # Health Route
66
+ # -------------------------------------------------
67
+ @app.get("/health", tags=["System"])
68
+ async def health():
69
+ return {"status": "ok", "message": "SAP MCP Server is running"}