Spaces:
Sleeping
Sleeping
Tracy André
commited on
Commit
·
953d6cd
1
Parent(s):
fd8d3c6
updated
Browse files- README_MCP_DEPLOYMENT.md +138 -0
- app.py +61 -14
- mcp_http_server.py +22 -0
- mcp_server.py +109 -4
README_MCP_DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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,36 +1,83 @@
|
|
| 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 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
if __name__ == "__main__":
|
| 36 |
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 |
+
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()
|
mcp_http_server.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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,6 +15,10 @@ import pandas as pd
|
|
| 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,9 +416,85 @@ async def call_tool(name: str, arguments: Dict[str, Any]) -> List[TextContent]:
|
|
| 412 |
)]
|
| 413 |
|
| 414 |
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 418 |
|
| 419 |
# Initialize the server
|
| 420 |
async with stdio_server() as (read_stream, write_stream):
|
|
@@ -428,6 +508,31 @@ async def main():
|
|
| 428 |
)
|
| 429 |
)
|
| 430 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 431 |
|
| 432 |
if __name__ == "__main__":
|
| 433 |
-
|
|
|
|
| 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 |
)]
|
| 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 |
)
|
| 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()
|