Repository navigation
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before.
Related issues (not duplicates):
- [FEATURE]: Granular per-agent tool permissions (allow/deny individual tools) #17607 requests per-agent tool allow/deny with glob patterns — similar scope but focused on trust/role separation, not model tool limits. Our issue is complementary.
- [FEATURE]: Add
hiddenfield totool.definitionhook output for tool suppression #23297 requests ahiddenfield ontool.definitionhook — overlaps with our Option B, but withoutagentcontext in the input it cannot solve per-agent filtering. We need bothhidden+agentin the hook input.- [FEATURE]: Filter which tools are loaded from MCP servers (includeTools/excludeTools) #7399 (closed) requested
includeTools/excludeToolsper MCP server config — global, not per-agent.
Problem
When using models with a hard tool limit (e.g. GPT-4o mini / github-copilot/gpt-5-mini with a 128-tool cap), agents that don't need all configured MCP servers still receive every tool definition in their context. This causes the request to exceed the model's tool limit and fail.
Example setup:
- 3 MCP servers configured globally:
gitlab(~40 tools),jira(~30 tools),sonarqube(~20 tools) librarianagent usesgpt-5-mini(128-tool limit)librarianonly needs built-in tools + web search — it has no use for gitlab/jira/sonarqube- Total tools sent to
librarian: 90+ MCP tools + built-in tools → exceeds 128
What doesn't work today
permission: deny (opencode native + oh-my-openagent)
{
"agents": {
"librarian": {
"permission": { "gitlab_*": "deny", "jira_*": "deny" }
}
}
}Blocks execution of those tools but does not remove them from the tool list sent to the model. The model still sees all tool definitions and they still count toward the limit.
tools: { "gitlab_*": false } (oh-my-openagent agent override)
oh-my-openagent migrates this to permission: deny internally — same problem, same result.
tools: { "gitlab_*": false } (opencode native agent config)
The tools key is not a recognized opencode agent field. It is silently routed into options and has no effect whatsoever.
tool.definition plugin hook
Only receives toolID — no agent context. Cannot conditionally filter per agent.
Requested feature
One or more of the following:
Option A: Per-agent disabled_mcps in opencode agent config
{
"agent": {
"librarian": {
"disabled_mcps": ["gitlab", "jira", "sonarqube"]
}
}
}Mirrors the top-level disabled_mcps that oh-my-openagent already supports, but scoped to a single agent.
Option B: Agent context + hidden field in the tool.definition plugin hook
"tool.definition"?: (input: {
toolID: string;
agent: string; // add this — needed for per-agent filtering
}, output: {
description: string;
parameters: any;
hidden?: boolean; // add this (as also requested in #23297) — removes tool from LLM tool list
}) => Promise<void>;Would allow plugins to filter tools per agent without needing native config support. Note: hidden alone (#23297) is insufficient — the agent field in the input is also required.
Option C: Native tools filter in opencode agent config
{
"agent": {
"librarian": {
"tools": { "gitlab_*": false, "jira_*": false }
}
}
}A glob-based allowlist/denylist that removes matching tools from the tool list before it is sent to the model.
Why this matters
- Models with small tool limits (GPT-4o mini, o1-mini, etc.) are unusable as sub-agents when many MCP servers are configured globally
- Specialized agents (librarian, explore, reviewer) have well-defined tool needs — giving them 100+ irrelevant tools wastes context tokens and hits limits
- The current workaround (disabling MCPs globally) defeats the purpose of having them configured
Environment
- opencode (latest)
- oh-my-openagent plugin
- MCP servers: gitlab, jira, sonarqube
- Affected agent:
librarian(model:github-copilot/gpt-5-mini, 128-tool limit)
Activity
github-actions commentedon May 21, 2026
This issue doesn't fully meet our contributing guidelines.
What needs to be fixed:
[FEATURE]:for feature requests (e.g.[FEATURE]: Per-agent MCP tool filtering to stay within model tool limits)Please edit this issue to address the above within 2 hours, or it will be automatically closed.
This issue might be a duplicate of existing issues. Please check:
hiddenfield totool.definitionhook output for tool suppression #23297: Requests ahiddenfield on thetool.definitionhook to suppress tools from the LLM tool list — overlaps with your Option BincludeTools/excludeToolsper MCP server config — related but global rather than per-agentIf you believe this was flagged incorrectly, please let a maintainer know.
[-]Feature: per-agent MCP tool filtering to stay within model tool limits[/-][+][FEATURE]: Per-agent MCP tool filtering to stay within model tool limits[/+]github-actions commentedon May 21, 2026
Thanks for updating the issue! It now meets our contributing guidelines — the feature request template is properly filled out with a clear problem description, concrete examples, and proposed solutions. The needs:compliance label has been removed.
github-actions commentedon May 21, 2026
Thanks for updating the issue! It now meets the contributing guidelines — the problem is clearly described, the verification checkbox is checked, environment details are included, and the requested options are well-explained. No further changes needed.
abi-jey commentedon May 26, 2026
+1 for this
rekram1-node commentedon Jun 6, 2026
This is not true, the permissions will omit them from context
CrystalMethod commentedon Jun 18, 2026
I actually dug into the opencode source to verify this, and the claim that "permissions omit them from context" doesn't match the current implementation.
The smoking gun is in
packages/opencode/src/session/llm.ts:What it actually does:
prepared.toolscontains every MCP and built-in tool before any filtering. The code only strips out "ask" tools — both "allow" and "deny" pass through unchanged. That full record then gets mapped innative-runtime.tsand sent directly to the model. There's a UI filter inregistry.ts, but it only hides denied tools from the TUI sidebar; it doesn't touch the LLM payload.Right now the split is clear: the LLM receives all the definitions (and they count against the tool limit), but the runtime blocks the actual calls.
@rekram1-node can you show me the exact file and lines where this logic is implemented?
mocun33 commentedon Aug 20, 2026
Reproducing on 1.18.19 (desktop, Windows) — the "permissions will omit them from context" claim doesn't hold here.
Setup:
opencode.jsonchas"tools": { "paper-search_*": false, "openviking_*": false, "browsermcp_*": false, ... }(8 MCP servers)opencode debug configconfirms these are auto-migrated topermission: { "paper-search_*": "deny", ... }Observed:
llm.ts(onlyasktools are stripped;allow/denypass through unchanged).permission: denydoes block execution (calls are rejected), but the schema is still injected into the model context.Impact:
toolsbehavior (e.g. opencode-mcp-triage, which writes"servername_*": falseand advertises "0 tokens in main session") silently fail to deliver the claimed token savings on current versions — the deny entries migrate topermissionand only gate calls.Question: is this a known limitation or a regression? Is there any supported way to hide tool definitions from the model (not just block calls) — e.g. the
hiddenfield ontool.definition(#23297) — or should we treat schema injection as permanent until a native per-agent tool filter lands?opencode-agent commentedon Aug 20, 2026
The last two comments are inspecting the wrong code path. A full
denydoes remove matching tool definitions before the request is sent to the model in V1dev/ 1.18.19.The relevant path is:
resolveTools(input)and returns that filtered record asprepared.tools(lines 181–185).resolveToolsmerges agent and session permissions, computes disabled tools, and filters them out.Permission.disabledtreats the effective final matching rule as tool-disabling when its argument pattern is"*"and its action is"deny".The
sessionPreapprovedToolscode cited above is inside theGitLabWorkflowLanguageModelintegration. It controls workflow approval behavior and operates on the already-filteredprepared.tools; it is not the general LLM tool-list filter:llm.ts#L149-L153.I also ran this single-file Bun reproduction directly against commit
b155b15694dbcc6768f11d2f25cc2bdd1f738ab4(packages/opencodeversion 1.18.19). It calls the realLLMRequestPrep.prepare, rather than copying the filtering logic:repro-mcp-permission-filter.ts
Run from
packages/opencodeafter placing it underpackages/opencode/script/:The important qualification is that only a full tool deny hides the definition. Argument-specific denies (for example, deny only
bashcommands matchingrm *) andaskrules must leave the tool visible because other calls remain possible. For MCP tools, a rule such as"paper-search_*": "deny"becomes a full deny (pattern: "*") and matching MCP definitions are omitted.