Skip to content

feat(http): enforce static CLI flags as upper bound for per-request filtering#2208

Open
SamMorrowDrums wants to merge 1 commit intomainfrom
http-static-flags-support
Open

feat(http): enforce static CLI flags as upper bound for per-request filtering#2208
SamMorrowDrums wants to merge 1 commit intomainfrom
http-static-flags-support

Conversation

@SamMorrowDrums
Copy link
Collaborator

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

Layer What it does
Static inventory (startup) Built once from CLI flags. Pre-filters tools/resources/prompts to create the allowed universe.
Per-request builder (each request) Starts from the static universe. Headers can narrow (e.g., select a toolset subset) but cannot expand.
Graceful degradation If a request header asks for a tool not in the static universe, it's silently dropped rather than returning an error.

Key design decisions

  • Static tools as upper bound: SetTools(staticTools) means per-request builders physically cannot see tools outside the static set
  • Backward compatible: No static flags → full tool universe (existing HTTP behavior unchanged)
  • Per-request defaults: When static flags are set, per-request builder defaults to WithToolsets(["all"]) within the static bounds, so all statically-allowed tools are visible unless headers narrow further
  • No exported API changes: New fields added to ServerConfig; DefaultInventoryFactory now uses the previously-ignored *ServerConfig parameter

Changes

  • pkg/http/server.go — Added ReadOnly, EnabledToolsets, EnabledTools, DynamicToolsets, ExcludeTools, InsidersMode to ServerConfig
  • pkg/http/handler.gobuildStaticInventory() pre-filters at startup; DefaultInventoryFactory captures static tools in closure; filterRequestTools() gracefully drops unknown tool names from request headers
  • cmd/github-mcp-server/main.go — Wired CLI flags to HTTP ServerConfig (matching stdio pattern)
  • pkg/http/handler_test.go — 13 new test cases covering static enforcement, non-overridability, narrowing, combinations, and backward compat

Relevant issues

Testing

$ script/lint → 0 issues $ script/test → all packages pass 
…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>
@SamMorrowDrums SamMorrowDrums requested a review from a team as a code owner March 13, 2026 09:38
Copilot AI review requested due to automatic review settings March 13, 2026 09:38
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ServerConfig and wired CLI flags in main.go
  • Built a startup-time static inventory in DefaultInventoryFactory that 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.

@nisarllc206-sys

This comment has been minimized.

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

Labels

None yet

3 participants