{"record":{"id":"b5f8608dea230e9b","repo":"github/github-mcp-server","slug":"unknown-tools-specified-in-withtools-s","errorCode":null,"errorMessage":"unknown tools specified in WithTools: %s","messagePattern":"unknown tools specified in WithTools: (.+?)","errorType":"http","errorClass":"ErrUnknownTools","httpStatus":400,"severity":"error","filePath":"pkg/inventory/builder.go","lineNumber":267,"sourceCode":"\t\tvar unrecognizedTools []string\n\t\tfor _, name := range cleanedTools {\n\t\t\t// Always include the original name - this handles the case where\n\t\t\t// the tool exists but is controlled by a feature flag that's OFF.\n\t\t\tr.additionalTools[name] = true\n\t\t\t// Also include the canonical name if this is a deprecated alias.\n\t\t\t// This handles the case where the feature flag is ON and only\n\t\t\t// the new consolidated tool is available.\n\t\t\tif canonical, isAlias := b.deprecatedAliases[name]; isAlias {\n\t\t\t\tr.additionalTools[canonical] = true\n\t\t\t} else if !validToolNames[name] {\n\t\t\t\t// Not a valid tool and not a deprecated alias - track as unrecognized\n\t\t\t\tunrecognizedTools = append(unrecognizedTools, name)\n\t\t\t}\n\t\t}\n\n\t\t// Error out if there are unrecognized tools\n\t\tif len(unrecognizedTools) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"%w: %s\", ErrUnknownTools, strings.Join(unrecognizedTools, \", \"))\n\t\t}\n\t}\n\n\tif b.generateInstructions {\n\t\tr.instructions = generateInstructions(r)\n\t}\n\n\treturn r, nil\n}\n\n// processToolsets processes the toolsetIDs configuration and returns:\n// - enabledToolsets map (nil means all enabled)\n// - unrecognizedToolsets list for warnings\n// - allToolsetIDs sorted list of all toolset IDs\n// - toolsetIDSet map for O(1) HasToolset lookup\n// - defaultToolsetIDs sorted list of default toolset IDs\n// - toolsetDescriptions map of toolset ID to description\nfunc (b *Builder) processToolsets() (map[ToolsetID]bool, []string, []ToolsetID, map[ToolsetID]bool, []ToolsetID, map[ToolsetID]string) {","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/inventory/builder.go#L249-L285","documentation":"inventory.Builder.Build() validates every tool name passed via WithTools against the registered catalog (validToolNames). Names that are neither registered tools nor entries in the deprecatedAliases map are collected and returned in one error wrapping the ErrUnknownTools sentinel, comma-joined. Known deprecated aliases are transparently remapped to their canonical tool, so only truly unknown names reach this error.","triggerScenarios":"Calling WithTools with a typo ('search_reopsitories'), a name that was renamed without a registered alias, or a name from a newer release's docs used against an older binary.","commonSituations":"Tool allowlists in config/env written against a different server version; copy-paste of tool IDs whose names include a suffix people drop; host-type-specific tools requested on a host that does not offer them.","solutions":["Diff your tool list against the deployed server's tools/list response - the exact registered names appear there","Check the deprecatedAliases map in pkg/inventory/builder.go and pkg/toolsets registrations for renames; switch to the canonical name","Align the allowlist with the server version you actually deploy (pin the version)","For renamed tools use the new canonical name - only aliases registered in deprecatedAliases are auto-mapped"],"exampleFix":"// before\ninv, err := inventory.NewBuilder().\n\tSetTools(...).\n\tWithTools([]string{\"search_reopsitories\"}).Build()\n\n// after\ninv, err := inventory.NewBuilder().\n\tSetTools(...).\n\tWithTools([]string{\"search_repositories\"}).Build()","handlingStrategy":"validation","validationCode":"// seed the allowed set from the same registry the builder uses\nvalid := map[string]bool{}\nfor _, name := range registeredToolNames(t, hostType) { // from github.AllTools(...)\n\tvalid[name] = true\n}\nfor _, name := range wantedTools {\n\tif !valid[name] {\n\t\treturn fmt.Errorf(\"tool %q is not registered in this server version/host\", name)\n\t}\n}","typeGuard":"func isUnknownTools(err error) bool { return errors.Is(err, inventory.ErrUnknownTools) }","tryCatchPattern":"if _, err := b.Build(); err != nil {\n\tif errors.Is(err, inventory.ErrUnknownTools) {\n\t\t// the comma-separated names after the colon are exactly the bad entries - fix each\n\t}\n\treturn err\n}","preventionTips":["Generate tool allowlists from the deployed version's tools/list output rather than hand-typing names","Pin the server version so documentation and binary agree","Prefer toolset-level config over individual tool names where possible"],"tags":["go","inventory","validation","toolsets","configuration"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}