Skip to main content
Glama

apps-search

Search registered apps across App Store and Google Play stores using names, IDs, or package identifiers to find and manage applications directly from AI clients.

Instructions

Search registered apps. Returns all apps if called without query.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryNoSearch term (slug, bundleId, packageName, name). Returns all apps if empty
storeNoStore filter (default: all)

Implementation Reference

  • Main handler function that implements the 'apps-search' tool logic: loads registered apps, performs search by query across slug/name/bundleId/packageName, applies store filter, formats output.
    export async function handleSearchApps(options: SearchAppsOptions) {
      const { query, store = "all" } = options;
    
      console.error(
        `[MCP] šŸ” Searching apps (query: ${query || "all"}, store: ${store})`
      );
    
      try {
        const config = loadRegisteredApps();
        console.error(`[MCP]   Loaded ${config.apps.length} apps from config`);
        if (config.apps.length > 0) {
          console.error(
            `[MCP]   App slugs: ${config.apps.map((a) => a.slug).join(", ")}`
          );
        }
        let results: RegisteredApp[];
    
        if (!query) {
          // If no query, return full list
          results = config.apps;
        } else {
          // Try exact match first (by slug, bundleId, packageName)
          const exactMatch = findApp(query);
    
          // Also search for partial matches
          const partialMatches = config.apps.filter((app) =>
            matchesQuery(app, query)
          );
    
          // Combine results: exact match first, then partial matches
          // Remove duplicates by slug
          const seenSlugs = new Set<string>();
          results = [];
    
          // Add exact match first if found
          if (exactMatch && !seenSlugs.has(exactMatch.slug)) {
            results.push(exactMatch);
            seenSlugs.add(exactMatch.slug);
          }
    
          // Add partial matches (excluding exact match if already added)
          for (const app of partialMatches) {
            if (!seenSlugs.has(app.slug)) {
              results.push(app);
              seenSlugs.add(app.slug);
            }
          }
        }
    
        // Apply store filter
        results = filterByStore(results, store);
    
        if (results.length === 0) {
          const message = query
            ? `No apps found matching "${query}".`
            : "No apps registered.";
    
          return {
            content: [
              {
                type: "text" as const,
                text: `āŒ ${message}
    
    šŸ’” Register apps using apps-add or apps-init tools.`,
              },
            ],
            _meta: { apps: [], count: 0 },
          };
        }
    
        const header = query
          ? `šŸ” Search results for "${query}": ${results.length}`
          : `šŸ“‹ Registered app list: ${results.length}`;
    
        const appList = results.map(formatAppInfo).join("\n\n");
    
        return {
          content: [
            {
              type: "text" as const,
              text: `${header}
    
    ${appList}`,
            },
          ],
          _meta: { apps: results, count: results.length },
        };
      } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
          content: [
            {
              type: "text" as const,
              text: `āŒ App search failed: ${message}`,
            },
          ],
          isError: true,
        };
      }
    }
  • src/index.ts:208-228 (registration)
    Registers the 'apps-search' tool with MCP server, including description, input schema (Zod), and links to the handler function.
    registerToolWithInfo(
      "apps-search",
      {
        description:
          "Search registered apps. Returns all apps if called without query.",
        inputSchema: z.object({
          query: z
            .string()
            .optional()
            .describe(
              "Search term (slug, bundleId, packageName, name). Returns all apps if empty"
            ),
          store: z
            .enum(["all", "appStore", "googlePlay"])
            .optional()
            .describe("Store filter (default: all)"),
        }),
      },
      handleSearchApps,
      "App Management"
    );
  • TypeScript interface defining input options for the apps-search handler, matching the Zod schema used in registration.
    interface SearchAppsOptions {
      /** Search term (slug, bundleId, packageName, name). Returns all apps if empty */
      query?: string;
      /** Store filter (default: all) */
      store?: "all" | "appStore" | "googlePlay";
    }
  • Helper function to check if a registered app matches the search query across multiple fields (slug, name, bundleId, packageName).
    function matchesQuery(app: RegisteredApp, query: string): boolean {
      const lowerQuery = query.toLowerCase();
    
      // slug match
      if (app.slug.toLowerCase().includes(lowerQuery)) return true;
    
      // name match
      if (app.name.toLowerCase().includes(lowerQuery)) return true;
    
      // App Store bundleId match
      if (app.appStore?.bundleId?.toLowerCase().includes(lowerQuery)) return true;
    
      // App Store name match
      if (app.appStore?.name?.toLowerCase().includes(lowerQuery)) return true;
    
      // Google Play packageName match
      if (app.googlePlay?.packageName?.toLowerCase().includes(lowerQuery))
        return true;
    
      // Google Play name match
      if (app.googlePlay?.name?.toLowerCase().includes(lowerQuery)) return true;
    
      return false;
    }
  • Helper function to format app information into a readable string output for the tool response.
    function formatAppInfo(app: RegisteredApp): string {
      const lines: string[] = [];
    
      lines.push(`šŸ“± **${app.name}** (\`${app.slug}\`)`);
    
      if (app.appStore) {
        lines.push(`   šŸŽ App Store: \`${app.appStore.bundleId}\``);
        if (app.appStore.appId) {
          lines.push(`      App ID: ${app.appStore.appId}`);
        }
      }
    
      if (app.googlePlay) {
        lines.push(`   šŸ¤– Google Play: \`${app.googlePlay.packageName}\``);
      }
    
      return lines.join("\n");
    }
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions the default behavior when called without a query but doesn't address other critical aspects like authentication requirements, rate limits, pagination, error handling, or what the return format looks like. For a search tool with zero annotation coverage, this leaves significant gaps in understanding how the tool behaves in practice.

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

Conciseness5/5

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

The description is extremely concise with just one sentence that efficiently communicates the core functionality and default behavior. Every word earns its place, and it's front-loaded with the primary purpose. There's no redundancy or unnecessary elaboration.

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

Completeness2/5

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

Given the tool's moderate complexity (search functionality with two parameters), lack of annotations, and absence of an output schema, the description is insufficiently complete. It doesn't explain what the search returns (e.g., app details, IDs, or metadata), how results are structured, or any behavioral constraints. This leaves the agent with significant uncertainty about how to interpret and use the tool's output.

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 fully documents both parameters (query and store). The description adds minimal value beyond the schema by reiterating that an empty query returns all apps, which is already stated in the schema's query description. No additional semantic context is provided for parameters, so the baseline score of 3 is appropriate.

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

Purpose4/5

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

The description clearly states the verb ('Search') and resource ('registered apps'), making the purpose immediately understandable. It distinguishes this tool from siblings like 'apps-add' or 'apps-init' by focusing on search functionality rather than creation or initialization. However, it doesn't specify what constitutes a 'registered app' or the scope of the search beyond the query parameter.

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

Usage Guidelines3/5

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

The description provides implied usage guidance by stating 'Returns all apps if called without query,' which suggests this tool can be used for both filtered searches and retrieving all apps. However, it doesn't explicitly mention when to use this tool versus alternatives like 'aso-pull' or 'release-check-versions,' nor does it provide any exclusion criteria or prerequisites for usage.

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/quartz-labs-dev/pabal-mcp'

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