Skip to content

Commit 8a0edfb

Browse files
committed
formalise insiders inventory support
1 parent e20cef3 commit 8a0edfb

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed

pkg/github/issues.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -602,8 +602,10 @@ func ListIssueTypes(t translations.TranslationHelperFunc) inventory.ServerTool {
602602
}
603603

604604
// ListAssignees creates a tool to list available assignees for a repository.
605+
// This tool is only available when insiders mode is enabled as it's a helper
606+
// for the MCP Apps UI.
605607
func ListAssignees(t translations.TranslationHelperFunc) inventory.ServerTool {
606-
return NewTool(
608+
st := NewTool(
607609
ToolsetMetadataIssues,
608610
mcp.Tool{
609611
Name: "list_assignees",
@@ -679,11 +681,15 @@ func ListAssignees(t translations.TranslationHelperFunc) inventory.ServerTool {
679681

680682
return utils.NewToolResultText(string(out)), nil, nil
681683
})
684+
st.InsidersOnly = true
685+
return st
682686
}
683687

684688
// ListMilestones creates a tool to list milestones for a repository.
689+
// This tool is only available when insiders mode is enabled as it's a helper
690+
// for the MCP Apps UI.
685691
func ListMilestones(t translations.TranslationHelperFunc) inventory.ServerTool {
686-
return NewTool(
692+
st := NewTool(
687693
ToolsetMetadataIssues,
688694
mcp.Tool{
689695
Name: "list_milestones",
@@ -775,6 +781,8 @@ func ListMilestones(t translations.TranslationHelperFunc) inventory.ServerTool {
775781

776782
return utils.NewToolResultText(string(out)), nil, nil
777783
})
784+
st.InsidersOnly = true
785+
return st
778786
}
779787

780788
// AddIssueComment creates a tool to add a comment to an issue.

pkg/inventory/builder.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,14 +351,19 @@ var insidersOnlyMetaKeys = []string{
351351
}
352352

353353
// stripInsidersFeatures removes insiders-only features from tools.
354-
// This includes Meta keys listed in insidersOnlyMetaKeys.
354+
// This includes removing tools marked with InsidersOnly and stripping
355+
// Meta keys listed in insidersOnlyMetaKeys from remaining tools.
355356
func stripInsidersFeatures(tools []ServerTool) []ServerTool {
356-
result := make([]ServerTool, len(tools))
357-
for i, tool := range tools {
357+
result := make([]ServerTool, 0, len(tools))
358+
for _, tool := range tools {
359+
// Skip tools marked as insiders-only
360+
if tool.InsidersOnly {
361+
continue
362+
}
358363
if stripped := stripInsidersMetaFromTool(tool); stripped != nil {
359-
result[i] = *stripped
364+
result = append(result, *stripped)
360365
} else {
361-
result[i] = tool
366+
result = append(result, tool)
362367
}
363368
}
364369
return result

pkg/inventory/registry_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,6 +1899,40 @@ func TestWithInsidersMode_EnabledPreservesUIMetadata(t *testing.T) {
18991899
}
19001900
}
19011901

1902+
func TestWithInsidersMode_EnabledPreservesInsidersOnlyTools(t *testing.T) {
1903+
normalTool := mockTool("normal", "toolset1", true)
1904+
insidersTool := mockTool("insiders_only", "toolset1", true)
1905+
insidersTool.InsidersOnly = true
1906+
1907+
// With insiders mode enabled, both tools should be available
1908+
reg := mustBuild(t, NewBuilder().
1909+
SetTools([]ServerTool{normalTool, insidersTool}).
1910+
WithToolsets([]string{"all"}).
1911+
WithInsidersMode(true))
1912+
available := reg.AvailableTools(context.Background())
1913+
1914+
require.Len(t, available, 2)
1915+
names := []string{available[0].Tool.Name, available[1].Tool.Name}
1916+
require.Contains(t, names, "normal")
1917+
require.Contains(t, names, "insiders_only")
1918+
}
1919+
1920+
func TestWithInsidersMode_DisabledRemovesInsidersOnlyTools(t *testing.T) {
1921+
normalTool := mockTool("normal", "toolset1", true)
1922+
insidersTool := mockTool("insiders_only", "toolset1", true)
1923+
insidersTool.InsidersOnly = true
1924+
1925+
// With insiders mode disabled, insiders-only tool should be removed
1926+
reg := mustBuild(t, NewBuilder().
1927+
SetTools([]ServerTool{normalTool, insidersTool}).
1928+
WithToolsets([]string{"all"}).
1929+
WithInsidersMode(false))
1930+
available := reg.AvailableTools(context.Background())
1931+
1932+
require.Len(t, available, 1)
1933+
require.Equal(t, "normal", available[0].Tool.Name)
1934+
}
1935+
19021936
func TestWithInsidersMode_ToolsWithoutUIMetaUnaffected(t *testing.T) {
19031937
toolNoUI := mockToolWithMeta("tool_no_ui", "toolset1", map[string]any{
19041938
"description": "kept",
@@ -2038,6 +2072,23 @@ func TestStripInsidersFeatures(t *testing.T) {
20382072
require.Nil(t, result[2].Tool.Meta)
20392073
}
20402074

2075+
func TestStripInsidersFeatures_RemovesInsidersOnlyTools(t *testing.T) {
2076+
// Create tools: one normal, one insiders-only, one normal
2077+
normalTool1 := mockTool("normal1", "toolset1", true)
2078+
insidersTool := mockTool("insiders_only", "toolset1", true)
2079+
insidersTool.InsidersOnly = true
2080+
normalTool2 := mockTool("normal2", "toolset1", true)
2081+
2082+
tools := []ServerTool{normalTool1, insidersTool, normalTool2}
2083+
2084+
result := stripInsidersFeatures(tools)
2085+
2086+
// Should only have 2 tools (insiders-only tool filtered out)
2087+
require.Len(t, result, 2)
2088+
require.Equal(t, "normal1", result[0].Tool.Name)
2089+
require.Equal(t, "normal2", result[1].Tool.Name)
2090+
}
2091+
20412092
func TestInsidersOnlyMetaKeys_FutureAdditions(t *testing.T) {
20422093
// This test verifies the mechanism works for multiple keys
20432094
// If we add new experimental keys to insidersOnlyMetaKeys, they should be stripped

pkg/inventory/server_tool.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ type ServerTool struct {
8282
// This includes the required scopes plus any higher-level scopes that provide
8383
// the necessary permissions due to scope hierarchy.
8484
AcceptedScopes []string
85+
86+
// InsidersOnly marks this tool as only available when insiders mode is enabled.
87+
// When insiders mode is disabled, tools with this flag set are completely omitted.
88+
InsidersOnly bool
8589
}
8690

8791
// IsReadOnly returns true if this tool is marked as read-only via annotations.

0 commit comments

Comments
 (0)