Skip to content

feat(mcp): agent-discoverable disabled tools (spec 049)#476

Merged
Dumbris merged 11 commits into
mainfrom
049-agent-discoverable-disabled-tools
May 18, 2026
Merged

feat(mcp): agent-discoverable disabled tools (spec 049)#476
Dumbris merged 11 commits into
mainfrom
049-agent-discoverable-disabled-tools

Conversation

@Dumbris
Copy link
Copy Markdown
Member

@Dumbris Dumbris commented May 18, 2026

Follow-up to #468. Lets agents discover, on demand, tools that exist but are locked, with machine-branchable status + remediation — at zero token cost on the default path.

Spec: specs/049-agent-discoverable-disabled-tools/ (speckit: spec/plan/tasks/research/data-model/contracts/quickstart).

What changed

  • retrieve_tools: opt-in include_disabled (default false). When true, returns a disabled[] list (name/server/description/status) after callable results (capped min(limit,10)) + a once-per-response remediation map keyed only by present statuses. Default output is byte-for-byte unchanged.
  • 5-state classifier (ClassifyDisabledTool): server_disableddisabled_by_configdisabled_by_userpending_approvaldisabled_unknown, fixed precedence; single source of truth shared by both surfaces.
  • upstream_servers list/get: conditional per-server tools count block, emitted only when a non-callable count > 0 (all-callable servers gain 0 bytes).
  • Reactive discovery: status-aware TOOL_BLOCKED now appends an include_disabled:true pointer; zero-callable-result responses carry a one-line count nudge.
  • No enforcement change (isToolCallable untouched), no new persistent storage, in-memory-only usage counter.

Testing

  • Unit: internal/runtime classifier (5-state precedence + bench 6.6 ns/op), internal/server discovery (default-unchanged, opt-in, cap, counter, nudge, blocked-message pointer, server counts), internal/contracts. All PASS.
  • verify-oas: PASS (MCP-only shapes; no REST swagger change).
  • Live curl + MCP: §1–§5 PASS — see quickstart.md verification table.
  • Note: a pre-existing feat(config): layered config tool filter — config_denied over user toggles #468 config→runtime disabled_tools load gap for stdio config-file servers is documented in quickstart.md; out of 049 scope.

Related #468

claude and others added 10 commits May 18, 2026 15:07
Follow-up to PR #468. Opt-in include_disabled on retrieve_tools +
conditional counts on upstream_servers, 5-state classifier, reactive
discovery nudges. Token-cost-zero until exercised.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Converts the brainstormed design (docs/superpowers/specs/2026-05-18-...)
into canonical speckit format. Opt-in include_disabled discovery,
5-state status + remediation map, conditional per-server counts,
reactive nudges. No enforcement/storage change.

Related #468

## Changes
- specs/049-agent-discoverable-disabled-tools/spec.md
- specs/049-agent-discoverable-disabled-tools/checklists/requirements.md

## Testing
- N/A (spec only); requirements checklist all items pass
Related #468

## Changes
- plan.md (constitution check PASS, no violations)
- research.md (decisions + codebase facts; no open unknowns)
- data-model.md (5-state status enum, additive response shapes)
- contracts/mcp-deltas.md (retrieve_tools + upstream_servers deltas)
- quickstart.md (curl + live-MCP verification recipe)
- CLAUDE.md active-technologies updated by speckit agent-context

## Testing
- N/A (planning docs only)
Related #468

## Changes
- tasks.md: Setup, Foundational (classifier+types), US1 MVP, US2, US3, Polish

## Testing
- N/A (task plan only)
Related #468

## Changes
- contracts: DisabledToolStatus consts, LockedToolEntry, ServerToolCounts
- runtime: ClassifyDisabledTool (pure, 5-state precedence, read-only)
- tests: precedence/unknown/pending table + 1k benchmark (6.6 ns/op)

## Testing
- go test ./internal/runtime -run TestClassifyDisabledTool: PASS
- BenchmarkClassifyDisabledTool: 6.6 ns/op (<<100ms budget)
Related #468

## Changes
- retrieve_tools: include_disabled param + one-line schema hint
- handler: split callable/disabled, agent-scope before classify,
  cap min(limit,10), once-per-response remediation map
- p.classifyDisabledTool (storage-sourced, mirrors runtime classifier)
- in-memory include_disabled usage counter (no persistence)

## Testing
- TestDisabledDiscovery_{DefaultPathUnchanged,OptIn,CapAtTen,UsageCounter}: PASS
- regressions (ExcludesDisabled, CallBlockedTool, BlockedToolMessageFor): PASS
Related #468

## Changes
- blockedToolMessageFor: append include_disabled:true pointer (both branches)
- retrieve_tools: when 0 callable + droppedCount>0 + flag off, emit a
  one-line 'notice' count nudge (no inline entries)

## Testing
- TestBlockedToolMessage_DiscoveryPointer, TestDisabledDiscovery_ZeroResultNudge: PASS
Related #468

## Changes
- upstream_servers list/get: emit ServerToolCounts only when a
  non-callable count > 0 (all-callable servers gain 0 bytes)
- classifyServerToolStatus: single storage-sourced truth (runtime-
  independent); classifyDisabledTool now delegates to it (no drift)

## Testing
- TestServerToolCounts_Conditional + full server/runtime suites: PASS
Related #468

## Changes
- quickstart.md: verification-results table (§1-§5 PASS), documents the
  pre-existing #468 config->runtime disabled_tools gap (out of 049 scope)
- tasks.md: all phases checked off

## Testing
- runtime/server/contracts unit suites: PASS; verify-oas: PASS
- live MCP+curl: default unchanged, include_disabled, counts, blocked msg
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 18, 2026

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1f2e07e
Status: ✅  Deploy successful!
Preview URL: https://6025f6d0.mcpproxy-docs.pages.dev
Branch Preview URL: https://049-agent-discoverable-disab.mcpproxy-docs.pages.dev

View logs

@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 70.13889% with 43 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/server/mcp.go 64.75% 37 Missing and 6 partials ⚠️

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 18, 2026

📦 Build Artifacts

Workflow Run: View Run
Branch: 049-agent-discoverable-disabled-tools

Available Artifacts

  • archive-darwin-amd64 (26 MB)
  • archive-darwin-arm64 (23 MB)
  • archive-linux-amd64 (15 MB)
  • archive-linux-arm64 (13 MB)
  • archive-windows-amd64 (26 MB)
  • archive-windows-arm64 (23 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (20 MB)
  • installer-dmg-darwin-arm64 (18 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 26034750884 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

…er notes)

Related #468

check-size is pre-existing/advisory (CLAUDE.md was 39347 chars at base,
already >25k; #468 merged through the same failing check). This commit
minimizes 049's footprint regardless.
@Dumbris Dumbris merged commit 95f5fa4 into main May 18, 2026
40 checks passed
Dumbris added a commit that referenced this pull request May 18, 2026
…477)

The merged #476 classifyServerToolStatus read config-denial only from the
storage ServerConfig copy. Config-file disabled_tools on stdio servers
live in the live runtime config and are not always mirrored to storage,
so disabled_by_config classification + upstream_servers counts were wrong
at runtime for that case (unit tests passed because the no-runtime
harness uses the storage fallback path).

Prefer p.mainServer.runtime.IsToolConfigDenied (same authority
isToolCallable/blockedToolMessage use); fall back to storage
IsToolAllowedByConfig only when no runtime is wired.

Adds a runtime regression test pinning that ClassifyDisabledTool reads
live config (the authority the server layer now delegates to).

Related #468
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants