Skip to main content
Glama

API-retrieve-a-block

Retrieve specific content blocks from Notion using their unique identifiers to access structured information within pages.

Instructions

Retrieve a block

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
block_idYesIdentifier for a Notion block

Implementation Reference

  • Generic handler that finds the OpenAPI operation for the tool name 'API-retrieve-a-block', executes it using httpClient.executeOperation, logs the response, updates the cache, and returns the response as MCP 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),
        },
      ],
    }
  • Tool registration in ListToolsRequestSchema handler: iterates over converted OpenAPI tools (from converter), constructs tool name as 'API-retrieve-a-block', truncates if needed, and adds to the tools list.
    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 and description for the tool from the OpenAPI spec's operation definition for 'retrieve-a-block' (tool name prefixed with 'API-').
    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 } : {}),
        }
      }
  • Post-execution helper that specifically caches responses from 'API-retrieve-a-block' in the blockCache Map for subsequent recursive retrievals.
    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);
      }
    }

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