Skip to main content
Glama

search_assets

Search the Spark AI assets marketplace to find agents, skills, prompts, MCP connectors, and bundles using filters for type, domain, and result limits.

Instructions

Search the Spark AI assets marketplace. Returns matching agents, skills, prompts, MCP connectors, and bundles.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch query (title, description)
typeNoFilter by asset type
domainNoFilter by domain slug (e.g. 'development', 'marketing')
limitNoNumber of results (1-50, default 10)

Implementation Reference

  • src/index.ts:216-260 (registration)
    Tool registration for 'search_assets' - defines the tool name, description, input schema (query, type, domain, limit parameters), and the handler function that searches the Spark API and formats results.
    server.tool(
      "search_assets",
      "Search the Spark AI assets marketplace. Returns matching agents, skills, prompts, MCP connectors, and bundles.",
      {
        query: z.string().describe("Search query (title, description)"),
        type: z
          .enum(["agent", "skill", "prompt", "prompt_chain", "mcp_connector", "bundle"])
          .optional()
          .describe("Filter by asset type"),
        domain: z.string().optional().describe("Filter by domain slug (e.g. 'development', 'marketing')"),
        limit: z.number().min(1).max(50).default(10).describe("Number of results (1-50, default 10)"),
      },
      async ({ query, type, domain, limit }) => {
        const params = new URLSearchParams();
        params.set("q", query);
        params.set("page_size", String(limit));
        if (type) params.set("asset_type", type);
        if (domain) params.set("domain", domain);
    
        const res = await sparkApi<PaginatedResponse<AssetListItem>>(
          `/assets?${params.toString()}`
        );
    
        if (res.items.length === 0) {
          return {
            content: [
              {
                type: "text" as const,
                text: `No assets found for "${query}". Try a different search term or remove filters.`,
              },
            ],
          };
        }
    
        const text = [
          `Found ${res.total} assets (showing ${res.items.length}):`,
          "",
          ...res.items.map(
            (a, i) => `${i + 1}. ${formatAssetSummary(a)}`
          ),
        ].join("\n");
    
        return { content: [{ type: "text" as const, text }] };
      }
    );
  • Tool handler implementation - constructs query parameters, calls the Spark API /assets endpoint, handles empty results, and formats asset summaries for display.
    async ({ query, type, domain, limit }) => {
      const params = new URLSearchParams();
      params.set("q", query);
      params.set("page_size", String(limit));
      if (type) params.set("asset_type", type);
      if (domain) params.set("domain", domain);
    
      const res = await sparkApi<PaginatedResponse<AssetListItem>>(
        `/assets?${params.toString()}`
      );
    
      if (res.items.length === 0) {
        return {
          content: [
            {
              type: "text" as const,
              text: `No assets found for "${query}". Try a different search term or remove filters.`,
            },
          ],
        };
      }
    
      const text = [
        `Found ${res.total} assets (showing ${res.items.length}):`,
        "",
        ...res.items.map(
          (a, i) => `${i + 1}. ${formatAssetSummary(a)}`
        ),
      ].join("\n");
    
      return { content: [{ type: "text" as const, text }] };
    }
  • Input schema definition using zod - defines the four parameters: query (required string), type (optional enum of asset types), domain (optional string), and limit (optional number 1-50, default 10).
    {
      query: z.string().describe("Search query (title, description)"),
      type: z
        .enum(["agent", "skill", "prompt", "prompt_chain", "mcp_connector", "bundle"])
        .optional()
        .describe("Filter by asset type"),
      domain: z.string().optional().describe("Filter by domain slug (e.g. 'development', 'marketing')"),
      limit: z.number().min(1).max(50).default(10).describe("Number of results (1-50, default 10)"),
    },
  • HTTP helper function 'sparkApi' - makes authenticated requests to the Spark API with error handling and JSON parsing, used by search_assets to fetch data.
    async function sparkApi<T = unknown>(path: string): Promise<T> {
      const url = `${SPARK_API}${path}`;
      const res = await fetch(url, {
        headers: { Accept: "application/json" },
      });
      if (!res.ok) {
        const text = await res.text().catch(() => res.statusText);
        throw new Error(`Spark API ${res.status}: ${text}`);
      }
      return res.json() as Promise<T>;
    }
  • Formatting helper 'formatAssetSummary' - formats an AssetListItem into a readable string with title, type, rating, downloads, description, pricing, AI models, domains, and URL.
    function formatAssetSummary(a: AssetListItem): string {
      const badges = [
        a.is_featured ? "Featured" : "",
        a.is_verified ? "Verified" : "",
      ]
        .filter(Boolean)
        .join(", ");
      const badgeStr = badges ? ` [${badges}]` : "";
    
      return [
        `**${a.title}**${badgeStr}`,
        `Type: ${a.type} | Rating: ${a.rating_avg.toFixed(1)}/5 (${a.rating_count}) | Downloads: ${a.downloads_count}`,
        `${a.short_description}`,
        `Price: ${a.pricing_type === "free" ? "Free" : `${a.price_credits} EVC`}`,
        a.ai_tags.length ? `AI Models: ${a.ai_tags.join(", ")}` : "",
        a.domain_tags.length
          ? `Domains: ${a.domain_tags.map((d) => d.child_name).join(", ")}`
          : "",
        `URL: ${assetUrl(a)}`,
      ]
        .filter(Boolean)
        .join("\n");
    }

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/entire-vc/evc-spark-mcp'

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