futu-stock-mcp-server 0.1.0__tar.gz → 0.1.1__tar.gz

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.

@@ -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,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.1
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
@@ -216,22 +216,75 @@ Run formatting:
216
216
  ruff format .
217
217
  ```
218
218
 
219
- ## Usage
219
+ ## 🔧 MCP Server 配置
220
220
 
221
- 1. Start the server:
222
- ```bash
223
- python -m futu_stock_mcp_server.server
221
+ ### Claude Desktop 中配置
222
+
223
+ 1. **找到配置文件位置**:
224
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
225
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
226
+
227
+ 2. **添加服务器配置**:
228
+ ```json
229
+ {
230
+ "mcpServers": {
231
+ "futu-stock": {
232
+ "command": "futu-mcp-server",
233
+ "env": {
234
+ "FUTU_HOST": "127.0.0.1",
235
+ "FUTU_PORT": "11111"
236
+ }
237
+ }
238
+ }
239
+ }
224
240
  ```
225
241
 
226
- 2. Connect to the server using an MCP client:
242
+ 3. **如果使用虚拟环境或从源码运行**:
243
+ ```json
244
+ {
245
+ "mcpServers": {
246
+ "futu-stock": {
247
+ "command": "/path/to/your/venv/bin/futu-mcp-server",
248
+ "env": {
249
+ "FUTU_HOST": "127.0.0.1",
250
+ "FUTU_PORT": "11111"
251
+ }
252
+ }
253
+ }
254
+ }
255
+ ```
256
+
257
+ 或者使用 Python 模块方式:
258
+ ```json
259
+ {
260
+ "mcpServers": {
261
+ "futu-stock": {
262
+ "command": "python",
263
+ "args": ["-m", "futu_stock_mcp_server.server"],
264
+ "cwd": "/path/to/futu-stock-mcp-server",
265
+ "env": {
266
+ "FUTU_HOST": "127.0.0.1",
267
+ "FUTU_PORT": "11111"
268
+ }
269
+ }
270
+ }
271
+ }
272
+ ```
273
+
274
+ ### 在其他 MCP 客户端中配置
275
+
276
+ #### 使用 Python MCP 客户端
227
277
  ```python
228
278
  from mcp import ClientSession, StdioServerParameters
229
279
  from mcp.client.stdio import stdio_client
230
280
 
231
281
  async def main():
232
282
  server_params = StdioServerParameters(
233
- command="python",
234
- args=["src/server.py"]
283
+ command="futu-mcp-server",
284
+ env={
285
+ "FUTU_HOST": "127.0.0.1",
286
+ "FUTU_PORT": "11111"
287
+ }
235
288
  )
236
289
 
237
290
  async with stdio_client(server_params) as (read, write):
@@ -241,7 +294,120 @@ async def main():
241
294
 
242
295
  # List available tools
243
296
  tools = await session.list_tools()
297
+ print("Available tools:", [tool.name for tool in tools.tools])
298
+ ```
244
299
 
300
+ #### 使用 Node.js MCP 客户端
301
+ ```javascript
302
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
303
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
304
+
305
+ const transport = new StdioClientTransport({
306
+ command: "futu-mcp-server",
307
+ env: {
308
+ FUTU_HOST: "127.0.0.1",
309
+ FUTU_PORT: "11111"
310
+ }
311
+ });
312
+
313
+ const client = new Client({
314
+ name: "futu-stock-client",
315
+ version: "1.0.0"
316
+ }, {
317
+ capabilities: {}
318
+ });
319
+
320
+ await client.connect(transport);
321
+ ```
322
+
323
+ ## 📋 使用方法
324
+
325
+ ### 1. 启动服务器(独立运行)
326
+ ```bash
327
+ # 通过 pip 安装后
328
+ futu-mcp-server
329
+
330
+ # 或从源码运行
331
+ python -m futu_stock_mcp_server.server
332
+ ```
333
+
334
+ ### 2. 环境变量配置
335
+ 创建 `.env` 文件或设置环境变量:
336
+ ```bash
337
+ FUTU_HOST=127.0.0.1
338
+ FUTU_PORT=11111
339
+ LOG_LEVEL=INFO
340
+ ```
341
+
342
+ ### 3. 验证连接
343
+ 启动服务器后,你应该看到类似的日志:
344
+ ```
345
+ 2024-10-02 14:20:52 | INFO | Initializing Futu connection...
346
+ 2024-10-02 14:20:52 | INFO | Successfully initialized Futu connection
347
+ 2024-10-02 14:20:52 | INFO | Starting MCP server in stdio mode...
348
+ 2024-10-02 14:20:52 | INFO | Press Ctrl+C to stop the server
349
+ ```
350
+
351
+ ### 4. 在 AI 工具中使用
352
+ 配置完成后,重启 Claude Desktop 或其他 MCP 客户端,你就可以:
353
+ - 查询股票实时行情
354
+ - 获取历史K线数据
355
+ - 订阅股票数据推送
356
+ - 查询账户信息
357
+ - 执行交易操作(需要交易权限)
358
+
359
+ ## 🔧 故障排除
360
+
361
+ ### 常见问题
362
+
363
+ #### 1. 命令 `futu-mcp-server` 找不到
364
+ ```bash
365
+ # 确保已正确安装
366
+ pip install futu-stock-mcp-server
367
+
368
+ # 或者检查是否在虚拟环境中
369
+ which futu-mcp-server
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",
@@ -174,22 +174,75 @@ Run formatting:
174
174
  ruff format .
175
175
  ```
176
176
 
177
- ## Usage
177
+ ## 🔧 MCP Server 配置
178
178
 
179
- 1. Start the server:
180
- ```bash
181
- python -m futu_stock_mcp_server.server
179
+ ### Claude Desktop 中配置
180
+
181
+ 1. **找到配置文件位置**:
182
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
183
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
184
+
185
+ 2. **添加服务器配置**:
186
+ ```json
187
+ {
188
+ "mcpServers": {
189
+ "futu-stock": {
190
+ "command": "futu-mcp-server",
191
+ "env": {
192
+ "FUTU_HOST": "127.0.0.1",
193
+ "FUTU_PORT": "11111"
194
+ }
195
+ }
196
+ }
197
+ }
182
198
  ```
183
199
 
184
- 2. Connect to the server using an MCP client:
200
+ 3. **如果使用虚拟环境或从源码运行**:
201
+ ```json
202
+ {
203
+ "mcpServers": {
204
+ "futu-stock": {
205
+ "command": "/path/to/your/venv/bin/futu-mcp-server",
206
+ "env": {
207
+ "FUTU_HOST": "127.0.0.1",
208
+ "FUTU_PORT": "11111"
209
+ }
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ 或者使用 Python 模块方式:
216
+ ```json
217
+ {
218
+ "mcpServers": {
219
+ "futu-stock": {
220
+ "command": "python",
221
+ "args": ["-m", "futu_stock_mcp_server.server"],
222
+ "cwd": "/path/to/futu-stock-mcp-server",
223
+ "env": {
224
+ "FUTU_HOST": "127.0.0.1",
225
+ "FUTU_PORT": "11111"
226
+ }
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ ### 在其他 MCP 客户端中配置
233
+
234
+ #### 使用 Python MCP 客户端
185
235
  ```python
186
236
  from mcp import ClientSession, StdioServerParameters
187
237
  from mcp.client.stdio import stdio_client
188
238
 
189
239
  async def main():
190
240
  server_params = StdioServerParameters(
191
- command="python",
192
- args=["src/server.py"]
241
+ command="futu-mcp-server",
242
+ env={
243
+ "FUTU_HOST": "127.0.0.1",
244
+ "FUTU_PORT": "11111"
245
+ }
193
246
  )
194
247
 
195
248
  async with stdio_client(server_params) as (read, write):
@@ -199,7 +252,120 @@ async def main():
199
252
 
200
253
  # List available tools
201
254
  tools = await session.list_tools()
255
+ print("Available tools:", [tool.name for tool in tools.tools])
256
+ ```
202
257
 
258
+ #### 使用 Node.js MCP 客户端
259
+ ```javascript
260
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
261
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
262
+
263
+ const transport = new StdioClientTransport({
264
+ command: "futu-mcp-server",
265
+ env: {
266
+ FUTU_HOST: "127.0.0.1",
267
+ FUTU_PORT: "11111"
268
+ }
269
+ });
270
+
271
+ const client = new Client({
272
+ name: "futu-stock-client",
273
+ version: "1.0.0"
274
+ }, {
275
+ capabilities: {}
276
+ });
277
+
278
+ await client.connect(transport);
279
+ ```
280
+
281
+ ## 📋 使用方法
282
+
283
+ ### 1. 启动服务器(独立运行)
284
+ ```bash
285
+ # 通过 pip 安装后
286
+ futu-mcp-server
287
+
288
+ # 或从源码运行
289
+ python -m futu_stock_mcp_server.server
290
+ ```
291
+
292
+ ### 2. 环境变量配置
293
+ 创建 `.env` 文件或设置环境变量:
294
+ ```bash
295
+ FUTU_HOST=127.0.0.1
296
+ FUTU_PORT=11111
297
+ LOG_LEVEL=INFO
298
+ ```
299
+
300
+ ### 3. 验证连接
301
+ 启动服务器后,你应该看到类似的日志:
302
+ ```
303
+ 2024-10-02 14:20:52 | INFO | Initializing Futu connection...
304
+ 2024-10-02 14:20:52 | INFO | Successfully initialized Futu connection
305
+ 2024-10-02 14:20:52 | INFO | Starting MCP server in stdio mode...
306
+ 2024-10-02 14:20:52 | INFO | Press Ctrl+C to stop the server
307
+ ```
308
+
309
+ ### 4. 在 AI 工具中使用
310
+ 配置完成后,重启 Claude Desktop 或其他 MCP 客户端,你就可以:
311
+ - 查询股票实时行情
312
+ - 获取历史K线数据
313
+ - 订阅股票数据推送
314
+ - 查询账户信息
315
+ - 执行交易操作(需要交易权限)
316
+
317
+ ## 🔧 故障排除
318
+
319
+ ### 常见问题
320
+
321
+ #### 1. 命令 `futu-mcp-server` 找不到
322
+ ```bash
323
+ # 确保已正确安装
324
+ pip install futu-stock-mcp-server
325
+
326
+ # 或者检查是否在虚拟环境中
327
+ which futu-mcp-server
328
+ ```
329
+
330
+ #### 2. Ctrl+C 无法退出服务器
331
+ - 新版本已修复此问题
332
+ - 如果仍然遇到,可以使用 `kill -9 <pid>` 强制终止
333
+
334
+ #### 3. 连接富途 OpenD 失败
335
+ ```bash
336
+ # 检查 OpenD 是否运行
337
+ netstat -an | grep 11111
338
+
339
+ # 检查环境变量
340
+ echo $FUTU_HOST
341
+ echo $FUTU_PORT
342
+ ```
343
+
344
+ #### 4. Claude Desktop 无法识别服务器
345
+ - 确保配置文件路径正确
346
+ - 检查 JSON 格式是否有效
347
+ - 重启 Claude Desktop
348
+ - 查看 Claude Desktop 的日志文件
349
+
350
+ #### 5. 权限问题
351
+ ```bash
352
+ # 确保有执行权限
353
+ chmod +x ~/.local/bin/futu-mcp-server
354
+
355
+ # 或者使用完整路径
356
+ python -m futu_stock_mcp_server.server
357
+ ```
358
+
359
+ ### 日志调试
360
+ 启用详细日志:
361
+ ```bash
362
+ export LOG_LEVEL=DEBUG
363
+ futu-mcp-server
364
+ ```
365
+
366
+ 日志文件位置:`./logs/futu_server.log`
367
+ tools = await session.list_tools()
368
+
203
369
  # Call a tool
204
370
  result = await session.call_tool(
205
371
  "get_stock_quote",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "futu-stock-mcp-server"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  description = "A Model Context Protocol (MCP) server for accessing Futu OpenAPI functionality"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -167,15 +167,24 @@ def signal_handler(signum, frame):
167
167
  """Handle process signals"""
168
168
  global _is_shutting_down
169
169
  if _is_shutting_down:
170
- return
170
+ logger.info("Already shutting down, forcing exit...")
171
+ os._exit(1)
171
172
 
172
173
  # 只处理 SIGINT 和 SIGTERM
173
174
  if signum not in (signal.SIGINT, signal.SIGTERM):
174
175
  return
175
176
 
176
177
  logger.info(f"Received signal {signum}, cleaning up...")
177
- cleanup_all()
178
- sys.exit(0)
178
+ _is_shutting_down = True
179
+
180
+ try:
181
+ cleanup_all()
182
+ logger.info("Cleanup completed, exiting...")
183
+ except Exception as e:
184
+ logger.error(f"Error during cleanup: {e}")
185
+ finally:
186
+ # 强制退出,确保进程能够终止
187
+ os._exit(0)
179
188
 
180
189
  # Register cleanup functions
181
190
  atexit.register(cleanup_all)
@@ -1438,7 +1447,8 @@ async def get_current_time() -> Dict[str, Any]:
1438
1447
  'timezone': datetime.now().astimezone().tzname()
1439
1448
  }
1440
1449
 
1441
- if __name__ == "__main__":
1450
+ def main():
1451
+ """Main entry point for the futu-mcp-server command."""
1442
1452
  try:
1443
1453
  # 清理旧的进程和文件
1444
1454
  cleanup_stale_processes()
@@ -1457,19 +1467,25 @@ if __name__ == "__main__":
1457
1467
  if init_futu_connection():
1458
1468
  logger.info("Successfully initialized Futu connection")
1459
1469
  logger.info("Starting MCP server in stdio mode...")
1470
+ logger.info("Press Ctrl+C to stop the server")
1460
1471
  try:
1461
1472
  mcp.run(transport='stdio')
1462
1473
  except KeyboardInterrupt:
1463
1474
  logger.info("Received keyboard interrupt, shutting down...")
1464
- sys.exit(0)
1475
+ cleanup_all()
1476
+ os._exit(0)
1465
1477
  except Exception as e:
1466
1478
  logger.error(f"Error running server: {str(e)}")
1467
- sys.exit(1)
1479
+ cleanup_all()
1480
+ os._exit(1)
1468
1481
  else:
1469
1482
  logger.error("Failed to initialize Futu connection. Server will not start.")
1470
- sys.exit(1)
1483
+ os._exit(1)
1471
1484
  except Exception as e:
1472
1485
  logger.error(f"Error starting server: {str(e)}")
1473
1486
  sys.exit(1)
1474
1487
  finally:
1475
- cleanup_all()
1488
+ cleanup_all()
1489
+
1490
+ if __name__ == "__main__":
1491
+ main()