Skip to main content
Glama

iask-search

Get AI-generated answers to complex questions using web content. Choose search modes for academic, forum, wiki, or deep analysis responses with adjustable detail levels.

Instructions

AI-powered search using IAsk.ai. Retrieves comprehensive, AI-generated responses based on web content. Supports different search modes (question, academic, forums, wiki, thinking) and detail levels (concise, detailed, comprehensive). Ideal for getting well-researched answers to complex questions.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesThe search query or question to ask. Supports natural language questions for comprehensive AI-generated responses.
modeNoSearch mode to use. Options: "question" (general questions), "academic" (scholarly/research), "forums" (community discussions), "wiki" (encyclopedia-style), "thinking" (deep analysis). Default is "question".question
detailLevelNoLevel of detail in the response. Options: "concise" (brief), "detailed" (moderate), "comprehensive" (extensive). Default is null (standard response).

Implementation Reference

  • The main handler function `iaskToolHandler` that destructures input params, calls the `searchIAsk` helper, formats the response as MCP content, and handles errors.
    export async function iaskToolHandler(params) { const { query, mode = 'thinking', detailLevel = null } = params; console.log(`Searching IAsk AI for: "${query}" (mode: ${mode}, detailLevel: ${detailLevel || 'default'})`); try { const response = await searchIAsk(query, mode, detailLevel); return { content: [ { type: 'text', text: response || 'No results found.' } ] }; } catch (error) { console.error(`Error in IAsk search: ${error.message}`); return { isError: true, content: [ { type: 'text', text: `Error searching IAsk: ${error.message}` } ] }; } }
  • The `iaskToolDefinition` object defining the tool's metadata, description, input schema for validation (query required, optional mode and detailLevel with enums), and annotations.
    export const iaskToolDefinition = { name: 'iask-search', title: 'IAsk AI Search', description: 'AI-powered search using IAsk.ai. Retrieves comprehensive, AI-generated responses based on web content. Supports different search modes (question, academic, forums, wiki, thinking) and detail levels (concise, detailed, comprehensive). Ideal for getting well-researched answers to complex questions.', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'The search query or question to ask. Supports natural language questions for comprehensive AI-generated responses.' }, mode: { type: 'string', description: 'Search mode to use. Options: "question" (general questions), "academic" (scholarly/research), "forums" (community discussions), "wiki" (encyclopedia-style), "thinking" (deep analysis). Default is "question".', enum: VALID_MODES, default: 'question' }, detailLevel: { type: 'string', description: 'Level of detail in the response. Options: "concise" (brief), "detailed" (moderate), "comprehensive" (extensive). Default is null (standard response).', enum: VALID_DETAIL_LEVELS } }, required: ['query'] }, annotations: { readOnlyHint: true, openWorldHint: false } };
  • src/index.js:35-40 (registration)
    Registration in MCP ListToolsRequest handler: includes iaskToolDefinition in the availableTools array returned to clients.
    server.setRequestHandler(ListToolsRequestSchema, async () => { console.log('Tools list requested, returning:', availableTools.length, 'tools'); return { tools: availableTools }; });
  • src/index.js:49-61 (registration)
    Registration in MCP CallToolRequest handler: switch case routes 'iask-search' calls to the iaskToolHandler.
    switch (name) { case 'web-search': return await searchToolHandler(args); case 'iask-search': return await iaskToolHandler(args); case 'monica-search': return await monicaToolHandler(args); default: throw new Error(`Tool not found: ${name}`); }
  • The `searchIAsk` helper function performs the actual search via WebSocket to iask.ai, handles caching, parsing, formatting of AI-generated responses, and exports VALID_MODES/VALID_DETAIL_LEVELS used in schema.
    async function searchIAsk(prompt, mode = 'thinking', detailLevel = null) { // Input validation if (!prompt || typeof prompt !== 'string') { throw new Error('Invalid prompt: prompt must be a non-empty string'); } // Validate mode if (!VALID_MODES.includes(mode)) { throw new Error(`Invalid mode: ${mode}. Valid modes are: ${VALID_MODES.join(', ')}`); } // Validate detail level if (detailLevel && !VALID_DETAIL_LEVELS.includes(detailLevel)) { throw new Error(`Invalid detail level: ${detailLevel}. Valid levels are: ${VALID_DETAIL_LEVELS.join(', ')}`); } console.log(`IAsk search starting: "${prompt}" (mode: ${mode}, detailLevel: ${detailLevel || 'default'})`); // Clear old cache entries clearOldCache(); const cacheKey = getCacheKey(prompt, mode, detailLevel); const cachedResults = resultsCache.get(cacheKey); if (cachedResults && Date.now() - cachedResults.timestamp < CACHE_DURATION) { console.log(`Cache hit for IAsk query: "${prompt}"`); return cachedResults.results; } // Build URL parameters const params = new URLSearchParams({ mode, q: prompt }); if (detailLevel) { params.append('options[detail_level]', detailLevel); } // Create a cookie jar for session management const jar = new CookieJar(); const client = wrapper(axios.create({ jar })); try { // Get initial page and extract tokens console.log('Fetching IAsk AI initial page...'); const response = await client.get(API_ENDPOINT, { params: Object.fromEntries(params), timeout: DEFAULT_TIMEOUT, headers: { 'User-Agent': getRandomUserAgent() } }); const $ = cheerio.load(response.data); const phxNode = $('[id^="phx-"]').first(); const csrfToken = $('[name="csrf-token"]').attr('content'); const phxId = phxNode.attr('id'); const phxSession = phxNode.attr('data-phx-session'); if (!phxId || !csrfToken) { throw new Error('Failed to extract required tokens from IAsk AI page'); } // Get the actual response URL (after any redirects) const responseUrl = response.request.res?.responseUrl || response.config.url; // Get cookies from the jar for WebSocket connection const cookies = await jar.getCookies(API_ENDPOINT); const cookieString = cookies.map(c => `${c.key}=${c.value}`).join('; '); // Build WebSocket URL const wsParams = new URLSearchParams({ '_csrf_token': csrfToken, 'vsn': '2.0.0' }); const wsUrl = `wss://iask.ai/live/websocket?${wsParams.toString()}`; return new Promise((resolve, reject) => { const ws = new WebSocket(wsUrl, { headers: { 'Cookie': cookieString, 'User-Agent': getRandomUserAgent(), 'Origin': 'https://iask.ai' } }); let buffer = ''; let timeoutId; let connectionTimeoutId; // Set connection timeout connectionTimeoutId = setTimeout(() => { ws.close(); reject(new Error('IAsk connection timeout: unable to establish WebSocket connection')); }, 15000); ws.on('open', () => { clearTimeout(connectionTimeoutId); console.log('IAsk WebSocket connection established'); // Send phx_join message ws.send(JSON.stringify([ null, null, `lv:${phxId}`, 'phx_join', { params: { _csrf_token: csrfToken }, url: responseUrl, session: phxSession } ])); // Set message timeout timeoutId = setTimeout(() => { ws.close(); if (buffer) { resolve(buffer || 'No results found.'); } else { reject(new Error('IAsk response timeout: no response received')); } }, DEFAULT_TIMEOUT); }); ws.on('message', (data) => { try { const msg = JSON.parse(data.toString()); if (!msg) return; const diff = msg[4]; if (!diff) return; let chunk = null; try { // Try to get chunk from diff.e[0][1].data if (diff.e) { chunk = diff.e[0][1].data; if (chunk) { let formatted; if (/<[^>]+>/.test(chunk)) { formatted = formatHtml(chunk); } else { formatted = chunk.replace(/<br\/>/g, '\n'); } buffer += formatted; } } else { throw new Error('No diff.e'); } } catch { // Fallback to cacheFind const cache = cacheFind(diff); if (cache) { let formatted; if (/<[^>]+>/.test(cache)) { formatted = formatHtml(cache); } else { formatted = cache; } buffer += formatted; // Close after cache find ws.close(); return; } } } catch (err) { console.error('Error parsing IAsk message:', err.message); } }); ws.on('close', () => { clearTimeout(timeoutId); clearTimeout(connectionTimeoutId); console.log(`IAsk search completed: ${buffer.length} characters received`); // Cache the result if (buffer) { resultsCache.set(cacheKey, { results: buffer, timestamp: Date.now() }); } resolve(buffer || 'No results found.'); }); ws.on('error', (err) => { clearTimeout(timeoutId); clearTimeout(connectionTimeoutId); console.error('IAsk WebSocket error:', err.message); if (err.message.includes('timeout')) { reject(new Error('IAsk WebSocket timeout: connection took too long')); } else if (err.message.includes('connection refused')) { reject(new Error('IAsk connection refused: service may be unavailable')); } else { reject(new Error(`IAsk WebSocket error: ${err.message}`)); } }); }); } catch (error) { console.error('Error in IAsk search:', error.message); // Enhanced error handling if (error.code === 'ENOTFOUND') { throw new Error('IAsk network error: unable to resolve host'); } if (error.code === 'ECONNREFUSED') { throw new Error('IAsk network error: connection refused'); } if (error.message.includes('timeout')) { throw new Error(`IAsk timeout: ${error.message}`); } throw new Error(`IAsk search failed for "${prompt}": ${error.message}`); } } export { searchIAsk, VALID_MODES, VALID_DETAIL_LEVELS };

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/OEvortex/ddg_search'

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