feat(mcp): publish ops skills via /mcp resources, prompts and getNetxSkill

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
oliver 2026-10-16 23:14:39 +08:00
parent 42d5f9c5a7
commit 166d2289c3
11 changed files with 1057 additions and 25 deletions

View file

@ -99,11 +99,11 @@ def parse_groups_param(raw: str | None) -> frozenset[str]:
return frozenset(p for p in parts if p in VALID_GROUPS)
def tools_for_request(
def capability_tools_for_request(
scopes: frozenset[str] | list[str] | None,
groups: frozenset[str] | None = None,
) -> list[dict[str, Any]]:
"""Filter by scopes and optional groups. scopes=None advertises all (offline)."""
"""Filter capability tools by scopes and optional groups. scopes=None → all (offline)."""
wanted_groups = groups or frozenset()
if scopes is None:
scoped = list(ALL_TOOLS)
@ -122,6 +122,19 @@ def tools_for_request(
return [t for t in scoped if t.get("_group") in wanted_groups]
def tools_for_request(
scopes: frozenset[str] | list[str] | None,
groups: frozenset[str] | None = None,
) -> list[dict[str, Any]]:
"""Capability tools plus getNetxSkill when ≥1 skill is visible (ignores ?groups= for meta)."""
from .skills import get_netx_skill_tool_dict, should_advertise_get_netx_skill
scoped = capability_tools_for_request(scopes, groups)
if should_advertise_get_netx_skill(scopes, groups):
return scoped + [get_netx_skill_tool_dict()]
return scoped
def to_mcp_tool(tool: dict[str, Any]) -> Tool:
ann = tool.get("annotations") or {}
return Tool(
@ -140,7 +153,16 @@ def to_mcp_tool(tool: dict[str, Any]) -> Tool:
def call_tool(name: str, args: dict[str, Any]) -> dict[str, Any]:
handler = _HANDLERS.get(str(name or "").strip())
from .skills import GET_NETX_SKILL_NAME, call_get_netx_skill
from .context import get_request_context
key = str(name or "").strip()
if key == GET_NETX_SKILL_NAME:
ctx = get_request_context()
scopes = None if ctx is None else ctx.scopes
groups = frozenset() if ctx is None else ctx.groups
return call_get_netx_skill(args, scopes, groups)
handler = _HANDLERS.get(key)
if handler is None:
raise ValueError(f"unknown tool: {name}")
return handler(name, args)