DefaultInventoryFactory creates the default inventory factory for HTTP mode. When the ServerConfig includes static flags (--toolsets, --read-only, etc.), a static inventory is built once at factory creation to pre-filter the tool universe. Per-request headers can only narrow within these bounds.
(cfg *ServerConfig, t translations.TranslationHelperFunc, featureChecker inventory.FeatureFlagChecker, scopeFetcher scopes.FetcherInterface)
| 246 | // a static inventory is built once at factory creation to pre-filter the tool |
| 247 | // universe. Per-request headers can only narrow within these bounds. |
| 248 | func DefaultInventoryFactory(cfg *ServerConfig, t translations.TranslationHelperFunc, featureChecker inventory.FeatureFlagChecker, scopeFetcher scopes.FetcherInterface) InventoryFactoryFunc { |
| 249 | // Build the static tool/resource/prompt universe from CLI flags. |
| 250 | // This is done once at startup and captured in the closure. |
| 251 | staticTools, staticResources, staticPrompts := buildStaticInventory(cfg, t) |
| 252 | hasStaticFilters := hasStaticConfig(cfg) |
| 253 | |
| 254 | // Pre-compute valid tool names for filtering per-request tool headers. |
| 255 | // When a request asks for a tool by name that's been excluded from the |
| 256 | // static universe, we silently drop it rather than returning an error. |
| 257 | validToolNames := make(map[string]bool, len(staticTools)) |
| 258 | for i := range staticTools { |
| 259 | validToolNames[staticTools[i].Tool.Name] = true |
| 260 | } |
| 261 | |
| 262 | return func(r *http.Request) (*inventory.Inventory, error) { |
| 263 | b := inventory.NewBuilder(). |
| 264 | SetTools(staticTools). |
| 265 | SetResources(staticResources). |
| 266 | SetPrompts(staticPrompts). |
| 267 | WithDeprecatedAliases(github.DeprecatedToolAliases). |
| 268 | WithFeatureChecker(featureChecker) |
| 269 | |
| 270 | // When static flags constrain the universe, default to showing |
| 271 | // everything within those bounds (per-request filters narrow further). |
| 272 | // When no static flags are set, preserve existing behavior where |
| 273 | // the default toolsets apply. |
| 274 | if hasStaticFilters { |
| 275 | b = b.WithToolsets([]string{"all"}) |
| 276 | } |
| 277 | |
| 278 | // Static read-only is an upper bound — enforce before request filters |
| 279 | if cfg.ReadOnly { |
| 280 | b = b.WithReadOnly(true) |
| 281 | } |
| 282 | |
| 283 | // Filter request tool names to only those in the static universe, |
| 284 | // so requests for statically-excluded tools degrade gracefully. |
| 285 | if hasStaticFilters { |
| 286 | r = filterRequestTools(r, validToolNames) |
| 287 | } |
| 288 | |
| 289 | b = InventoryFiltersForRequest(r, b) |
| 290 | b = PATScopeFilter(b, r, scopeFetcher) |
| 291 | |
| 292 | b.WithServerInstructions() |
| 293 | |
| 294 | return b.Build() |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | // filterRequestTools returns a shallow copy of the request with any per-request |
| 299 | // tool names (from X-MCP-Tools header) filtered to only include tools that exist |
no test coverage detected