PD03 commited on
Commit
db17f98
·
verified ·
1 Parent(s): 682d4ee

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -42
app.py CHANGED
@@ -1,48 +1,89 @@
1
- import os
2
- import json
3
  import httpx
4
- from fastapi import FastAPI, Request, HTTPException
5
- from mcp.server import Server
6
- from mcp.server.sse import sse_server
7
- from mcp.types import Tool, TextContent
8
-
9
- # Create MCP Server
10
- server = Server("sap-mcp-proxy")
11
-
12
- # SAP function
13
- async def fetch_supplier_invoices():
14
- api_key = os.getenv("API_KEY")
15
- if not api_key:
16
- return {"error": "API_KEY not configured"}
17
- url = "https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_SUPPLIERINVOICE_PROCESS_SRV/A_BR_SupplierInvoiceNFDocument?$top=50&$inlinecount=allpages"
18
- headers = {"APIKey": api_key, "Accept": "application/json"}
19
- async with httpx.AsyncClient() as client:
20
- resp = await client.get(url, headers=headers)
21
- return resp.json() if resp.status_code == 200 else {"error": resp.status_code}
22
 
23
- # Register tools
24
- @server.list_tools()
25
- async def list_tools() -> list[Tool]:
26
- return [Tool(name="get_supplier_invoices", description="Fetch supplier invoices from SAP", inputSchema={"type": "object", "properties": {}})]
27
 
28
- @server.call_tool()
29
- async def call_tool(name: str, arguments: dict) -> list[TextContent]:
30
- if name == "get_supplier_invoices":
31
- result = await fetch_supplier_invoices()
32
- return [TextContent(type="text", text=json.dumps(result))]
33
- raise ValueError(f"Unknown tool: {name}")
34
 
35
- # Create app using MCP's built-in SSE server helper
36
- app = sse_server(server)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- # Add auth middleware
39
- API_GATEWAY_KEY = os.getenv("API_GATEWAY_KEY")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- @app.middleware("http")
42
- async def check_api_key(request: Request, call_next):
43
- if request.url.path in ["/", "/health"]:
44
- return await call_next(request)
45
- token = request.headers.get("X-API-Key")
46
- if not token or token != API_GATEWAY_KEY:
47
- raise HTTPException(status_code=401, detail="Unauthorized")
48
- return await call_next(request)
 
1
+ from mcp.server.fastmcp import FastMCP
 
2
  import httpx
3
+ import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ # SAP API Configuration
6
+ SAP_API_URL = "https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata4/sap/api_purchaserequisition_2/srvd_a2x/sap/purchaserequisition/0001/PurchaseReqn"
7
+ SAP_API_KEY = os.getenv("SAP_API_KEY", "your_sap_api_key_here")
 
8
 
9
+ # Initialize FastMCP server
10
+ mcp = FastMCP("SAP_PurchaseRequisition")
 
 
 
 
11
 
12
+ @mcp.tool()
13
+ async def get_purchase_requisitions(top: int = 50) -> dict:
14
+ """
15
+ Fetch purchase requisitions from SAP S/4HANA Cloud API.
16
+
17
+ Args:
18
+ top: Number of records to fetch (default 50, max 100)
19
+
20
+ Returns:
21
+ Dictionary containing purchase requisition data
22
+ """
23
+ headers = {
24
+ "APIKey": SAP_API_KEY,
25
+ "Accept": "application/json"
26
+ }
27
+
28
+ params = {
29
+ "$top": min(top, 100) # Limit to max 100 records
30
+ }
31
+
32
+ async with httpx.AsyncClient(timeout=30.0) as client:
33
+ try:
34
+ response = await client.get(
35
+ SAP_API_URL,
36
+ headers=headers,
37
+ params=params
38
+ )
39
+ response.raise_for_status()
40
+ data = response.json()
41
+ return {
42
+ "status": "success",
43
+ "data": data,
44
+ "count": len(data.get("value", []))
45
+ }
46
+ except httpx.HTTPStatusError as e:
47
+ return {
48
+ "status": "error",
49
+ "message": f"HTTP error occurred: {e.response.status_code}",
50
+ "details": str(e)
51
+ }
52
+ except Exception as e:
53
+ return {
54
+ "status": "error",
55
+ "message": "Failed to fetch purchase requisitions",
56
+ "details": str(e)
57
+ }
58
 
59
+ @mcp.tool()
60
+ async def get_purchase_requisition_summary(top: int = 10) -> str:
61
+ """
62
+ Get a summary of recent purchase requisitions.
63
+
64
+ Args:
65
+ top: Number of records to summarize (default 10)
66
+
67
+ Returns:
68
+ Formatted summary string
69
+ """
70
+ result = await get_purchase_requisitions(top)
71
+
72
+ if result["status"] == "error":
73
+ return f"Error: {result['message']}"
74
+
75
+ items = result["data"].get("value", [])
76
+ if not items:
77
+ return "No purchase requisitions found."
78
+
79
+ summary = f"Found {result['count']} purchase requisitions:\n\n"
80
+ for idx, item in enumerate(items, 1):
81
+ pr_number = item.get("PurchaseRequisition", "N/A")
82
+ description = item.get("PurchaseRequisitionDescription", "No description")
83
+ summary += f"{idx}. PR#{pr_number}: {description}\n"
84
+
85
+ return summary
86
 
87
+ if __name__ == "__main__":
88
+ # Run with streamable HTTP transport for Hugging Face Spaces
89
+ mcp.run(transport="streamable-http", port=7860)