Skip to main content
Glama

githubSearchRepositories

Read-onlyIdempotent

Search GitHub repositories by keywords or topics to discover open-source projects, using filters like stars, owner, and activity dates to refine results.

Instructions

Search repositories by keywords/topics

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queriesYesResearch queries for githubSearchRepositories (1-3 queries per call for optimal resource management). Review schema before use for optimal results

Implementation Reference

  • Core execution logic for the githubSearchRepositories tool: expands queries for topics/keywords, performs bulk GitHub repository searches via API, processes results, generates pagination and search-specific hints.
    async function searchMultipleGitHubRepos(
      queries: GitHubReposSearchQuery[],
      authInfo?: AuthInfo,
      sessionId?: string
    ): Promise<CallToolResult> {
      const expandedQueries = expandQueriesWithBothSearchTypes(queries);
    
      return executeBulkOperation(
        expandedQueries,
        async (query: GitHubReposSearchQuery, _index: number) => {
          try {
            const apiResult = await searchGitHubReposAPI(
              query,
              authInfo,
              sessionId
            );
    
            const apiError = handleApiError(apiResult, query);
            if (apiError) return apiError;
    
            const repositories =
              'data' in apiResult
                ? apiResult.data.repositories || []
                : ([] satisfies SimplifiedRepository[]);
    
            const pagination =
              'data' in apiResult ? apiResult.data.pagination : undefined;
    
            // Generate pagination hints with full context for navigation
            const paginationHints: string[] = [];
            if (pagination) {
              const { currentPage, totalPages, totalMatches, perPage, hasMore } =
                pagination;
              const startItem = (currentPage - 1) * perPage + 1;
              const endItem = Math.min(currentPage * perPage, totalMatches);
    
              // Main pagination summary
              paginationHints.push(
                `Page ${currentPage}/${totalPages} (showing ${startItem}-${endItem} of ${totalMatches} repos)`
              );
    
              // Navigation hints
              if (hasMore) {
                paginationHints.push(`Next: page=${currentPage + 1}`);
              }
              if (currentPage > 1) {
                paginationHints.push(`Previous: page=${currentPage - 1}`);
              }
              if (!hasMore) {
                paginationHints.push('Final page');
              }
    
              // Quick navigation hint for multi-page results
              if (totalPages > 2) {
                paginationHints.push(
                  `Jump to: page=1 (first) or page=${totalPages} (last)`
                );
              }
            }
    
            // Generate search-type specific hints from metadata
            const searchHints = generateSearchSpecificHints(
              query,
              repositories.length > 0
            );
    
            // Use unified pattern: extraHints for pagination and search-specific hints
            return createSuccessResult(
              query,
              { repositories, pagination },
              repositories.length > 0,
              TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES,
              {
                extraHints: [...paginationHints, ...(searchHints || [])],
              }
            );
          } catch (error) {
            return handleCatchError(error, query);
          }
        },
        {
          toolName: TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES,
          keysPriority: ['repositories', 'pagination', 'error'] satisfies Array<
            keyof RepoSearchResult
          >,
        }
      );
    }
  • Zod schema for input validation of githubSearchRepositories tool queries, supporting bulk queries with keywords/topics search, filters, sorting, and pagination.
    export const GitHubReposSearchQuerySchema = createBulkQuerySchema(
      TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES,
      GitHubReposSearchSingleQuerySchema
    );
  • Registers the githubSearchRepositories tool on the MCP server, specifying name, description, input schema, annotations, and security-wrapped handler function.
    export function registerSearchGitHubReposTool(
      server: McpServer,
      callback?: ToolInvocationCallback
    ) {
      return server.registerTool(
        TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES,
        {
          description: DESCRIPTIONS[TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES],
          inputSchema: GitHubReposSearchQuerySchema,
          annotations: {
            title: 'GitHub Repository Search',
            readOnlyHint: true,
            destructiveHint: false,
            idempotentHint: true,
            openWorldHint: true,
          },
        },
        withSecurityValidation(
          TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES,
          async (
            args: {
              queries: GitHubReposSearchQuery[];
            },
            authInfo,
            sessionId
          ): Promise<CallToolResult> => {
            const queries = args.queries || [];
    
            await invokeCallbackSafely(
              callback,
              TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES,
              queries
            );
    
            return searchMultipleGitHubRepos(queries, authInfo, sessionId);
          }
        )
      );
    }
  • Helper function implementing the GitHub repository search API call using Octokit, query building, result mapping to simplified repositories, pagination calculation, and error handling.
    async function searchGitHubReposAPIInternal(
      params: GitHubReposSearchQuery,
      authInfo?: AuthInfo
    ): Promise<
      GitHubAPIResponse<{
        repositories: SimplifiedRepository[];
        pagination?: RepoSearchPagination;
      }>
    > {
      try {
        const octokit = await getOctokit(authInfo);
        const query = buildRepoSearchQuery(params);
    
        if (!query.trim()) {
          await logSessionError(
            TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES,
            SEARCH_ERRORS.QUERY_EMPTY.code
          );
          return {
            error: SEARCH_ERRORS.QUERY_EMPTY.message,
            type: 'http',
            status: 400,
          };
        }
    
        const perPage = Math.min(params.limit || 30, 100);
        const currentPage = params.page || 1;
    
        const searchParams: SearchReposParameters = {
          q: query,
          per_page: perPage,
          page: currentPage,
        };
    
        if (params.sort && params.sort !== 'best-match') {
          searchParams.sort = params.sort as SearchReposParameters['sort'];
        }
    
        const result = await octokit.rest.search.repos(searchParams);
    
        const repositories = result.data.items.map((repo: RepoSearchResultItem) => {
          const fullName = repo.full_name;
          const parts = fullName.split('/');
          const owner = parts[0] || '';
          const repoName = parts[1] || '';
    
          return {
            owner,
            repo: repoName,
            defaultBranch: repo.default_branch,
            stars: repo.stargazers_count || 0,
            description: repo.description
              ? repo.description.length > 150
                ? repo.description.substring(0, 150) + '...'
                : repo.description
              : 'No description',
            url: repo.html_url,
            createdAt: repo.created_at,
            updatedAt: repo.updated_at,
            pushedAt: repo.pushed_at,
            visibility: repo.visibility,
            ...(repo.topics && repo.topics.length > 0 && { topics: repo.topics }),
            ...(repo.forks_count &&
              repo.forks_count > 0 && {
                forksCount: repo.forks_count,
              }),
            ...(repo.open_issues_count &&
              repo.open_issues_count > 0 && {
                openIssuesCount: repo.open_issues_count,
              }),
          };
        });
    
        // GitHub caps at 1000 total results
        const totalMatches = Math.min(result.data.total_count, 1000);
        const totalPages = Math.min(Math.ceil(totalMatches / perPage), 10);
        const hasMore = currentPage < totalPages;
    
        return {
          data: {
            repositories,
            pagination: {
              currentPage,
              totalPages,
              perPage,
              totalMatches,
              hasMore,
            },
          },
          status: 200,
          headers: result.headers,
        };
      } catch (error: unknown) {
        return handleGitHubAPIError(error);
      }
    }
  • Tool configuration entry that defines and exports the registration function for githubSearchRepositories in the ALL_TOOLS array.
    export const GITHUB_SEARCH_REPOSITORIES: ToolConfig = {
      name: TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES,
      description: getDescription(TOOL_NAMES.GITHUB_SEARCH_REPOSITORIES),
      isDefault: true,
      isLocal: false,
      type: 'search',
      fn: registerSearchGitHubReposTool,
    };
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, destructiveHint=false, openWorldHint=true, and idempotentHint=true, covering safety and idempotency. The description adds valuable behavioral context beyond annotations: it mentions 'Archived repositories are excluded automatically', advises on 'Freshness: Check 'pushedAt' in response', and provides optimization tips like 'Use 'stars' >1000 to filter noise'. No contradiction with annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description uses a structured format with sections (<when>, <fromTool>, <gotchas>, <examples>) that makes it easy to scan, but it is somewhat verbose with multiple bullet points. Each sentence earns its place by providing actionable guidance, though it could be more front-loaded with the core purpose immediately visible. The structure enhances usability despite the length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (search with many parameters) and the absence of an output schema, the description provides extensive contextual completeness. It covers usage scenarios, alternatives, behavioral nuances (e.g., freshness, auto-filtering), examples, and integration with sibling tools. This compensates well for the lack of output schema and aligns with the rich annotations provided.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds some semantic context in <examples> (e.g., 'topicsToSearch=["typescript", "cli"], stars=">1000"') and <gotchas> (e.g., 'Matches against: Name, Description, and README (use 'match' param to filter)'), but this is marginal value over the comprehensive schema. Baseline 3 is appropriate as the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'Search repositories by keywords/topics' as the core purpose, providing a specific verb ('Search') and resource ('repositories') with clear scope ('by keywords/topics'). It distinguishes from siblings by mentioning 'AVOID: Known package → use 'packageSearch' FIRST' and referencing other tools for follow-up actions, making the differentiation explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes explicit guidance in structured sections: <when> specifies use cases ('Starting research | Finding repos | Discovering projects') and exclusions ('AVOID: Known package → use 'packageSearch' FIRST'), <fromTool> lists alternative tools for different scenarios, and <gotchas> provides detailed context on when to use other tools after finding repos. This offers comprehensive when/when-not/alternatives guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bgauryy/octocode-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server