Skip to content

Commit 5719a88

Browse files
committed
add suppport for tool aliases for backwards compatibility when tool names change
1 parent 82c4930 commit 5719a88

File tree

2 files changed

+81
-6
lines changed

2 files changed

+81
-6
lines changed

pkg/github/tools.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,14 @@ func GetDefaultToolsetIDs() []string {
160160
}
161161
}
162162

163+
// DeprecatedToolAliases maps old tool names to their new canonical names.
164+
// This allows tool renames without breaking existing user configurations.
165+
// When a user requests an old tool name, it will silently resolve to the new name.
166+
var DeprecatedToolAliases = map[string]string{
167+
"test_1": "get_me",
168+
"test_2": "get_me",
169+
}
170+
163171
func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetGQLClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc, contentWindowSize int, flags FeatureFlags, cache *lockdown.RepoAccessCache) *toolsets.ToolsetGroup {
164172
tsg := toolsets.NewToolsetGroup(readOnly)
165173

@@ -378,6 +386,9 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
378386
tsg.AddToolset(stargazers)
379387
tsg.AddToolset(labels)
380388

389+
// Register deprecated tool aliases for backward compatibility
390+
tsg.AddDeprecatedToolAliases(DeprecatedToolAliases)
391+
381392
return tsg
382393
}
383394

pkg/toolsets/toolsets.go

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,19 +192,42 @@ func (t *Toolset) AddReadTools(tools ...ServerTool) *Toolset {
192192
}
193193

194194
type ToolsetGroup struct {
195-
Toolsets map[string]*Toolset
196-
everythingOn bool
197-
readOnly bool
195+
Toolsets map[string]*Toolset
196+
deprecatedAliases map[string]string // oldName → newName for renamed tools
197+
everythingOn bool
198+
readOnly bool
198199
}
199200

200201
func NewToolsetGroup(readOnly bool) *ToolsetGroup {
201202
return &ToolsetGroup{
202-
Toolsets: make(map[string]*Toolset),
203-
everythingOn: false,
204-
readOnly: readOnly,
203+
Toolsets: make(map[string]*Toolset),
204+
deprecatedAliases: make(map[string]string),
205+
everythingOn: false,
206+
readOnly: readOnly,
205207
}
206208
}
207209

210+
// AddDeprecatedToolAlias registers an alias for a renamed tool.
211+
// When a user requests oldName, it will resolve to newName.
212+
// This allows tool renames without breaking existing user configurations.
213+
func (tg *ToolsetGroup) AddDeprecatedToolAlias(oldName, newName string) {
214+
tg.deprecatedAliases[oldName] = newName
215+
}
216+
217+
// AddDeprecatedToolAliases registers multiple aliases for renamed tools.
218+
func (tg *ToolsetGroup) AddDeprecatedToolAliases(aliases map[string]string) {
219+
for oldName, newName := range aliases {
220+
tg.deprecatedAliases[oldName] = newName
221+
}
222+
}
223+
224+
// IsDeprecatedToolAlias checks if a tool name is a deprecated alias.
225+
// Returns the canonical name and true if it's an alias, or empty string and false otherwise.
226+
func (tg *ToolsetGroup) IsDeprecatedToolAlias(toolName string) (canonicalName string, isAlias bool) {
227+
canonicalName, isAlias = tg.deprecatedAliases[toolName]
228+
return canonicalName, isAlias
229+
}
230+
208231
func (tg *ToolsetGroup) AddToolset(ts *Toolset) {
209232
if tg.readOnly {
210233
ts.SetReadOnly()
@@ -307,9 +330,23 @@ func NewToolDoesNotExistError(name string) *ToolDoesNotExistError {
307330
return &ToolDoesNotExistError{Name: name}
308331
}
309332

333+
// ToolLookupResult contains the result of a tool lookup operation.
334+
type ToolLookupResult struct {
335+
Tool *ServerTool
336+
ToolsetName string
337+
RequestedName string // The name that was requested (may differ from Tool.Name if alias was used)
338+
AliasUsed bool // True if the requested name was a deprecated alias
339+
}
340+
310341
// FindToolByName searches all toolsets (enabled or disabled) for a tool by name.
342+
// It resolves deprecated aliases automatically.
311343
// Returns the tool, its parent toolset name, and an error if not found.
312344
func (tg *ToolsetGroup) FindToolByName(toolName string) (*ServerTool, string, error) {
345+
// Resolve deprecated alias if applicable
346+
if canonicalName, isAlias := tg.deprecatedAliases[toolName]; isAlias {
347+
toolName = canonicalName
348+
}
349+
313350
for toolsetName, toolset := range tg.Toolsets {
314351
// Check read tools
315352
for _, tool := range toolset.readTools {
@@ -327,9 +364,36 @@ func (tg *ToolsetGroup) FindToolByName(toolName string) (*ServerTool, string, er
327364
return nil, "", NewToolDoesNotExistError(toolName)
328365
}
329366

367+
// FindToolWithAliasInfo searches all toolsets for a tool by name and returns
368+
// additional metadata about whether a deprecated alias was used.
369+
// Use this when you need to track/log deprecated alias usage (e.g., for telemetry).
370+
func (tg *ToolsetGroup) FindToolWithAliasInfo(toolName string) (*ToolLookupResult, error) {
371+
requestedName := toolName
372+
aliasUsed := false
373+
374+
// Check if this is a deprecated alias and resolve to canonical name
375+
if canonicalName, isAlias := tg.deprecatedAliases[toolName]; isAlias {
376+
toolName = canonicalName
377+
aliasUsed = true
378+
}
379+
380+
tool, toolsetName, err := tg.FindToolByName(toolName)
381+
if err != nil {
382+
return nil, NewToolDoesNotExistError(requestedName)
383+
}
384+
385+
return &ToolLookupResult{
386+
Tool: tool,
387+
ToolsetName: toolsetName,
388+
RequestedName: requestedName,
389+
AliasUsed: aliasUsed,
390+
}, nil
391+
}
392+
330393
// RegisterSpecificTools registers only the specified tools.
331394
// Respects read-only mode (skips write tools if readOnly=true).
332395
// Returns error if any tool is not found.
396+
// Deprecated tool aliases are resolved automatically.
333397
func (tg *ToolsetGroup) RegisterSpecificTools(s *mcp.Server, toolNames []string, readOnly bool) error {
334398
var skippedTools []string
335399
for _, toolName := range toolNames {

0 commit comments

Comments
 (0)