应用声明

当某个插件的 MCP 服务器作为桌面应用的前台时,它需要声明这是哪个应用,以及该服务器对它有何依赖。核心会在主机上评估该声明,并据此决定是否放行该服务器的工具,以及任何点名该应用的 skill。解析器只依赖标准库和 hermes_platform。

相关词汇定义位于 hermes_platform/declaration.py。一份声明是"数据加策略",从普通映射(已解码的 YAML、JSON、dict 字面量——解析器从不直接触碰文件)解析而来:

from hermes_platform import declaration

decl = declaration.parse_declaration(
    "my-server",
    raw_app={"linux": {"presence": "executable", "location": "/opt/my-app/server"}},
    raw_requires={"app": True},
    where="my-plugin/plugin.yaml",   # 用于错误信息中的人类可读标签
)
declaration.register("my-server", decl)

register(server_name, decl) 以配置的服务器名,把一份声明存入进程内注册表。加载器集成是另一件事;核心不会自动读取插件 YAML。

未注册的 MCP 服务器保留其仅做连接检查的行为。显式点名未注册服务器的 skill 会被隐藏。clear() 会移除所有注册,它不是按插件卸载的操作。注册是进程级的,不按 profile 划分。

app — 如何在各操作系统上找到应用 {#app--how-to-find-the-application-on-each-os}

app:
  win32:
    presence: executable
    location: "%ProgramFiles%/Vendor/Vendor App/McpServer/Server.exe"
    version: { kind: uninstall_registry, display_name_prefix: "Vendor App" }
    liveness:
      kind: server_json
      path: "%LOCALAPPDATA%/Vendor/Vendor App/McpServer/server.json"
      pid_key: pid
      url_key: http
      token_key: token
      endpoint_path: /mcp
  darwin:
    presence: bundle
    location: /Applications/Vendor.app
    version: { kind: plist }
字段类型规则映射到 AppDef
<os>win32 | darwin | linux至少一个;未知键即报错AppDef.os_family
presenceexecutable | bundle每个操作系统必填.presence
locationstr必填;Windows 上须为盘符根路径(C:\\...),或以 ~ / %VAR% / $VAR 开头;拒绝 UNC 路径,以确保存在性检查绝不触碰网络;不得含 .. 段或 URL scheme;在查找时展开.location
version.kindpe_resource | plist | uninstall_registry | none默认 none;pe_resource/uninstall_registry 仅用于 win32,plist 仅用于 darwin.version_kind
version.display_name_prefixstr当 uninstall_registry 时必填.version_arg
liveness.kindserver_json | none默认 none.liveness_kind
liveness.pathstr当 server_json 时必填.liveness_path
liveness.pid_key / url_key / token_keystr默认 pid / http / token.liveness_*_key
liveness.endpoint_pathstr默认 /mcp;用于 initialize 的路径,绝不是文件里那个路径.endpoint_path

当 requires.app 为 true,而 app: 中缺少某操作系统时,得到 unsupported_os。

requires — 服务器在被提供之前需要什么 {#requires--what-the-server-needs-before-it-is-offered}

requires:
  app: true
  min_version: "2.3.0"
字段类型规则
appbool为 true 时,必须存在 app: 块,且服务器的放行以应用存在为门槛
min_versionstr要求 app: true;点分数字形式;每个适用的 app.<os> 都必须声明真实的 version.kind;按段逐段做数值比较,段内的非数字字符会被丢弃(2.3.0.12594 ≥ 2.3.0;预发布后缀不参与排序)

requires.app: true 却没有 app: 块,属于 DeclarationError。

可用性:每个读取方共用的唯一评估 {#availability-the-one-evaluation-every-reader-uses}

hermes_platform/resolver/availability.py::availability(decl) -> Availability

Availability(
  state:   available | installed_not_running | missing_app | version_too_old
         | unsupported_os | no_requirements,
  version: str | None,       # 检测到的版本(若存在)
  path:    str | None,       # 应用被找到或被查找的位置
  min_version: str | None,   # 来自 requires
)
  • no_requirements:没有 requires.app;应用门槛通过,但连接检查仍然适用。
  • unsupported_os:有 requires.app,但没有 app.<当前操作系统> 块。零 I/O。
  • missing_app:locate 在 location 处什么都没找到。
  • version_too_old:版本低于最低要求,或无法读取。
  • available:应用存在,版本可接受,或不要求版本。
  • installed_not_running:保留词汇;本评估器永远不会产出它。

评估使用 locate 和可选的版本检测。它绝不探测服务器、启动应用或建立连接。工具注册表保留其现有的可用性缓存。

两道门槛 {#the-two-gates}

  • MCP check_fn(tools/mcp_tool_handlers.py::_make_check_fn):连接存活,并且(当为该服务器注册了带 requires.app 的声明时)availability(decl).offerable。返回普通 bool,因为注册表缓存的是 bool(fn())。
  • Skill 的 requires_apps: frontmatter(agent/skill_utils.py::skill_matches_apps):每个名字都通过 declaration.lookup 解析;未知名字会隐藏该 skill(失败即关闭)。属于提供时过滤,与 environments: 类似。