Skip to main content
Glama

API-retrieve-a-page

Retrieve specific Notion page content using its unique identifier, optionally filtering properties to access targeted information from your workspace.

Instructions

Retrieve a page

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
page_idYesIdentifier for a Notion page
filter_propertiesNoA 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`.

Implementation Reference

  • Core handler logic for executing 'API-retrieve-a-page': looks up OpenAPI operation, calls HTTP client to proxy to Notion API, caches response, and returns JSON in MCP format
    // 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),
        },
      ],
    }
  • Generates the inputSchema and description for 'retrieve-a-page' tool (prefixed to API-) from OpenAPI operation parameters, requestBody, and responses
    private convertOperationToMCPMethod(operation: OpenAPIV3.OperationObject, method: string, path: string): NewToolMethod | null {
      if (!operation.operationId) {
        console.warn(`Operation without operationId at ${method} ${path}`)
        return null
      }
    
      const methodName = operation.operationId
    
      const inputSchema: IJsonSchema & { type: 'object' } = {
        $defs: this.convertComponentsToJsonSchema(),
        type: 'object',
        properties: {},
        required: [],
      }
    
      // 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 schema = this.convertOpenApiSchemaToJsonSchema(paramObj.schema, new Set(), false)
            // Merge parameter-level description if available
            if (paramObj.description) {
              schema.description = paramObj.description
            }
            inputSchema.properties![paramObj.name] = schema
            if (paramObj.required) {
              inputSchema.required!.push(paramObj.name)
            }
          }
        }
      }
    
      // Handle requestBody
      if (operation.requestBody) {
        const bodyObj = this.resolveRequestBody(operation.requestBody)
        if (bodyObj?.content) {
          // Handle multipart/form-data for file uploads
          // We convert the multipart/form-data schema to a JSON schema and we require
          // that the user passes in a string for each file that points to the local file
          if (bodyObj.content['multipart/form-data']?.schema) {
            const formSchema = this.convertOpenApiSchemaToJsonSchema(bodyObj.content['multipart/form-data'].schema, new Set(), false)
            if (formSchema.type === 'object' && formSchema.properties) {
              for (const [name, propSchema] of Object.entries(formSchema.properties)) {
                inputSchema.properties![name] = propSchema
              }
              if (formSchema.required) {
                inputSchema.required!.push(...formSchema.required!)
              }
            }
          }
          // Handle application/json
          else if (bodyObj.content['application/json']?.schema) {
            const bodySchema = this.convertOpenApiSchemaToJsonSchema(bodyObj.content['application/json'].schema, new Set(), false)
            // Merge body schema into the inputSchema's properties
            if (bodySchema.type === 'object' && bodySchema.properties) {
              for (const [name, propSchema] of Object.entries(bodySchema.properties)) {
                inputSchema.properties![name] = propSchema
              }
              if (bodySchema.required) {
                inputSchema.required!.push(...bodySchema.required!)
              }
            } else {
              // If the request body is not an object, just put it under "body"
              inputSchema.properties!['body'] = bodySchema
              inputSchema.required!.push('body')
            }
          }
        }
      }
    
      // Build description including error responses
      let description = operation.summary || operation.description || ''
      if (operation.responses) {
        const errorResponses = Object.entries(operation.responses)
          .filter(([code]) => code.startsWith('4') || code.startsWith('5'))
          .map(([code, response]) => {
            const responseObj = this.resolveResponse(response)
            let errorDesc = responseObj?.description || ''
            return `${code}: ${errorDesc}`
          })
    
        if (errorResponses.length > 0) {
          description += '\nError Responses:\n' + errorResponses.join('\n')
        }
      }
    
      // Extract return type (response schema)
      const returnSchema = this.extractResponseType(operation.responses)
    
      // Generate Zod schema from input schema
      try {
        // const zodSchemaStr = jsonSchemaToZod(inputSchema, { module: "cjs" })
        // console.log(zodSchemaStr)
        // // Execute the function with the zod instance
        // const zodSchema = eval(zodSchemaStr) as z.ZodType
    
        return {
          name: methodName,
          description,
          inputSchema,
          ...(returnSchema ? { returnSchema } : {}),
        }
      } catch (error) {
        console.warn(`Failed to generate Zod schema for ${methodName}:`, error)
        // Fallback to a basic object schema
        return {
          name: methodName,
          description,
          inputSchema,
          ...(returnSchema ? { returnSchema } : {}),
        }
      }
    }
  • Registers 'API-retrieve-a-page' in the MCP tools list by constructing tool name from OpenAPI-derived methods and adding to response
    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}`)
      })
    })
  • Helper function updates pageCache specifically for 'API-retrieve-a-page' responses
    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) {
  • Helper to lookup OpenAPI operation details for tool names like 'API-retrieve-a-page' from pre-converted lookup table
    private findOperation(operationId: string): (OpenAPIV3.OperationObject & { method: string; path: string }) | null {
      return this.openApiLookup[operationId] ?? null
    }
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. 'Retrieve a page' implies a read-only operation but doesn't specify authentication requirements, rate limits, error handling, or what the response contains. For a tool with no annotation coverage, this is a significant gap in behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with just two words, 'Retrieve a page', which is front-loaded and wastes no space. While under-specified in content, it earns full marks for brevity and structure as every word contributes directly to the core purpose without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of a retrieval tool with 2 parameters, no annotations, and no output schema, the description is incomplete. It doesn't explain what a 'page' is in context (Notion), how results are returned, or any behavioral aspects. The agent lacks sufficient context to use this tool effectively beyond basic parameter passing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, with both parameters ('page_id' and 'filter_properties') fully documented in the input schema. The description adds no additional parameter information beyond what the schema provides, so it meets the baseline score of 3 for adequate coverage when the schema handles the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Retrieve a page' is a tautology that essentially restates the tool name 'API-retrieve-a-page'. It doesn't specify what kind of page (Notion page) or provide any distinguishing context from sibling tools like 'API-retrieve-a-database' or 'API-retrieve-a-block'. The purpose is minimally stated but lacks specificity and differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. With sibling tools like 'API-retrieve-a-database' and 'API-retrieve-a-block', the description offers no context about when this tool is appropriate, what prerequisites exist, or when other tools might be better suited. This leaves the agent without usage direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

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/Taewoong1378/notion-readonly-mcp-server'

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