Spaces:
Running
Running
Tracy André
commited on
Commit
·
d65ab6d
1
Parent(s):
953d6cd
updated
Browse files- README_MCP_DEPLOYMENT.md +0 -138
- app.py +14 -61
- mcp_http_server.py +0 -22
- 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
|
| 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
|
| 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 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 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 |
-
|
| 420 |
-
|
| 421 |
-
|
| 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())
|