Ai_Assistant/hakuro_MCP/DiceCaller/dice_server.py
2026-06-10 21:40:08 +02:00

99 lines
3.6 KiB
Python

import random
import json
import yaml
import os
from dotenv import load_dotenv
from fastmcp import FastMCP
from fastmcp.server.auth.providers.jwt import RSAKeyPair
from fastmcp.server.auth import JWTVerifier
from pyngrok import ngrok
from pathlib import Path
load_dotenv()
# ─────────────────────────────
# 🔧 Detect paths and config
# ─────────────────────────────
# Example: /home/user/riko_project_mcp/DiceCaller/dice_roller.py
current_file = Path(__file__).resolve()
module_folder = current_file.parent.name # → "DiceCaller"
project_root = current_file.parents[1] # → "riko_project_mcp"
config_yaml_path = project_root / "riko_mcp_config.yaml"
# Load or create YAML
if not config_yaml_path.exists():
default_config = {"project_name": project_root.name, "port": 9000, "ngrok": True}
with open(config_yaml_path, "w") as f:
yaml.dump(default_config, f)
print(f"🆕 Created default YAML config: {config_yaml_path}")
with open(config_yaml_path, "r") as f:
config_yaml = yaml.safe_load(f)
project_name = config_yaml.get("project_name", project_root.name)
port = config_yaml.get("port", 9000)
use_ngrok = config_yaml.get("ngrok", True)
server_name = module_folder # Automatically derived from folder
# ─────────────────────────────
# 🗂️ Credential + Config Paths
# ─────────────────────────────
config_json_path = project_root / "mcp_config.json"
# ─────────────────────────────
# 🔐 Authentication
# ─────────────────────────────
key_pair = RSAKeyPair.generate()
access_token = key_pair.create_token(audience=server_name)
auth = JWTVerifier(
public_key=key_pair.public_key,
audience=server_name,
)
# ─────────────────────────────
# 🌍 Ngrok Tunnel (optional)
# ─────────────────────────────
if use_ngrok:
# 1. Ngrok Token aus der .env holen
ngrok_token = os.getenv("NGROK_AUTHTOKEN")
if not ngrok_token:
print("⚠️ Warnung: NGROK_AUTHTOKEN nicht in der .env gefunden!")
else:
# 2. Ngrok den Token übergeben
ngrok.set_auth_token(ngrok_token)
public_url = ngrok.connect(port, "http").public_url
else:
public_url = f"http://localhost:{port}"
print(f"🌍 MCP Public URL: {public_url}")
# ─────────────────────────────
# 🧮 MCP Server Setup
# ─────────────────────────────
mcp = FastMCP(name=server_name)
# Example tool
@mcp.tool(meta={"tool_type": "can_async"}, exclude_args=["manual_call"])
def roll_dice(n_dice: int, manual_call: bool = False):
"""Roll `n_dice` 6-sided dice and return the results."""
print(f"🎲 roll_dice called with n_dice={n_dice}")
dice_result = [random.randint(1, 6) for _ in range(n_dice)]
if manual_call == True:
return f"this function was manually called"
return dice_result
# ─────────────────────────────
# ▶️ Run Server
# ─────────────────────────────
if __name__ == "__main__":
print(f"\n---\n🔑 {server_name} Access Token:\n{access_token}\n---\n")
mcp.run(transport="http", port=port, stateless_http=True)