为 MCP 提供 prompts 能力 https://modelcontextprotocol.io/specification/2025-11-25/server/prompts - #55
Open
endless-bot wants to merge 106 commits into
Open
为 MCP 提供 prompts 能力
https://modelcontextprotocol.io/specification/2025-11-25/server/prompts#55endless-bot wants to merge 106 commits into
endless-bot wants to merge 106 commits into
Conversation
## 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
Adds LobeHub MCP badge linking to https://lobehub.com/mcp/longbridge-longbridge-mcp 🤖 Generated with [Claude Code](https://claude.com/claude-code)
## 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>
… top movers, rank (#49) ## Summary Adds 14 new tools across 5 domains, all verified against live API. ### Shareholders | Tool | Endpoint | |------|----------| | `shareholder_top` | `GET /v1/quote/shareholders/top` | | `shareholder_detail` | `GET /v1/quote/shareholders/holding` | ### Valuation Comparison | Tool | Endpoint | |------|----------| | `valuation_comparison` | `GET /v1/quote/compare/valuation` | ### Short Selling | Tool | Endpoint | |------|----------| | `short_positions` | `GET /v1/quote/short-positions/hk` + `/us` (auto-routed) | | `short_trades` | `GET /v1/quote/short-trades/hk` + `/us` (auto-routed) | ### Market Data | Tool | Endpoint | |------|----------| | `top_movers` | `POST /v1/quote/market/stock-events` | | `rank_categories` | `GET /v1/quote/market/rank/categories` | | `rank_list` | `GET /v1/quote/market/rank/list` | ### Stock Screener | Tool | Endpoint | |------|----------| | `screener_recommend_strategies` | `GET /v1/quote/screener/strategies/recommend` | | `screener_user_strategies` | `GET /v1/quote/screener/strategies/mine` | | `screener_strategy` | `GET /v1/quote/screener/strategy` | | `screener_search` | `POST /v1/quote/screener/search` | | `screener_indicators` | `GET /v1/quote/screener/indicators` | Also includes: - `security_list`: remove US-only restriction, add `page`/`count` pagination, support HK/CN/SG ### screener_search design Two modes — AI can use either without calling intermediate tools: - **Mode A** (`strategy_id`): auto-fetches saved strategy and builds filters - **Mode B** (`conditions`): `["pettm:10:20", "roe:15:", "divyld:3:"]` — `filter_` prefix added automatically, `returns[]` auto-built from condition keys - `extra_returns`: display-only columns that don't act as filters (verified: API supports keys in `returns[]` without requiring them in `filters[]`) - `sort_by_key` / `sort_order`: key-name sorting instead of opaque numeric index ### Bugs fixed during review All found by testing against live API: | Fix | Detail | |-----|--------| | `screener_search` key names | ~half the documented keys were wrong (`pb`→`pbmrq`, `ps`→`psttm`, `netprofitgrowthrate`→`netincomegrowthyoy`, `debtassetratio`→`la`, `eps`→`epsttm`, `balance`→`group_balance`, `close`→`prevclose`, `grossmargin`/`currentratio` don't exist) | | `marketcap` unit | unit is 亿 for A/HK, documented explicitly | | `shareholder` position param | missing `position=detail` (was returning entry-level only) | | `rank_list` params | missing `market` and `size` params | | `top_movers` `next_params` | was sending `null`, changed to `{}` | | `top_movers` timestamps | `events[].timestamp` was raw Unix; now converted to RFC3339 via `http_post_tool_unix` | | `shareholder_detail` description | wrong shape (`accum_buy/sell` are in `tradings[]`, not a separate `holding_summary`) | | `short_trades` / `short_positions` rate | `rate` is a decimal ratio (0.4173 = 41.73%), now documented | | `market` optional in Mode A | `screener_search` `market` changed to `Option<String>` | | `security_list` US-only restriction | removed, now supports HK/CN/SG | ### Other - Sync `data/IX.csv` from longbridge-terminal (648 entries) - Remove `app_id` from tools metadata and `tools_app_id.json` - Add Zed `context_servers` config to README - zh-CN + zh-HK locale entries for all new/changed tools ## Test plan - [x] `cargo build` ✅ - [x] `cargo clippy --all-features --all-targets` ✅ (0 warnings) - [x] `cargo test` ✅ (54 passed) - [x] All 14 new tools called against live API ✅ - [x] `screener_search` full parameter coverage: Mode A, Mode B (conditions + extra_returns + sort_by_key + sort_order + page + size), US + HK markets ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary Version bump `0.3.2` → `0.4.0` following the merge of #49. Minor version increment (0.3 → 0.4) reflects the addition of 14 new tools and associated changes. ### Changes - `Cargo.toml`: `0.3.2` → `0.4.0` - `server.json`: version, OCI image tag (`ghcr.io/...:0.4.0`), tool count `133 → 145`, category counts updated, localized descriptions updated - `README.md`: tool count `133 → 145`, category count `12 → 13`, add screener category ### New tool breakdown (133 → 145) | Category | Before | After | New tools | |----------|--------|-------|-----------| | fundamental | 19 | 22 | `shareholder_top`, `shareholder_detail`, `valuation_comparison` | | market | 10 | 14 | `short_trades`, `top_movers`, `rank_categories`, `rank_list` | | screener | — | 5 | `screener_recommend_strategies`, `screener_user_strategies`, `screener_strategy`, `screener_search`, `screener_indicators` | 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
https://modelcontextprotocol.io/specification/2025-11-25/server/prompts Generated by Endless task #8. Co-authored-by: Huacnlee Li Huashun <huacnlee@longbridge-inc.com>
…ket param (#56) ## Summary Migrates all screener MCP tools to `/v1/quote/ai/screener/*` endpoints per [longbridge-terminal PR #217](longbridge/longbridge-terminal#217). ### Endpoint changes | Tool | Old | New | |------|-----|-----| | `screener_recommend_strategies` | `GET /v1/quote/screener/strategies/recommend` | `GET /v1/quote/ai/screener/strategies/recommend?market=` | | `screener_user_strategies` | `GET /v1/quote/screener/strategies/mine` | `GET /v1/quote/ai/screener/strategies/mine?market=` | | `screener_strategy` | `GET /v1/quote/screener/strategy?id=` | `GET /v1/quote/ai/screener/strategy/{id}` | | `screener_search` (Mode A internal) | `GET /v1/quote/screener/strategy?id=` | `GET /v1/quote/ai/screener/strategy/{id}` | | `screener_search` (POST) | `POST /v1/quote/screener/search` | `POST /v1/quote/ai/screener/search` | | `screener_indicators` | `GET /v1/quote/screener/indicators` | `GET /v1/quote/ai/screener/indicators` | ### New parameters - `screener_recommend_strategies` / `screener_user_strategies`: optional `market` param (US/HK/CN/SG, default US) ### Critical fix included The AI strategy endpoint changed response shape. Without the fix, Mode A silently returns all stocks unfiltered: - **Old**: `{groups: [{indicators: [{key, min, max, id}]}]}` - **New**: `{market, filter: {filters: [{key, min, max, tech_values}]}}` Mode A now reads `strategy["filter"]["filters"][]` and preserves `tech_values` from the API response. ### Other - `page` changed to 0-indexed (match terminal PR #217) - `screener_strategy` description updated to reflect new response shape - Removed implementation-detail wording ("AI endpoint") from user-facing descriptions 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Improvements
### Stock Screener
- **`screener_recommend_strategies`** / **`screener_user_strategies`**:
added `market` param (US/HK/CN/SG, default US)
- **`screener_search`** Mode B: `conditions[]` accepts filter objects
`{key, min, max, tech_values}` — tech_values supported for technical
indicators (MACD/RSI/KDJ/BOLL)
- **`screener_search`**: every result now includes 7 default columns —
`prevclose`, `prevchg`, `marketcap`, `salesgrowthyoy`, `pettm`, `pbmrq`,
`industry`
- **`screener_indicators`**: exposes `tech_values` schema per technical
indicator (e.g. `macd_day`: category = goldenfork/deadcross/upzero,
period = day/week)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary
- `next_params` was typed as `Option<serde_json::Value>`, causing the
JSON Schema to emit only a
description with no `type` field
- Inspected the real API response: `next_params` is always `{"visited":
["id1", "id2", ...]}`, so
defined a concrete `TopMoversNextParams { visited: Vec<String> }` struct
- Schema now correctly emits `type: object` with a fully described
`visited: string[]` property
## Test plan
- [ ] `cargo build` passes
- [ ] `GET /mcp/tools.json` shows `$defs/TopMoversNextParams` with
`type: object` and `visited` field
- [ ] Pagination works correctly when passing `next_params` from a
previous response
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Bump version from 0.4.1 to 0.4.2. --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary - Bump version from 0.4.2 to 0.4.3 in `Cargo.toml` and `server.json` - Fix `top_movers` `next_params` schema: replace `$ref`/`anyOf` with an inline open-object (`type: object, additionalProperties: true`) - Add Chinese parameter descriptions (`properties`) for 9 tools that were missing them in `zh-CN` and `zh-HK` locales: `rank_list`, `screener_indicators`, `screener_strategy`, `screener_user_strategies`, `shareholder_detail`, `shareholder_top`, `short_positions`, `short_trades`, `valuation_comparison` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Combines #61 and #62 with CI fixes. ## Changes ### fix(schema): strip null from input schema type arrays schemars generates `["string", "null"]` for `Option<T>` fields. MCP convention expresses optionality via absence from `required`, not nullable types. Post-process all tool `inputSchema`s to convert `["string","null"]` → `"string"` etc. Override `ServerHandler::list_tools()` so both the MCP protocol path and `/mcp/tools.json` go through the same transform. ### fix(tools): anomaly missing size param returns empty results `/v1/quote/changes` requires a `size` parameter to return data. The MCP implementation only sent `market` and `category=0`, omitting `size` — causing the backend to always return `{"changes":[]}`. Default `size=50` (max 100), matching the CLI. Also adds optional `symbol` filtering and corrects the description (`changes[]` not `items[]`). ### fix: clippy - Collapse nested `if let` in `strip_null_from_type_arrays` (collapsible_if) - Remove unused `MarketParam` from `market.rs` (replaced by `AnomalyParam`) ## Closes - #61 - #62 🤖 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>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…om Host header (#64) ## Summary Two related fixes for multi-domain / path-flexible deployments: ### 1. Serve MCP at root path (`/`) in addition to `/mcp` Deployments where the gateway routes the domain root directly (e.g. `https://mcp.example.com/`) received HTTP 404 because the MCP handler was only mounted at `/mcp`. A second auth-wrapped `StreamableHttpService` is now registered via `fallback_service` so both `/mcp` and `/` work. Existing explicit routes (`/.well-known/*`, `/health`, `/metrics`, `/mcp/tools.json`) continue to take precedence. ### 2. Dynamic `resource` URL derived from request `Host` header The `/.well-known/oauth-protected-resource` `resource` field and `WWW-Authenticate` header previously returned the fixed `--base-url` value, which broke when the same binary is reachable via multiple domains. Now `resource_url_from_headers()` reads: - `Host` header → hostname - `X-Forwarded-Proto` header → scheme (falls back to the scheme in `--base-url` so local HTTP deployments without a proxy still work) ### 3. `data/scopes.json`: add `key` field + trailing newline ## Test plan - [ ] `POST /mcp` → 401 (endpoint exists, auth required) - [ ] `POST /` → 401 (endpoint exists, auth required) - [ ] `GET /.well-known/oauth-protected-resource` → 200, `resource` matches request Host - [ ] `GET /health` → 200 (not captured by fallback) - [ ] Claude Code connects to `https://mcp.longbridge.xyz/` without 404 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Bump version from 0.4.4 to 0.4.5. Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Problem When a reverse proxy routes `openapi.longbridge.xyz/mcp` to the backend at `mcp.longbridge.xyz/`, the `Host` header seen by the backend is `mcp.longbridge.xyz` (internal), not `openapi.longbridge.xyz` (external). The `resource` field in `/.well-known/oauth-protected-resource` returned the internal hostname, causing MCP clients to reject the OAuth flow with: ``` Protected resource https://mcp.longbridge.xyz does not match expected https://openapi.longbridge.xyz/mcp ``` ## Fix Check `X-Forwarded-Host` before `Host` when building the resource URL. The reverse proxy sets `X-Forwarded-Host: openapi.longbridge.xyz` to communicate the original external hostname. | Header present | Result | |----------------|--------| | `X-Forwarded-Host: openapi.longbridge.xyz` | `https://openapi.longbridge.xyz` | | `Host: mcp.longbridge.xyz` only | `https://mcp.longbridge.xyz` | | Neither | falls back to `--base-url` | 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Summary `/v1/quote/finance_calendar` is paginated — a multi-day query only returns the first page plus a `next_date` cursor. The previous implementation made a single request, silently dropping all events on pages 2+. This caused real data loss: e.g. a `report / US / 2026-05-23 → 2026-05-30` query was missing CRM.US, PDD.US, MRVL.US (reported externally in longbridge/developers#1045). **Changes:** - Auto-follow `next_date` cursor: use the returned `next_date` as the new `date` parameter on subsequent requests (keeping `date_end` unchanged), matching CLI behaviour - Pass `next=later`, `count=100`, `offset=0` on every request — aligned with CLI - Merge all pages with dedup by event `id` (`datetime+market` fallback for id-less entries); date buckets sorted chronologically - Hard cap of 20 pages to prevent runaway loops (same limit as CLI) - Add same-cursor guard to break if `next_date` doesn't advance - Create a fresh HTTP client per page to avoid `SendRequest` errors from connection reuse - Tool description (EN / zh-CN / zh-HK) now advises keeping date range ≤ 2 weeks - Bump version to 0.4.7 ## Test plan - [x] 12 unit tests: `next_date_of` edge cases, `merge_pages` dedup + date sorting, pagination boundary conditions - [x] `cargo test` — 70 tests pass - [x] `cargo clippy --all-features --all-targets` — no warnings - [x] Local smoke-test: `report / US / 2026-06-02 → 2026-06-06` returns 4 unique date buckets, no duplicates 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## What Make MCP-originated upstream requests identifiable by the Longbridge backend via a standards-compliant `User-Agent`, and pin the SDK to a published crate version. ## Why The backend previously could not tell that a request came from this MCP server, nor which client (Claude Code, Codex, …) drove it. CLI already tags itself with `longbridge-cli/<version>`; MCP had no equivalent. ## How - **`McpContext::user_agent()`** builds an RFC 9110 product-token chain: `<client-ua> longbridge-mcp/<version>`, e.g. `claude-code/2.1.89 (cli) longbridge-mcp/0.4.6`. Acting as a proxy, we append our token to the client's UA rather than inventing a custom header, so a single standard field carries both identities. Falls back to just `longbridge-mcp/<version>` when the client sends no UA (e.g. Codex currently sends none). - Applied on both paths: `create_http_client` (REST) and `create_config` (Context / WebSocket upgrades), mirroring `longbridge-cli`. - The client's raw `User-Agent` is no longer forwarded as-is (`SKIP_FORWARD_HEADERS`); it is captured in `extract_context` and folded into the chain. - **Dependency**: switch `longbridge` from a git dependency to the published crate **`4.2.2`**, which provides the `Config::header` builder used above. ## Verification - `cargo clippy --all-features --all-targets`: no issues. - `cargo test`: 58 passed, including a new end-to-end test (`upstream_request_carries_synthesized_user_agent`) that redirects the SDK base URL to a local echo server via `LONGBRIDGE_HTTP_URL` and asserts the real on-the-wire `User-Agent`. - Impact of the SDK bump (4.0.5 → 4.2.2) is contained: most tools use the REST path (`create_http_client`) and are unaffected by the typed-struct changes; only quote/trade/content/statement use high-level Contexts and all compile + test green. `alert` uses REST, so the 4.1.0 `AlertContext` breaking change does not affect it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tool names Revert all changes to src/tools/mod.rs that were not part of task #8: - Re-add mod atm, mod ipo, mod search declarations - Restore 24 deleted tool handler functions - Restore header-forwarding infrastructure (extra_headers, collect_headers, SKIP_FORWARD_HEADERS) - Restore JWT utility functions (account_channel, decode_jwt_account_channel, base64url_decode) - Restore tool_result structured_content object filter - Restore all full tool descriptions - Restore collect_headers tests The only intentional changes kept from efb5edf are the model type imports (GetPromptRequestParams, GetPromptResult, ListPromptsResult, PaginatedRequestParams, prompt_handler) and the #[prompt_handler] attribute on impl ServerHandler. Also fix five incorrect tool names in src/prompts.rs prompt text strings: - financial_summary -> financial_report + valuation - option_chain -> option_chain_expiry_date_list + option_chain_info_by_date - estimate_max_buy_quantity -> estimate_max_purchase_quantity - market_indices -> quote - market_turnover_anomaly -> anomaly Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…raded) (#70) ## What The `quote` tool now cleans up its extended-hours (pre/post/overnight) output. ## Why `quote` serialized the SDK `SecurityQuote` verbatim. For sessions that have not traded, the upstream returns a **zero-filled** object (`last_done == 0`), which AI callers read as a real **-100%** move — exactly the kind of after-close misjudgement we want to avoid for the most-called tool. The keys were also verbose (`*_quote`). ## How `normalize_extended_sessions` post-processes the serialized value: - **Drop the `_quote` suffix**: `post_market` / `overnight` / `pre_market` (in that order). - **Null out untraded sessions**: a session with `last_done <= 0` (or missing) becomes `null` instead of a zero-filled object. Handles both string- and number-serialized `Decimal`. This mirrors the corresponding CLI change (longbridge-terminal#228). ## Verification `cargo clippy --all-features --all-targets`: clean. Two unit tests cover the rename, the null-out, key ordering, and both `Decimal` serialization shapes: ``` tools::quote::tests::normalizes_sessions_string_last_done ... ok tools::quote::tests::normalizes_sessions_numeric_last_done ... ok ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The attribute was dropped when resolving merge conflicts in src/tools/mod.rs during 'Merge branch main into endless/task-8'. The import (use rmcp::prompt_handler) remained but the attribute itself was missing, so list_prompts/get_prompt were never wired up and the prompts capability was not advertised in get_info(). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace 5 generic prompts with 10 prompts organised by capability domain: market_data, derivatives, fundamentals, research, portfolio_account, orders_trading, ipo, quant, watchlist, content. Each prompt covers the key tools for its domain and references only registered tool names. Shared argument types (SymbolArgs, TradeArgs, MarketArgs, QuantArgs) replace one-off structs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
hogan-yuan
force-pushed
the
main
branch
2 times, most recently
from
July 6, 2026 02:22
8284189 to
c33ad40
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Auto-generated by Endless task #8.
Initiated by: Huacnlee Li Huashun
背景
MCP(Model Context Protocol)规范在 tools 之外还定义了
prompts能力,允许服务端向 AI 客户端暴露可复用的工作流模板。客户端(如 Claude Desktop、Cursor)可通过prompts/list发现这些模板,再通过prompts/get获取填充好参数的消息序列,从而引导 LLM 按步骤调用相关工具并汇总结果。longbridge-mcp 目前仅实现了
tools能力,缺少prompts能力的声明与实现。这意味着连接该 MCP 服务的客户端无法发现和使用任何预定义的 Longbridge 工作流模板,用户每次都需要手动拼凑复杂的多步提示词。摘要
prompts能力,使 AI 客户端能够发现并调用 5 个预定义的 Longbridge 工作流模板。src/prompts.rs:使用 rmcp#[prompt_router]+#[prompt]宏定义 5 个提示词(股票研究、持仓分析、期权筛选、交易执行、市场概览)。src/main.rs:添加mod prompts;将新模块纳入编译。src/tools/mod.rs:在impl ServerHandler for Longbridge上叠加#[prompt_handler]宏,并补充对应 model 类型的use导入。#[prompt]/#[prompt_router]/#[prompt_handler]),与现有 tool 宏用法完全一致,不需要手动实现ServerHandlertrait 方法。#[tool_handler]会自动检测同一impl块上的#[prompt_handler]兄弟属性,在生成的get_info()中同时调用enable_tools()和enable_prompts(),无需修改ServerCapabilities构造代码。cargo build无错误,cargo clippy --all-features --all-targets无警告;本地运行后通过 JSON-RPC 调用prompts/list(期望返回 5 个提示词)和prompts/get(期望返回含userrole 的消息)进行功能验证。修改
src/prompts.rs#[prompt_router]impl 块,含 5 个#[prompt]方法及对应参数 structsrc/main.rsmod prompts;声明src/tools/mod.rsuse rmcp::prompt_handler、扩展 model 导入、在impl ServerHandler上叠加#[prompt_handler]关键决策
#[prompt_handler]与#[tool_handler]叠加在同一impl ServerHandler块上:rmcp-macros 中tool_handler通过has_sibling_handler检测到prompt_handler后,会在生成的get_info()中同时enable_tools()和enable_prompts();而prompt_handler检测到tool_handler存在后,会跳过自己生成get_info()以避免冲突。这一设计无需改动任何已有代码逻辑,侵入性最小。