Add the power discovery profile (catalog meta-tools) - #504
Conversation
5dcad59 to
255f803
Compare
4f11894 to
f0af312
Compare
adriannoes
left a comment
There was a problem hiding this comment.
The power profile lands cleanly as a distinct post-floor branch: nine visible tools, meta-tools outside PIPEFY_TOOL_NAMES, and execute_tool preserving INVALID_ARGUMENTS / TOOL_NOT_FOUND through PipefyValidationTool.run. Unit coverage for the surface and floor withhold path looks solid.
One startup contract needs a fix before merge. When wants_power wins, resolve_selection never runs, so PIPEFY_MCP_TOOLSETS=power,typo starts the server while workflow,typo still raises and --toolsets power,typo still fails in main. That is a fail-open hole relative to the env fail-closed path established for domain selection. Details on the inline.
Also noted (non-blocking):
- execute_tool's broad except Exception soft-wraps unexpected ToolError raises into a code-less envelope. No catalog tool raises UrlElicitationRequiredError today, so this is polish rather than a live protocol break.
- --toolsets help and the settings Field still read as domains-only after power/architect ship in docs/config.md. Worth aligning at the operator edge.
- power (or architect) co-listed with a domain silently becomes full power. Intentional per AGENTS.md; a one-line warning in config.md or --help would help operators.
| if wants_power(toolsets): | ||
| registry.apply_power_profile() | ||
| else: | ||
| registry.apply_toolset_selection(toolsets) |
There was a problem hiding this comment.
When wants_power(toolsets) is true this branch calls apply_power_profile and never apply_toolset_selection, so resolve_selection never runs. A value like PIPEFY_MCP_TOOLSETS=power,typo therefore starts the server, while workflow,typo still raises and --toolsets power,typo still fails in main.py. That breaks the documented contract that a bad env toolsets value surfaces the same unknown-toolset error at server build.
On the prior stack slice that introduced domain selection, unknown env tokens still fail closed at build (ugly exit 1 vs flag exit 2, but the process does not start). The power short-circuit turns that into silent acceptance of the typo while applying full power.
I would validate tokens before the power/domain branch (for example always call resolve_selection(toolsets) for its ValueError, or fold power into one profile resolver that rejects unknown names first), then keep the existing power XOR domain behavior for valid specs.
Done when:
- PIPEFY_MCP_TOOLSETS=power,typo (no CLI flag) fails at build with the unknown-toolset message
- a regression test covers that path
- power / architect alone still yield the nine-tool surface
255f803 to
d46d07c
Compare
f0af312 to
2ed1f2a
Compare
d46d07c to
edfcb82
Compare
2ed1f2a to
a44fe38
Compare
adriannoes
left a comment
There was a problem hiding this comment.
Thanks Roberto. The power,typo fail-closed path is in place now: resolve_selection runs before apply_power_profile, with a regression test on the build path, and the help/settings copy calls out power/architect.
The power profile itself still looks right: nine-tool surface, post-floor catalog snapshot, meta-tools outside PIPEFY_TOOL_NAMES, and execute_tool keeping the validation envelopes. Happy to approve on a44fe38.
Optional polish only (non-blocking): narrow execute_tool's broad except Exception for unexpected ToolError raises, and a one-line operator note that power co-listed with a domain still means full power.
Add --toolsets power (alias architect): hide the curated tools behind four catalog meta-tools in tools/meta_tools.py — get_tool_categories, search_tools, describe_tool, execute_tool — kept visible alongside the raw-GraphQL tools (POWER_GRAPHQL_TOOLS), so the model-facing set is nine tools regardless of catalog size. ToolRegistry.apply_power_profile snapshots the curated tools that survived the floor, removes them from tools/list, and registers the meta-tools over that snapshot; server.py routes to this branch via wants_power before the domain path. execute_tool dispatches through each hidden tool's own PipefyValidationTool.run, so argument validation and the error envelope apply exactly as a direct call. Because the snapshot is taken after apply_remote_profile, execute_tool can never reach a floor-withheld tool. The meta-tools are profile-only and not in PIPEFY_TOOL_NAMES, so the partition drift-guard and remote seed are unaffected. Part of #308.
a44fe38 to
f499ec4
Compare
|
Applied both optional items on
Thanks for the thorough pass. |
adriannoes
left a comment
There was a problem hiding this comment.
Re-checked on f499ec4. Still good to merge.
The power,typo fail-closed path remains in place, and the latest push tightens two follow-ups: execute_tool now dispatches transparently (raises propagate like a direct call; validation envelopes still return from PipefyValidationTool), and docs/config.md spells out that co-listing power with a domain applies the full power profile.
Approving again on the current head.
adriannoes
left a comment
There was a problem hiding this comment.
LGTM, little robert.
Motivation
Even a curated toolset can be too large for a client that eagerly loads every schema, and some MCP clients cannot defer tool loading at all. Those clients need a model-facing working set that stays small no matter how many tools exist — without losing reach to the rest.
Outcome
--toolsets power(aliasarchitect) hides the curated tools behind four catalog meta-tools —get_tool_categories,search_tools,describe_tool,execute_tool— kept visible alongside the raw-GraphQL tools, so the model-facing set is nine tools regardless of catalog size. The model discovers tools by category or keyword and dispatches by name;execute_toolruns each hidden tool through its own argument validation and error envelope, exactly as a direct call would. The catalog is snapshotted after the remote floor, soexecute_toolcan never reach a tool the profile withholds. Power is a distinct branch from domain selection and, like it, runs after the floor. The meta-tools are profile-only, so they are not counted inPIPEFY_TOOL_NAMESand do not touch the partition drift-guard or the remote seed.Part of #308. Completes the two client-independent discovery mechanisms; overlapping persona profiles follow in a later stacked PR.
Stacked on #502; CI fires once the stack merges down to
dev.Live validation (in-process MCP sessions → live API)
execute_tooldispatched through to the live Pipefy API and returned real data (test pipe303088927):--toolsets powersurfacesearch_tools("pipe")get_pipe(25 hits)get_tool_categoriesexecute_tool→ liveget_pipe"000 aqui"returnedexecute_toolmissing required argINVALID_ARGUMENTSenvelopeexecute_toolunknown nameTOOL_NOT_FOUND