Initial commit
This commit is contained in:
186
mcp-server/main.py
Normal file
186
mcp-server/main.py
Normal file
@@ -0,0 +1,186 @@
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from pydantic import BaseModel
|
||||
from typing import Dict, Any, List
|
||||
import logging
|
||||
|
||||
from config import settings
|
||||
from claude_client import claude_client
|
||||
from perplexity_client import perplexity_client
|
||||
from mcp_tools import mcp_tools
|
||||
|
||||
# AI 클라이언트 선택
|
||||
ai_client = perplexity_client if settings.AI_PROVIDER == "perplexity" else claude_client
|
||||
|
||||
# 로깅 설정
|
||||
logging.basicConfig(
|
||||
level=getattr(logging, settings.LOG_LEVEL.upper(), logging.INFO),
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
app = FastAPI(
|
||||
title="Auto Stock Trading MCP Server",
|
||||
description="Model Context Protocol Server for Stock Trading with Claude AI",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
# CORS 설정
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
class ToolCallRequest(BaseModel):
|
||||
tool_name: str
|
||||
parameters: Dict[str, Any]
|
||||
|
||||
|
||||
class AnalysisRequest(BaseModel):
|
||||
analysis_type: str # RULE_VALIDATION, MARKET_ANALYSIS, RISK_ASSESSMENT
|
||||
data: Dict[str, Any]
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {
|
||||
"message": "MCP Server for Auto Stock Trading",
|
||||
"version": "1.0.0",
|
||||
"status": "running"
|
||||
}
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
return {
|
||||
"status": "healthy",
|
||||
"ai_provider": settings.AI_PROVIDER,
|
||||
"claude_configured": bool(settings.ANTHROPIC_API_KEY),
|
||||
"perplexity_configured": bool(settings.PERPLEXITY_API_KEY)
|
||||
}
|
||||
|
||||
|
||||
@app.get("/tools")
|
||||
async def list_tools():
|
||||
"""사용 가능한 도구 목록"""
|
||||
return {
|
||||
"tools": mcp_tools.get_tool_definitions()
|
||||
}
|
||||
|
||||
|
||||
@app.post("/tools/call")
|
||||
async def call_tool(request: ToolCallRequest):
|
||||
"""MCP 도구 호출"""
|
||||
try:
|
||||
result = await mcp_tools.call_tool(request.tool_name, request.parameters)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Tool call error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@app.post("/analyze")
|
||||
async def analyze(request: AnalysisRequest):
|
||||
"""Claude를 통한 분석"""
|
||||
try:
|
||||
analysis_type = request.analysis_type
|
||||
data = request.data
|
||||
|
||||
if analysis_type == "RULE_VALIDATION":
|
||||
# 규칙 검증
|
||||
rule = data.get("rule")
|
||||
market_data = data.get("market_data")
|
||||
|
||||
if not rule or not market_data:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="rule and market_data are required"
|
||||
)
|
||||
|
||||
result = await ai_client.validate_trading_rule(rule, market_data)
|
||||
return {
|
||||
"analysis_type": analysis_type,
|
||||
"result": result
|
||||
}
|
||||
|
||||
elif analysis_type == "MARKET_ANALYSIS":
|
||||
# 시장 분석
|
||||
stock_code = data.get("stock_code")
|
||||
market_data = data.get("market_data")
|
||||
news = data.get("news", [])
|
||||
|
||||
if not stock_code or not market_data:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="stock_code and market_data are required"
|
||||
)
|
||||
|
||||
result = await ai_client.analyze_market(stock_code, market_data, news)
|
||||
return {
|
||||
"analysis_type": analysis_type,
|
||||
"result": result
|
||||
}
|
||||
|
||||
elif analysis_type == "RISK_ASSESSMENT":
|
||||
# 리스크 평가
|
||||
portfolio = data.get("portfolio")
|
||||
trade_plan = data.get("trade_plan")
|
||||
|
||||
if not portfolio or not trade_plan:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="portfolio and trade_plan are required"
|
||||
)
|
||||
|
||||
result = await ai_client.assess_risk(portfolio, trade_plan)
|
||||
return {
|
||||
"analysis_type": analysis_type,
|
||||
"result": result
|
||||
}
|
||||
|
||||
elif analysis_type == "FAIR_PRICE":
|
||||
# 적정가 분석
|
||||
stock_code = data.get("stock_code")
|
||||
market_data = data.get("market_data")
|
||||
financial_data = data.get("financial_data")
|
||||
|
||||
if not stock_code or not market_data:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="stock_code and market_data are required"
|
||||
)
|
||||
|
||||
result = await ai_client.calculate_fair_price(
|
||||
stock_code, market_data, financial_data
|
||||
)
|
||||
return {
|
||||
"analysis_type": analysis_type,
|
||||
"result": result
|
||||
}
|
||||
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Unknown analysis type: {analysis_type}"
|
||||
)
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Analysis error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(
|
||||
"main:app",
|
||||
host=settings.MCP_SERVER_HOST,
|
||||
port=settings.MCP_SERVER_PORT,
|
||||
reload=True
|
||||
)
|
||||
Reference in New Issue
Block a user