Tracy André commited on
Commit
d65ab6d
·
1 Parent(s): 953d6cd
Files changed (4) hide show
  1. README_MCP_DEPLOYMENT.md +0 -138
  2. app.py +14 -61
  3. mcp_http_server.py +0 -22
  4. mcp_server.py +4 -109
README_MCP_DEPLOYMENT.md DELETED
@@ -1,138 +0,0 @@
1
- # 🤖 Déploiement MCP HTTP sur Hugging Face Spaces
2
-
3
- ## Vue d'ensemble
4
-
5
- Cette configuration permet d'exposer le serveur MCP via HTTP en plus de l'interface Gradio sur Hugging Face Spaces.
6
-
7
- ## 🎯 URLs d'accès
8
-
9
- Après déploiement sur HF Spaces :
10
-
11
- ### Interface Gradio
12
- ```
13
- https://huggingface.co/spaces/[votre-username]/agricultural-analysis
14
- ```
15
-
16
- ### Serveur MCP HTTP
17
- ```
18
- https://[votre-username]-agricultural-analysis.hf.space:8000
19
- ```
20
-
21
- ## 🔧 Endpoints MCP disponibles
22
-
23
- ### Informations du serveur
24
- ```http
25
- GET https://[votre-username]-agricultural-analysis.hf.space:8000/
26
- ```
27
-
28
- ### Lister les ressources
29
- ```http
30
- GET https://[votre-username]-agricultural-analysis.hf.space:8000/mcp/resources
31
- ```
32
-
33
- ### Obtenir une ressource spécifique
34
- ```http
35
- GET https://[votre-username]-agricultural-analysis.hf.space:8000/mcp/resources/agricultural://data/summary
36
- ```
37
-
38
- ### Lister les outils
39
- ```http
40
- GET https://[votre-username]-agricultural-analysis.hf.space:8000/mcp/tools
41
- ```
42
-
43
- ### Appeler un outil
44
- ```http
45
- POST https://[votre-username]-agricultural-analysis.hf.space:8000/mcp/call/filter_data
46
- Content-Type: application/json
47
-
48
- {
49
- "years": [2022, 2023, 2024],
50
- "plots": ["P001", "P002"]
51
- }
52
- ```
53
-
54
- ## 🛠️ Configuration MCP Inspector
55
-
56
- Pour utiliser avec MCP Inspector :
57
-
58
- 1. **URL du serveur** : `https://[votre-username]-agricultural-analysis.hf.space:8000`
59
- 2. **Protocole** : HTTP/REST
60
- 3. **Format** : JSON
61
-
62
- ## 📋 Exemples d'utilisation
63
-
64
- ### Test de connectivité
65
- ```bash
66
- curl https://[votre-username]-agricultural-analysis.hf.space:8000/
67
- ```
68
-
69
- ### Obtenir les outils disponibles
70
- ```bash
71
- curl https://[votre-username]-agricultural-analysis.hf.space:8000/mcp/tools
72
- ```
73
-
74
- ### Analyser la pression adventices
75
- ```bash
76
- curl -X POST https://[votre-username]-agricultural-analysis.hf.space:8000/mcp/call/analyze_weed_pressure \
77
- -H "Content-Type: application/json" \
78
- -d '{"years": [2022, 2023, 2024], "include_visualization": true}'
79
- ```
80
-
81
- ### Prédire la pression future
82
- ```bash
83
- curl -X POST https://[votre-username]-agricultural-analysis.hf.space:8000/mcp/call/predict_weed_pressure \
84
- -H "Content-Type: application/json" \
85
- -d '{"target_years": [2025, 2026, 2027]}'
86
- ```
87
-
88
- ### Identifier les parcelles adaptées
89
- ```bash
90
- curl -X POST https://[votre-username]-agricultural-analysis.hf.space:8000/mcp/call/identify_suitable_plots \
91
- -H "Content-Type: application/json" \
92
- -d '{"target_years": [2025, 2026, 2027], "max_ift_threshold": 1.0}'
93
- ```
94
-
95
- ## 🔍 Logs et Debug
96
-
97
- Les logs des deux services (Gradio + MCP) apparaîtront dans les logs du Space Hugging Face.
98
-
99
- ### Vérifier le statut
100
- - **Gradio** : Interface web accessible
101
- - **MCP HTTP** : Endpoint `/` répond avec infos du serveur
102
-
103
- ## ⚙️ Variables d'environnement
104
-
105
- ```bash
106
- # Mode de déploiement
107
- MCP_MODE=http
108
-
109
- # Configuration réseau
110
- MCP_HOST=0.0.0.0
111
- MCP_PORT=8000
112
- GRADIO_SERVER_NAME=0.0.0.0
113
- GRADIO_SERVER_PORT=7860
114
-
115
- # Configuration Hugging Face
116
- HF_TOKEN=your_token_here
117
- DATASET_ID=HackathonCRA/2024
118
- ```
119
-
120
- ## 🚀 Déploiement
121
-
122
- 1. **Push vers HF Spaces** avec les fichiers modifiés
123
- 2. **Attendre le démarrage** (vérifier les logs)
124
- 3. **Tester la connectivité** sur les deux ports
125
- 4. **Configurer MCP Inspector** avec l'URL
126
-
127
- ## 🔧 Dépannage
128
-
129
- ### Problème de port
130
- Si le port 8000 n'est pas accessible, Hugging Face Spaces peut avoir des restrictions. Essayez :
131
- - Port 8080 ou 3000
132
- - Modifier `MCP_PORT` dans `app.py`
133
-
134
- ### Problème de CORS
135
- Les headers CORS sont configurés pour `allow_origins=["*"]`. Si nécessaire, ajuster dans `mcp_server.py`.
136
-
137
- ### Timeout de démarrage
138
- Le MCP server a 2 secondes pour démarrer avant Gradio. Augmentez si nécessaire dans `app.py`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -1,83 +1,36 @@
1
  """
2
  Hugging Face Space compatible version of the agricultural analysis app.
3
  This is the main entry point for deployment on Hugging Face Spaces.
4
- Launches both Gradio interface and MCP HTTP server.
5
  """
6
 
7
  import os
8
  import sys
9
  import gradio as gr
10
- import asyncio
11
- import threading
12
- import time
13
- import logging
14
 
15
  # Add current directory to Python path
16
  sys.path.append(os.path.dirname(os.path.abspath(__file__)))
17
 
18
- # Import the main Gradio app and MCP server
19
  from gradio_app import create_gradio_app
20
- from mcp_server import main_http
21
-
22
- # Set up logging
23
- logging.basicConfig(level=logging.INFO)
24
- logger = logging.getLogger("hf-space-launcher")
25
-
26
- def run_mcp_server():
27
- """Run MCP HTTP server in a separate thread."""
28
- logger.info("🤖 Starting MCP HTTP Server...")
29
- os.environ["MCP_MODE"] = "http"
30
- os.environ["MCP_PORT"] = "8000"
31
- os.environ["MCP_HOST"] = "0.0.0.0"
32
-
33
- try:
34
- asyncio.run(main_http())
35
- except Exception as e:
36
- logger.error(f"❌ MCP Server failed: {e}")
37
-
38
- def run_gradio_app():
39
- """Run Gradio app."""
40
- logger.info("🌐 Starting Gradio Interface...")
41
-
42
- try:
43
- app = create_gradio_app()
44
- app.launch(
45
- server_name="0.0.0.0",
46
- server_port=7860,
47
- share=False, # Don't share in HF Spaces
48
- debug=False, # Disable debug in production
49
- show_error=True,
50
- quiet=False,
51
- prevent_thread_lock=True # Important for threading
52
- )
53
- except Exception as e:
54
- logger.error(f"❌ Gradio failed: {e}")
55
 
56
  def main():
57
- """Main function for Hugging Face deployment - runs both services."""
58
- logger.info("🚀 Starting Agricultural Analysis Space...")
59
- logger.info("📊 Gradio Interface will be on port 7860")
60
- logger.info("🤖 MCP HTTP Server will be on port 8000")
61
-
62
  # Set up environment
63
  os.environ.setdefault("GRADIO_SERVER_NAME", "0.0.0.0")
64
  os.environ.setdefault("GRADIO_SERVER_PORT", "7860")
65
 
66
- try:
67
- # Start MCP server in a separate thread
68
- mcp_thread = threading.Thread(target=run_mcp_server, daemon=True)
69
- mcp_thread.start()
70
- logger.info("✅ MCP Server thread started")
71
-
72
- # Give MCP server time to start
73
- time.sleep(2)
74
-
75
- # Start Gradio app in main thread
76
- run_gradio_app()
77
-
78
- except Exception as e:
79
- logger.error(f"❌ Failed to start services: {e}")
80
- raise
81
 
82
  if __name__ == "__main__":
83
  main()
 
1
  """
2
  Hugging Face Space compatible version of the agricultural analysis app.
3
  This is the main entry point for deployment on Hugging Face Spaces.
 
4
  """
5
 
6
  import os
7
  import sys
8
  import gradio as gr
 
 
 
 
9
 
10
  # Add current directory to Python path
11
  sys.path.append(os.path.dirname(os.path.abspath(__file__)))
12
 
13
+ # Import the main Gradio app
14
  from gradio_app import create_gradio_app
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  def main():
17
+ """Main function for Hugging Face deployment."""
 
 
 
 
18
  # Set up environment
19
  os.environ.setdefault("GRADIO_SERVER_NAME", "0.0.0.0")
20
  os.environ.setdefault("GRADIO_SERVER_PORT", "7860")
21
 
22
+ # Create and launch the app
23
+ app = create_gradio_app()
24
+
25
+ # Launch with Hugging Face compatible settings
26
+ app.launch(
27
+ server_name="0.0.0.0",
28
+ server_port=7860,
29
+ share=False, # Don't share in HF Spaces
30
+ debug=False, # Disable debug in production
31
+ show_error=True,
32
+ quiet=False
33
+ )
 
 
 
34
 
35
  if __name__ == "__main__":
36
  main()
mcp_http_server.py DELETED
@@ -1,22 +0,0 @@
1
- """
2
- Standalone HTTP MCP Server for Hugging Face Spaces deployment.
3
- This file launches only the MCP HTTP server on a different port.
4
- """
5
-
6
- import os
7
- import asyncio
8
- import logging
9
- from mcp_server import main_http
10
-
11
- # Set up logging
12
- logging.basicConfig(level=logging.INFO)
13
- logger = logging.getLogger("mcp-http-server")
14
-
15
- if __name__ == "__main__":
16
- # Force HTTP mode
17
- os.environ["MCP_MODE"] = "http"
18
- os.environ["MCP_PORT"] = "8000"
19
- os.environ["MCP_HOST"] = "0.0.0.0"
20
-
21
- logger.info("🤖 Starting MCP HTTP Server on port 8000...")
22
- asyncio.run(main_http())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
mcp_server.py CHANGED
@@ -15,10 +15,6 @@ import pandas as pd
15
  from data_loader import AgriculturalDataLoader
16
  from analysis_tools import AgriculturalAnalyzer
17
  import plotly.io as pio
18
- import os
19
- from fastapi import FastAPI, HTTPException
20
- from fastapi.middleware.cors import CORSMiddleware
21
- import uvicorn
22
 
23
 
24
  # Set up logging
@@ -416,85 +412,9 @@ async def call_tool(name: str, arguments: Dict[str, Any]) -> List[TextContent]:
416
  )]
417
 
418
 
419
- # FastAPI app for HTTP interface
420
- fastapi_app = FastAPI(
421
- title="Agricultural MCP Server",
422
- description="MCP Server for Agricultural Data Analysis",
423
- version="1.0.0"
424
- )
425
-
426
- # Add CORS middleware for web access
427
- fastapi_app.add_middleware(
428
- CORSMiddleware,
429
- allow_origins=["*"],
430
- allow_credentials=True,
431
- allow_methods=["*"],
432
- allow_headers=["*"],
433
- )
434
-
435
- @fastapi_app.get("/")
436
- async def root():
437
- """Root endpoint with server info."""
438
- return {
439
- "name": "Agricultural MCP Server",
440
- "version": "1.0.0",
441
- "description": "MCP Server for Agricultural Data Analysis",
442
- "endpoints": {
443
- "resources": "/mcp/resources",
444
- "tools": "/mcp/tools",
445
- "call": "/mcp/call/{tool_name}"
446
- }
447
- }
448
-
449
- @fastapi_app.get("/mcp/resources")
450
- async def get_resources():
451
- """Get available MCP resources."""
452
- try:
453
- resources = await list_resources()
454
- return {"resources": [resource.model_dump() for resource in resources]}
455
- except Exception as e:
456
- logger.error(f"Error listing resources: {e}")
457
- raise HTTPException(status_code=500, detail=str(e))
458
-
459
- @fastapi_app.get("/mcp/resources/{resource_uri:path}")
460
- async def get_resource(resource_uri: str):
461
- """Get a specific resource."""
462
- try:
463
- content = await read_resource(resource_uri)
464
- return {"uri": resource_uri, "content": content}
465
- except Exception as e:
466
- logger.error(f"Error reading resource {resource_uri}: {e}")
467
- raise HTTPException(status_code=500, detail=str(e))
468
-
469
- @fastapi_app.get("/mcp/tools")
470
- async def get_tools():
471
- """Get available MCP tools."""
472
- try:
473
- tools = await list_tools()
474
- return {"tools": [tool.model_dump() for tool in tools]}
475
- except Exception as e:
476
- logger.error(f"Error listing tools: {e}")
477
- raise HTTPException(status_code=500, detail=str(e))
478
-
479
- @fastapi_app.post("/mcp/call/{tool_name}")
480
- async def call_mcp_tool(tool_name: str, arguments: Dict[str, Any] = None):
481
- """Call an MCP tool."""
482
- try:
483
- if arguments is None:
484
- arguments = {}
485
- result = await call_tool(tool_name, arguments)
486
- return {
487
- "tool": tool_name,
488
- "arguments": arguments,
489
- "result": [content.model_dump() for content in result]
490
- }
491
- except Exception as e:
492
- logger.error(f"Error calling tool {tool_name}: {e}")
493
- raise HTTPException(status_code=500, detail=str(e))
494
-
495
- async def main_stdio():
496
- """Main function to run the MCP server via stdio."""
497
- logger.info("Starting Agricultural MCP Server (stdio mode)...")
498
 
499
  # Initialize the server
500
  async with stdio_server() as (read_stream, write_stream):
@@ -508,31 +428,6 @@ async def main_stdio():
508
  )
509
  )
510
 
511
- async def main_http():
512
- """Main function to run the MCP server via HTTP."""
513
- logger.info("Starting Agricultural MCP Server (HTTP mode)...")
514
-
515
- port = int(os.getenv("MCP_PORT", "8000"))
516
- host = os.getenv("MCP_HOST", "0.0.0.0")
517
-
518
- config = uvicorn.Config(
519
- fastapi_app,
520
- host=host,
521
- port=port,
522
- log_level="info",
523
- access_log=True
524
- )
525
- server_instance = uvicorn.Server(config)
526
- await server_instance.serve()
527
-
528
- def main():
529
- """Main entry point - choose mode based on environment."""
530
- mode = os.getenv("MCP_MODE", "stdio")
531
-
532
- if mode == "http":
533
- asyncio.run(main_http())
534
- else:
535
- asyncio.run(main_stdio())
536
 
537
  if __name__ == "__main__":
538
- main()
 
15
  from data_loader import AgriculturalDataLoader
16
  from analysis_tools import AgriculturalAnalyzer
17
  import plotly.io as pio
 
 
 
 
18
 
19
 
20
  # Set up logging
 
412
  )]
413
 
414
 
415
+ async def main():
416
+ """Main function to run the MCP server."""
417
+ logger.info("Starting Agricultural MCP Server...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
 
419
  # Initialize the server
420
  async with stdio_server() as (read_stream, write_stream):
 
428
  )
429
  )
430
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
 
432
  if __name__ == "__main__":
433
+ asyncio.run(main())