API-retrieve-a-page
Fetch specific Notion page data by providing the page ID and optional property filters using a read-only server designed for efficient content retrieval.
Instructions
Retrieve a page
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filter_properties | No | A list of page property value IDs associated with the page. Use this param to limit the response to a specific page property value or values. To retrieve multiple properties, specify each page property ID. For example: `?filter_properties=iAk8&filter_properties=b7dh`. | |
| page_id | Yes | Identifier for a Notion page |
Implementation Reference
- src/openapi-mcp-server/mcp/proxy.ts:107-199 (registration)MCP tool registration via ListToolsRequestSchema handler. Converts OpenAPI spec to MCP tools using OpenAPIToMCPConverter and lists 'API-retrieve-a-page' among others with its schema and description.// Handle tool listing this.server.setRequestHandler(ListToolsRequestSchema, async () => { const tools: Tool[] = [] // Log available tools console.log('One Pager Assistant - Available tools:') // Add methods as separate tools to match the MCP format Object.entries(this.tools).forEach(([toolName, def]) => { def.methods.forEach(method => { const toolNameWithMethod = `${toolName}-${method.name}`; const truncatedToolName = this.truncateToolName(toolNameWithMethod); tools.push({ name: truncatedToolName, description: method.description, inputSchema: method.inputSchema as Tool['inputSchema'], }) console.log(`- ${truncatedToolName}: ${method.description}`) }) }) // Add extended One Pager tool const onePagerTool = { name: 'API-get-one-pager', description: 'Recursively retrieve a full Notion page with all its blocks, databases, and related content', inputSchema: { type: 'object', properties: { page_id: { type: 'string', description: 'Identifier for a Notion page', }, maxDepth: { type: 'integer', description: 'Maximum recursion depth (default: 5)', }, includeDatabases: { type: 'boolean', description: 'Whether to include linked databases (default: true)', }, includeComments: { type: 'boolean', description: 'Whether to include comments (default: true)', }, includeProperties: { type: 'boolean', description: 'Whether to include detailed page properties (default: true)', }, maxParallelRequests: { type: 'integer', description: 'Maximum number of parallel requests (default: 15)', }, batchSize: { type: 'integer', description: 'Batch size for parallel processing (default: 10)', }, timeoutMs: { type: 'integer', description: 'Timeout in milliseconds (default: 300000)', }, runInBackground: { type: 'boolean', description: 'Process request in background without timeout (default: true)', } }, required: ['page_id'], } as Tool['inputSchema'], }; tools.push(onePagerTool); console.log(`- ${onePagerTool.name}: ${onePagerTool.description}`); // Add tool to retrieve background processing results const backgroundResultTool = { name: 'API-get-background-result', description: 'Retrieve the result of a background processing request', inputSchema: { type: 'object', properties: { page_id: { type: 'string', description: 'Identifier for the Notion page that was processed in background', }, }, required: ['page_id'], } as Tool['inputSchema'], }; tools.push(backgroundResultTool); console.log(`- ${backgroundResultTool.name}: ${backgroundResultTool.description}`); return { tools } })
- Core handler logic for calling 'API-retrieve-a-page': resolves OpenAPI operation by name, executes HTTP request via HttpClient, logs response, updates cache, returns JSON-stringified response as text content.// Find the operation in OpenAPI spec const operation = this.findOperation(name) if (!operation) { const error = `Method ${name} not found.` console.error(error) return { content: [ { type: 'text', text: JSON.stringify({ status: 'error', message: error, code: 404 }), }, ], } } // Optimized parallel processing for API-get-block-children if (name === 'API-get-block-children') { // Create basic options for logging control const blockOptions: RecursiveExplorationOptions = { runInBackground: false, // Default to not showing logs for regular API calls }; return await this.handleBlockChildrenParallel(operation, params, blockOptions); } // Other regular API calls console.log(`Notion API call: ${operation.method.toUpperCase()} ${operation.path}`) const response = await this.httpClient.executeOperation(operation, params) // Log response summary console.log('Notion API response code:', response.status) if (response.status !== 200) { console.error('Response error:', response.data) } else { console.log('Response success') } // Update cache with response data this.updateCacheFromResponse(name, response.data); // Convert response to MCP format return { content: [ { type: 'text', text: JSON.stringify(response.data), }, ], }
- Helper function updateCacheFromResponse specifically caches page objects from 'API-retrieve-a-page' responses in pageCache Map.private updateCacheFromResponse(apiName: string, data: any): void { if (!data || typeof data !== 'object') return; try { // Update appropriate cache based on API response type if (apiName === 'API-retrieve-a-page' && data.object === 'page' && data.id) { this.pageCache.set(data.id, data); } else if (apiName === 'API-retrieve-a-block' && data.object === 'block' && data.id) { this.blockCache.set(data.id, data); } else if (apiName === 'API-retrieve-a-database' && data.object === 'database' && data.id) { this.databaseCache.set(data.id, data); } else if (apiName === 'API-retrieve-a-comment' && data.results) { // Cache comments from result list data.results.forEach((comment: any) => { if (comment.object === 'comment' && comment.id) { this.commentCache.set(comment.id, comment); } }); } else if (apiName === 'API-retrieve-a-page-property' && data.results) { // Page property caching - would need params from call context // Skip this in current context console.log('Page property information has been cached'); } // API-get-block-children handled in handleBlockChildrenParallel } catch (error) { console.warn('Error updating cache:', error); } }
- Helper method retrievePageRecursively uses 'API-retrieve-a-page' tool to fetch page data, with caching and timeout handling.// 1. Get basic page info (check cache) let pageData: any; if (!options.skipCache && this.pageCache.has(pageId)) { pageData = this.pageCache.get(pageId); if (options.runInBackground) { console.log(`Page cache hit: ${pageId}`); } } else { // Retrieve page info via API call const operation = this.findOperation('API-retrieve-a-page'); if (!operation) { throw new Error('API-retrieve-a-page method not found.'); } if (options.runInBackground) { console.log(`Notion API call: ${operation.method.toUpperCase()} ${operation.path} (pageId: ${pageId})`); } // Only race with timeout if timeoutMs is set let response; if (options.timeoutMs && options.timeoutMs > 0) { response = await Promise.race([ this.httpClient.executeOperation(operation, { page_id: pageId }), timeoutPromise ]) as any; } else { response = await this.httpClient.executeOperation(operation, { page_id: pageId }); } if (response.status !== 200) { if (options.runInBackground) { console.error('Error retrieving page information:', response.data); } return { id: pageId, error: "Failed to retrieve page", status: response.status, details: response.data }; } pageData = response.data; // Only cache successful responses this.pageCache.set(pageId, pageData); }
- Schema generation: Calls OpenAPIToMCPConverter.convertToMCPTools() which derives inputSchema for 'API-retrieve-a-page' from Notion OpenAPI spec parameters and requestBody.const converter = new OpenAPIToMCPConverter(openApiSpec) const { tools, openApiLookup } = converter.convertToMCPTools() this.tools = tools this.openApiLookup = openApiLookup