futu-stock-mcp-server 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of futu-stock-mcp-server might be problematic. Click here for more details.

@@ -42,13 +42,20 @@ logger.add(
42
42
  format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}"
43
43
  )
44
44
 
45
- # Add console handler
45
+ # Add console handler - output to stderr to avoid polluting MCP JSON communication
46
46
  logger.add(
47
- lambda msg: print(msg),
47
+ sys.stderr,
48
48
  level="INFO",
49
- format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}"
49
+ format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
50
+ colorize=False # Disable colors to avoid ANSI escape sequences
50
51
  )
51
52
 
53
+ # Suppress other library logs that might interfere with MCP communication
54
+ import logging
55
+ logging.getLogger().setLevel(logging.WARNING) # Suppress INFO logs from other libraries
56
+ logging.getLogger("mcp").setLevel(logging.WARNING) # Suppress MCP internal logs
57
+ logging.getLogger("futu").setLevel(logging.WARNING) # Suppress Futu API logs
58
+
52
59
  logger.info(f"Starting server with log directory: {log_dir}")
53
60
 
54
61
  # PID file path
@@ -167,15 +174,24 @@ def signal_handler(signum, frame):
167
174
  """Handle process signals"""
168
175
  global _is_shutting_down
169
176
  if _is_shutting_down:
170
- return
177
+ logger.info("Already shutting down, forcing exit...")
178
+ os._exit(1)
171
179
 
172
180
  # 只处理 SIGINT 和 SIGTERM
173
181
  if signum not in (signal.SIGINT, signal.SIGTERM):
174
182
  return
175
183
 
176
184
  logger.info(f"Received signal {signum}, cleaning up...")
177
- cleanup_all()
178
- sys.exit(0)
185
+ _is_shutting_down = True
186
+
187
+ try:
188
+ cleanup_all()
189
+ logger.info("Cleanup completed, exiting...")
190
+ except Exception as e:
191
+ logger.error(f"Error during cleanup: {e}")
192
+ finally:
193
+ # 强制退出,确保进程能够终止
194
+ os._exit(0)
179
195
 
180
196
  # Register cleanup functions
181
197
  atexit.register(cleanup_all)
@@ -1438,8 +1454,13 @@ async def get_current_time() -> Dict[str, Any]:
1438
1454
  'timezone': datetime.now().astimezone().tzname()
1439
1455
  }
1440
1456
 
1441
- if __name__ == "__main__":
1457
+ def main():
1458
+ """Main entry point for the futu-mcp-server command."""
1442
1459
  try:
1460
+ # Ensure no color output in MCP mode
1461
+ os.environ['NO_COLOR'] = '1'
1462
+ os.environ['TERM'] = 'dumb'
1463
+
1443
1464
  # 清理旧的进程和文件
1444
1465
  cleanup_stale_processes()
1445
1466
 
@@ -1457,19 +1478,25 @@ if __name__ == "__main__":
1457
1478
  if init_futu_connection():
1458
1479
  logger.info("Successfully initialized Futu connection")
1459
1480
  logger.info("Starting MCP server in stdio mode...")
1481
+ logger.info("Press Ctrl+C to stop the server")
1460
1482
  try:
1461
1483
  mcp.run(transport='stdio')
1462
1484
  except KeyboardInterrupt:
1463
1485
  logger.info("Received keyboard interrupt, shutting down...")
1464
- sys.exit(0)
1486
+ cleanup_all()
1487
+ os._exit(0)
1465
1488
  except Exception as e:
1466
1489
  logger.error(f"Error running server: {str(e)}")
1467
- sys.exit(1)
1490
+ cleanup_all()
1491
+ os._exit(1)
1468
1492
  else:
1469
1493
  logger.error("Failed to initialize Futu connection. Server will not start.")
1470
- sys.exit(1)
1494
+ os._exit(1)
1471
1495
  except Exception as e:
1472
1496
  logger.error(f"Error starting server: {str(e)}")
1473
1497
  sys.exit(1)
1474
1498
  finally:
1475
- cleanup_all()
1499
+ cleanup_all()
1500
+
1501
+ if __name__ == "__main__":
1502
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: futu-stock-mcp-server
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: A Model Context Protocol (MCP) server for accessing Futu OpenAPI functionality
5
5
  Project-URL: Homepage, https://github.com/shuizhengqi1/futu-stock-mcp-server
6
6
  Project-URL: Documentation, https://github.com/shuizhengqi1/futu-stock-mcp-server#readme
@@ -40,6 +40,8 @@ Requires-Dist: pytest-asyncio; extra == 'dev'
40
40
  Requires-Dist: ruff; extra == 'dev'
41
41
  Description-Content-Type: text/markdown
42
42
 
43
+ [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/shuizhengqi1-futu-stocp-mcp-server-badge.png)](https://mseep.ai/app/shuizhengqi1-futu-stocp-mcp-server)
44
+
43
45
  # Futu Stock MCP Server
44
46
 
45
47
  [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org)
@@ -101,16 +103,25 @@ Description-Content-Type: text/markdown
101
103
 
102
104
  ## 🚀 快速开始
103
105
 
104
- ### 方式一:通过 PyPI 安装(推荐)
106
+ ### 方式一:通过 pipx 安装(推荐)
105
107
 
106
108
  ```bash
109
+ # 安装 pipx(如果还没有安装)
110
+ brew install pipx # macOS
111
+ # 或者 pip install --user pipx # 其他系统
112
+
107
113
  # 安装包
108
- pip install futu-stock-mcp-server
114
+ pipx install futu-stock-mcp-server
109
115
 
110
116
  # 运行服务器
111
117
  futu-mcp-server
112
118
  ```
113
119
 
120
+ > **为什么使用 pipx?**
121
+ > - pipx 专门用于安装 Python 应用程序到全局环境
122
+ > - 自动管理独立的虚拟环境,避免依赖冲突
123
+ > - 命令直接可用,无需激活虚拟环境
124
+
114
125
  ### 方式二:通过 Docker 运行
115
126
 
116
127
  ```bash
@@ -216,22 +227,61 @@ Run formatting:
216
227
  ruff format .
217
228
  ```
218
229
 
219
- ## Usage
230
+ ## 🔧 MCP Server 配置
220
231
 
221
- 1. Start the server:
222
- ```bash
223
- python -m futu_stock_mcp_server.server
232
+ ### Claude Desktop 中配置
233
+
234
+ 1. **找到配置文件位置**:
235
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
236
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
237
+
238
+ 2. **添加服务器配置**:
239
+ ```json
240
+ {
241
+ "mcpServers": {
242
+ "futu-stock": {
243
+ "command": "futu-mcp-server",
244
+ "env": {
245
+ "FUTU_HOST": "127.0.0.1",
246
+ "FUTU_PORT": "11111"
247
+ }
248
+ }
249
+ }
250
+ }
251
+ ```
252
+
253
+ 3. **故障排除配置**:
254
+ 如果上述配置不工作,可以尝试使用完整路径:
255
+ ```json
256
+ {
257
+ "mcpServers": {
258
+ "futu-stock": {
259
+ "command": "/Users/your-username/.local/bin/futu-mcp-server",
260
+ "env": {
261
+ "FUTU_HOST": "127.0.0.1",
262
+ "FUTU_PORT": "11111"
263
+ }
264
+ }
265
+ }
266
+ }
224
267
  ```
225
268
 
226
- 2. Connect to the server using an MCP client:
269
+ > **提示**:使用 `which futu-mcp-server` 命令查看完整路径
270
+
271
+ ### 在其他 MCP 客户端中配置
272
+
273
+ #### 使用 Python MCP 客户端
227
274
  ```python
228
275
  from mcp import ClientSession, StdioServerParameters
229
276
  from mcp.client.stdio import stdio_client
230
277
 
231
278
  async def main():
232
279
  server_params = StdioServerParameters(
233
- command="python",
234
- args=["src/server.py"]
280
+ command="futu-mcp-server",
281
+ env={
282
+ "FUTU_HOST": "127.0.0.1",
283
+ "FUTU_PORT": "11111"
284
+ }
235
285
  )
236
286
 
237
287
  async with stdio_client(server_params) as (read, write):
@@ -241,7 +291,123 @@ async def main():
241
291
 
242
292
  # List available tools
243
293
  tools = await session.list_tools()
294
+ print("Available tools:", [tool.name for tool in tools.tools])
295
+ ```
244
296
 
297
+ #### 使用 Node.js MCP 客户端
298
+ ```javascript
299
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
300
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
301
+
302
+ const transport = new StdioClientTransport({
303
+ command: "futu-mcp-server",
304
+ env: {
305
+ FUTU_HOST: "127.0.0.1",
306
+ FUTU_PORT: "11111"
307
+ }
308
+ });
309
+
310
+ const client = new Client({
311
+ name: "futu-stock-client",
312
+ version: "1.0.0"
313
+ }, {
314
+ capabilities: {}
315
+ });
316
+
317
+ await client.connect(transport);
318
+ ```
319
+
320
+ ## 📋 使用方法
321
+
322
+ ### 1. 启动服务器(独立运行)
323
+ ```bash
324
+ # 通过 pip 安装后
325
+ futu-mcp-server
326
+
327
+ # 或从源码运行
328
+ python -m futu_stock_mcp_server.server
329
+ ```
330
+
331
+ ### 2. 环境变量配置
332
+ 创建 `.env` 文件或设置环境变量:
333
+ ```bash
334
+ FUTU_HOST=127.0.0.1
335
+ FUTU_PORT=11111
336
+ LOG_LEVEL=INFO
337
+ ```
338
+
339
+ ### 3. 验证连接
340
+ 启动服务器后,你应该看到类似的日志:
341
+ ```
342
+ 2024-10-02 14:20:52 | INFO | Initializing Futu connection...
343
+ 2024-10-02 14:20:52 | INFO | Successfully initialized Futu connection
344
+ 2024-10-02 14:20:52 | INFO | Starting MCP server in stdio mode...
345
+ 2024-10-02 14:20:52 | INFO | Press Ctrl+C to stop the server
346
+ ```
347
+
348
+ ### 4. 在 AI 工具中使用
349
+ 配置完成后,重启 Claude Desktop 或其他 MCP 客户端,你就可以:
350
+ - 查询股票实时行情
351
+ - 获取历史K线数据
352
+ - 订阅股票数据推送
353
+ - 查询账户信息
354
+ - 执行交易操作(需要交易权限)
355
+
356
+ ## 🔧 故障排除
357
+
358
+ ### 常见问题
359
+
360
+ #### 1. 命令 `futu-mcp-server` 找不到
361
+ ```bash
362
+ # 确保已正确安装
363
+ pipx install futu-stock-mcp-server
364
+
365
+ # 检查命令是否可用
366
+ which futu-mcp-server
367
+
368
+ # 如果还是找不到,检查 PATH
369
+ echo $PATH | grep -o '[^:]*\.local/bin[^:]*'
370
+ ```
371
+
372
+ #### 2. Ctrl+C 无法退出服务器
373
+ - 新版本已修复此问题
374
+ - 如果仍然遇到,可以使用 `kill -9 <pid>` 强制终止
375
+
376
+ #### 3. 连接富途 OpenD 失败
377
+ ```bash
378
+ # 检查 OpenD 是否运行
379
+ netstat -an | grep 11111
380
+
381
+ # 检查环境变量
382
+ echo $FUTU_HOST
383
+ echo $FUTU_PORT
384
+ ```
385
+
386
+ #### 4. Claude Desktop 无法识别服务器
387
+ - 确保配置文件路径正确
388
+ - 检查 JSON 格式是否有效
389
+ - 重启 Claude Desktop
390
+ - 查看 Claude Desktop 的日志文件
391
+
392
+ #### 5. 权限问题
393
+ ```bash
394
+ # 确保有执行权限
395
+ chmod +x ~/.local/bin/futu-mcp-server
396
+
397
+ # 或者使用完整路径
398
+ python -m futu_stock_mcp_server.server
399
+ ```
400
+
401
+ ### 日志调试
402
+ 启用详细日志:
403
+ ```bash
404
+ export LOG_LEVEL=DEBUG
405
+ futu-mcp-server
406
+ ```
407
+
408
+ 日志文件位置:`./logs/futu_server.log`
409
+ tools = await session.list_tools()
410
+
245
411
  # Call a tool
246
412
  result = await session.call_tool(
247
413
  "get_stock_quote",
@@ -0,0 +1,7 @@
1
+ futu_stock_mcp_server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ futu_stock_mcp_server/server.py,sha256=xFtYbURXhj0DOkbCFgwHDKHCAATWlSxdBZudrWsodVc,52810
3
+ futu_stock_mcp_server-0.1.2.dist-info/METADATA,sha256=CmSaX6UUSExUdbci62zSZER2udDlV6Fqfqd3SSYHSlg,20453
4
+ futu_stock_mcp_server-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
+ futu_stock_mcp_server-0.1.2.dist-info/entry_points.txt,sha256=GAdKqPJD9dJ_fRA3e3m0NRia0elN5OcjEeAI30vOcIM,70
6
+ futu_stock_mcp_server-0.1.2.dist-info/licenses/LICENSE,sha256=XQBSQkjjpkymu_uLdyis4oNynV60VH1X7nS16uwM6g0,1069
7
+ futu_stock_mcp_server-0.1.2.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Futu Stock MCP Server
3
+ Copyright (c) 2024 yanghengxing
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,7 +0,0 @@
1
- futu_stock_mcp_server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- futu_stock_mcp_server/server.py,sha256=UcP4esdCD2BlPhsdok0OrhBu_ipGnTaI1VUtGAI_-pY,51723
3
- futu_stock_mcp_server-0.1.0.dist-info/METADATA,sha256=QEbY7SIHGOZzsKTzQmayzDkvXd2VkhTrELHKsxT5KT4,16529
4
- futu_stock_mcp_server-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
- futu_stock_mcp_server-0.1.0.dist-info/entry_points.txt,sha256=GAdKqPJD9dJ_fRA3e3m0NRia0elN5OcjEeAI30vOcIM,70
6
- futu_stock_mcp_server-0.1.0.dist-info/licenses/LICENSE,sha256=0sCjXbZOqpxlrCLnRTr9M9mNvvltzqUqzyK8d42nMN0,1078
7
- futu_stock_mcp_server-0.1.0.dist-info/RECORD,,