get_quick_test
Retrieve a single quick test by its ID to view its status and results.
Instructions
Get a single quick test by ID, including status and results.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| testId | Yes |
Implementation Reference
- src/tools/quickTest.js:38-47 (handler)The 'get_quick_test' tool definition, including its schema (testId required) and handler that calls api.get('/quick-test/${testId}')
{ name: 'get_quick_test', description: 'Get a single quick test by ID, including status and results.', inputSchema: { type: 'object', properties: { testId: { type: 'string' } }, required: ['testId'], }, handler: async ({ testId }) => api.get(`/quick-test/${testId}`), }, - src/tools/quickTest.js:3-69 (registration)The quickTestTools array is exported and registered in src/index.js (line 26/35). This file defines all quick test tools including get_quick_test.
export const quickTestTools = [ { name: 'run_quick_test', description: 'Start a "quick test" — a low-cost (1 credit) AI-visibility snapshot for a domain. ' + 'Returns immediately; the test runs asynchronously. Use `get_quick_test` to poll. ' + 'If your API key is scoped to a project, `websiteId` must match that project.', inputSchema: { type: 'object', properties: { domain: { type: 'string', description: 'Root domain, e.g. "example.com"' }, brandName: { type: 'string', description: 'Brand name (optional — auto-detected if omitted)' }, country: { type: 'string', description: 'ISO-2 country code (e.g. "US")' }, engines: { type: 'array', items: { type: 'string' }, description: 'AI engines to query (e.g. ["chatgpt", "perplexity"]). Defaults to all available.', }, websiteId: { type: 'string', description: 'Optional — link the test to an existing project.' }, }, required: ['domain'], }, handler: async (input) => api.post('/quick-test', input), }, { name: 'list_quick_tests', description: 'List quick tests, optionally filtered by project.', inputSchema: { type: 'object', properties: { websiteId: { type: 'string', description: 'Filter to a specific project (optional)' }, }, }, handler: async ({ websiteId }) => api.get('/quick-test', { websiteId }), }, { name: 'get_quick_test', description: 'Get a single quick test by ID, including status and results.', inputSchema: { type: 'object', properties: { testId: { type: 'string' } }, required: ['testId'], }, handler: async ({ testId }) => api.get(`/quick-test/${testId}`), }, { name: 'select_quick_test_keywords', description: 'After a quick test reaches `awaiting_keyword_selection`, pick 1–5 keywords to analyse ' + 'in depth. This kicks off the main analysis pass.', inputSchema: { type: 'object', properties: { testId: { type: 'string' }, keywords: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: 5, }, }, required: ['testId', 'keywords'], }, handler: async ({ testId, keywords }) => api.post(`/quick-test/${testId}/select-keywords`, { keywords }), }, ]; - src/index.js:31-41 (registration)All tools (including quickTestTools) are collected into ALL_TOOLS and then a Map is built (line 41) keyed by tool name for dispatch via CallToolRequestSchema handler.
const ALL_TOOLS = [ ...projectTools, ...keywordTools, ...reportTools, ...quickTestTools, ...keywordResearchTools, ...competitorTools, ...opportunityTools, ]; const toolByName = new Map(ALL_TOOLS.map((t) => [t.name, t])); - src/index.js:66-96 (helper)The CallToolRequestSchema handler dispatches tool calls by name; it looks up the tool in toolByName map and calls tool.handler(args), which for get_quick_test calls the API client.
// Execute a tool. server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args = {} } = request.params; const tool = toolByName.get(name); if (!tool) { return { isError: true, content: [{ type: 'text', text: `Unknown tool: ${name}` }], }; } try { const result = await tool.handler(args); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (err) { // Surface the SurfRank error message verbatim so the model can react // (e.g. "insufficient credits" → tell the user to top up). const message = err?.message || 'Unknown error'; return { isError: true, content: [{ type: 'text', text: message }], }; } }); - src/client.js:33-83 (helper)The HTTP client used by the get_quick_test handler. api.get(path, query) calls request('GET', ...) which sends a fetch to the SurfRank API with the API key header.
export async function request(method, path, { query, body } = {}) { const url = new URL(baseUrl() + path); if (query) { for (const [k, v] of Object.entries(query)) { if (v !== undefined && v !== null && v !== '') url.searchParams.set(k, String(v)); } } const headers = { 'X-API-Key': apiKey(), Accept: 'application/json', 'User-Agent': '@surfrank/mcp-server', }; const init = { method, headers }; if (body !== undefined) { headers['Content-Type'] = 'application/json'; init.body = JSON.stringify(body); } let res; try { res = await fetch(url, init); } catch (err) { throw new Error(`SurfRank API network error: ${err.message}`); } const text = await res.text(); let parsed; try { parsed = text ? JSON.parse(text) : null; } catch { parsed = null; } if (!res.ok) { const apiMsg = parsed?.error || parsed?.message || text || res.statusText; const err = new Error(`SurfRank ${res.status}: ${apiMsg}`); err.status = res.status; err.body = parsed; throw err; } return parsed; } export const api = { get: (path, query) => request('GET', path, { query }), post: (path, body) => request('POST', path, { body }), patch: (path, body) => request('PATCH', path, { body }), delete: (path) => request('DELETE', path), };