Skip to content

分析当前 MCP 实现是否提供 tools search 功能,目前功能较多,未来每个 tools 将会有更多更详细的说明。类似于 longbridge cli 一样 -h 是看到基础摘要的说明。而 - #53

Open
endless-bot wants to merge 86 commits into
mainfrom
endless/task-7

Conversation

@endless-bot

Copy link
Copy Markdown

🤖 Auto-generated by Endless task #7.

Initiated by: Huacnlee Li Huashun

背景

longbridge-mcp 目前暴露 133 个 MCP tools,AI client 每次使用前需通过 tools/list 获取全量列表才能找到目标工具。当工具数量持续增长时,上下文消耗显著增加,且没有任何机制支持按关键词过滤或分层查阅。

MCP 标准本身只定义了 tools/list(全量列出)和 tools/call(调用),没有内置搜索或分级帮助能力。业界通行做法是将工具发现能力实现为元工具(meta-tools),作为 MCP tools 本身暴露给 AI agent。

本次改动参照 longbridge CLI 的 -h(摘要)/ --help(详情)分层帮助设计,为 MCP server 引入完整的工具发现与搜索机制。

摘要

  • 解决的问题:AI agent 面对 136 个工具时,无法高效定位目标工具,上下文消耗大
  • 做了什么:
    • 新增 src/tools/meta.rs,实现三个无需鉴权的元工具
    • src/tools/mod.rs 注册三个新工具到 #[tool_router] impl
    • 在 zh-CN / zh-HK locale 文件中为三个新工具添加翻译条目
    • 更新 server.json 中的 toolCount(133→136)和分类统计
  • 为什么这样做:
    • 元工具直接复用 list_tools() 静态注册信息,无任何外部 I/O,无需 Bearer token,实现最简
    • 关键词过滤用大小写不敏感子串匹配,覆盖工具名称和描述,无需维护静态分类表
    • 遵循现有 now 工具模式(sync 逻辑 + async 包装),不引入新外部依赖
  • 如何验证:
    1. cargo build — 无编译错误
    2. cargo clippy --all-features --all-targets — 零 warning
    3. cargo testlocales_match_live_tool_schema 测试验证 locale 完整性
    4. 启动 server 后调用 tools_list({}) 返回 136 个工具摘要,tools_search({"query":"order"}) 返回订单相关工具,tools_describe({"name":"depth"}) 返回完整参数文档

修改

文件 改动内容
src/tools/meta.rs 新增文件:tools_listtools_searchtools_describe 三个函数的实现
src/tools/mod.rs 添加 mod meta; 声明;在 #[tool_router] impl 中注册三个新工具方法
locales/zh-CN/tools.json 新增 tools_listtools_searchtools_describe 的简体中文翻译条目
locales/zh-HK/tools.json 新增 tools_listtools_searchtools_describe 的繁体中文翻译条目
server.json toolCount 133→136,utility 分类计数 1→4,三处本地化描述更新

关键决策

元工具不调用 extract_context:三个新工具只访问本地工具注册信息,不需要 Bearer token。这是有意为之——工具发现本身是公开信息,要求认证会增加 AI agent 的使用摩擦。

通过现有 list_tools() 获取注册信息:未引入新的全局状态或缓存,list_tools() 本身已经高效(Lazy<Vec<Tool>>),重复调用无开销。

description 截断到 ~120 字符(词边界)tools_list 作为 -h 等价物返回摘要,过长描述会破坏可读性。完整描述通过 tools_search / tools_describe 获取。

huacnlee and others added 30 commits April 16, 2026 17:09
## Summary

- Add a 5-second force-exit fallback in `shutdown_signal()` so
SSE/streaming connections that linger indefinitely don't block port
reuse when restarting the server
- Reduce graceful shutdown timeout from 10s to 5s to align with the
force-exit window

## Test plan

- [ ] Start the server and connect an SSE client
- [ ] Send SIGINT — verify the server exits within 5 seconds even with
an active SSE connection
- [ ] Verify a new instance can bind to the same port immediately after

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary

- Add `GET /mcp/tools.json` endpoint (no auth required) that returns all
registered MCP tool names and descriptions as JSON
- Expose `tool_router` with `pub(crate)` visibility via
`#[tool_router(vis = "pub(crate)")]`
- Add `tools::list_tools()` public helper backed by
`ToolRouter::list_all()`
- Log tool count and URL on server startup

## Test plan

- [ ] Start server and verify startup log shows `tools available count=N
url=.../mcp/tools.json`
- [ ] `curl http://localhost:8000/mcp/tools.json` returns JSON with
`tools` array containing name/description for each tool

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Config always enables overnight trading
- Remove LONGBRIDGE_LANGUAGE (determined by Accept-Language header)
- Remove LONGBRIDGE_ENABLE_OVERNIGHT (always on)
- Remove RUST_LOG from README
- McpContext bundles token + language, methods create_config/create_http_client
- Language from Accept-Language header sets SDK Config.language
- enable_overnight always on
- Single struct param makes future extensions backward-compatible
…emium, statement_list, and security_list

- financial_report: add required `kind` param (IS/BS/CF/ALL, default ALL)
- valuation: add required `indicator` (default pe) and `range` (default 1) params
- ah_premium: add `AhPremiumParam` with `period` and `count`; map to `line_type`/`line_num`
- statement_list: replace broken HTTP endpoint with SDK AssetContext.statements()
- security_list: clarify that `category` must be "Overnight" in param doc and tool description
- broker_holding: add period param (rct_1/rct_5/rct_20/rct_60, default rct_1)
- profit_analysis: merge summary + sublist into single response, matching terminal behavior
…trade_sessions, calendar category, alert frequency, and statement sections
hogan-yuan and others added 28 commits April 30, 2026 22:37
…put (#25)

Follow-up to #24 — audit of the 13 typed output schemas against the SDK
source caught **6 places** where the declared shape didn't match what
`tool_json` actually emits, plus one `account_channel` nullability fix.

## Bugs fixed

| Schema | Before (in #24) | After (this PR) | Why |
|---|---|---|---|
| `StockPositionsResponse` | `channels: [...]` | `list: [...]` | SDK
uses `#[serde(rename = "list")]` |
| `FundPositionsResponse` | `channels: [...]` | `list: [...]` | same |
| `StockPositionChannel` | `positions: [...]` | `stock_info: [...]` |
SDK uses `#[serde(rename = "stock_info")]` |
| `FundPositionChannel` | `positions: [...]` | `fund_info: [...]` | SDK
uses `#[serde(rename = "fund_info")]` |
| `StockPositionChannel.account_channel`
`FundPositionChannel.account_channel` | `String` | `Option<String>` |
`to_tool_json` overwrites this field to `null` for privacy regardless of
upstream value |
| `MarketTemperatureResponse.updated_at` | — | `timestamp` | The SDK
field name is `timestamp`; `alias = "updated_at"` only takes effect on
**deserialize**, not serialize |
| `HistoryMarketTemperatureResponse.records` | `records: [...]` | `list:
[...]` | SDK uses `#[serde(rename = "list")]` |

## Audit method

Cross-referenced each declared schema against:
1. The SDK type source (`longbridge::trade::types::*`,
`longbridge::quote::types::*`, etc.) — pulled directly from
`~/.cargo/git/checkouts/openapi-*/rust/src/`
2. The `serde_utils::*` custom serializers (decimals stringify, enums
via `collect_str`, RFC3339 timestamps, `Option` nullability rules)
3. The local `to_tool_json` transform (snake_case + `_at`-i64-to-RFC3339
+ `counter_id` → `symbol` rename + `aaid` / `account_channel` → `null`)

## Verified clean (no changes needed)

- `OrderIdResponse` (`{order_id}`)
- `StatementUrlResponse` (`{url}`)
- `EstimateMaxQtyResponse` (`{cash_max_qty, margin_max_qty}`)
- `MarginRatioResponse` (`{im_factor, mm_factor, fm_factor}`)
- `DepthResponse` (`{bids, asks}` with `{position, price, volume,
order_num}` per level)
- `BrokersResponse` (`{bid_brokers, ask_brokers}`)
- `CapitalDistributionResponse` (`{timestamp, capital_in, capital_out}`)
- `TradingDaysResponse` (`{trading_days, half_trading_days}`)
- `OrderDetailResponse` (25 documented fields; commission/fee tail
covered by JSON Schema's default `additionalProperties: true`)

## Test plan

- [x] `cargo +nightly fmt` clean
- [x] `cargo build` clean
- [x] `cargo clippy --all-features --all-targets` — 0 warnings
- [x] `cargo test` — 48 passed
- [x] Live `GET /mcp/tools.json` confirms each fixed schema now emits
the corrected field names (`list`, `stock_info`, `fund_info`,
`timestamp`)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary

- Reorder `FinanceCalendarParam` fields: `category` first (primary
selector), then date range, then optional `market`
- Expand `category` field doc with plain-language descriptions for each
value:
  - `report` — earnings reports (includes financial statements)
  - `dividend` — dividend announcements
  - `split` — stock splits **and** reverse splits (share consolidations)
  - `ipo` — upcoming IPO listings
- `macrodata` — macro economic data releases (CPI, NFP, rate decisions,
etc.)
  - `closed` — market closure days
- Remove deprecated `financial` from category list (it's included
automatically under `report`)
- Clarify `market` is optional and list all supported codes: HK, US, CN,
SG, JP, UK, DE, AU
- Update tool-level description in `mod.rs` to reflect the same
information

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
… server version from Cargo.pkg (#28)

Closes longbridge/developers#953.

## Root cause

v0.1.11 added `outputSchema` declarations to 13 tools but never updated
the tool response format. MCP spec §tool-result states:

> A tool that declares an `outputSchema` **MUST** return
`structuredContent` in its response.

`tool_result()` was returning only `content: [{ type: "text", text:
"..." }]` with `structuredContent` absent. Clients that validate this
requirement — including Claude Code — raised:

```
Tool stock_positions has an output schema but did not return structured content
```

A second unrelated issue was also found during the audit: `initialize`
responses always reported `serverInfo.version = "0.1.6"` because the
`#[tool_handler]` macro had a hardcoded `version = "0.1.6"` attribute
that was never bumped.

## What changed (`src/tools/mod.rs` only, 9 lines)

### Fix 1 — populate `structured_content` on every tool response

```rust
// before
fn tool_result(json: String) -> CallToolResult {
    CallToolResult::success(vec![Content::text(json)])
}

// after
fn tool_result(json: String) -> CallToolResult {
    let structured = serde_json::from_str::<serde_json::Value>(&json).ok();
    let mut result = CallToolResult::success(vec![Content::text(json)]);
    result.structured_content = structured;
    result
}
```

Text content is preserved (backwards-compatible). `structuredContent` is
now always populated for every tool that goes through `tool_result()`,
so the invariant holds for all 13 tools with `outputSchema` and any
future ones.

### Fix 2 — remove hardcoded server version

```rust
// before
#[tool_handler(name = "longbridge-mcp", version = "0.1.6", instructions = "...")]

// after
#[tool_handler(name = "longbridge-mcp", instructions = "...")]
```

When `name` is present but `version` is absent the rmcp macro falls
through to its built-in `env!("CARGO_PKG_VERSION")` path, so
`serverInfo.version` in `initialize` responses now automatically matches
`Cargo.toml`.

## Test plan

- [x] `cargo +nightly fmt` clean
- [x] `cargo build` clean
- [x] `cargo clippy --all-features --all-targets` — 0 warnings
- [x] `cargo test` — 48 passed
- [x] Live comparison: local returns `structuredContent`, prod does not
- [x] `serverInfo.version` in `initialize` now shows `0.1.11`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GitHub username changed from `wuxsoft` to `hogan-yuan`. Updates
`glama.json` so the new username has admin access to the Glama listing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Glama's build system invokes servers via `mcp-proxy --` which expects a
**stdio** MCP process. Since `longbridge-mcp` is an HTTP server, this
script bridges the gap:

1. Starts the HTTP server in the background
2. Waits up to 10 s for `/health` to respond  
3. `exec`s `mcp-proxy http://localhost:8000/mcp` — replacing itself with
an stdio↔HTTP proxy

Data flow inside Glama's container:
```
Glama scanner → [stdio] → outer mcp-proxy -- glama-start.sh
                                               └→ [stdio] → inner mcp-proxy (exec'd)
                                                              └→ [HTTP] → longbridge-mcp :8000
```

**Glama config update needed:**  
CMD arguments: `["/app/scripts/glama-start.sh"]`  
Build steps: add `chmod +x /app/scripts/glama-start.sh` at the end

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## What

Adds a `--stdio` transport mode so Glama's build system can scan the
server's tool definitions without needing a real OAuth token.

```
# New flag — does not affect the existing HTTP server in any way
longbridge-mcp --stdio
```

When `--stdio` is passed the binary:
1. Listens for MCP JSON-RPC messages on **stdin**
2. Responds on **stdout** (logs go to **stderr**, keeping stdout clean)
3. Holds the server alive via `RunningService::waiting()` until stdin
closes

`tools/list` works fully without credentials. `tools/call` returns auth
errors for any upstream calls that require a Longbridge token — which is
expected and acceptable for a directory scanner.

## Why

Glama's build system wraps every server with `mcp-proxy --`, which
expects a **stdio** MCP process. Our server is an HTTP server, so the
wrapper always timed out or errored. This flag bridges that gap with
minimal code (~20 lines in `main.rs`).

## What doesn't change

The existing HTTP server path is completely untouched — no behaviour
change when running without `--stdio`.

## Files changed

| File | Change |
|---|---|
| `src/main.rs` | `--stdio` flag → rmcp `AsyncRwTransport` over
stdin/stdout; logs explicitly routed to stderr |
| `Cargo.toml` | enable rmcp `transport-io` feature |
| `scripts/glama-start.sh` | simplified: `exec longbridge-mcp --stdio` |

## Test plan

- [x] `cargo build` clean
- [x] `cargo clippy --all-features --all-targets` — 0 warnings  
- [x] `cargo test` — 48 passed
- [x] HTTP mode: `--bind 0.0.0.0:8001` starts normally, `/health` 200,
`/mcp/tools.json` 109 tools
- [x] stdio mode: `initialize` + `tools/list` returns 109 tools with
title / annotations / outputSchema all present; stdout is pure JSON-RPC,
logs on stderr

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ls (#34)

## Summary

- **Search**: `news_search`, `topic_search` — search news articles and
community topics by keyword
- **Fundamental**: `financial_statement`, `financial_report_latest`,
`valuation_rank`, `analyst_estimates`, `institution_rating_history`,
`institution_rating_industry_rank`
- **Trade / Asset**: `short_margin`, `holding_period`, `trade_info`
- **ATM**: `bank_cards`, `withdrawals`, `deposits`
- **IPO**: `ipo_subscriptions`, `ipo_calendar`, `ipo_listed`,
`ipo_detail`, `ipo_orders`, `ipo_order_detail`, `ipo_profit_loss`

Ports 20 new tools from [longbridge-terminal PR
#185](longbridge/longbridge-terminal#185). New
sub-modules `atm.rs`, `ipo.rs`, and `search.rs` added; `fundamental.rs`
and `trade.rs` extended.

## Test plan

- [ ] `cargo build` passes
- [ ] `cargo clippy --all-features --all-targets` zero warnings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary

- **version**: bump `Cargo.toml` and `server.json` to `0.2.1`
- **calendar**: switch `finance_calendar` to `http_get_tool_unix` —
converts `list[].infos[].datetime` from unix to ISO 8601
- **ipo**: convert `ipo_calendar` `timestamp` field to ISO 8601
- **portfolio**: add `start_time` to `profit_analysis` unix path
conversion (was missing alongside `end_time`)
- **mod**: fix `static_info` description (`name` → `name_cn, name_en`)
and `depth` description (`bid/ask` → `asks/bids`)

## Test plan

- [x] `cargo build` passes
- [x] Full 128-tool test suite: PASS 95 / WARN 2 / SKIP 31 / FAIL 0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary

Ref longbridge/developers#982

- 删除 `AnalystEstimatesParam` struct
- 删除 `fundamental::analyst_estimates` 函数
- 删除对应的 MCP tool `analyst_estimates`

## Test plan

- [ ] 确认编译无错误
- [ ] 确认其他 MCP tools 功能不受影响

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…, fix registry link

- locales: remove analyst_estimates from zh-CN and zh-HK (tool removed in #37)
- README/server.json: 110 → 127 tools, add IPO/Search/ATM categories
- README: fix MCP Registry badge href (404 → /versions endpoint)
- server.json: update localizedDescriptions and toolCategories

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…olation (#38)

## Summary

- Switch MCP server to stateless mode to fix session-not-found errors on
multi-instance deployments
- Fix `structuredContent` type violation that caused Cursor to reject
array tool responses

## Fix 1 — Stateless mode (`src/auth/mod.rs`)

**Root cause**: The server is designed for stateless multi-instance
deployment, but was using `stateful_mode: true` (the rmcp default) with
an in-memory `LocalSessionManager`. Under a load balancer, sessions
created on Instance A are unknown to Instance B, triggering a failure
chain in Cursor:

1. POST with cached `Mcp-Session-Id` → **404 Session not found**
(session lives on another instance)
2. Cursor falls back to legacy SSE V1 protocol (GET without session ID)
→ **400 Session ID is required**

Claude Code and Codex are unaffected because they re-initialize on every
connection rather than caching session IDs.

**Fix**: Replace `LocalSessionManager` with `NeverSessionManager` and
set `stateful_mode(false)`. The `Mcp-Session-Id` header is completely
ignored in stateless mode; each POST is handled independently with no
session state.

## Fix 2 — `structuredContent` type (`src/tools/mod.rs`)

**Root cause**: `tool_result` unconditionally assigned the parsed JSON
value to `structured_content`. Tools returning `Vec<T>` (e.g. `quote`,
`static_info`, `trades`, `candlesticks`, `participants`) serialize to a
JSON array. The MCP spec requires `structuredContent` to be a JSON
**object** (record); Cursor validates this strictly and rejects array
values with:

```
Invalid input: expected record, received array
```

**Fix**: Added `.filter(serde_json::Value::is_object)` so
`structured_content` is only set for JSON object responses. Array
responses leave it as `None`, which is valid per spec. The fix is
centralized in `tool_result` and covers all tools.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
)

## Summary

- Add `extra_headers: Vec<(String, String)>` to `McpContext` to carry
all incoming request headers
- In `create_http_client()`, chain `.header()` calls to attach extra
headers to every upstream REST request
- In `extract_context()`, collect all headers from the MCP request
(skipping non-UTF-8 values)
- Add a `tracing::debug!` log line to verify forwarded headers during
development

## Notes

- `longbridge::Config` in the current dependency version (`485cf02`) has
no `header()` method, so WebSocket-based SDK clients (`QuoteContext`,
`TradeContext`) do not yet receive the extra headers — only
`HttpClient`-based REST calls are affected
- The MCP `Accept: application/json, text/event-stream` header will be
forwarded to upstream; if upstream returns 406, filtering out the
`accept` header is the minimal fix needed

## Test plan

- [ ] Start server with `RUST_LOG=longbridge_mcp=debug`
- [ ] Send a request with a custom header (`X-My-Custom: hello`) plus
`Accept: application/json, text/event-stream`
- [ ] Confirm the debug log shows the custom header in the forwarded
list

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary

- Bump `Cargo.toml` and `server.json` (version + OCI identifier) to
`0.2.3`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary

`mcp-publisher publish` rejects descriptions > 100 characters. Removes
"real-time " (10 chars) to bring it within limit (104 → 94 chars).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…er_id lookup (#44)

## Summary

- Replaces the runtime-initialized `OnceLock<HashSet>` with a
compile-time `phf::Set` generated by `build.rs` via `phf_codegen`,
eliminating startup initialization cost
- Merges ETF, IX, and WT counter_id lists (25k+ entries) into a single
`SPECIAL_COUNTER_IDS` set embedded in the binary
- Unifies `symbol_to_counter_id` to resolve all special types
(ETF/IX/WT) via set lookup, adds leading-dot handling for US index
symbols and leading-zero stripping for numeric codes
- Keeps `index_symbol_to_counter_id` as a compatibility alias delegating
to `symbol_to_counter_id`

## Test plan

- [ ] `cargo test` passes (54 tests including new `ix_hk_via_set`,
`ix_us_leading_dot`, `wt_hk_via_set`, `index_alias`)
- [ ] `SPY.US` → `ETF/US/SPY`, `HSI.HK` → `IX/HK/HSI`, `10005.HK` →
`WT/HK/10005`, `TSLA.US` → `ST/US/TSLA`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary

Implements 6 new tools from `docs/stock-detail-mcp-prompt.md`:

| Tool | Path |
|------|------|
| `business_segments` | `GET /v1/quote/fundamentals/business-segments` |
| `business_segments_history` | `GET
/v1/quote/fundamentals/business-segments/history` |
| `institutional_views` | `GET /v1/quote/ratings/institutional` |
| `industry_rank` | `GET /v1/quote/industry/rank` |
| `industry_peers` | `GET /v1/quote/industries/peers` |
| `financial_report_snapshot` | `GET
/v1/quote/financials/earnings-snapshot` |

### Details
- `counter.rs`: added `bk_symbol_to_counter` / `bk_counter_to_symbol`
for `IN00xxx.US ↔ BK/US/IN00xxx` conversion
- `industry_rank`: recursively converts BK `counter_id` fields to
`symbol` in response
- `locales`: zh-CN and zh-HK entries added for all 6 tools
- `cargo test locales_match_live_tool_schema` ✅

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
#47)

## Summary

Improves all 133 tool `description` strings to raise Glama
`quality_grade` from B to A.

### Changes
- Every "Get X" description now lists key return fields with example
values
- Parameter doc comments clarified with format examples (e.g.
`"AAPL.US"`, `"YYYYMMDD"`)
- Enum parameter values documented with defaults

### Verification
- `cargo build` ✅
- `cargo clippy --all-features --all-targets -- -D warnings` ✅ (0
warnings)
- `cargo test locales_match_live_tool_schema` ✅

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary

Improves all 133 Chinese tool descriptions in zh-CN and zh-HK locale
files.

- Average description length: **36 → 90 chars**
- Added return field names in Chinese (最新价, 成交量, 除权日, etc.)
- Added parameter examples and constraints
- zh-HK uses consistent Traditional Chinese (繁體)

## Verification
- `cargo test locales_match_live_tool_schema` ✅

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary

- `today_executions` and `history_executions` now include a `side` field
(Buy/Sell) by concurrently fetching the corresponding orders and joining
by `order_id`
- `order_detail` already serializes the full SDK struct, so `history`
(execution records) is automatically included in the response

## Test plan

- [ ] `today_executions` — verify `side` field appears in the result
- [ ] `history_executions` — verify `side` field appears in the result
- [ ] `order_detail` — verify `history` array is present with
status/time/price/quantity/msg

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…json (#51)

## Summary

### New files
- **`data/tools_app_id.json`** — Maps each MCP tool to its `id` in
`open_api_entries.json`. 111/133 tools matched; 22 WebSocket-only
QuoteContext tools have no HTTP endpoint (app_id: null)
- **`data/scopes.json`** — Moved from root to `data/`

### Changes
- **`/mcp/tools.json`** HTTP endpoint now includes `app_id` per tool
(null for WebSocket-only tools)
- **`src/auth/mod.rs`** — Merges `app_id` from `data/tools_app_id.json`
into the tools.json response at startup
- **`data/scopes.json`** — Added `General` scope (id=0) containing 95
tools not covered by scopes 4/6/10/11

### Scope breakdown
| id | name | tools |
|----|------|-------|
| 0 | General | 95 |
| 4 | Watchlist | 5 |
| 6 | Account & Positions | 16 |
| 10 | Trade Order Lookup | 9 |
| 11 | Trade Execution | 8 |

### Note
`app_id` is only returned by the `/mcp/tools.json` HTTP endpoint. The
MCP protocol `tools/list` response does **not** include `app_id`
(verified).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary

- `calc_indexes` tool was returning raw unscaled Greek values that
differ from what the Longbridge app displays
- Apply the same normalization as `longbridge-terminal` CLI before
returning results:
- **theta**: raw value is annualized (×252) → divide by 252 for
per-trading-day value
- **vega**: raw value is scaled by 100 → divide by 100 for
per-1%-IV-change value
- **rho**: raw value is scaled by 100 → divide by 100 for
per-1%-rate-change value

## Test plan

- [ ] Start MCP server locally and call `calc_indexes` with `theta`,
`vega`, `rho` fields
- [ ] Verify returned values match the Longbridge app display (same as
`longbridge calc-index` CLI output)

Fixes longbridge/developers#1014

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…的说明。类似于 longbridge cli 一样 -h 是看到基础摘要的说明。而

Generated by Endless task #7.

Co-authored-by: Huacnlee Li Huashun <huacnlee@longbridge-inc.com>
@hogan-yuan
hogan-yuan force-pushed the main branch 2 times, most recently from 8284189 to c33ad40 Compare July 6, 2026 02:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants