1+ # ...existing code...
2+ import os
3+ import json
4+ import requests
5+ from typing import Any , Dict , Optional
6+ from mcp .server .fastmcp import FastMCP
7+
8+ BASE_URL = os .getenv ("FINANCIAL_API_BASE_URL" , "http://localhost:8060" )
9+
10+ mcp = FastMCP ("financial-search-mcp-server" )
11+
12+
13+ def _post (path : str , payload : Dict [str , Any ], stream : bool = False ) -> Dict [str , Any ]:
14+ url = BASE_URL .rstrip ("/" ) + path
15+ try :
16+ resp = requests .post (url , json = payload , stream = stream , timeout = 30 )
17+ resp .raise_for_status ()
18+ if stream :
19+ # 收集流式返回的每一行 JSON(如果服务以行分块返回 JSON)
20+ items = []
21+ for line in resp .iter_lines (decode_unicode = True ):
22+ if not line :
23+ continue
24+ try :
25+ items .append (json .loads (line ))
26+ except Exception :
27+ # 如果不是 JSON,作为文本行保存
28+ items .append ({"raw" : line })
29+ return {"status" : "success" , "result" : {"items" : items }}
30+ else :
31+ body = resp .json ()
32+ return {"status" : "success" , "result" : body .get ("result" , body )}
33+ except requests .HTTPError as he :
34+ try :
35+ body = resp .json ()
36+ except Exception :
37+ body = resp .text if resp is not None else str (he )
38+ return {"status" : "error" , "result" : {"error" : str (he ), "body" : body }}
39+ except Exception as e :
40+ return {"status" : "error" , "result" : {"error" : str (e )}}
41+
42+
43+ @mcp .tool ()
44+ def get_stock_history (ticker : str , start_date : str , end_date : str ) -> Dict [str , Any ]:
45+ """调用 /get_stock_history"""
46+ payload = {"ticker" : ticker , "start_date" : start_date , "end_date" : end_date }
47+ return _post ("/get_stock_history" , payload , stream = False )
48+
49+
50+ @mcp .tool ()
51+ def get_company_news (ticker : str , start_date : str , end_date : str , crawl_content : bool = True ) -> Dict [str , Any ]:
52+ """调用 /get_company_news,服务如支持流式会按行聚合并返回 items 列表"""
53+ payload = {
54+ "ticker" : ticker ,
55+ "start_date" : start_date ,
56+ "end_date" : end_date ,
57+ "crawl_content" : crawl_content ,
58+ }
59+ return _post ("/get_company_news" , payload , stream = True )
60+
61+
62+ @mcp .tool ()
63+ def get_general_news (start_date : str , end_date : str , crawl_content : bool = True , max_items : int = 100 ) -> Dict [str , Any ]:
64+ payload = {
65+ "start_date" : start_date ,
66+ "end_date" : end_date ,
67+ "crawl_content" : crawl_content ,
68+ "max_items" : max_items ,
69+ }
70+ return _post ("/get_general_news" , payload , stream = True )
71+
72+
73+ @mcp .tool ()
74+ def get_financials_reported (ticker : str , start_date : str , end_date : str , freq : str = "annual" ) -> Dict [str , Any ]:
75+ payload = {"ticker" : ticker , "start_date" : start_date , "end_date" : end_date , "freq" : freq }
76+ return _post ("/get_financials_reported" , payload , stream = False )
77+
78+
79+ if __name__ == "__main__" :
80+ # 以 FastMCP 的方式启动(根据你项目的 FastMCP 用法调整)
81+ try :
82+ mcp .run ()
83+ except Exception :
84+ # 若 run 名称不同,改为 mcp.serve() 或按项目其他 MCP 启动方式
85+ pass
0 commit comments