mcpField
Q
QualityScreener

QualityScreener

远程服务
qualityscreener.io金融数据01 天前更新

关于 QualityScreener

QualityScreener 是将股票筛选和评分 API 提供给 AI Agent 使用的 MCP 服务。投资者可筛选已评分股票、创建自定义评分系统、查看历史分数并分享筛选结果,所有操作使用其个人账户权限。

主要功能

  1. 01筛选并排列已评分股票
  2. 02计算自定义质量分数
  3. 03查看历史评分
  4. 04管理已保存的评分系统
  5. 05生成可分享的筛选链接

适用场景

  1. 01按行业或市值筛选股票
  2. 02比较当前与历史评分
  3. 03创建并复用自定义评分标准
  4. 04分享配置好的股票筛选结果

MCP 相关

该服务通过 stdio 或 Streamable HTTP 将经过身份验证的 Quality Screener API 操作作为 MCP 工具提供。请求使用登录用户的令牌,每个工具返回对应的 API 响应。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://mcp.qualityscreener.io/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

详细介绍

Quality Screener MCP 服务

一个独立的 Model Context Protocol(MCP)服务,可将 Quality Screener 股票筛选引擎作为工具提供给 AI Agent(Claude、Cursor 及其他 MCP 客户端)。

连接后,Agent 可以筛选和过滤已评分的股票池、计算自定义质量评分、查看评分历史、管理已保存的评分系统,并生成可分享的筛选链接——以已登录用户的身份操作,使用的数据与用户在 Web 控制面板中看到的相同。

  • 不依赖 SDK。该服务是一个基于 Quality Screener 公共 API 的轻量 HTTP 层。它不依赖后端 Python 包——每个工具只调用 REST 端点并返回 JSON 载荷。
  • **支持多租户,且无需服务凭据。**通过 HTTP 部署时,该服务不存储自身凭据。每个请求都携带调用者自己的访问令牌,服务会将其转发给 API,因此单个公开部署即可为许多用户提供服务,而无需使用共享账户。

目录


工作原理

┌─────────────┐   MCP (stdio | streamable-HTTP)   ┌──────────────────┐   HTTPS   ┌──────────────────────┐
│  AI agent   │ ────────────────────────────────► │  qscreener-mcp   │ ────────► │ Quality Screener API │
│ (MCP client)│ ◄──────────────────────────────── │   (this server)  │ ◄──────── │   (FastAPI backend)  │
└─────────────┘         tool calls / JSON          └──────────────────┘  REST     └──────────────────────┘

每个 MCP 工具都映射到一个 Quality Screener REST 端点。服务会在每个出站请求中附加调用者的 bearer 令牌(接受请求头 X-Stobot-CLI-Token,也接受 Authorization: Bearer …),并返回解码后的 JSON。服务本身不包含业务逻辑——它是 API 的类型化、经过身份验证的门面。

它支持两种传输模式:

传输方式用途身份验证
stdio(默认)本地 Agent(例如 Claude Code)将服务作为子进程启动来自 $QSCREENER_TOKEN 或 ~/.config/qscreener/credentials.json 的令牌
streamable-http可从外部访问的远程部署(例如 Railway)端到端 MCP OAuth 2.0——客户端打开浏览器登录一次,之后会自动发送令牌;或者使用每个请求的 X-Stobot-CLI-Token 请求头

通过 HTTP 访问时,MCP 端点位于 /mcp。


快速开始(远程)

使用该服务最简单的方法是让 MCP 客户端连接到托管部署。无需复制令牌——客户端首次连接时会触发浏览器登录:

{
  "mcpServers": {
    "qscreener": {
      "type": "streamable-http",
      "url": "https://mcp.qualityscreener.io/mcp"
    }
  }
}

首次使用时,浏览器会打开 Quality Screener 登录页面。授权一次后,Agent 就会保持连接。你需要拥有 Quality Screener 账户;Agent 将继承你的所有访问权限。


本地运行

需要 uv。

# Install dependencies
uv sync

# stdio — for a local agent that launches this as a subprocess
uv run qscreener-mcp

# streamable-HTTP — mirrors the remote deployment
QSCREENER_MCP_TRANSPORT=streamable-http QSCREENER_MCP_PORT=8080 \
  QSCREENER_API_URL=http://localhost:8001 \
  uv run qscreener-mcp
# -> MCP endpoint at http://localhost:8080/mcp

使用 Docker:

docker build -t qscreener-mcp .
docker run --rm -p 8080:8080 \
  -e QSCREENER_API_URL=https://your-backend.example.com \
  -e QSCREENER_MCP_PUBLIC_URL=http://localhost:8080 \
  qscreener-mcp
# -> MCP endpoint at http://localhost:8080/mcp

默认情况下,容器会在端口 8080 上运行 streamable-http 传输模式。


配置

所有配置均通过环境变量设置,并在启动时解析。

环境变量默认值含义
QSCREENER_API_URLhttp://localhost:8001工具调用的 Quality Screener 后端 API 基础 URL
QSCREENER_MCP_TRANSPORTstdiostdio、streamable-http 或 sse
QSCREENER_WEBSITE_URLhttp://localhost:3001Web 应用基础 URL,用于构建 OAuth 浏览器登录链接和可分享的筛选网址
QSCREENER_MCP_PUBLIC_URLhttp://localhost:{PORT|8080}(或在 Vercel 上为 https://$VERCEL_URL)此服务可公开访问的基础 URL,用作 OAuth 颁发者和回调 URL
QSCREENER_OAUTH_SIGNING_KEY—用于签署 OAuth 状态、授权码和客户端注册信息的 HMAC 密钥。在 Vercel 上为必填;单个长时间运行的进程可选
PORT—HTTP 传输的绑定端口(Railway 会自动设置)
QSCREENER_MCP_PORT8080未设置 PORT 时使用的备用绑定端口
QSCREENER_MCP_HOST0.0.0.0HTTP 传输的绑定主机
QSCREENER_TOKEN—stdio 模式的 Bearer 令牌覆盖值(单用户)
QSCREENER_CONFIG_DIR~/.config/qscreenerstdio 模式下存放 credentials.json 的目录

身份验证

服务按以下优先级为每次调用解析 Bearer 令牌:

  1. HTTP 请求标头 — X-Stobot-CLI-Token,然后是 Authorization: Bearer <token>。
  2. $QSCREENER_TOKEN 环境变量。
  3. $QSCREENER_CONFIG_DIR/credentials.json — token 字段。
远程(OAuth 2.0)

对于 streamable-http 部署,身份验证通过 MCP OAuth 流程全自动完成:

  1. MCP 客户端发现授权服务器,并打开用户的浏览器。
  2. 浏览器打开 Quality Screener Web 应用;该应用将用户的 Web 会话换取短期 CLI 令牌,然后重定向回此服务的 /oauth/callback。
  3. 服务将令牌交给 MCP 客户端,客户端随后在每个请求中将其作为 Bearer 令牌发送。

服务通过调用后端的 /v1/cli/auth/whoami 端点,在每次请求时验证令牌,因此已撤销或过期的令牌会立即被拒绝。服务绝不会持久化用户令牌。访问令牌本身就是 CLI 令牌,因此无需本地存储。设置 QSCREENER_OAUTH_SIGNING_KEY 后,待处理的登录状态、授权码和动态注册的客户端会使用 HMAC 签名的 JWT;多实例主机(Vercel)需要此设置。单个进程在未设置密钥时,则沿用原有的内存行为。

本地(stdio)

通过浏览器登录流程获取令牌并将其保存在本地,然后通过 stdio 运行服务:

qscreener auth login                          # opens the web app, stores a token
cat ~/.config/qscreener/credentials.json      # the "token" field is your bearer token

也可以直接为 CI / 脚本化使用设置 QSCREENER_TOKEN。


工具

所有工具都需要身份验证。筛选条件在单个筛选项内采用 OR 逻辑,在多个筛选项之间采用 AND 逻辑。市值始终以 USD 计。

账户与状态
工具签名描述
auth_statusauth_status()是否存在令牌,以及该令牌对应的用户。
account_profileaccount_profile()已登录用户的个人资料(电子邮件、用户名、组织)。
healthhealth()API 和数据库健康检查。
评分与筛选
工具签名描述
scores_topscores_top(limit=20)按质量评分列出排名靠前的股票代码,结果为 {ticker: score} 映射。
scores_listscores_list(ticker=None, sectors=None, industries=None, countries=None, currencies=None, exchanges=None, min_score=None, max_score=None, min_market_cap_usd=None, max_market_cap_usd=None, sort_by="quality_score", sort_order="desc", offset=0, limit=50, include_duplicates=False)列出已评分的股票代码,可选应用筛选条件。
scores_showscores_show(ticker)显示单个股票代码对应的完整评分行。
scores_for_tickersscores_for_tickers(tickers, scoring_system_id=None)根据默认评分体系或已保存的评分体系,获取指定股票代码列表的当前评分。未知的股票代码将被忽略。
scores_statisticsscores_statistics(sectors=None, min_score=None, max_score=None, min_market_cap_usd=None, max_market_cap_usd=None)计算筛选后范围内的最低、最高和平均评分统计数据。
scores_market_capscores_market_cap(sectors=None, min_score=None)计算筛选后范围内的总市值(USD)。
score_computescore_compute(config, scoring_universe=None, sectors=None, industries=None, regions=None, countries=None, currencies=None, exchanges=None, min_market_cap_usd=None, max_market_cap_usd=None, sort_by="quality_score", sort_order="desc", offset=0, limit=50, include_duplicates=False)根据 CustomScoreConfig 计算自定义评分。scoring_universe 用于选择同类群组(会改变评分);其他筛选条件用于选择行(不会改变评分)。
分享
工具签名描述
screen_sharescreen_share(config)保存 CustomScoreConfig,并返回一个公开、可复制粘贴的分享链接(url、slug、created、view_count)。内容寻址:相同的配置会返回相同的链接。
筛选条件与股票代码
工具签名描述
filters_listfilters_list()可用的筛选值(行业板块、行业、国家、货币、交易所)。
tickers_listtickers_list(limit=None)可用的股票代码列表,可选择将结果截断至 limit 条。
tickers_searchtickers_search(query)根据不区分大小写的子字符串搜索可用的股票代码。
评分历史

日期格式为 YYYY-MM-DD。传入 scoring_system_id,即可使用已保存的评分体系而非默认质量评分来计算历史数据。

工具签名描述
history_tickerhistory_ticker(ticker, start=None, end=None, scoring_system_id=None)查询单个股票代码在指定日期范围内的评分历史。
history_batchhistory_batch(tickers, start=None, end=None, scoring_system_id=None)一次查询多个股票代码的评分历史。
history_tophistory_top(top=10, scoring_system_id=None)获取当前排名前 N 的股票代码,并返回其评分历史。
已保存的评分体系

评分体系是一个命名的、可重复使用的 CustomScoreConfig,保存在你的账户中。

工具签名描述
systems_listsystems_list()列出你已保存的评分体系。
systems_showsystems_show(system_id)按 ID 显示已保存的评分体系。
systems_createsystems_create(name, config, description=None)根据配置对象创建已保存的评分体系。
systems_updatesystems_update(system_id, name=None, config=None, description=None)更新已保存的评分体系。
systems_deletesystems_delete(system_id)删除已保存的评分体系。
systems_applysystems_apply(system_id)应用已保存的评分体系(使用次数加 1)。

使用 CustomScoreConfig

score_compute、screen_share 和 systems_* 工具接受一个 CustomScoreConfig 对象,用于描述财务指标的权重设置。其结构与 Web 仪表板中的评分构建器相同:包含加权的分组,每组包含加权的指标,以及评分参数和可选的嵌套 filters 块。最简示例:

{
  "name": "My quality screen",
  "winsorizePercentile": 5,
  "missingDataPercentile": 0.25,
  "normalizeGroupZScores": false,
  "includeDuplicatesInScoring": false,
  "groups": [
    {
      "id": "returns",
      "name": "Returns",
      "weight": 0.5,
      "metrics": [
        { "id": "roe", "name": "ROE", "weight": 0.5 },
        { "id": "roic", "name": "ROIC", "weight": 0.5 }
      ]
    },
    {
      "id": "profitability",
      "name": "Profitability",
      "weight": 0.5,
      "metrics": [
        { "id": "profit_margin", "name": "Profit Margin", "weight": 1.0 }
      ]
    }
  ],
  "scoringUniverseFilters": { "countries": ["Italy"], "min_market_cap": 1 },
  "filters": { "min_score": 1.2 }
}

评分参数使用 camelCase:winsorizePercentile(1-10)、missingDataPercentile (0.1-0.5)、normalizeGroupZScores 和 includeDuplicatesInScoring(布尔值)。 scoringUniverseFilters 定义计算分数时所依据的同类群体;嵌套的 filters 块保存已保存筛选条件的状态。这两个块中的市值单位均为十亿美元(USD)(工具参数使用 USD)。系统会自动将宽松输入规范化为此结构,例如 snake_case 键、旧版 winsorize/zScore 标记,或放在顶层的筛选键,但建议直接按此结构传入。使用 filters_list 查找有效的筛选值;如果想要一个可复制的起点,可以在仪表板中交互式地构建配置。

两个阶段:先确定评分范围,再筛选

质量分数是相对值——每家公司都要在某个群体中进行缩尾处理和 Z 分数标准化——因此,同类群体包含哪些公司与查看哪些行是两个不同的问题,score_compute 会分别处理。

阶段位置效果
1. 评分范围scoring_universe 参数,或 config.scoringUniverseFilters在缩尾处理/Z 分数标准化之前应用——会改变每个分数
2. 结果筛选条件sectors / countries / … 参数在评分之后应用——绝不会改变分数

“以欧洲科技公司为参照评选最佳欧洲科技公司”与“以全球公司为参照评选最佳欧洲科技公司”会得到不同的列表,而不是同一列表经过重新缩放——缩小范围会以不同幅度改变每项指标的边界、均值和 σ,因此公司排名确实会发生变化:

// judged against European tech — the peer group is European tech
score_compute(config, scoring_universe={"sectors": ["Technology"], "regions": ["Europe"]})

// judged against the world — the peer group is everyone, then Europe is shown
score_compute(config, sectors=["Technology"], regions=["Europe"])

阶段 1 接受 sectors、industries、regions、countries、currencies、exchanges、 min_market_cap_usd 和 max_market_cap_usd。若传入 min_score、max_score、ticker 或 tickers,会报错而非忽略:前两个会根据正在计算的分数进行筛选,其余参数用于选择行。

每个响应都包含一个 scoring_universe 字段,用于说明同类群体及其规模。针对不同同类群体计算出的分数不可比较——不要将它们混在同一张表中。

需要了解的两个边界情况:

  • **作为阶段 2 参数传入的 min_market_cap_usd 也会设定评分群体的下限。**这是后端长期存在的行为,为保持兼容而保留。请在 scoring_universe 中设置 min_market_cap_usd,以显式控制同类群体;该设置会覆盖阶段 2 的下限。 max_market_cap_usd 只筛选行,除非你也在 scoring_universe 中设置它。
  • **群体规模很小时仍会评分。**目前没有最小群体规模限制,因此,对十几家公司按第 5/95 百分位进行缩尾处理,会得出看似确定、实则荒谬的结果。
嵌套 filters 块的作用

它保存的是已保存筛选条件的状态。screen_share 和 systems_create/systems_update 会持久化该状态,以便在仪表板中重新打开共享筛选视图或已保存的评分系统时,还原其筛选条件。

它不定义同类群体——这由 scoringUniverseFilters 定义。将已保存配置传给 score_compute 时,其中的 filters 块会作为阶段 2筛选条件应用(显式传入的参数优先),与仪表板的行为一致,因此重新评分已保存的系统时会保留其视图。


连接 MCP 客户端

远程(推荐)

任何 streamable-http MCP 客户端均可使用。无需令牌——通过 OAuth 登录:

{
  "mcpServers": {
    "qscreener": {
      "type": "streamable-http",
      "url": "https://mcp.qualityscreener.io/mcp"
    }
  }
}

如果你的客户端无法执行 OAuth 流程,可以直接发送生成的令牌:

{
  "mcpServers": {
    "qscreener": {
      "url": "https://mcp.qualityscreener.io/mcp",
      "headers": { "X-Stobot-CLI-Token": "<your token>" }
    }
  }
}
本地(stdio)
{
  "mcpServers": {
    "qscreener": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/quality-screener-mcp-server", "qscreener-mcp"],
      "env": { "QSCREENER_API_URL": "https://your-backend.example.com" }
    }
  }
}

部署

此服务以单个容器的形式部署。在 Railway 上:

  1. New service → Deploy from repo,指向此代码库。Dockerfile 是独立完整的,因此构建上下文为代码库根目录。

  2. 设置环境变量:

    • QSCREENER_MCP_TRANSPORT=streamable-http
    • QSCREENER_API_URL=https://<your-backend-domain>
    • QSCREENER_WEBSITE_URL=https://<your-frontend-domain>
    • QSCREENER_MCP_PUBLIC_URL=https://<generated-mcp-domain>

    Railway 会自动注入 PORT;服务会绑定到该端口。

  3. Networking → Generate Domain。MCP 端点为 https://<generated-domain>/mcp。

    • 将 HTTP 健康检查路径留空(或使用 TCP 检查):对普通 GET 请求,/mcp 会返回 406 Not Acceptable,因此预期返回 200 的 HTTP 健康检查会将部署标记为不健康。
  4. Connect 你的 MCP 客户端——首次连接时会自动触发 OAuth 流程。


在 Vercel 上部署

Docker/Railway 通过 mcp.run() 提供服务的同一个 ASGI 应用,会从 app.py 导出为 FastAPI app,供 Vercel 的 Python 运行时作为单个 Function 托管。FastMCP 应用已监听 /mcp、/.well-known/*、 /authorize、/token、/register 和 /oauth/callback;Vercel 会将 每个请求连同原始路径一并路由到该 Function,因此这些 URL 无需重新映射即可正常访问。vercel.json 只为 app.py 设置了 maxDuration(60s)。

不要将 /mcp(或 OAuth 路径)重写到 /——FastMCP 会匹配 字面路径。

创建一个指向此代码库的 Vercel 项目(Framework Preset:FastAPI / Other,Root Directory:代码库根目录)。设置以下环境变量——只填写变量名;切勿提交变量值:

环境变量必需用途
QSCREENER_API_URL是工具调用的 Quality Screener 后端基础 URL
QSCREENER_WEBSITE_URL是用于 OAuth 浏览器登录和可分享筛选链接的 Web 应用源站
QSCREENER_MCP_PUBLIC_URL使用自定义域名时必需此部署的公共源站(OAuth 颁发者 + /oauth/callback)。预览部署可省略此项,并会使用 https://$VERCEL_URL
QSCREENER_OAUTH_SIGNING_KEY是用于签署 OAuth 待处理状态、授权码和动态客户端注册信息的 HMAC 密钥,使其在多次 Function 调用之间保持有效。请使用较长的随机字符串(至少 32 字节)

Vercel 会自动注入 VERCEL_URL(不含协议的主机名)。仅当未设置 QSCREENER_MCP_PUBLIC_URL 时,它才会作为备用颁发者。如果 MCP 客户端将通过自定义域名连接,请勿将其用作生产环境的颁发者。

以下环境变量在 Vercel 上不需要(app.py 入口始终使用 HTTP, 且 Function 不会绑定端口):

  • QSCREENER_MCP_TRANSPORT
  • QSCREENER_MCP_HOST
  • QSCREENER_MCP_PORT / PORT
  • QSCREENER_TOKEN
  • QSCREENER_CONFIG_DIR

部署后,MCP 端点为 https://<vercel-domain>/mcp。像 Railway 部署一样,将 MCP 客户端指向此 URL。如果自定义评分达到 60s 上限,请提高 vercel.json 中的 functions["app.py"].maxDuration。


开发

uv sync            # install dependencies (including dev)
uv run pytest      # run the test suite

代码库小巧且自成一体:

路径用途
qscreener_mcp/server.pyFastMCP 服务、工具定义、传输入口
qscreener_mcp/client.py附加 bearer token 的精简 httpx 客户端
qscreener_mcp/oauth.pyMCP OAuth 2.0 提供方(令牌验证、浏览器流程)
app.pyVercel FastAPI 入口,用于挂载 streamable-HTTP ASGI 应用
tests/pytest 测试套件(令牌解析、筛选器转发、分享链接构建)

隐私政策

完整的隐私政策发布于 PRIVACY.md (https://github.com/quality-screener/quality-screener-mcp-server/blob/main/PRIVACY.md)。

简而言之:

  • 唯一保留的个人数据是用于识别你账户的电子邮箱地址。用户名和组织是可选的个人资料字段。
  • MCP 服务是无状态代理——它不持有数据库,也不会将任何个人数据写入自己的存储。每个请求都会使用你的访问令牌转发至 Quality Screener API,而非使用共享账户。
  • 你的数据不会被出售,不会用于广告,也不会用于训练机器学习模型。
  • 运营日志通过假名化用户 ID(而非电子邮箱)关联账户。
  • 删除账户时,账户数据也会被删除。

有关数据保留期限、第三方接收方、国际传输和你的 GDPR 权利,请参阅隐私政策。


支持

渠道用途
[email protected]支持请求、安全报告、隐私和数据主体请求
GitHub Issues错误报告和功能请求

本 README 是 MCP 服务的权威文档: https://github.com/quality-screener/quality-screener-mcp-server

如发现疑似安全漏洞,请通过电子邮件私下报告,而不要公开提交问题。


许可证

MIT © Quality Screener.

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。