feat(http): enforce static CLI flags as upper bound for per-request filtering#2208
Open
SamMorrowDrums wants to merge 1 commit intomainfrom
Open
feat(http): enforce static CLI flags as upper bound for per-request filtering#2208SamMorrowDrums wants to merge 1 commit intomainfrom
SamMorrowDrums wants to merge 1 commit intomainfrom
Conversation
…iltering The HTTP server now respects the same static CLI flags as the stdio server: --toolsets, --tools, --exclude-tools, --read-only, --dynamic-toolsets, and --insiders. A static inventory is built once at startup from these flags, producing a pre-filtered tool/resource/prompt universe. Per-request headers (X-MCP-Toolsets, X-MCP-Tools, etc.) can only narrow within these bounds, never expand beyond them. When no static flags are set, the existing behavior is preserved — headers have full access to all toolsets. Fixes #2156 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes #2156 by wiring the static CLI flags (--read-only, --toolsets, --tools, --exclude-tools, --dynamic-toolsets, --insiders) into the HTTP server, ensuring they act as an upper bound on per-request header-based filtering.
Changes:
- Added static filtering fields to
ServerConfigand wired CLI flags inmain.go - Built a startup-time static inventory in
DefaultInventoryFactorythat constrains per-request tool visibility - Added 13 table-driven tests covering static enforcement, non-overridability, narrowing, and backward compatibility
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
pkg/http/server.go |
Added 6 new fields to ServerConfig for static filtering; enhanced startup log |
pkg/http/handler.go |
Implemented buildStaticInventory, hasStaticConfig, filterRequestTools; updated DefaultInventoryFactory to use static bounds |
cmd/github-mcp-server/main.go |
Wired CLI flags to HTTP ServerConfig matching stdio pattern |
pkg/http/handler_test.go |
Added mockToolFull helper and TestStaticConfigEnforcement with 13 test cases |
You can also share your feedback on Copilot code review. Take the survey.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The HTTP server now respects the same static CLI flags as the stdio server:
--toolsets,--tools,--exclude-tools,--read-only,--dynamic-toolsets, and--insiders.A static inventory is built once at startup from these flags, producing a pre-filtered tool/resource/prompt universe. Per-request headers (
X-MCP-Toolsets,X-MCP-Tools, etc.) can only narrow within these bounds, never expand beyond them. When no static flags are set, existing behavior is preserved — headers have full access to all toolsets.Problem
Users deploying the HTTP server expected
--read-only,--toolsets, and other CLI flags to work the same as in stdio mode. Instead, these flags were ignored entirely — any request header could access any tool regardless of server configuration.Approach
Key design decisions
SetTools(staticTools)means per-request builders physically cannot see tools outside the static setWithToolsets(["all"])within the static bounds, so all statically-allowed tools are visible unless headers narrow furtherServerConfig;DefaultInventoryFactorynow uses the previously-ignored*ServerConfigparameterChanges
pkg/http/server.go— AddedReadOnly,EnabledToolsets,EnabledTools,DynamicToolsets,ExcludeTools,InsidersModetoServerConfigpkg/http/handler.go—buildStaticInventory()pre-filters at startup;DefaultInventoryFactorycaptures static tools in closure;filterRequestTools()gracefully drops unknown tool names from request headerscmd/github-mcp-server/main.go— Wired CLI flags to HTTPServerConfig(matching stdio pattern)pkg/http/handler_test.go— 13 new test cases covering static enforcement, non-overridability, narrowing, combinations, and backward compatRelevant issues
--read-onlyflag fails to restrict write tools in HTTP modeTesting