API-retrieve-a-page-property
Retrieve specific property values from a Notion page using page and property identifiers. Supports pagination for large datasets.
Instructions
Retrieve a page property item
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| page_id | Yes | Identifier for a Notion page | |
| property_id | Yes | Identifier for a page [property](https://developers.notion.com/reference/page#all-property-values) | |
| page_size | No | For paginated properties. The max number of property item objects on a page. The default size is 100 | |
| start_cursor | No | For paginated properties. |
Implementation Reference
- Core handler logic for API-retrieve-a-page-property tool calls within the MCP CallToolRequestSchema handler. Locates the OpenAPI operation and proxies the HTTP request via HttpClient, returning the response as MCP content.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), }, ], }
- src/openapi-mcp-server/mcp/proxy.ts:115-126 (registration)Tool registration in ListToolsRequestSchema handler. Converts grouped OpenAPI methods into individual MCP tools like API-retrieve-a-page-property by combining toolName ('API') with method.name.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}`) }) })
- Generates the inputSchema JSON Schema for MCP tools from OpenAPI operation parameters and requestBody. Used for API-retrieve-a-page-property schema (page_id and property_id parameters).private convertOperationToJsonSchema( operation: OpenAPIV3.OperationObject, method: string, path: string, ): IJsonSchema & { type: 'object' } { const schema: IJsonSchema & { type: 'object' } = { type: 'object', properties: {}, required: [], $defs: this.convertComponentsToJsonSchema(), } // Handle parameters (path, query, header, cookie) if (operation.parameters) { for (const param of operation.parameters) { const paramObj = this.resolveParameter(param) if (paramObj && paramObj.schema) { const paramSchema = this.convertOpenApiSchemaToJsonSchema(paramObj.schema, new Set()) // Merge parameter-level description if available if (paramObj.description) { paramSchema.description = paramObj.description } schema.properties![paramObj.name] = paramSchema if (paramObj.required) { schema.required!.push(paramObj.name) } } } } // Handle requestBody if (operation.requestBody) { const bodyObj = this.resolveRequestBody(operation.requestBody) if (bodyObj?.content) { if (bodyObj.content['application/json']?.schema) { const bodySchema = this.convertOpenApiSchemaToJsonSchema(bodyObj.content['application/json'].schema, new Set()) if (bodySchema.type === 'object' && bodySchema.properties) { for (const [name, propSchema] of Object.entries(bodySchema.properties)) { schema.properties![name] = propSchema } if (bodySchema.required) { schema.required!.push(...bodySchema.required) } } } } } return schema }
- Helper method enrichPageProperties uses API-retrieve-a-page-property to fetch detailed property information for each page property.const operation = this.findOperation('API-retrieve-a-page-property'); if (!operation) { if (options.runInBackground) { console.warn('API-retrieve-a-page-property method not found.'); } return; } const response = await this.httpClient.executeOperation(operation, { page_id: pageId, property_id: propId }).catch(error => {
- Low-level HTTP execution for OpenAPI operations. Called by the MCP handler to perform the actual Notion API request for retrieve-a-page-property.async executeOperation<T = any>( operation: OpenAPIV3.OperationObject & { method: string; path: string }, params: Record<string, any> = {}, ): Promise<HttpClientResponse<T>> { const api = await this.api const operationId = operation.operationId if (!operationId) { throw new Error('Operation ID is required') } // Handle file uploads if present const formData = await this.prepareFileUpload(operation, params) // Separate parameters based on their location const urlParameters: Record<string, any> = {} const bodyParams: Record<string, any> = formData || { ...params } // Extract path and query parameters based on operation definition if (operation.parameters) { for (const param of operation.parameters) { if ('name' in param && param.name && param.in) { if (param.in === 'path' || param.in === 'query') { if (params[param.name] !== undefined) { urlParameters[param.name] = params[param.name] if (!formData) { delete bodyParams[param.name] } } } } } } // Add all parameters as url parameters if there is no requestBody defined if (!operation.requestBody && !formData) { for (const key in bodyParams) { if (bodyParams[key] !== undefined) { urlParameters[key] = bodyParams[key] delete bodyParams[key] } } } const operationFn = (api as any)[operationId] if (!operationFn) { throw new Error(`Operation ${operationId} not found`) } try { // If we have form data, we need to set the correct headers const hasBody = Object.keys(bodyParams).length > 0 const headers = formData ? formData.getHeaders() : { ...(hasBody ? { 'Content-Type': 'application/json' } : { 'Content-Type': null }) } const requestConfig = { headers: { ...headers, }, } // first argument is url parameters, second is body parameters const response = await operationFn(urlParameters, hasBody ? bodyParams : undefined, requestConfig) // Convert axios headers to Headers object const responseHeaders = new Headers() Object.entries(response.headers).forEach(([key, value]) => { if (value) responseHeaders.append(key, value.toString()) }) return { data: response.data, status: response.status, headers: responseHeaders, } } catch (error: any) { if (error.response) { console.error('Error in http client', error) const headers = new Headers() Object.entries(error.response.headers).forEach(([key, value]) => { if (value) headers.append(key, value.toString()) }) throw new HttpClientError(error.response.statusText || 'Request failed', error.response.status, error.response.data, headers) } throw error } }