Spaces:
Sleeping
Sleeping
| import os, hmac, hashlib, time, json | |
| from typing import Optional, Dict, Any, List | |
| from fastapi import FastAPI, Header, HTTPException, Request | |
| from pydantic import BaseModel | |
| import uvicorn | |
| import numpy as np | |
| # app.py'nin en üstüne ekle (import'lardan sonra) | |
| try: | |
| from advanced_tools import advanced_tools | |
| ADVANCED_ENABLED = True | |
| print("[OK] Advanced tools loaded successfully!") | |
| except Exception as e: | |
| ADVANCED_ENABLED = False | |
| print(f"[WARN] Advanced tools not available: {e}") | |
| advanced_tools = None | |
| # Basit başlayalım - sadece temel tool'lar | |
| API_KEY = os.getenv("API_KEY", "") | |
| ALLOW_CLOCK_SKEW = 60 | |
| app = FastAPI(title="CPU-Only MCP Madness") | |
| # Güvenlik | |
| def verify_api_key(x_api_key: Optional[str]): | |
| if not API_KEY: | |
| raise HTTPException(status_code=500, detail="API_KEY not set") | |
| if not x_api_key or x_api_key != API_KEY: | |
| raise HTTPException(status_code=401, detail="Unauthorized") | |
| def verify_hmac(body: bytes, timestamp: Optional[str], signature: Optional[str]): | |
| if timestamp is None or signature is None: | |
| return | |
| try: | |
| ts = int(timestamp) | |
| except: | |
| raise HTTPException(status_code=400, detail="Invalid timestamp") | |
| now = int(time.time()) | |
| if abs(now - ts) > ALLOW_CLOCK_SKEW: | |
| raise HTTPException(status_code=401, detail="Stale request") | |
| secret = API_KEY.encode() | |
| base = f"{ts}\n".encode() + body | |
| expected = hmac.new(secret, base, hashlib.sha256).hexdigest() | |
| if not hmac.compare_digest(expected, signature): | |
| raise HTTPException(status_code=401, detail="Bad signature") | |
| # Request/Response modelleri | |
| class HandshakeResponse(BaseModel): | |
| ok: bool | |
| message: str | |
| tools: List[str] | |
| class MCPRequest(BaseModel): | |
| tool: str | |
| input: dict | |
| class MCPResponse(BaseModel): | |
| ok: bool | |
| result: dict | |
| # Basit tool'lar | |
| class SimpleTools: | |
| def echo(input_data: dict) -> dict: | |
| """Echo tool - ne gönderirsen geri alırsın""" | |
| return {"echoed": input_data, "timestamp": time.time()} | |
| def sum_numbers(input_data: dict) -> dict: | |
| """Sayıları toplar""" | |
| numbers = input_data.get("numbers", []) | |
| return { | |
| "sum": sum(numbers), | |
| "count": len(numbers), | |
| "average": sum(numbers) / len(numbers) if numbers else 0 | |
| } | |
| def text_stats(input_data: dict) -> dict: | |
| """Text istatistikleri""" | |
| text = input_data.get("text", "") | |
| return { | |
| "length": len(text), | |
| "words": len(text.split()), | |
| "sentences": text.count('.') + text.count('!') + text.count('?'), | |
| "uppercase": sum(1 for c in text if c.isupper()), | |
| "lowercase": sum(1 for c in text if c.islower()) | |
| } | |
| def personality_lite(input_data: dict) -> dict: | |
| """Basit personality dönüşümü""" | |
| text = input_data.get("text", "") | |
| style = input_data.get("style", "pirate") | |
| styles = { | |
| "pirate": { | |
| "prefix": "Arr matey! ", | |
| "suffix": " Shiver me timbers!", | |
| "replacements": { | |
| "hello": "ahoy", | |
| "friend": "matey", | |
| "yes": "aye", | |
| "you": "ye" | |
| } | |
| }, | |
| "robot": { | |
| "prefix": "[BEEP BOOP] ", | |
| "suffix": " [END TRANSMISSION]", | |
| "replacements": { | |
| "hello": "GREETINGS", | |
| "I": "THIS UNIT", | |
| "think": "COMPUTE", | |
| "feel": "PROCESS" | |
| } | |
| }, | |
| "yoda": { | |
| "prefix": "Hmm, ", | |
| "suffix": " it is.", | |
| "replacements": {} | |
| } | |
| } | |
| if style not in styles: | |
| style = "pirate" | |
| style_config = styles[style] | |
| result = text | |
| # Basit replacements | |
| for old, new in style_config["replacements"].items(): | |
| result = result.replace(old, new) | |
| # Prefix ve suffix ekle | |
| result = style_config["prefix"] + result + style_config["suffix"] | |
| return { | |
| "original": text, | |
| "styled": result, | |
| "style": style | |
| } | |
| def random_facts(input_data: dict) -> dict: | |
| """Random fun facts generator""" | |
| import random | |
| facts = [ | |
| "Octopuses have three hearts!", | |
| "Bananas are berries, but strawberries aren't!", | |
| "A day on Venus is longer than its year!", | |
| "Honey never spoils - archaeologists found 3000 year old honey that was still edible!", | |
| "The human brain uses 20% of the body's energy!", | |
| "There are more possible chess games than atoms in the universe!", | |
| "CPU stands for Central Processing Unit!", | |
| "The first computer bug was an actual bug - a moth!", | |
| "Python is named after Monty Python, not the snake!" | |
| ] | |
| topic = input_data.get("topic", "random").lower() | |
| if "animal" in topic: | |
| relevant_facts = [f for f in facts if any(a in f.lower() for a in ["octopus", "banana", "honey"])] | |
| elif "space" in topic: | |
| relevant_facts = [f for f in facts if "venus" in f.lower() or "universe" in f.lower()] | |
| elif "computer" in topic or "tech" in topic: | |
| relevant_facts = [f for f in facts if any(t in f.lower() for t in ["cpu", "computer", "python", "bug"])] | |
| else: | |
| relevant_facts = facts | |
| selected = random.sample(relevant_facts, min(3, len(relevant_facts))) | |
| return { | |
| "facts": selected, | |
| "topic": topic, | |
| "total_facts_available": len(relevant_facts) | |
| } | |
| # Tool registry | |
| # TOOLS dictionary'sini güncelle | |
| TOOLS = { | |
| "echo": SimpleTools.echo, | |
| "sum": SimpleTools.sum_numbers, | |
| "text_stats": SimpleTools.text_stats, | |
| "personality": SimpleTools.personality_lite, | |
| "facts": SimpleTools.random_facts, | |
| } | |
| # Advanced tools ekle (eğer yüklendiyse) | |
| if ADVANCED_ENABLED and advanced_tools: | |
| TOOLS.update({ | |
| "sentiment": advanced_tools.sentiment_analysis, | |
| "entities": advanced_tools.entity_extraction, | |
| "similarity": advanced_tools.semantic_similarity, | |
| "embedding": advanced_tools.text_embedding, | |
| "cache": advanced_tools.smart_cache, | |
| }) | |
| # Endpoints | |
| async def root(): | |
| """Root endpoint - test için""" | |
| return { | |
| "message": "CPU-Only MCP Madness is running!", | |
| "status": "healthy", | |
| "available_tools": list(TOOLS.keys()), | |
| "advanced_enabled": ADVANCED_ENABLED, | |
| "total_tools": len(TOOLS) | |
| } | |
| async def handshake( | |
| request: Request, | |
| x_api_key: Optional[str] = Header(default=None), | |
| x_timestamp: Optional[str] = Header(default=None), | |
| x_signature: Optional[str] = Header(default=None), | |
| ): | |
| body = await request.body() | |
| verify_api_key(x_api_key) | |
| verify_hmac(body, x_timestamp, x_signature) | |
| return HandshakeResponse( | |
| ok=True, | |
| message="Handshake successful! Ready to rock", | |
| tools=list(TOOLS.keys()) | |
| ) | |
| async def mcp_invoke( | |
| payload: MCPRequest, | |
| request: Request, | |
| x_api_key: Optional[str] = Header(default=None), | |
| x_timestamp: Optional[str] = Header(default=None), | |
| x_signature: Optional[str] = Header(default=None), | |
| ): | |
| body = await request.body() | |
| verify_api_key(x_api_key) | |
| verify_hmac(body, x_timestamp, x_signature) | |
| tool_name = payload.tool | |
| tool_input = payload.input | |
| if tool_name not in TOOLS: | |
| raise HTTPException(status_code=404, detail=f"Unknown tool: {tool_name}") | |
| try: | |
| result = TOOLS[tool_name](tool_input) | |
| return MCPResponse(ok=True, result=result) | |
| except Exception as e: | |
| return MCPResponse(ok=False, result={"error": str(e)}) | |
| async def health(): | |
| """Health check""" | |
| return {"status": "healthy", "timestamp": time.time()} | |
| if __name__ == "__main__": | |
| port = int(os.getenv("PORT", "7860")) | |
| uvicorn.run("app:app", host="0.0.0.0", port=port, reload=False) | |