chore: baseline — ORM migration + systemd deploy + MCP server + daily check
- ORM migration: models/ops 重构 - deploy: 标准化 systemd timer/service 部署体系 - MCP server: 5 个只读工具(任务/状态/数据集) - daily check: 数据一致性巡检 - watch: task_watch 后台监控 - kline_daily: 麦蕊优先,时间门禁15:00 - 删除: task_industry_sector, task_sector_features
This commit is contained in:
+53
-10
@@ -34,6 +34,7 @@ if str(_PROJECT_ROOT) not in sys.path:
|
||||
|
||||
# ── MCP server bootstrap ────────────────────────────────────────────
|
||||
from mcp.server import Server
|
||||
from mcp.server.sse import SseServerTransport
|
||||
from mcp.server.stdio import stdio_server
|
||||
from mcp.types import Tool, TextContent
|
||||
|
||||
@@ -125,9 +126,10 @@ def list_datasets() -> list[dict]:
|
||||
from sqlalchemy import func, select
|
||||
from app.core.db.models import (
|
||||
KlineStock, KlineIndex, Kline5Min, Moneyflow, Share, TickTrade,
|
||||
SectorIndices, SectorFeaturesDaily, MarketRegimeDaily,
|
||||
LonghubangDaily, LonghubangSeat, Stock, Industry,
|
||||
MarketRegimeDaily,
|
||||
LonghubangDaily, LonghubangSeat, Stock,
|
||||
NodeCategory, Node, StockNodeMap, KlineStockMADaily,
|
||||
KlineStockMACDDaily, KlineStockKDJDaily, KlineStockBOLLDaily,
|
||||
)
|
||||
from app.core.db.orm import SessionLocal
|
||||
|
||||
@@ -140,15 +142,15 @@ def list_datasets() -> list[dict]:
|
||||
("moneyflow", Moneyflow),
|
||||
("share", Share),
|
||||
("tick_trade", TickTrade),
|
||||
("sector_indices", SectorIndices),
|
||||
("sector_features_daily", SectorFeaturesDaily),
|
||||
("market_regime_daily", MarketRegimeDaily),
|
||||
("longhubang_daily", LonghubangDaily),
|
||||
("longhubang_seat", LonghubangSeat),
|
||||
("industry", Industry),
|
||||
("node_categories", NodeCategory),
|
||||
("nodes", Node),
|
||||
("stock_node_map", StockNodeMap),
|
||||
("kline_stock_macd_daily", KlineStockMACDDaily),
|
||||
("kline_stock_kdj_daily", KlineStockKDJDaily),
|
||||
("kline_stock_boll_daily", KlineStockBOLLDaily),
|
||||
]
|
||||
out = []
|
||||
with SessionLocal() as s:
|
||||
@@ -175,9 +177,10 @@ def get_dataset_info(table_name: str) -> dict:
|
||||
allowed = {
|
||||
"stocks", "kline_stock", "kline_index", "kline_5min",
|
||||
"kline_stock_ma_daily", "moneyflow", "share", "tick_trade",
|
||||
"sector_indices", "sector_features_daily", "market_regime_daily",
|
||||
"longhubang_daily", "longhubang_seat", "industry",
|
||||
"market_regime_daily",
|
||||
"longhubang_daily", "longhubang_seat",
|
||||
"node_categories", "nodes", "stock_node_map",
|
||||
"kline_stock_macd_daily", "kline_stock_kdj_daily", "kline_stock_boll_daily",
|
||||
"dataset_registry", "sync_history", "config",
|
||||
}
|
||||
if table_name not in allowed:
|
||||
@@ -291,11 +294,51 @@ async def call_tool(name: str, arguments: dict):
|
||||
|
||||
# ── main ────────────────────────────────────────────────────────────
|
||||
|
||||
async def main():
|
||||
# 启动时注册数据源(让 datasource.health_check 之类方法可用)
|
||||
async def main_sse(host: str = "127.0.0.1", port: int = 8101):
|
||||
"""启动 MCP 的 SSE (HTTP) 服务,供持久运行。
|
||||
|
||||
客户端连接: http://{host}:{port}/sse
|
||||
"""
|
||||
sse_transport = SseServerTransport("/messages")
|
||||
|
||||
async def app(scope, receive, send):
|
||||
if scope["type"] != "http":
|
||||
return
|
||||
path = scope.get("path", "")
|
||||
if path == "/sse":
|
||||
async with sse_transport.connect_sse(scope, receive, send) as (read, write):
|
||||
await server.run(read, write, server.create_initialization_options())
|
||||
elif path == "/messages" and scope.get("method") == "POST":
|
||||
await sse_transport.handle_post_message(scope, receive, send)
|
||||
|
||||
import uvicorn
|
||||
from app.core.utils.logging import get_logger
|
||||
logger = get_logger("mcp")
|
||||
logger.info(f"MCP SSE server listening on http://{host}:{port}/sse")
|
||||
config = uvicorn.Config(app, host=host, port=port, log_level="info")
|
||||
srv = uvicorn.Server(config)
|
||||
await srv.serve()
|
||||
|
||||
|
||||
def main():
|
||||
from app.core.datasource.registry import build_default_registry
|
||||
build_default_registry()
|
||||
|
||||
import sys
|
||||
if "--sse" in sys.argv:
|
||||
host = "127.0.0.1"
|
||||
port = 8101
|
||||
for i, arg in enumerate(sys.argv):
|
||||
if arg == "--host" and i + 1 < len(sys.argv):
|
||||
host = sys.argv[i + 1]
|
||||
if arg == "--port" and i + 1 < len(sys.argv):
|
||||
port = int(sys.argv[i + 1])
|
||||
asyncio.run(main_sse(host, port))
|
||||
else:
|
||||
asyncio.run(_stdio_main())
|
||||
|
||||
|
||||
async def _stdio_main():
|
||||
async with stdio_server() as (read_stream, write_stream):
|
||||
await server.run(
|
||||
read_stream,
|
||||
@@ -305,4 +348,4 @@ async def main():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
main()
|
||||
Reference in New Issue
Block a user