feat(mcp): curated exclude list for cloudflare + glob tool filters + default_excluded manifests

The cloudflare entry's 3,320-endpoint surface is ~43% product families a
personal/dev account never touches (Zero Trust org-fleet suite, Magic
Transit/WAN, Cloudforce One, Radar analytics, API Shield, legacy
migration surfaces). Ship a 34-pattern curated exclude list in the
manifest: 3,320 -> 1,905 tools kept, and everything Cloudflare adds
later stays enabled by default.

Mechanism, two small extensions:
- tools/mcp_tool.py: tools.include/exclude entries containing glob
  metacharacters now match via fnmatch (plain names stay exact-match),
  so a product family is one pattern instead of hundreds of stale
  literals.
- hermes_cli/mcp_catalog.py: manifests may declare
  tools.default_excluded (mutually exclusive with default_enabled);
  install writes it to tools.exclude and skips the probe/checklist —
  a 3,320-row curses checklist is not a UX. Prior user include
  selections still win on reinstall.

Verified by replaying the real filter functions over the live-probed
3,320-tool list: 1,415 excluded, zero overmatch against a per-product
target audit; DNS/Workers/R2/D1/tunnels/Access/AI kept.
This commit is contained in:
Teknium 2026-07-20 08:51:47 -07:00
parent ce0defe4d8
commit 58c97b9ddd
No known key found for this signature in database
6 changed files with 295 additions and 14 deletions

View file

@ -92,6 +92,7 @@ Thread safety:
import asyncio
import contextvars
import concurrent.futures
import fnmatch
import inspect
import json
import logging
@ -4862,7 +4863,7 @@ def _build_utility_schemas(server_name: str) -> List[dict]:
def _normalize_name_filter(value: Any, label: str) -> set[str]:
"""Normalize include/exclude config to a set of tool names."""
"""Normalize include/exclude config to a set of tool names/patterns."""
if value is None:
return set()
if isinstance(value, str):
@ -4873,6 +4874,23 @@ def _normalize_name_filter(value: Any, label: str) -> set[str]:
return set()
def _name_filter_matches(name: str, filter_set: set) -> bool:
"""True if *name* matches any entry in a normalized include/exclude set.
Entries containing a glob metacharacter (``*``, ``?``, ``[``) are matched
with :func:`fnmatch.fnmatchcase`; plain entries are exact names. Globs let
huge auto-generated surfaces (e.g. an OpenAPI-derived MCP exposing
thousands of endpoint tools) be filtered by product family
(``*_accounts_magic_*``) instead of thousand-line literal lists.
"""
if name in filter_set:
return True
for pat in filter_set:
if ("*" in pat or "?" in pat or "[" in pat) and fnmatch.fnmatchcase(name, pat):
return True
return False
def _parse_boolish(value: Any, default: bool = True) -> bool:
"""Parse a bool-like config value with safe fallback."""
if value is None:
@ -5047,9 +5065,9 @@ def _register_server_tools(name: str, server: MCPServerTask, config: dict) -> Li
def _should_register(tool_name: str) -> bool:
if include_set:
return tool_name in include_set
return _name_filter_matches(tool_name, include_set)
if exclude_set:
return tool_name not in exclude_set
return not _name_filter_matches(tool_name, exclude_set)
return True
for mcp_tool in server._tools: