Skip to main content
Glama

search-source

Search for token-specific data across platforms like Dune, IQ Wiki, and news sources using token name and ticker symbol, enabling focused Web3 research directly from the MCP server.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sourceYesSource to search (e.g., 'Dune', 'IQ Wiki', 'News')
tokenNameYesName of the token
tokenTickerYesTicker symbol of the token

Implementation Reference

  • Registers the "search-source" tool with the MCP server, providing input schema and inline handler function.
    server.tool( "search-source", { tokenName: z.string().describe("Name of the token"), tokenTicker: z.string().describe("Ticker symbol of the token"), source: z .string() .describe("Source to search (e.g., 'Dune', 'IQ Wiki', 'News')"), }, async ({ tokenName, tokenTicker, source, }: { tokenName: string; tokenTicker: string; source: string; }) => { storage.addLogEntry( `Searching ${source} for ${tokenName} (${tokenTicker})` ); try { const results = await searchSource(tokenName, tokenTicker, source); storage.addToSection("searchResults", { [source]: results, }); let responseText = `Search results for ${source} about ${tokenName} (${tokenTicker}):\n\n`; if (results.results && results.results.length > 0) { const topResults = results.results.slice(0, 5); responseText += JSON.stringify(topResults, null, 2); if (topResults[0] && topResults[0].url) { const url = topResults[0].url; responseText += `\n\nFetching content from top result: ${url}`; try { await sleep(3000); const content = await fetchContent(url, "text"); const resourceId = `${source.toLowerCase()}_${tokenName.toLowerCase()}_${new Date().getTime()}`; storage.addToSection("resources", { [resourceId]: { url, format: "text", content, source, fetchedAt: new Date().toISOString(), }, }); responseText += `\n\nContent has been saved as a resource. Use 'research://resource/${resourceId}' to access it.`; } catch (fetchError) { responseText += `\n\nCould not fetch content from URL: ${fetchError}`; } } } else { responseText += `No results found.`; } return { content: [ { type: "text", text: responseText, }, ], }; } catch (error) { storage.addLogEntry(`Error searching ${source}: ${error}`); return { isError: true, content: [ { type: "text", text: `Error searching ${source}: ${error}`, }, ], }; } } );
  • Zod schema defining inputs for the search-source tool: tokenName, tokenTicker, source.
    { tokenName: z.string().describe("Name of the token"), tokenTicker: z.string().describe("Ticker symbol of the token"), source: z .string() .describe("Source to search (e.g., 'Dune', 'IQ Wiki', 'News')"), },
  • Handler function that executes the tool: logs action, calls searchSource helper, stores results, fetches and stores content from top result, returns formatted response.
    async ({ tokenName, tokenTicker, source, }: { tokenName: string; tokenTicker: string; source: string; }) => { storage.addLogEntry( `Searching ${source} for ${tokenName} (${tokenTicker})` ); try { const results = await searchSource(tokenName, tokenTicker, source); storage.addToSection("searchResults", { [source]: results, }); let responseText = `Search results for ${source} about ${tokenName} (${tokenTicker}):\n\n`; if (results.results && results.results.length > 0) { const topResults = results.results.slice(0, 5); responseText += JSON.stringify(topResults, null, 2); if (topResults[0] && topResults[0].url) { const url = topResults[0].url; responseText += `\n\nFetching content from top result: ${url}`; try { await sleep(3000); const content = await fetchContent(url, "text"); const resourceId = `${source.toLowerCase()}_${tokenName.toLowerCase()}_${new Date().getTime()}`; storage.addToSection("resources", { [resourceId]: { url, format: "text", content, source, fetchedAt: new Date().toISOString(), }, }); responseText += `\n\nContent has been saved as a resource. Use 'research://resource/${resourceId}' to access it.`; } catch (fetchError) { responseText += `\n\nCould not fetch content from URL: ${fetchError}`; } } } else { responseText += `No results found.`; } return { content: [ { type: "text", text: responseText, }, ], }; } catch (error) { storage.addLogEntry(`Error searching ${source}: ${error}`); return { isError: true, content: [ { type: "text", text: `Error searching ${source}: ${error}`, }, ], }; } }
  • Helper function implementing source-specific search query construction and delegation to performSearch (DuckDuckGo scraper).
    export async function searchSource( tokenName: string, tokenTicker: string, source: string ): Promise<any> { const extraTerms = ["crypto", "token"]; switch (source.toLowerCase()) { case "coinmarketcap": extraTerms.push("price", "market", "chart"); break; case "docs": extraTerms.push("documentation", "whitepaper", "github"); break; case "vesting": extraTerms.push("tokenomics", "schedule", "unlock"); break; case "raise": extraTerms.push("funding", "investment", "ico", "seed"); break; case "news": extraTerms.push("latest", "announcement", "update"); break; case "crypto token": case "dashboard": case "iq wiki": case "dune": extraTerms.push("dashboard", "crypto", "stats"); break; case "airdrop": break; default: } const query = `${tokenName} ${tokenTicker} ${source} ${extraTerms.join(" ")}`; if (source.toLowerCase() === "news") { return performSearch(query, "news"); } return performSearch(query, "web"); }

Other Tools

Related 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/aaronjmars/web3-research-mcp'

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