Skip to main content
Glama

relentless_list

Retrieve all entries from a Notion database to view existing content or search through database records for comprehensive content management.

Instructions

List all entries from a Notion database. Returns full content for all entries. Use this to see what content exists or to search through entries.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
databaseYesThe database name (e.g., "blog", "docs", "leads")

Implementation Reference

  • Handler for the relentless_list tool. Validates input, constructs API endpoint, calls relentlessRequest to fetch all entries from the database, and returns formatted text content with the list of entries.
    case 'relentless_list': { const { database } = args as { database: string } if (!database) { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: database') } console.error(`[${new Date().toISOString()}] Listing all from ${database}`) const endpoint = `${RELENTLESS_API_BASE}/api/v1/public/db/${database}/list` const result = await relentlessRequest(endpoint) return { content: [ { type: 'text', text: `Found ${Array.isArray(result) ? result.length : 0} entries:\n\n${JSON.stringify( result, null, 2 )}`, }, ], } }
  • src/index.ts:264-278 (registration)
    Tool registration entry for 'relentless_list' in the ListToolsRequestSchema handler, defining the tool name, description, and input schema.
    { name: 'relentless_list', description: 'List all entries from a Notion database. Returns full content for all entries. Use this to see what content exists or to search through entries.', inputSchema: { type: 'object', properties: { database: { type: 'string', description: 'The database name (e.g., "blog", "docs", "leads")', }, }, required: ['database'], }, },
  • Input schema definition for the relentless_list tool, specifying the required 'database' parameter.
    inputSchema: { type: 'object', properties: { database: { type: 'string', description: 'The database name (e.g., "blog", "docs", "leads")', }, }, required: ['database'], },
  • Helper function used by the handler to make API requests to Relentless with retry logic, timeout, and error handling.
    async function relentlessRequest( endpoint: string, options?: RequestInit, maxRetries = 3 ): Promise<any> { const url = endpoint.includes('?') ? `${endpoint}&api_key=${RELENTLESS_API_KEY}` : `${endpoint}?api_key=${RELENTLESS_API_KEY}` let lastError: Error | null = null for (let attempt = 0; attempt < maxRetries; attempt++) { try { // Add timeout using AbortController const controller = new AbortController() const timeoutId = setTimeout(() => controller.abort(), 30000) // 30s timeout const response = await fetch(url, { ...options, signal: controller.signal, headers: { 'Content-Type': 'application/json', ...options?.headers, }, }) clearTimeout(timeoutId) // Handle rate limiting (429) if (response.status === 429) { const retryAfter = response.headers.get('Retry-After') const delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000 console.error(`⏳ Rate limited. Retrying in ${delay / 1000}s...`) await sleep(delay) continue } // Handle success if (response.ok) { return response.json() } // Handle errors with detailed messages const errorBody = await response.json().catch(() => ({ message: 'Unknown error' })) let errorMessage = errorBody.message || errorBody.error || 'Unknown error' // Provide helpful error messages based on status code switch (response.status) { case 401: errorMessage = 'Invalid API key. Check RELENTLESS_API_KEY environment variable.' break case 403: errorMessage = 'Access forbidden. Verify you own this API and have proper permissions.' break case 404: errorMessage = `API path not found. Check that the API exists in your Relentless dashboard.` break case 422: errorMessage = `Validation error: ${errorMessage}. Check that property names match your Notion database exactly (case-sensitive).` break case 500: errorMessage = `Relentless API error: ${errorMessage}` break } // Don't retry client errors (4xx) except 429 if (response.status >= 400 && response.status < 500) { throw new McpError( ErrorCode.InvalidRequest, `Relentless API error (${response.status}): ${errorMessage}` ) } // Server errors (5xx) - will retry lastError = new Error(`Server error (${response.status}): ${errorMessage}`) console.error(`❌ Attempt ${attempt + 1}/${maxRetries} failed: ${errorMessage}`) } catch (error: any) { lastError = error // Handle timeout if (error.name === 'AbortError') { throw new McpError(ErrorCode.InternalError, 'Request timeout after 30 seconds') } // Handle MCP errors (don't retry) if (error instanceof McpError) { throw error } // Network errors - will retry console.error(`❌ Attempt ${attempt + 1}/${maxRetries} failed: ${error.message}`) } // Exponential backoff before retry (except on last attempt) if (attempt < maxRetries - 1) { const backoffDelay = Math.min(Math.pow(2, attempt) * 1000, 10000) // Max 10s console.error(`⏳ Retrying in ${backoffDelay / 1000}s...`) await sleep(backoffDelay) } } // All retries exhausted throw new McpError( ErrorCode.InternalError, `Failed after ${maxRetries} attempts: ${lastError?.message || 'Unknown error'}` ) }

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/PranaytheSingh/relentless-mcp'

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