From 228ef6fba920789d95ff6b2297de0a9959fbf445 Mon Sep 17 00:00:00 2001 From: Brandon Bennett <107384180+branben@users.noreply.github.com> Date: Tue, 18 Aug 2026 09:52:38 -0400 Subject: [PATCH] fix(mcp): make GitHub skill tools discoverable through omniroute_tool_search (#10575) Add githubSkillTools to getAllToolDefinitions() so the searchable MCP catalog matches TOTAL_MCP_TOOL_COUNT, which already counts them. The GitHub skill tools were registered and counted but missing from the catalog, so omniroute_tool_search could not surface them. Adds regression tests at both layers: catalog aggregation and client-visible discovery via the MCP client. Co-authored-by: Brandon Bennett --- .../fixes/10575-mcp-github-tool-search.md | 1 + .../__tests__/toolSearch.catalog.test.ts | 12 ++++++++++++ .../__tests__/toolSearch.tool.test.ts | 19 ++++++++++++++++++- open-sse/mcp-server/toolSearch/catalog.ts | 7 +++++-- 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 changelog.d/fixes/10575-mcp-github-tool-search.md diff --git a/changelog.d/fixes/10575-mcp-github-tool-search.md b/changelog.d/fixes/10575-mcp-github-tool-search.md new file mode 100644 index 0000000000..108466845f --- /dev/null +++ b/changelog.d/fixes/10575-mcp-github-tool-search.md @@ -0,0 +1 @@ +- **fix(mcp):** make GitHub skill tools discoverable through `omniroute_tool_search` diff --git a/open-sse/mcp-server/__tests__/toolSearch.catalog.test.ts b/open-sse/mcp-server/__tests__/toolSearch.catalog.test.ts index b5a982e548..fc8878bb75 100644 --- a/open-sse/mcp-server/__tests__/toolSearch.catalog.test.ts +++ b/open-sse/mcp-server/__tests__/toolSearch.catalog.test.ts @@ -1,6 +1,12 @@ import { describe, it, expect } from "vitest"; import { getAllToolDefinitions } from "../toolSearch/catalog.ts"; +const GITHUB_SKILL_TOOL_NAMES = [ + "omniroute_github_skills_search", + "omniroute_github_skills_scan", + "omniroute_github_skills_install", +] as const; + describe("getAllToolDefinitions", () => { const all = getAllToolDefinitions(); it("aggregates many tools across collections", () => { @@ -18,6 +24,12 @@ describe("getAllToolDefinitions", () => { const names = all.map((t) => t.name); expect(new Set(names).size).toBe(names.length); }); + it("includes all GitHub skill tools", () => { + const names = new Set(all.map((tool) => tool.name)); + for (const name of GITHUB_SKILL_TOOL_NAMES) { + expect(names.has(name)).toBe(true); + } + }); it("includes every canonical CCR lifecycle tool", () => { for (const name of ["store", "retrieve", "inspect", "list", "delete", "stats"]) { expect(all.find((tool) => tool.name === `omniroute_ccr_${name}`)).toBeTruthy(); diff --git a/open-sse/mcp-server/__tests__/toolSearch.tool.test.ts b/open-sse/mcp-server/__tests__/toolSearch.tool.test.ts index 2c74a22635..6425b8bd22 100644 --- a/open-sse/mcp-server/__tests__/toolSearch.tool.test.ts +++ b/open-sse/mcp-server/__tests__/toolSearch.tool.test.ts @@ -29,11 +29,28 @@ describe("omniroute_tool_search", () => { }); it("returns relevant tool with a signature, not itself", async () => { - const res = await client.callTool({ name: "omniroute_tool_search", arguments: { query: "health" } }); + const res = await client.callTool({ + name: "omniroute_tool_search", + arguments: { query: "health" }, + }); const text = (res.content as Array<{ text: string }>)[0].text; const parsed = JSON.parse(text); expect(parsed.tools.some((t: any) => t.name === "omniroute_get_health")).toBe(true); expect(parsed.tools.every((t: any) => t.name !== "omniroute_tool_search")).toBe(true); expect(typeof parsed.tools[0].signature).toBe("string"); }); + + it("discovers all GitHub skill tools", async () => { + const res = await client.callTool({ + name: "omniroute_tool_search", + arguments: { query: "GitHub skills", limit: 25 }, + }); + const text = (res.content as Array<{ text: string }>)[0].text; + const parsed = JSON.parse(text); + const names = new Set(parsed.tools.map((tool: { name: string }) => tool.name)); + + expect(names.has("omniroute_github_skills_search")).toBe(true); + expect(names.has("omniroute_github_skills_scan")).toBe(true); + expect(names.has("omniroute_github_skills_install")).toBe(true); + }); }); diff --git a/open-sse/mcp-server/toolSearch/catalog.ts b/open-sse/mcp-server/toolSearch/catalog.ts index df39f0d9ae..c91c5a272c 100644 --- a/open-sse/mcp-server/toolSearch/catalog.ts +++ b/open-sse/mcp-server/toolSearch/catalog.ts @@ -2,8 +2,9 @@ * getAllToolDefinitions — unified catalog of all MCP tool definitions. * * Aggregates the same collections referenced by TOTAL_MCP_TOOL_COUNT in server.ts: - * MCP_TOOLS + memoryTools + skillTools + agentSkillTools + poolTools + - * gamificationTools + pluginTools + notionTools + obsidianTools + * MCP_TOOLS + memoryTools + skillTools + agentSkillTools + githubSkillTools + + * poolTools + gamificationTools + pluginTools + notionTools + obsidianTools + + * localCorpusTools + compressionTools * * Tolerates both Array and Record shapes. Deduplicates by name (first wins). */ @@ -12,6 +13,7 @@ import { MCP_TOOLS } from "../schemas/tools.ts"; import { memoryTools } from "../tools/memoryTools.ts"; import { skillTools } from "../tools/skillTools.ts"; import { agentSkillTools } from "../tools/agentSkillTools.ts"; +import { githubSkillTools } from "../tools/githubSkillTools.ts"; import { poolTools } from "../tools/poolTools.ts"; import { gamificationTools } from "../tools/gamificationTools.ts"; import { pluginTools } from "../tools/pluginTools.ts"; @@ -72,6 +74,7 @@ export function getAllToolDefinitions(): ToolCatalogEntry[] { memoryTools, skillTools, agentSkillTools, + githubSkillTools, poolTools, gamificationTools, pluginTools,