research-with-keywords
Conduct focused Web3 research by analyzing tokens and their related keywords to uncover relevant insights and trends in the crypto space.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| keywords | Yes | Keywords to search for | |
| tokenName | Yes | Name of the token | |
| tokenTicker | Yes | Ticker symbol of the token |
Implementation Reference
- src/tools/researchTools.ts:176-251 (handler)Handler function that iterates over provided keywords, constructs search queries with token name and ticker, performs web searches using performSearch, stores top 3 results per keyword, creates a combined JSON resource in storage, and returns a text summary with highlights and resource URI.async ({ tokenName, tokenTicker, keywords, }: { tokenName: string; tokenTicker: string; keywords: string[]; }) => { storage.addLogEntry( `Researching ${tokenName} with keywords: ${keywords.join(", ")}` ); try { const results: Record<string, any> = {}; for (const keyword of keywords) { const query = `${tokenName} ${tokenTicker} ${keyword}`; storage.addLogEntry(`Searching for: ${query}`); await sleep(2000); const searchResults = await performSearch(query, "web"); if (!searchResults.results || searchResults.results.length === 0) { results[keyword] = { error: "No results found" }; continue; } const topResults = searchResults.results.slice(0, 3); results[keyword] = topResults; storage.addToSection("searchResults", { [keyword]: topResults }); } const resourceId = `combined_search_${tokenName.toLowerCase()}_${new Date().getTime()}`; storage.addToSection("resources", { [resourceId]: { format: "json", content: JSON.stringify(results, null, 2), title: `Combined search results for ${tokenName}`, fetchedAt: new Date().toISOString(), }, }); return { content: [ { type: "text", text: `Completed searches for ${tokenName} with keywords: ${keywords.join( ", " )}\n\nResults saved as resource: research://resource/${resourceId}\n\nHighlights:\n${Object.entries( results ) .map(([keyword, data]) => { if (Array.isArray(data) && data.length > 0) { return `- ${keyword}: ${data[0].title} (${data[0].url})`; } return `- ${keyword}: No results`; }) .join("\n")}`, }, ], }; } catch (error) { storage.addLogEntry(`Error in keyword research: ${error}`); return { isError: true, content: [ { type: "text", text: `Error performing keyword research: ${error}`, }, ], }; } }
- src/tools/researchTools.ts:171-175 (schema)Input schema defined using Zod for validating tool parameters: tokenName (string), tokenTicker (string), keywords (array of strings).{ tokenName: z.string().describe("Name of the token"), tokenTicker: z.string().describe("Ticker symbol of the token"), keywords: z.array(z.string()).describe("Keywords to search for"), },
- src/tools/researchTools.ts:169-252 (registration)Registration of the 'research-with-keywords' tool on the MCP server using server.tool(), specifying name, input schema, and handler function. This occurs within the registerResearchTools function.server.tool( "research-with-keywords", { tokenName: z.string().describe("Name of the token"), tokenTicker: z.string().describe("Ticker symbol of the token"), keywords: z.array(z.string()).describe("Keywords to search for"), }, async ({ tokenName, tokenTicker, keywords, }: { tokenName: string; tokenTicker: string; keywords: string[]; }) => { storage.addLogEntry( `Researching ${tokenName} with keywords: ${keywords.join(", ")}` ); try { const results: Record<string, any> = {}; for (const keyword of keywords) { const query = `${tokenName} ${tokenTicker} ${keyword}`; storage.addLogEntry(`Searching for: ${query}`); await sleep(2000); const searchResults = await performSearch(query, "web"); if (!searchResults.results || searchResults.results.length === 0) { results[keyword] = { error: "No results found" }; continue; } const topResults = searchResults.results.slice(0, 3); results[keyword] = topResults; storage.addToSection("searchResults", { [keyword]: topResults }); } const resourceId = `combined_search_${tokenName.toLowerCase()}_${new Date().getTime()}`; storage.addToSection("resources", { [resourceId]: { format: "json", content: JSON.stringify(results, null, 2), title: `Combined search results for ${tokenName}`, fetchedAt: new Date().toISOString(), }, }); return { content: [ { type: "text", text: `Completed searches for ${tokenName} with keywords: ${keywords.join( ", " )}\n\nResults saved as resource: research://resource/${resourceId}\n\nHighlights:\n${Object.entries( results ) .map(([keyword, data]) => { if (Array.isArray(data) && data.length > 0) { return `- ${keyword}: ${data[0].title} (${data[0].url})`; } return `- ${keyword}: No results`; }) .join("\n")}`, }, ], }; } catch (error) { storage.addLogEntry(`Error in keyword research: ${error}`); return { isError: true, content: [ { type: "text", text: `Error performing keyword research: ${error}`, }, ], }; } } );