HarperFast / HarperFast/harper
MCP: let an agent discover unavailable operations and request access (human-approved)
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
## Idea (from @dawsontoth, [harper#1554 review](https://github.com/HarperFast/harper/pull/1554#discussion_r3531035096))
Give an MCP client (LLM/agent) a way to see which operations it *doesn't* have access to, and a way to request access to them — with human approval (or by instructing the human to update a config).
## Why it doesn't work today
Two independent layers make an operation unavailable, and neither is introspectable by the client:
1. **Config filter** — `mcp.operations.allow` / `deny` globs plus the `DEFAULT_EXCLUDED` set (e.g. the secret ops). Applied at *tool-registration* time (`components/mcp/tools/operations.ts` — `if (!isOperationAllowed(operationName, config)) continue;`): a denied op is **never registered as a tool**, so it never appears in `tools/list`. The client has no signal it exists.
2. **RBAC** — the authenticated user's permissions, applied at *invocation* time (`chooseOperation` throws permission-denied even for a registered tool).
There is no discovery of what's filtered out, and no request/escalation path. Changing access is a manual human action (edit allow/deny, or adjust the caller's role).
## Proposed shape
- **`list_unavailable_operations`** — returns the operations filtered out for the current session, each tagged with the *reason* (config-denied vs RBAC-denied) so the agent can reason about what it needs. Must not leak anything sensitive beyond operation names/descriptions the operator is willing to expose.
- **`request_operation_access`** — stages an access change (a config edit to `mcp.operations.allow`, or a role grant) that a **human approves** before it takes effect. Given secret ops are default-deny + super_user-gated, human-in-the-loop is the right default; the plain fallback is to emit a clear instruction telling the human which config/role to change.
## Dependencies / sequencing
- Overlaps **#1545** (RBAC-filtered ops registry folded into the agent toolset) — that owns the RBAC dimension of "what's available."
- Ties into the agent-auth direction (scoped agent user + JWT, relaxing the hard super_user gate) — that's where "who requests / who approves" is decided.
- Should land **after** those rather than being bolted onto the secrets-store PR (#1554).
Not small, but coherent. Filing to track.
Contributor guide
Research direction
Start with components/mcp/tools/operations.ts, especially registration filtering and chooseOperation, then read the dependency noted in #1545 and the agent-auth direction. Define how unavailable operations are reported by reason and how access requests remain human-approved without exposing sensitive details. Done should cover both config-filtered and RBAC-denied cases after those dependencies land.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- api, authorization, backend, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100