This commit is contained in:
2026-07-06 10:55:06 +03:00
parent 333a4c592d
commit 66087d5797
3 changed files with 72 additions and 2 deletions
+1
View File
@@ -4,6 +4,7 @@ __pycache__/
.mcpregistry_*
.playwright-mcp/
.salt
.venv
*.egg-info/
*.pyc
build
+2 -2
View File
@@ -119,12 +119,12 @@ def _parse_args(argv=None) -> argparse.Namespace:
parser.add_argument(
"--enabled-tools",
default=None,
help="Comma-separated whitelist of tool names to expose",
help="Comma-separated whitelist of tool names or group aliases (read-only, write-only) to expose",
)
parser.add_argument(
"--disabled-tools",
default=None,
help="Comma-separated blacklist of tool names to hide",
help="Comma-separated blacklist of tool names or group aliases (read-only, write-only) to hide",
)
return parser.parse_args(argv)
+69
View File
@@ -213,6 +213,59 @@ class SessionKeepalive:
logger.debug("Keepalive ping failed (non-critical): %s", exc)
# ── Tool groups ─────────────────────────────────────────────────────────
TOOL_GROUPS: dict[str, set[str]] = {
"read-only": {
"get_emails",
"get_email",
"search_emails",
"get_calendar_events",
"get_event_links",
"find_person",
"get_folders",
"check_session",
"find_free_time",
"find_meeting_time",
"get_meeting_stats",
"get_meeting_contacts",
"download_event_attachments",
"get_email_links",
"download_attachments",
"login",
},
"write-only": {
"send_email",
"reply_email",
"forward_email",
"delete_email",
"move_email",
"mark_email_read",
"create_meeting",
"update_meeting",
"cancel_meeting",
"respond_to_meeting",
"create_folder",
"rename_folder",
"empty_folder",
"delete_folder",
"move_folder",
},
}
# ── Alias resolution ────────────────────────────────────────────────────
def _resolve_aliases(names: list[str]) -> set[str]:
resolved: set[str] = set()
for name in names:
if name in TOOL_GROUPS:
resolved |= TOOL_GROUPS[name]
else:
resolved.add(name)
return resolved
# ── Tool filtering ───────────────────────────────────────────────────────
@@ -236,8 +289,24 @@ def apply_tool_filters(
if not canonical:
return
# ── Group integrity check ───────────────────────────────────────────────
all_grouped: set[str] = set().union(*TOOL_GROUPS.values())
missing = canonical - all_grouped
assert not missing, f"Tools not in any group: {sorted(missing)}"
overlaps: set[str] = set()
for i, (g1, s1) in enumerate(TOOL_GROUPS.items()):
for g2, s2 in list(TOOL_GROUPS.items())[i + 1 :]:
overlaps |= s1 & s2
assert not overlaps, f"Tools in multiple groups: {sorted(overlaps)}"
allowed: set[str] = set(canonical)
# ── Resolve aliases ────────────────────────────────────────────────────
if enabled:
enabled = sorted(_resolve_aliases(enabled))
if disabled:
disabled = sorted(_resolve_aliases(disabled))
# ── Whitelist ──────────────────────────────────────────────────────────
if enabled:
enabled_set = {n.strip() for n in enabled if n.strip()}