Repository navigation
[Feature]: profile suggest - aggregate blocked calls into reviewable profile fixes #1700
Description
Problem / motivation
Deny-by-default profiles are the right default (max_tier: read, unannotated: deny), but tuning them is a manual loop: an agent hits blocked by profile: fx:note_set is a write tool; profile "research" allows read tools only, the operator notices, runs mcpproxy access explain --tool fx:note_set --token research-agent, reads the fixes, then runs profile update or profile classify. access explain is good, but it answers one tool for one subject, so after an agent has run for a day the operator has to find the blocked calls (activity list --status blocked), de-duplicate them by hand and run explain on each.
What is missing is the aggregate view: "what did my agents get blocked on in the last 7 days, how often, and what is the smallest change that would admit each tool?".
Proposed solution
A read-only command, for example mcpproxy profile suggest [<name>] [--from -7d] [--token T] (or access suggest), that reads the blocked policy_decision records, groups them by profile, server, tool and block_reason, and prints one row per group with the count, the tokens involved and the last time seen, followed by the same fix access explain would give for that group: profile update <p> --add-allow server:tool for profile_tier, profile classify <p> server:tool <tier> for profile_unannotated, --add-server for profile_server_scope. Deny-rule blocks (profile_rule) would be reported but not suggested for widening, and profile_code_execution / profile_management would carry a warning. -o json for scripts and the UI, where it could sit next to the profile's "blocked 24h" counter.
It must never apply anything by itself: the output is a list the operator reads, trims and runs. It adds no new data and no new enforcement, only aggregation over records and fixes that already exist.
I wrote a ~100-line bash + jq prototype over activity list --status blocked -o json that does the grouping and prints the commands (it works from block_reason and the refusal text, not from explain's fix list, so it cannot see the preferred fix when several apply). I can turn it into a real subcommand sharing the access explain fix builder if you want it in the CLI.
Alternatives considered
- Keep it as an external script. That is what I am doing now; it duplicates the reason-to-fix mapping and will drift from
access explainwhen fixes change. - A "learning mode" profile that logs instead of blocking. Faster to tune but it runs the calls, so it is the wrong tool for the destructive ones, and it is a different enforcement mode to maintain.
- UI only (a "blocked calls" tab on the profile page). Useful, but a CLI/JSON form is what an operator running headless or scripting a review needs.
Which edition?
Both (personal and server).
- I searched existing issues and discussions for a similar request (nothing found; related:
access explain/fix_actionfrom the profiles work)
Activity
Dumbris commentedon Oct 20, 2026
This is exactly the kind of tooling I want around profiles: keep them strict, make the review loop cheap, never auto-apply. Two small preferences before you start. I would put it next to the explainer as mcpproxy access suggest rather than under profile, since access already owns the fix builder, and build it as one server-side service so the CLI, REST and the profiles MCP tool are thin renders of the same thing. Re-run Explain per group so already-fixed tools drop out, and for the server-scope case stay admin-only and never pre-fill a tier for an unannotated tool. Looking forward to the PR.