This is page 2 of 2. Use http://codebase.md/makenotion/notion-mcp-server?format=md&lines=true&page={x} to view the full context.

# Directory Structure

```
├── .dockerignore
├── .gitignore
├── docker-compose.yml
├── Dockerfile
├── docs
│   └── images
│       ├── connections.png
│       ├── integration-access.png
│       ├── integrations-capabilities.png
│       ├── integrations-creation.png
│       └── page-access-edit.png
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── scripts
│   ├── build-cli.js
│   ├── notion-openapi.json
│   └── start-server.ts
├── smithery.yaml
├── src
│   ├── init-server.ts
│   └── openapi-mcp-server
│       ├── auth
│       │   ├── index.ts
│       │   ├── template.ts
│       │   └── types.ts
│       ├── client
│       │   ├── __tests__
│       │   │   ├── http-client-upload.test.ts
│       │   │   ├── http-client.integration.test.ts
│       │   │   └── http-client.test.ts
│       │   ├── http-client.ts
│       │   └── polyfill-headers.ts
│       ├── index.ts
│       ├── mcp
│       │   ├── __tests__
│       │   │   └── proxy.test.ts
│       │   └── proxy.ts
│       ├── openapi
│       │   ├── __tests__
│       │   │   ├── file-upload.test.ts
│       │   │   ├── parser-multipart.test.ts
│       │   │   └── parser.test.ts
│       │   ├── file-upload.ts
│       │   └── parser.ts
│       └── README.md
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/src/openapi-mcp-server/openapi/__tests__/parser.test.ts:
--------------------------------------------------------------------------------

```typescript
   1 | import { OpenAPIToMCPConverter } from '../parser'
   2 | import { OpenAPIV3 } from 'openapi-types'
   3 | import { describe, expect, it } from 'vitest'
   4 | import { JSONSchema7 as IJsonSchema } from 'json-schema'
   5 | 
   6 | interface ToolMethod {
   7 |   name: string
   8 |   description: string
   9 |   inputSchema: any
  10 |   returnSchema?: any
  11 | }
  12 | 
  13 | interface Tool {
  14 |   methods: ToolMethod[]
  15 | }
  16 | 
  17 | interface Tools {
  18 |   [key: string]: Tool
  19 | }
  20 | 
  21 | // Helper function to verify tool method structure without checking the exact Zod schema
  22 | function verifyToolMethod(actual: ToolMethod, expected: any, toolName: string) {
  23 |   expect(actual.name).toBe(expected.name)
  24 |   expect(actual.description).toBe(expected.description)
  25 |   expect(actual.inputSchema, `inputSchema ${actual.name} ${toolName}`).toEqual(expected.inputSchema)
  26 |   if (expected.returnSchema) {
  27 |     expect(actual.returnSchema, `returnSchema ${actual.name} ${toolName}`).toEqual(expected.returnSchema)
  28 |   }
  29 | }
  30 | 
  31 | // Helper function to verify tools structure
  32 | function verifyTools(actual: Tools, expected: any) {
  33 |   expect(Object.keys(actual)).toEqual(Object.keys(expected))
  34 |   for (const [key, value] of Object.entries(actual)) {
  35 |     expect(value.methods.length).toBe(expected[key].methods.length)
  36 |     value.methods.forEach((method: ToolMethod, index: number) => {
  37 |       verifyToolMethod(method, expected[key].methods[index], key)
  38 |     })
  39 |   }
  40 | }
  41 | 
  42 | // A helper function to derive a type from a possibly complex schema.
  43 | // If no explicit type is found, we assume 'object' for testing purposes.
  44 | function getTypeFromSchema(schema: IJsonSchema): string {
  45 |   if (schema.type) {
  46 |     return Array.isArray(schema.type) ? schema.type[0] : schema.type
  47 |   } else if (schema.$ref) {
  48 |     // If there's a $ref, we treat it as an object reference.
  49 |     return 'object'
  50 |   } else if (schema.oneOf || schema.anyOf || schema.allOf) {
  51 |     // Complex schema combos - assume object for these tests.
  52 |     return 'object'
  53 |   }
  54 |   return 'object'
  55 | }
  56 | 
  57 | // Updated helper function to get parameters from inputSchema
  58 | // Now handles $ref by treating it as an object reference without expecting properties.
  59 | function getParamsFromSchema(method: { inputSchema: IJsonSchema }) {
  60 |   return Object.entries(method.inputSchema.properties || {}).map(([name, prop]) => {
  61 |     if (typeof prop === 'boolean') {
  62 |       throw new Error(`Boolean schema not supported for parameter ${name}`)
  63 |     }
  64 | 
  65 |     // If there's a $ref, treat it as an object reference.
  66 |     const schemaType = getTypeFromSchema(prop)
  67 |     return {
  68 |       name,
  69 |       type: schemaType,
  70 |       description: prop.description,
  71 |       optional: !(method.inputSchema.required || []).includes(name),
  72 |     }
  73 |   })
  74 | }
  75 | 
  76 | // Updated helper function to get return type from returnSchema
  77 | // No longer requires that the schema be fully expanded. If we have a $ref, just note it as 'object'.
  78 | function getReturnType(method: { returnSchema?: IJsonSchema }) {
  79 |   if (!method.returnSchema) return null
  80 |   const schema = method.returnSchema
  81 |   return {
  82 |     type: getTypeFromSchema(schema),
  83 |     description: schema.description,
  84 |   }
  85 | }
  86 | 
  87 | describe('OpenAPIToMCPConverter', () => {
  88 |   describe('Simple API Conversion', () => {
  89 |     const sampleSpec: OpenAPIV3.Document = {
  90 |       openapi: '3.0.0',
  91 |       info: {
  92 |         title: 'Test API',
  93 |         version: '1.0.0',
  94 |       },
  95 |       paths: {
  96 |         '/pets/{petId}': {
  97 |           get: {
  98 |             operationId: 'getPet',
  99 |             summary: 'Get a pet by ID',
 100 |             parameters: [
 101 |               {
 102 |                 name: 'petId',
 103 |                 in: 'path',
 104 |                 required: true,
 105 |                 description: 'The ID of the pet',
 106 |                 schema: {
 107 |                   type: 'integer',
 108 |                 },
 109 |               },
 110 |             ],
 111 |             responses: {
 112 |               '200': {
 113 |                 description: 'Pet found',
 114 |                 content: {
 115 |                   'application/json': {
 116 |                     schema: {
 117 |                       type: 'object',
 118 |                       properties: {
 119 |                         id: { type: 'integer' },
 120 |                         name: { type: 'string' },
 121 |                       },
 122 |                     },
 123 |                   },
 124 |                 },
 125 |               },
 126 |             },
 127 |           },
 128 |         },
 129 |       },
 130 |     }
 131 | 
 132 |     it('converts simple OpenAPI paths to MCP tools', () => {
 133 |       const converter = new OpenAPIToMCPConverter(sampleSpec)
 134 |       const { tools, openApiLookup } = converter.convertToMCPTools()
 135 | 
 136 |       expect(tools).toHaveProperty('API')
 137 |       expect(tools.API.methods).toHaveLength(1)
 138 |       expect(Object.keys(openApiLookup)).toHaveLength(1)
 139 | 
 140 |       const getPetMethod = tools.API.methods.find((m) => m.name === 'getPet')
 141 |       expect(getPetMethod).toBeDefined()
 142 | 
 143 |       const params = getParamsFromSchema(getPetMethod!)
 144 |       expect(params).toContainEqual({
 145 |         name: 'petId',
 146 |         type: 'integer',
 147 |         description: 'The ID of the pet',
 148 |         optional: false,
 149 |       })
 150 |     })
 151 | 
 152 |     it('truncates tool names exceeding 64 characters', () => {
 153 |       const longOperationId = 'a'.repeat(65)
 154 |       const specWithLongName: OpenAPIV3.Document = {
 155 |         openapi: '3.0.0',
 156 |         info: {
 157 |           title: 'Test API',
 158 |           version: '1.0.0'
 159 |         },
 160 |         paths: {
 161 |           '/pets/{petId}': {
 162 |             get: {
 163 |               operationId: longOperationId,
 164 |               summary: 'Get a pet by ID',
 165 |               parameters: [
 166 |                 {
 167 |                   name: 'petId',
 168 |                   in: 'path',
 169 |                   required: true,
 170 |                   description: 'The ID of the pet',
 171 |                   schema: {
 172 |                     type: 'integer'
 173 |                   }
 174 |                 }
 175 |               ],
 176 |               responses: {
 177 |                 '200': {
 178 |                   description: 'Pet found',
 179 |                   content: {
 180 |                     'application/json': {
 181 |                       schema: {
 182 |                         type: 'object',
 183 |                         properties: {
 184 |                           id: { type: 'integer' },
 185 |                           name: { type: 'string' }
 186 |                         }
 187 |                       }
 188 |                     }
 189 |                   }
 190 |                 }
 191 |               }
 192 |             }
 193 |           }
 194 |         }
 195 |       }
 196 | 
 197 |       const converter = new OpenAPIToMCPConverter(specWithLongName)
 198 |       const { tools } = converter.convertToMCPTools()
 199 | 
 200 |       const longNameMethod = tools.API.methods.find(m => m.name.startsWith('a'.repeat(59)))
 201 |       expect(longNameMethod).toBeDefined()
 202 |       expect(longNameMethod!.name.length).toBeLessThanOrEqual(64)
 203 |     })
 204 |   })
 205 | 
 206 |   describe('Complex API Conversion', () => {
 207 |     const complexSpec: OpenAPIV3.Document = {
 208 |       openapi: '3.0.0',
 209 |       info: { title: 'Complex API', version: '1.0.0' },
 210 |       components: {
 211 |         schemas: {
 212 |           Error: {
 213 |             type: 'object',
 214 |             required: ['code', 'message'],
 215 |             properties: {
 216 |               code: { type: 'integer' },
 217 |               message: { type: 'string' },
 218 |             },
 219 |           },
 220 |           Pet: {
 221 |             type: 'object',
 222 |             required: ['id', 'name'],
 223 |             properties: {
 224 |               id: { type: 'integer', description: 'The ID of the pet' },
 225 |               name: { type: 'string', description: 'The name of the pet' },
 226 |               category: { $ref: '#/components/schemas/Category', description: 'The category of the pet' },
 227 |               tags: {
 228 |                 type: 'array',
 229 |                 description: 'The tags of the pet',
 230 |                 items: { $ref: '#/components/schemas/Tag' },
 231 |               },
 232 |               status: {
 233 |                 type: 'string',
 234 |                 description: 'The status of the pet',
 235 |                 enum: ['available', 'pending', 'sold'],
 236 |               },
 237 |             },
 238 |           },
 239 |           Category: {
 240 |             type: 'object',
 241 |             required: ['id', 'name'],
 242 |             properties: {
 243 |               id: { type: 'integer' },
 244 |               name: { type: 'string' },
 245 |               subcategories: {
 246 |                 type: 'array',
 247 |                 items: { $ref: '#/components/schemas/Category' },
 248 |               },
 249 |             },
 250 |           },
 251 |           Tag: {
 252 |             type: 'object',
 253 |             required: ['id', 'name'],
 254 |             properties: {
 255 |               id: { type: 'integer' },
 256 |               name: { type: 'string' },
 257 |             },
 258 |           },
 259 |         },
 260 |         parameters: {
 261 |           PetId: {
 262 |             name: 'petId',
 263 |             in: 'path',
 264 |             required: true,
 265 |             description: 'ID of pet to fetch',
 266 |             schema: { type: 'integer' },
 267 |           },
 268 |           QueryLimit: {
 269 |             name: 'limit',
 270 |             in: 'query',
 271 |             description: 'Maximum number of results to return',
 272 |             schema: { type: 'integer', minimum: 1, maximum: 100, default: 20 },
 273 |           },
 274 |         },
 275 |         responses: {
 276 |           NotFound: {
 277 |             description: 'The specified resource was not found',
 278 |             content: {
 279 |               'application/json': {
 280 |                 schema: { $ref: '#/components/schemas/Error' },
 281 |               },
 282 |             },
 283 |           },
 284 |         },
 285 |       },
 286 |       paths: {
 287 |         '/pets': {
 288 |           get: {
 289 |             operationId: 'listPets',
 290 |             summary: 'List all pets',
 291 |             parameters: [{ $ref: '#/components/parameters/QueryLimit' }],
 292 |             responses: {
 293 |               '200': {
 294 |                 description: 'A list of pets',
 295 |                 content: {
 296 |                   'application/json': {
 297 |                     schema: {
 298 |                       type: 'array',
 299 |                       items: { $ref: '#/components/schemas/Pet' },
 300 |                     },
 301 |                   },
 302 |                 },
 303 |               },
 304 |             },
 305 |           },
 306 |           post: {
 307 |             operationId: 'createPet',
 308 |             summary: 'Create a pet',
 309 |             requestBody: {
 310 |               required: true,
 311 |               content: {
 312 |                 'application/json': {
 313 |                   schema: { $ref: '#/components/schemas/Pet' },
 314 |                 },
 315 |               },
 316 |             },
 317 |             responses: {
 318 |               '201': {
 319 |                 description: 'Pet created',
 320 |                 content: {
 321 |                   'application/json': {
 322 |                     schema: { $ref: '#/components/schemas/Pet' },
 323 |                   },
 324 |                 },
 325 |               },
 326 |             },
 327 |           },
 328 |         },
 329 |         '/pets/{petId}': {
 330 |           get: {
 331 |             operationId: 'getPet',
 332 |             summary: 'Get a pet by ID',
 333 |             parameters: [{ $ref: '#/components/parameters/PetId' }],
 334 |             responses: {
 335 |               '200': {
 336 |                 description: 'Pet found',
 337 |                 content: {
 338 |                   'application/json': {
 339 |                     schema: { $ref: '#/components/schemas/Pet' },
 340 |                   },
 341 |                 },
 342 |               },
 343 |               '404': {
 344 |                 $ref: '#/components/responses/NotFound',
 345 |               },
 346 |             },
 347 |           },
 348 |           put: {
 349 |             operationId: 'updatePet',
 350 |             summary: 'Update a pet',
 351 |             parameters: [{ $ref: '#/components/parameters/PetId' }],
 352 |             requestBody: {
 353 |               required: true,
 354 |               content: {
 355 |                 'application/json': {
 356 |                   schema: { $ref: '#/components/schemas/Pet' },
 357 |                 },
 358 |               },
 359 |             },
 360 |             responses: {
 361 |               '200': {
 362 |                 description: 'Pet updated',
 363 |                 content: {
 364 |                   'application/json': {
 365 |                     schema: { $ref: '#/components/schemas/Pet' },
 366 |                   },
 367 |                 },
 368 |               },
 369 |               '404': {
 370 |                 $ref: '#/components/responses/NotFound',
 371 |               },
 372 |             },
 373 |           },
 374 |         },
 375 |       },
 376 |     }
 377 | 
 378 |     it('converts operations with referenced parameters', () => {
 379 |       const converter = new OpenAPIToMCPConverter(complexSpec)
 380 |       const { tools } = converter.convertToMCPTools()
 381 | 
 382 |       const getPetMethod = tools.API.methods.find((m) => m.name === 'getPet')
 383 |       expect(getPetMethod).toBeDefined()
 384 |       const params = getParamsFromSchema(getPetMethod!)
 385 |       expect(params).toContainEqual({
 386 |         name: 'petId',
 387 |         type: 'integer',
 388 |         description: 'ID of pet to fetch',
 389 |         optional: false,
 390 |       })
 391 |     })
 392 | 
 393 |     it('converts operations with query parameters', () => {
 394 |       const converter = new OpenAPIToMCPConverter(complexSpec)
 395 |       const { tools } = converter.convertToMCPTools()
 396 | 
 397 |       const listPetsMethod = tools.API.methods.find((m) => m.name === 'listPets')
 398 |       expect(listPetsMethod).toBeDefined()
 399 | 
 400 |       const params = getParamsFromSchema(listPetsMethod!)
 401 |       expect(params).toContainEqual({
 402 |         name: 'limit',
 403 |         type: 'integer',
 404 |         description: 'Maximum number of results to return',
 405 |         optional: true,
 406 |       })
 407 |     })
 408 | 
 409 |     it('converts operations with array responses', () => {
 410 |       const converter = new OpenAPIToMCPConverter(complexSpec)
 411 |       const { tools } = converter.convertToMCPTools()
 412 | 
 413 |       const listPetsMethod = tools.API.methods.find((m) => m.name === 'listPets')
 414 |       expect(listPetsMethod).toBeDefined()
 415 | 
 416 |       const returnType = getReturnType(listPetsMethod!)
 417 |       // Now we only check type since description might not be carried through
 418 |       // if we are not expanding schemas.
 419 |       expect(returnType).toMatchObject({
 420 |         type: 'array',
 421 |       })
 422 |     })
 423 | 
 424 |     it('converts operations with request bodies using $ref', () => {
 425 |       const converter = new OpenAPIToMCPConverter(complexSpec)
 426 |       const { tools } = converter.convertToMCPTools()
 427 | 
 428 |       const createPetMethod = tools.API.methods.find((m) => m.name === 'createPet')
 429 |       expect(createPetMethod).toBeDefined()
 430 | 
 431 |       const params = getParamsFromSchema(createPetMethod!)
 432 |       // Now that we are preserving $ref, the request body won't be expanded into multiple parameters.
 433 |       // Instead, we'll have a single "body" parameter referencing Pet.
 434 |       expect(params).toEqual(
 435 |         expect.arrayContaining([
 436 |           expect.objectContaining({
 437 |             name: 'body',
 438 |             type: 'object', // Because it's a $ref
 439 |             optional: false,
 440 |           }),
 441 |         ]),
 442 |       )
 443 |     })
 444 | 
 445 |     it('converts operations with referenced error responses', () => {
 446 |       const converter = new OpenAPIToMCPConverter(complexSpec)
 447 |       const { tools } = converter.convertToMCPTools()
 448 | 
 449 |       const getPetMethod = tools.API.methods.find((m) => m.name === 'getPet')
 450 |       expect(getPetMethod).toBeDefined()
 451 | 
 452 |       // We just check that the description includes the error references now.
 453 |       expect(getPetMethod?.description).toContain('404: The specified resource was not found')
 454 |     })
 455 | 
 456 |     it('handles recursive schema references without expanding them', () => {
 457 |       const converter = new OpenAPIToMCPConverter(complexSpec)
 458 |       const { tools } = converter.convertToMCPTools()
 459 | 
 460 |       const createPetMethod = tools.API.methods.find((m) => m.name === 'createPet')
 461 |       expect(createPetMethod).toBeDefined()
 462 | 
 463 |       const params = getParamsFromSchema(createPetMethod!)
 464 |       // Since "category" would be inside Pet, and we're not expanding,
 465 |       // we won't see 'category' directly. We only have 'body' as a reference.
 466 |       // Thus, the test no longer checks for a direct 'category' param.
 467 |       expect(params.find((p) => p.name === 'body')).toBeDefined()
 468 |     })
 469 | 
 470 |     it('converts all operations correctly respecting $ref usage', () => {
 471 |       const converter = new OpenAPIToMCPConverter(complexSpec)
 472 |       const { tools } = converter.convertToMCPTools()
 473 | 
 474 |       expect(tools.API.methods).toHaveLength(4)
 475 | 
 476 |       const methodNames = tools.API.methods.map((m) => m.name)
 477 |       expect(methodNames).toEqual(expect.arrayContaining(['listPets', 'createPet', 'getPet', 'updatePet']))
 478 | 
 479 |       tools.API.methods.forEach((method) => {
 480 |         expect(method).toHaveProperty('name')
 481 |         expect(method).toHaveProperty('description')
 482 |         expect(method).toHaveProperty('inputSchema')
 483 |         expect(method).toHaveProperty('returnSchema')
 484 | 
 485 |         // For 'get' operations, we just check the return type is recognized correctly.
 486 |         if (method.name.startsWith('get')) {
 487 |           const returnType = getReturnType(method)
 488 |           // With $ref usage, we can't guarantee description or direct expansion.
 489 |           expect(returnType?.type).toBe('object')
 490 |         }
 491 |       })
 492 |     })
 493 |   })
 494 | 
 495 |   describe('Complex Schema Conversion', () => {
 496 |     // A similar approach for the nested spec
 497 |     // Just as in the previous tests, we no longer test for direct property expansion.
 498 |     // We only confirm that parameters and return types are recognized and that references are preserved.
 499 | 
 500 |     const nestedSpec: OpenAPIV3.Document = {
 501 |       openapi: '3.0.0',
 502 |       info: { title: 'Nested API', version: '1.0.0' },
 503 |       components: {
 504 |         schemas: {
 505 |           Organization: {
 506 |             type: 'object',
 507 |             required: ['id', 'name'],
 508 |             properties: {
 509 |               id: { type: 'integer' },
 510 |               name: { type: 'string' },
 511 |               departments: {
 512 |                 type: 'array',
 513 |                 items: { $ref: '#/components/schemas/Department' },
 514 |               },
 515 |               metadata: { $ref: '#/components/schemas/Metadata' },
 516 |             },
 517 |           },
 518 |           Department: {
 519 |             type: 'object',
 520 |             required: ['id', 'name'],
 521 |             properties: {
 522 |               id: { type: 'integer' },
 523 |               name: { type: 'string' },
 524 |               employees: {
 525 |                 type: 'array',
 526 |                 items: { $ref: '#/components/schemas/Employee' },
 527 |               },
 528 |               subDepartments: {
 529 |                 type: 'array',
 530 |                 items: { $ref: '#/components/schemas/Department' },
 531 |               },
 532 |               metadata: { $ref: '#/components/schemas/Metadata' },
 533 |             },
 534 |           },
 535 |           Employee: {
 536 |             type: 'object',
 537 |             required: ['id', 'name'],
 538 |             properties: {
 539 |               id: { type: 'integer' },
 540 |               name: { type: 'string' },
 541 |               role: { $ref: '#/components/schemas/Role' },
 542 |               skills: {
 543 |                 type: 'array',
 544 |                 items: { $ref: '#/components/schemas/Skill' },
 545 |               },
 546 |               metadata: { $ref: '#/components/schemas/Metadata' },
 547 |             },
 548 |           },
 549 |           Role: {
 550 |             type: 'object',
 551 |             required: ['id', 'name'],
 552 |             properties: {
 553 |               id: { type: 'integer' },
 554 |               name: { type: 'string' },
 555 |               permissions: {
 556 |                 type: 'array',
 557 |                 items: { $ref: '#/components/schemas/Permission' },
 558 |               },
 559 |             },
 560 |           },
 561 |           Permission: {
 562 |             type: 'object',
 563 |             required: ['id', 'name'],
 564 |             properties: {
 565 |               id: { type: 'integer' },
 566 |               name: { type: 'string' },
 567 |               scope: { type: 'string' },
 568 |             },
 569 |           },
 570 |           Skill: {
 571 |             type: 'object',
 572 |             required: ['id', 'name'],
 573 |             properties: {
 574 |               id: { type: 'integer' },
 575 |               name: { type: 'string' },
 576 |               level: {
 577 |                 type: 'string',
 578 |                 enum: ['beginner', 'intermediate', 'expert'],
 579 |               },
 580 |             },
 581 |           },
 582 |           Metadata: {
 583 |             type: 'object',
 584 |             properties: {
 585 |               createdAt: { type: 'string', format: 'date-time' },
 586 |               updatedAt: { type: 'string', format: 'date-time' },
 587 |               tags: {
 588 |                 type: 'array',
 589 |                 items: { type: 'string' },
 590 |               },
 591 |               customFields: {
 592 |                 type: 'object',
 593 |                 additionalProperties: true,
 594 |               },
 595 |             },
 596 |           },
 597 |         },
 598 |         parameters: {
 599 |           OrgId: {
 600 |             name: 'orgId',
 601 |             in: 'path',
 602 |             required: true,
 603 |             description: 'Organization ID',
 604 |             schema: { type: 'integer' },
 605 |           },
 606 |           DeptId: {
 607 |             name: 'deptId',
 608 |             in: 'path',
 609 |             required: true,
 610 |             description: 'Department ID',
 611 |             schema: { type: 'integer' },
 612 |           },
 613 |           IncludeMetadata: {
 614 |             name: 'includeMetadata',
 615 |             in: 'query',
 616 |             description: 'Include metadata in response',
 617 |             schema: { type: 'boolean', default: false },
 618 |           },
 619 |           Depth: {
 620 |             name: 'depth',
 621 |             in: 'query',
 622 |             description: 'Depth of nested objects to return',
 623 |             schema: { type: 'integer', minimum: 1, maximum: 5, default: 1 },
 624 |           },
 625 |         },
 626 |       },
 627 |       paths: {
 628 |         '/organizations/{orgId}': {
 629 |           get: {
 630 |             operationId: 'getOrganization',
 631 |             summary: 'Get organization details',
 632 |             parameters: [
 633 |               { $ref: '#/components/parameters/OrgId' },
 634 |               { $ref: '#/components/parameters/IncludeMetadata' },
 635 |               { $ref: '#/components/parameters/Depth' },
 636 |             ],
 637 |             responses: {
 638 |               '200': {
 639 |                 description: 'Organization details',
 640 |                 content: {
 641 |                   'application/json': {
 642 |                     schema: { $ref: '#/components/schemas/Organization' },
 643 |                   },
 644 |                 },
 645 |               },
 646 |             },
 647 |           },
 648 |         },
 649 |         '/organizations/{orgId}/departments/{deptId}': {
 650 |           get: {
 651 |             operationId: 'getDepartment',
 652 |             summary: 'Get department details',
 653 |             parameters: [
 654 |               { $ref: '#/components/parameters/OrgId' },
 655 |               { $ref: '#/components/parameters/DeptId' },
 656 |               { $ref: '#/components/parameters/IncludeMetadata' },
 657 |               { $ref: '#/components/parameters/Depth' },
 658 |             ],
 659 |             responses: {
 660 |               '200': {
 661 |                 description: 'Department details',
 662 |                 content: {
 663 |                   'application/json': {
 664 |                     schema: { $ref: '#/components/schemas/Department' },
 665 |                   },
 666 |                 },
 667 |               },
 668 |             },
 669 |           },
 670 |           put: {
 671 |             operationId: 'updateDepartment',
 672 |             summary: 'Update department details',
 673 |             parameters: [{ $ref: '#/components/parameters/OrgId' }, { $ref: '#/components/parameters/DeptId' }],
 674 |             requestBody: {
 675 |               required: true,
 676 |               content: {
 677 |                 'application/json': {
 678 |                   schema: { $ref: '#/components/schemas/Department' },
 679 |                 },
 680 |               },
 681 |             },
 682 |             responses: {
 683 |               '200': {
 684 |                 description: 'Department updated',
 685 |                 content: {
 686 |                   'application/json': {
 687 |                     schema: { $ref: '#/components/schemas/Department' },
 688 |                   },
 689 |                 },
 690 |               },
 691 |             },
 692 |           },
 693 |         },
 694 |       },
 695 |     }
 696 | 
 697 |     it('handles deeply nested object references', () => {
 698 |       const converter = new OpenAPIToMCPConverter(nestedSpec)
 699 |       const { tools } = converter.convertToMCPTools()
 700 | 
 701 |       const getOrgMethod = tools.API.methods.find((m) => m.name === 'getOrganization')
 702 |       expect(getOrgMethod).toBeDefined()
 703 | 
 704 |       const params = getParamsFromSchema(getOrgMethod!)
 705 |       expect(params).toEqual(
 706 |         expect.arrayContaining([
 707 |           expect.objectContaining({
 708 |             name: 'orgId',
 709 |             type: 'integer',
 710 |             description: 'Organization ID',
 711 |             optional: false,
 712 |           }),
 713 |           expect.objectContaining({
 714 |             name: 'includeMetadata',
 715 |             type: 'boolean',
 716 |             description: 'Include metadata in response',
 717 |             optional: true,
 718 |           }),
 719 |           expect.objectContaining({
 720 |             name: 'depth',
 721 |             type: 'integer',
 722 |             description: 'Depth of nested objects to return',
 723 |             optional: true,
 724 |           }),
 725 |         ]),
 726 |       )
 727 |     })
 728 | 
 729 |     it('handles recursive array references without requiring expansion', () => {
 730 |       const converter = new OpenAPIToMCPConverter(nestedSpec)
 731 |       const { tools } = converter.convertToMCPTools()
 732 | 
 733 |       const updateDeptMethod = tools.API.methods.find((m) => m.name === 'updateDepartment')
 734 |       expect(updateDeptMethod).toBeDefined()
 735 | 
 736 |       const params = getParamsFromSchema(updateDeptMethod!)
 737 |       // With $ref usage, we have a body parameter referencing Department.
 738 |       // The subDepartments array is inside Department, so we won't see it expanded here.
 739 |       // Instead, we just confirm 'body' is present.
 740 |       const bodyParam = params.find((p) => p.name === 'body')
 741 |       expect(bodyParam).toBeDefined()
 742 |       expect(bodyParam?.type).toBe('object')
 743 |     })
 744 | 
 745 |     it('handles complex nested object hierarchies without expansion', () => {
 746 |       const converter = new OpenAPIToMCPConverter(nestedSpec)
 747 |       const { tools } = converter.convertToMCPTools()
 748 | 
 749 |       const getDeptMethod = tools.API.methods.find((m) => m.name === 'getDepartment')
 750 |       expect(getDeptMethod).toBeDefined()
 751 | 
 752 |       const params = getParamsFromSchema(getDeptMethod!)
 753 |       // Just checking top-level params:
 754 |       expect(params).toEqual(
 755 |         expect.arrayContaining([
 756 |           expect.objectContaining({
 757 |             name: 'orgId',
 758 |             type: 'integer',
 759 |             optional: false,
 760 |           }),
 761 |           expect.objectContaining({
 762 |             name: 'deptId',
 763 |             type: 'integer',
 764 |             optional: false,
 765 |           }),
 766 |           expect.objectContaining({
 767 |             name: 'includeMetadata',
 768 |             type: 'boolean',
 769 |             optional: true,
 770 |           }),
 771 |           expect.objectContaining({
 772 |             name: 'depth',
 773 |             type: 'integer',
 774 |             optional: true,
 775 |           }),
 776 |         ]),
 777 |       )
 778 |     })
 779 | 
 780 |     it('handles schema with mixed primitive and reference types without expansion', () => {
 781 |       const converter = new OpenAPIToMCPConverter(nestedSpec)
 782 |       const { tools } = converter.convertToMCPTools()
 783 | 
 784 |       const updateDeptMethod = tools.API.methods.find((m) => m.name === 'updateDepartment')
 785 |       expect(updateDeptMethod).toBeDefined()
 786 | 
 787 |       const params = getParamsFromSchema(updateDeptMethod!)
 788 |       // Since we are not expanding, we won't see metadata fields directly.
 789 |       // We just confirm 'body' referencing Department is there.
 790 |       expect(params.find((p) => p.name === 'body')).toBeDefined()
 791 |     })
 792 | 
 793 |     it('converts all operations with complex schemas correctly respecting $ref', () => {
 794 |       const converter = new OpenAPIToMCPConverter(nestedSpec)
 795 |       const { tools } = converter.convertToMCPTools()
 796 | 
 797 |       expect(tools.API.methods).toHaveLength(3)
 798 | 
 799 |       const methodNames = tools.API.methods.map((m) => m.name)
 800 |       expect(methodNames).toEqual(expect.arrayContaining(['getOrganization', 'getDepartment', 'updateDepartment']))
 801 | 
 802 |       tools.API.methods.forEach((method) => {
 803 |         expect(method).toHaveProperty('name')
 804 |         expect(method).toHaveProperty('description')
 805 |         expect(method).toHaveProperty('inputSchema')
 806 |         expect(method).toHaveProperty('returnSchema')
 807 | 
 808 |         // If it's a GET operation, check that return type is recognized.
 809 |         if (method.name.startsWith('get')) {
 810 |           const returnType = getReturnType(method)
 811 |           // Without expansion, just check type is recognized as object.
 812 |           expect(returnType).toMatchObject({
 813 |             type: 'object',
 814 |           })
 815 |         }
 816 |       })
 817 |     })
 818 |   })
 819 | 
 820 |   it('preserves description on $ref nodes', () => {
 821 |     const spec: OpenAPIV3.Document = {
 822 |       openapi: '3.0.0',
 823 |       info: { title: 'Test API', version: '1.0.0' },
 824 |       paths: {},
 825 |       components: {
 826 |         schemas: {
 827 |           TestSchema: {
 828 |             type: 'object',
 829 |             properties: {
 830 |               name: { type: 'string' },
 831 |             },
 832 |           },
 833 |         },
 834 |       },
 835 |     }
 836 | 
 837 |     const converter = new OpenAPIToMCPConverter(spec)
 838 |     const result = converter.convertOpenApiSchemaToJsonSchema(
 839 |       {
 840 |         $ref: '#/components/schemas/TestSchema',
 841 |         description: 'A schema description',
 842 |       },
 843 |       new Set(),
 844 |     )
 845 | 
 846 |     expect(result).toEqual({
 847 |       $ref: '#/$defs/TestSchema',
 848 |       description: 'A schema description',
 849 |     })
 850 |   })
 851 | })
 852 | 
 853 | // Additional complex test scenarios as a table test
 854 | describe('OpenAPIToMCPConverter - Additional Complex Tests', () => {
 855 |   interface TestCase {
 856 |     name: string
 857 |     input: OpenAPIV3.Document
 858 |     expected: {
 859 |       tools: Record<
 860 |         string,
 861 |         {
 862 |           methods: Array<{
 863 |             name: string
 864 |             description: string
 865 |             inputSchema: IJsonSchema & { type: 'object' }
 866 |             returnSchema?: IJsonSchema
 867 |           }>
 868 |         }
 869 |       >
 870 |       openApiLookup: Record<string, OpenAPIV3.OperationObject & { method: string; path: string }>
 871 |     }
 872 |   }
 873 | 
 874 |   const cases: TestCase[] = [
 875 |     {
 876 |       name: 'Cyclic References with Full Descriptions',
 877 |       input: {
 878 |         openapi: '3.0.0',
 879 |         info: {
 880 |           title: 'Cyclic Test API',
 881 |           version: '1.0.0',
 882 |         },
 883 |         paths: {
 884 |           '/ab': {
 885 |             get: {
 886 |               operationId: 'getAB',
 887 |               summary: 'Get an A-B object',
 888 |               responses: {
 889 |                 '200': {
 890 |                   description: 'Returns an A object',
 891 |                   content: {
 892 |                     'application/json': {
 893 |                       schema: { $ref: '#/components/schemas/A' },
 894 |                     },
 895 |                   },
 896 |                 },
 897 |               },
 898 |             },
 899 |             post: {
 900 |               operationId: 'createAB',
 901 |               summary: 'Create an A-B object',
 902 |               requestBody: {
 903 |                 required: true,
 904 |                 content: {
 905 |                   'application/json': {
 906 |                     schema: {
 907 |                       $ref: '#/components/schemas/A',
 908 |                       description: 'A schema description',
 909 |                     },
 910 |                   },
 911 |                 },
 912 |               },
 913 |               responses: {
 914 |                 '201': {
 915 |                   description: 'Created A object',
 916 |                   content: {
 917 |                     'application/json': {
 918 |                       schema: { $ref: '#/components/schemas/A' },
 919 |                     },
 920 |                   },
 921 |                 },
 922 |               },
 923 |             },
 924 |           },
 925 |         },
 926 |         components: {
 927 |           schemas: {
 928 |             A: {
 929 |               type: 'object',
 930 |               description: 'A schema description',
 931 |               required: ['name', 'b'],
 932 |               properties: {
 933 |                 name: {
 934 |                   type: 'string',
 935 |                   description: 'Name of A',
 936 |                 },
 937 |                 b: {
 938 |                   $ref: '#/components/schemas/B',
 939 |                   description: 'B property in A',
 940 |                 },
 941 |               },
 942 |             },
 943 |             B: {
 944 |               type: 'object',
 945 |               description: 'B schema description',
 946 |               required: ['title', 'a'],
 947 |               properties: {
 948 |                 title: {
 949 |                   type: 'string',
 950 |                   description: 'Title of B',
 951 |                 },
 952 |                 a: {
 953 |                   $ref: '#/components/schemas/A',
 954 |                   description: 'A property in B',
 955 |                 },
 956 |               },
 957 |             },
 958 |           },
 959 |         },
 960 |       } as OpenAPIV3.Document,
 961 |       expected: {
 962 |         tools: {
 963 |           API: {
 964 |             methods: [
 965 |               {
 966 |                 name: 'getAB',
 967 |                 description: 'Get an A-B object',
 968 |                 // Error responses might not be listed here since none are defined.
 969 |                 // Just end the description with no Error Responses section.
 970 |                 inputSchema: {
 971 |                   type: 'object',
 972 |                   properties: {},
 973 |                   required: [],
 974 |                   $defs: {
 975 |                     A: {
 976 |                       type: 'object',
 977 |                       description: 'A schema description',
 978 |                       additionalProperties: true,
 979 |                       properties: {
 980 |                         name: {
 981 |                           type: 'string',
 982 |                           description: 'Name of A',
 983 |                         },
 984 |                         b: {
 985 |                           description: 'B property in A',
 986 |                           $ref: '#/$defs/B',
 987 |                         },
 988 |                       },
 989 |                       required: ['name', 'b'],
 990 |                     },
 991 |                     B: {
 992 |                       type: 'object',
 993 |                       description: 'B schema description',
 994 |                       additionalProperties: true,
 995 |                       properties: {
 996 |                         title: {
 997 |                           type: 'string',
 998 |                           description: 'Title of B',
 999 |                         },
1000 |                         a: {
1001 |                           description: 'A property in B',
1002 |                           $ref: '#/$defs/A',
1003 |                         },
1004 |                       },
1005 |                       required: ['title', 'a'],
1006 |                     },
1007 |                   },
1008 |                 },
1009 |                 returnSchema: {
1010 |                   $ref: '#/$defs/A',
1011 |                   description: 'Returns an A object',
1012 |                   $defs: {
1013 |                     A: {
1014 |                       type: 'object',
1015 |                       description: 'A schema description',
1016 |                       additionalProperties: true,
1017 |                       properties: {
1018 |                         name: {
1019 |                           type: 'string',
1020 |                           description: 'Name of A',
1021 |                         },
1022 |                         b: {
1023 |                           description: 'B property in A',
1024 |                           $ref: '#/$defs/B',
1025 |                         },
1026 |                       },
1027 |                       required: ['name', 'b'],
1028 |                     },
1029 |                     B: {
1030 |                       type: 'object',
1031 |                       description: 'B schema description',
1032 |                       additionalProperties: true,
1033 |                       properties: {
1034 |                         title: {
1035 |                           type: 'string',
1036 |                           description: 'Title of B',
1037 |                         },
1038 |                         a: {
1039 |                           description: 'A property in B',
1040 |                           $ref: '#/$defs/A',
1041 |                         },
1042 |                       },
1043 |                       required: ['title', 'a'],
1044 |                     },
1045 |                   },
1046 |                 },
1047 |               },
1048 |               {
1049 |                 name: 'createAB',
1050 |                 description: 'Create an A-B object',
1051 |                 inputSchema: {
1052 |                   type: 'object',
1053 |                   properties: {
1054 |                     // The requestBody references A. We keep it as a single body field with a $ref.
1055 |                     body: {
1056 |                       $ref: '#/$defs/A',
1057 |                       description: 'A schema description',
1058 |                     },
1059 |                   },
1060 |                   required: ['body'],
1061 | 
1062 |                   $defs: {
1063 |                     A: {
1064 |                       type: 'object',
1065 |                       description: 'A schema description',
1066 |                       additionalProperties: true,
1067 |                       properties: {
1068 |                         name: {
1069 |                           type: 'string',
1070 |                           description: 'Name of A',
1071 |                         },
1072 |                         b: {
1073 |                           description: 'B property in A',
1074 |                           $ref: '#/$defs/B',
1075 |                         },
1076 |                       },
1077 |                       required: ['name', 'b'],
1078 |                     },
1079 |                     B: {
1080 |                       type: 'object',
1081 |                       description: 'B schema description',
1082 |                       additionalProperties: true,
1083 |                       properties: {
1084 |                         title: {
1085 |                           type: 'string',
1086 |                           description: 'Title of B',
1087 |                         },
1088 |                         a: {
1089 |                           description: 'A property in B',
1090 |                           $ref: '#/$defs/A',
1091 |                         },
1092 |                       },
1093 |                       required: ['title', 'a'],
1094 |                     },
1095 |                   },
1096 |                 },
1097 |                 returnSchema: {
1098 |                   $ref: '#/$defs/A',
1099 |                   description: 'Created A object',
1100 | 
1101 |                   $defs: {
1102 |                     A: {
1103 |                       type: 'object',
1104 |                       description: 'A schema description',
1105 |                       additionalProperties: true,
1106 |                       properties: {
1107 |                         name: {
1108 |                           type: 'string',
1109 |                           description: 'Name of A',
1110 |                         },
1111 |                         b: {
1112 |                           description: 'B property in A',
1113 |                           $ref: '#/$defs/B',
1114 |                         },
1115 |                       },
1116 |                       required: ['name', 'b'],
1117 |                     },
1118 |                     B: {
1119 |                       type: 'object',
1120 |                       description: 'B schema description',
1121 |                       additionalProperties: true,
1122 |                       properties: {
1123 |                         title: {
1124 |                           type: 'string',
1125 |                           description: 'Title of B',
1126 |                         },
1127 |                         a: {
1128 |                           description: 'A property in B',
1129 |                           $ref: '#/$defs/A',
1130 |                         },
1131 |                       },
1132 |                       required: ['title', 'a'],
1133 |                     },
1134 |                   },
1135 |                 },
1136 |               },
1137 |             ],
1138 |           },
1139 |         },
1140 |         openApiLookup: {
1141 |           'API-getAB': {
1142 |             operationId: 'getAB',
1143 |             summary: 'Get an A-B object',
1144 |             responses: {
1145 |               '200': {
1146 |                 description: 'Returns an A object',
1147 |                 content: {
1148 |                   'application/json': {
1149 |                     schema: { $ref: '#/components/schemas/A' },
1150 |                   },
1151 |                 },
1152 |               },
1153 |             },
1154 |             method: 'get',
1155 |             path: '/ab',
1156 |           },
1157 |           'API-createAB': {
1158 |             operationId: 'createAB',
1159 |             summary: 'Create an A-B object',
1160 |             requestBody: {
1161 |               required: true,
1162 |               content: {
1163 |                 'application/json': {
1164 |                   schema: {
1165 |                     $ref: '#/components/schemas/A',
1166 |                     description: 'A schema description',
1167 |                   },
1168 |                 },
1169 |               },
1170 |             },
1171 |             responses: {
1172 |               '201': {
1173 |                 description: 'Created A object',
1174 |                 content: {
1175 |                   'application/json': {
1176 |                     schema: { $ref: '#/components/schemas/A' },
1177 |                   },
1178 |                 },
1179 |               },
1180 |             },
1181 |             method: 'post',
1182 |             path: '/ab',
1183 |           },
1184 |         },
1185 |       },
1186 |     },
1187 |     {
1188 |       name: 'allOf/oneOf References with Full Descriptions',
1189 |       input: {
1190 |         openapi: '3.0.0',
1191 |         info: { title: 'Composed Schema API', version: '1.0.0' },
1192 |         paths: {
1193 |           '/composed': {
1194 |             get: {
1195 |               operationId: 'getComposed',
1196 |               summary: 'Get a composed resource',
1197 |               responses: {
1198 |                 '200': {
1199 |                   description: 'A composed object',
1200 |                   content: {
1201 |                     'application/json': {
1202 |                       schema: { $ref: '#/components/schemas/C' },
1203 |                     },
1204 |                   },
1205 |                 },
1206 |               },
1207 |             },
1208 |           },
1209 |         },
1210 |         components: {
1211 |           schemas: {
1212 |             Base: {
1213 |               type: 'object',
1214 |               description: 'Base schema description',
1215 |               properties: {
1216 |                 baseName: {
1217 |                   type: 'string',
1218 |                   description: 'Name in the base schema',
1219 |                 },
1220 |               },
1221 |             },
1222 |             D: {
1223 |               type: 'object',
1224 |               description: 'D schema description',
1225 |               properties: {
1226 |                 dProp: {
1227 |                   type: 'integer',
1228 |                   description: 'D property integer',
1229 |                 },
1230 |               },
1231 |             },
1232 |             E: {
1233 |               type: 'object',
1234 |               description: 'E schema description',
1235 |               properties: {
1236 |                 choice: {
1237 |                   description: 'One of these choices',
1238 |                   oneOf: [
1239 |                     {
1240 |                       $ref: '#/components/schemas/F',
1241 |                     },
1242 |                     {
1243 |                       $ref: '#/components/schemas/G',
1244 |                     },
1245 |                   ],
1246 |                 },
1247 |               },
1248 |             },
1249 |             F: {
1250 |               type: 'object',
1251 |               description: 'F schema description',
1252 |               properties: {
1253 |                 fVal: {
1254 |                   type: 'boolean',
1255 |                   description: 'Boolean in F',
1256 |                 },
1257 |               },
1258 |             },
1259 |             G: {
1260 |               type: 'object',
1261 |               description: 'G schema description',
1262 |               properties: {
1263 |                 gVal: {
1264 |                   type: 'string',
1265 |                   description: 'String in G',
1266 |                 },
1267 |               },
1268 |             },
1269 |             C: {
1270 |               description: 'C schema description',
1271 |               allOf: [{ $ref: '#/components/schemas/Base' }, { $ref: '#/components/schemas/D' }, { $ref: '#/components/schemas/E' }],
1272 |             },
1273 |           },
1274 |         },
1275 |       } as OpenAPIV3.Document,
1276 |       expected: {
1277 |         tools: {
1278 |           API: {
1279 |             methods: [
1280 |               {
1281 |                 name: 'getComposed',
1282 |                 description: 'Get a composed resource',
1283 |                 inputSchema: {
1284 |                   type: 'object',
1285 |                   properties: {},
1286 |                   required: [],
1287 |                   $defs: {
1288 |                     Base: {
1289 |                       type: 'object',
1290 |                       description: 'Base schema description',
1291 |                       additionalProperties: true,
1292 |                       properties: {
1293 |                         baseName: {
1294 |                           type: 'string',
1295 |                           description: 'Name in the base schema',
1296 |                         },
1297 |                       },
1298 |                     },
1299 |                     C: {
1300 |                       description: 'C schema description',
1301 |                       allOf: [{ $ref: '#/$defs/Base' }, { $ref: '#/$defs/D' }, { $ref: '#/$defs/E' }],
1302 |                     },
1303 |                     D: {
1304 |                       type: 'object',
1305 |                       additionalProperties: true,
1306 |                       description: 'D schema description',
1307 |                       properties: {
1308 |                         dProp: {
1309 |                           type: 'integer',
1310 |                           description: 'D property integer',
1311 |                         },
1312 |                       },
1313 |                     },
1314 |                     E: {
1315 |                       type: 'object',
1316 |                       additionalProperties: true,
1317 |                       description: 'E schema description',
1318 |                       properties: {
1319 |                         choice: {
1320 |                           description: 'One of these choices',
1321 |                           oneOf: [{ $ref: '#/$defs/F' }, { $ref: '#/$defs/G' }],
1322 |                         },
1323 |                       },
1324 |                     },
1325 |                     F: {
1326 |                       type: 'object',
1327 |                       additionalProperties: true,
1328 |                       description: 'F schema description',
1329 |                       properties: {
1330 |                         fVal: {
1331 |                           type: 'boolean',
1332 |                           description: 'Boolean in F',
1333 |                         },
1334 |                       },
1335 |                     },
1336 |                     G: {
1337 |                       type: 'object',
1338 |                       additionalProperties: true,
1339 |                       description: 'G schema description',
1340 |                       properties: {
1341 |                         gVal: {
1342 |                           type: 'string',
1343 |                           description: 'String in G',
1344 |                         },
1345 |                       },
1346 |                     },
1347 |                   },
1348 |                 },
1349 |                 returnSchema: {
1350 |                   $ref: '#/$defs/C',
1351 |                   description: 'A composed object',
1352 |                   $defs: {
1353 |                     Base: {
1354 |                       type: 'object',
1355 |                       description: 'Base schema description',
1356 |                       additionalProperties: true,
1357 |                       properties: {
1358 |                         baseName: {
1359 |                           type: 'string',
1360 |                           description: 'Name in the base schema',
1361 |                         },
1362 |                       },
1363 |                     },
1364 |                     C: {
1365 |                       description: 'C schema description',
1366 |                       allOf: [{ $ref: '#/$defs/Base' }, { $ref: '#/$defs/D' }, { $ref: '#/$defs/E' }],
1367 |                     },
1368 |                     D: {
1369 |                       type: 'object',
1370 |                       additionalProperties: true,
1371 |                       description: 'D schema description',
1372 |                       properties: {
1373 |                         dProp: {
1374 |                           type: 'integer',
1375 |                           description: 'D property integer',
1376 |                         },
1377 |                       },
1378 |                     },
1379 |                     E: {
1380 |                       type: 'object',
1381 |                       additionalProperties: true,
1382 |                       description: 'E schema description',
1383 |                       properties: {
1384 |                         choice: {
1385 |                           description: 'One of these choices',
1386 |                           oneOf: [{ $ref: '#/$defs/F' }, { $ref: '#/$defs/G' }],
1387 |                         },
1388 |                       },
1389 |                     },
1390 |                     F: {
1391 |                       type: 'object',
1392 |                       additionalProperties: true,
1393 |                       description: 'F schema description',
1394 |                       properties: {
1395 |                         fVal: {
1396 |                           type: 'boolean',
1397 |                           description: 'Boolean in F',
1398 |                         },
1399 |                       },
1400 |                     },
1401 |                     G: {
1402 |                       type: 'object',
1403 |                       additionalProperties: true,
1404 |                       description: 'G schema description',
1405 |                       properties: {
1406 |                         gVal: {
1407 |                           type: 'string',
1408 |                           description: 'String in G',
1409 |                         },
1410 |                       },
1411 |                     },
1412 |                   },
1413 |                 },
1414 |               },
1415 |             ],
1416 |           },
1417 |         },
1418 |         openApiLookup: {
1419 |           'API-getComposed': {
1420 |             operationId: 'getComposed',
1421 |             summary: 'Get a composed resource',
1422 |             responses: {
1423 |               '200': {
1424 |                 description: 'A composed object',
1425 |                 content: {
1426 |                   'application/json': {
1427 |                     schema: { $ref: '#/components/schemas/C' },
1428 |                   },
1429 |                 },
1430 |               },
1431 |             },
1432 |             method: 'get',
1433 |             path: '/composed',
1434 |           },
1435 |         },
1436 |       },
1437 |     },
1438 |   ]
1439 | 
1440 |   it.each(cases)('$name', ({ input, expected }) => {
1441 |     const converter = new OpenAPIToMCPConverter(input)
1442 |     const { tools, openApiLookup } = converter.convertToMCPTools()
1443 | 
1444 |     // Use the custom verification instead of direct equality
1445 |     verifyTools(tools, expected.tools)
1446 |     expect(openApiLookup).toEqual(expected.openApiLookup)
1447 |   })
1448 | })
1449 | 
```

--------------------------------------------------------------------------------
/scripts/notion-openapi.json:
--------------------------------------------------------------------------------

```json
   1 | {
   2 |   "openapi": "3.1.0",
   3 |   "info": {
   4 |     "title": "Notion API",
   5 |     "version": "1"
   6 |   },
   7 |   "servers": [
   8 |     {
   9 |       "url": "https://api.notion.com"
  10 |     }
  11 |   ],
  12 |   "components": {
  13 |     "securitySchemes": {
  14 |       "bearerAuth": {
  15 |         "type": "http",
  16 |         "scheme": "bearer"
  17 |       },
  18 |       "basicAuth": {
  19 |         "type": "http",
  20 |         "scheme": "basic"
  21 |       }
  22 |     },
  23 |     "parameters": {},
  24 |     "schemas": {}
  25 |   },
  26 |   "security": [
  27 |     {
  28 |       "bearerAuth": []
  29 |     }
  30 |   ],
  31 |   "paths": {
  32 |     "/v1/users/{user_id}": {
  33 |       "get": {
  34 |         "summary": "Retrieve a user",
  35 |         "description": "",
  36 |         "operationId": "get-user",
  37 |         "parameters": [
  38 |           {
  39 |             "name": "user_id",
  40 |             "in": "path",
  41 |             "required": true,
  42 |             "schema": {
  43 |               "type": "string",
  44 |               "format": "uuid"
  45 |             }
  46 |           }
  47 |         ],
  48 |         "responses": {
  49 |           "200": {
  50 |             "description": "200",
  51 |             "content": {
  52 |               "application/json": {
  53 |                 "examples": {
  54 |                   "Result": {
  55 |                     "value": "{\n  \"object\": \"user\",\n  \"id\": \"d40e767c-d7af-4b18-a86d-55c61f1e39a4\",\n  \"type\": \"person\",\n\t\"person\": {\n\t\t\"email\": \"avo@example.org\",\n\t},\n  \"name\": \"Avocado Lovelace\",\n  \"avatar_url\": \"https://secure.notion-static.com/e6a352a8-8381-44d0-a1dc-9ed80e62b53d.jpg\",\n}"
  56 |                   }
  57 |                 }
  58 |               }
  59 |             }
  60 |           },
  61 |           "400": {
  62 |             "description": "400",
  63 |             "content": {
  64 |               "application/json": {
  65 |                 "examples": {
  66 |                   "Result": {
  67 |                     "value": "{}"
  68 |                   }
  69 |                 },
  70 |                 "schema": {
  71 |                   "type": "object",
  72 |                   "properties": {}
  73 |                 }
  74 |               }
  75 |             }
  76 |           }
  77 |         },
  78 |         "deprecated": false,
  79 |         "security": []
  80 |       }
  81 |     },
  82 |     "/v1/users": {
  83 |       "get": {
  84 |         "summary": "List all users",
  85 |         "operationId": "get-users",
  86 |         "parameters": [
  87 |           {
  88 |             "name": "start_cursor",
  89 |             "in": "query",
  90 |             "description": "If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results.",
  91 |             "schema": {
  92 |               "type": "string"
  93 |             }
  94 |           },
  95 |           {
  96 |             "name": "page_size",
  97 |             "in": "query",
  98 |             "description": "The number of items from the full list desired in the response. Maximum: 100",
  99 |             "schema": {
 100 |               "type": "integer",
 101 |               "default": 100
 102 |             }
 103 |           }
 104 |         ],
 105 |         "responses": {
 106 |           "400": {
 107 |             "description": "400",
 108 |             "content": {
 109 |               "application/json": {
 110 |                 "examples": {
 111 |                   "Result": {
 112 |                     "value": "{}"
 113 |                   }
 114 |                 },
 115 |                 "schema": {
 116 |                   "type": "object",
 117 |                   "properties": {}
 118 |                 }
 119 |               }
 120 |             }
 121 |           }
 122 |         },
 123 |         "deprecated": false
 124 |       }
 125 |     },
 126 |     "/v1/users/me": {
 127 |       "get": {
 128 |         "summary": "Retrieve your token's bot user",
 129 |         "description": "",
 130 |         "operationId": "get-self",
 131 |         "parameters": [],
 132 |         "responses": {
 133 |           "200": {
 134 |             "description": "200",
 135 |             "content": {
 136 |               "application/json": {
 137 |                 "examples": {
 138 |                   "Result": {
 139 |                     "value": "{\n  \"object\": \"user\",\n  \"id\": \"16d84278-ab0e-484c-9bdd-b35da3bd8905\",\n  \"name\": \"pied piper\",\n  \"avatar_url\": null,\n  \"type\": \"bot\",\n  \"bot\": {\n    \"owner\": {\n      \"type\": \"user\",\n      \"user\": {\n        \"object\": \"user\",\n        \"id\": \"5389a034-eb5c-47b5-8a9e-f79c99ef166c\",\n        \"name\": \"christine makenotion\",\n        \"avatar_url\": null,\n        \"type\": \"person\",\n        \"person\": {\n          \"email\": \"christine@makenotion.com\"\n        }\n      }\n    }\n  }\n}"
 140 |                   }
 141 |                 },
 142 |                 "schema": {
 143 |                   "type": "object",
 144 |                   "properties": {
 145 |                     "object": {
 146 |                       "type": "string",
 147 |                       "example": "user"
 148 |                     },
 149 |                     "id": {
 150 |                       "type": "string",
 151 |                       "example": "16d84278-ab0e-484c-9bdd-b35da3bd8905"
 152 |                     },
 153 |                     "name": {
 154 |                       "type": "string",
 155 |                       "example": "pied piper"
 156 |                     },
 157 |                     "avatar_url": {},
 158 |                     "type": {
 159 |                       "type": "string",
 160 |                       "example": "bot"
 161 |                     },
 162 |                     "bot": {
 163 |                       "type": "object",
 164 |                       "properties": {
 165 |                         "owner": {
 166 |                           "type": "object",
 167 |                           "properties": {
 168 |                             "type": {
 169 |                               "type": "string",
 170 |                               "example": "user"
 171 |                             },
 172 |                             "user": {
 173 |                               "type": "object",
 174 |                               "properties": {
 175 |                                 "object": {
 176 |                                   "type": "string",
 177 |                                   "example": "user"
 178 |                                 },
 179 |                                 "id": {
 180 |                                   "type": "string",
 181 |                                   "example": "5389a034-eb5c-47b5-8a9e-f79c99ef166c"
 182 |                                 },
 183 |                                 "name": {
 184 |                                   "type": "string",
 185 |                                   "example": "christine makenotion"
 186 |                                 },
 187 |                                 "avatar_url": {},
 188 |                                 "type": {
 189 |                                   "type": "string",
 190 |                                   "example": "person"
 191 |                                 },
 192 |                                 "person": {
 193 |                                   "type": "object",
 194 |                                   "properties": {
 195 |                                     "email": {
 196 |                                       "type": "string",
 197 |                                       "example": "christine@makenotion.com"
 198 |                                     }
 199 |                                   }
 200 |                                 }
 201 |                               }
 202 |                             }
 203 |                           }
 204 |                         }
 205 |                       }
 206 |                     }
 207 |                   }
 208 |                 }
 209 |               }
 210 |             }
 211 |           }
 212 |         },
 213 |         "deprecated": false,
 214 |         "security": []
 215 |       }
 216 |     },
 217 |     "/v1/databases/{database_id}/query": {
 218 |       "post": {
 219 |         "summary": "Query a database",
 220 |         "description": "",
 221 |         "operationId": "post-database-query",
 222 |         "parameters": [
 223 |           {
 224 |             "name": "database_id",
 225 |             "in": "path",
 226 |             "description": "Identifier for a Notion database.",
 227 |             "schema": {
 228 |               "type": "string"
 229 |             },
 230 |             "required": true
 231 |           },
 232 |           {
 233 |             "name": "filter_properties",
 234 |             "in": "query",
 235 |             "description": "A list of page property value IDs associated with the database. Use this param to limit the response to a specific page property value or values for pages that meet the `filter` criteria.",
 236 |             "schema": {
 237 |               "type": "array",
 238 |               "items": {
 239 |                 "type": "string"
 240 |               }
 241 |             }
 242 |           }
 243 |         ],
 244 |         "requestBody": {
 245 |           "content": {
 246 |             "application/json": {
 247 |               "schema": {
 248 |                 "type": "object",
 249 |                 "properties": {
 250 |                   "filter": {
 251 |                     "type": "object",
 252 |                     "description": "When supplied, limits which pages are returned based on the [filter conditions](ref:post-database-query-filter).",
 253 |                     "or": {
 254 |                       "type": "array",
 255 |                       "items": {
 256 |                         "type": "object",
 257 |                         "properties": {
 258 |                           "type": "object",
 259 |                           "properties": {
 260 |                             "property": {
 261 |                               "type": "string"
 262 |                             },
 263 |                             "title": {
 264 |                               "type": "object",
 265 |                               "properties": {
 266 |                                 "equals": {
 267 |                                   "type": "string"
 268 |                                 },
 269 |                                 "does_not_equal": {
 270 |                                   "type": "string"
 271 |                                 },
 272 |                                 "contains": {
 273 |                                   "type": "string"
 274 |                                 },
 275 |                                 "does_not_contain": {
 276 |                                   "type": "string"
 277 |                                 },
 278 |                                 "starts_with": {
 279 |                                   "type": "string"
 280 |                                 },
 281 |                                 "ends_with": {
 282 |                                   "type": "string"
 283 |                                 }
 284 |                               }
 285 |                             },
 286 |                             "rich_text": {
 287 |                               "type": "object",
 288 |                               "properties": {
 289 |                                 "equals": {
 290 |                                   "type": "string"
 291 |                                 },
 292 |                                 "does_not_equal": {
 293 |                                   "type": "string"
 294 |                                 },
 295 |                                 "contains": {
 296 |                                   "type": "string"
 297 |                                 },
 298 |                                 "does_not_contain": {
 299 |                                   "type": "string"
 300 |                                 },
 301 |                                 "starts_with": {
 302 |                                   "type": "string"
 303 |                                 },
 304 |                                 "ends_with": {
 305 |                                   "type": "string"
 306 |                                 }
 307 |                               }
 308 |                             },
 309 |                             "url": {
 310 |                               "type": "object",
 311 |                               "properties": {
 312 |                                 "equals": {
 313 |                                   "type": "string"
 314 |                                 },
 315 |                                 "does_not_equal": {
 316 |                                   "type": "string"
 317 |                                 },
 318 |                                 "contains": {
 319 |                                   "type": "string"
 320 |                                 },
 321 |                                 "does_not_contain": {
 322 |                                   "type": "string"
 323 |                                 },
 324 |                                 "starts_with": {
 325 |                                   "type": "string"
 326 |                                 },
 327 |                                 "ends_with": {
 328 |                                   "type": "string"
 329 |                                 }
 330 |                               }
 331 |                             },
 332 |                             "email": {
 333 |                               "type": "object",
 334 |                               "properties": {
 335 |                                 "equals": {
 336 |                                   "type": "string"
 337 |                                 },
 338 |                                 "does_not_equal": {
 339 |                                   "type": "string"
 340 |                                 },
 341 |                                 "contains": {
 342 |                                   "type": "string"
 343 |                                 },
 344 |                                 "does_not_contain": {
 345 |                                   "type": "string"
 346 |                                 },
 347 |                                 "starts_with": {
 348 |                                   "type": "string"
 349 |                                 },
 350 |                                 "ends_with": {
 351 |                                   "type": "string"
 352 |                                 }
 353 |                               }
 354 |                             },
 355 |                             "phone_number": {
 356 |                               "type": "object",
 357 |                               "properties": {
 358 |                                 "equals": {
 359 |                                   "type": "string"
 360 |                                 },
 361 |                                 "does_not_equal": {
 362 |                                   "type": "string"
 363 |                                 },
 364 |                                 "contains": {
 365 |                                   "type": "string"
 366 |                                 },
 367 |                                 "does_not_contain": {
 368 |                                   "type": "string"
 369 |                                 },
 370 |                                 "starts_with": {
 371 |                                   "type": "string"
 372 |                                 },
 373 |                                 "ends_with": {
 374 |                                   "type": "string"
 375 |                                 }
 376 |                               }
 377 |                             },
 378 |                             "number": {
 379 |                               "type": "object",
 380 |                               "properties": {
 381 |                                 "equals": {
 382 |                                   "type": "number"
 383 |                                 },
 384 |                                 "does_not_equal": {
 385 |                                   "type": "number"
 386 |                                 },
 387 |                                 "contains": {
 388 |                                   "type": "number"
 389 |                                 },
 390 |                                 "does_not_contain": {
 391 |                                   "type": "number"
 392 |                                 },
 393 |                                 "starts_with": {
 394 |                                   "type": "number"
 395 |                                 },
 396 |                                 "ends_with": {
 397 |                                   "type": "number"
 398 |                                 }
 399 |                               }
 400 |                             },
 401 |                             "checkbox": {
 402 |                               "type": "object",
 403 |                               "properties": {
 404 |                                 "equals": {
 405 |                                   "type": "boolean"
 406 |                                 },
 407 |                                 "does_not_equal": {
 408 |                                   "type": "boolean"
 409 |                                 }
 410 |                               }
 411 |                             },
 412 |                             "select": {
 413 |                               "type": "object",
 414 |                               "properties": {
 415 |                                 "equals": {
 416 |                                   "type": "string"
 417 |                                 },
 418 |                                 "does_not_equal": {
 419 |                                   "type": "string"
 420 |                                 }
 421 |                               }
 422 |                             },
 423 |                             "multi_select": {
 424 |                               "type": "object",
 425 |                               "properties": {
 426 |                                 "contains": {
 427 |                                   "type": "string"
 428 |                                 },
 429 |                                 "does_not_contain": {
 430 |                                   "type": "string"
 431 |                                 }
 432 |                               }
 433 |                             },
 434 |                             "status": {
 435 |                               "type": "object",
 436 |                               "properties": {
 437 |                                 "equals": {
 438 |                                   "type": "string"
 439 |                                 },
 440 |                                 "does_not_equal": {
 441 |                                   "type": "string"
 442 |                                 }
 443 |                               }
 444 |                             },
 445 |                             "date": {
 446 |                               "type": "object",
 447 |                               "properties": {
 448 |                                 "equals": {
 449 |                                   "type": "string",
 450 |                                   "format": "date"
 451 |                                 },
 452 |                                 "before": {
 453 |                                   "type": "string",
 454 |                                   "format": "date"
 455 |                                 },
 456 |                                 "after": {
 457 |                                   "type": "string",
 458 |                                   "format": "date"
 459 |                                 },
 460 |                                 "on_or_before": {
 461 |                                   "type": "string",
 462 |                                   "format": "date"
 463 |                                 },
 464 |                                 "on_or_after": {
 465 |                                   "type": "string",
 466 |                                   "format": "date"
 467 |                                 }
 468 |                               }
 469 |                             },
 470 |                             "created_time": {
 471 |                               "type": "object",
 472 |                               "properties": {
 473 |                                 "equals": {
 474 |                                   "type": "string",
 475 |                                   "format": "date"
 476 |                                 },
 477 |                                 "before": {
 478 |                                   "type": "string",
 479 |                                   "format": "date"
 480 |                                 },
 481 |                                 "after": {
 482 |                                   "type": "string",
 483 |                                   "format": "date"
 484 |                                 },
 485 |                                 "on_or_before": {
 486 |                                   "type": "string",
 487 |                                   "format": "date"
 488 |                                 },
 489 |                                 "on_or_after": {
 490 |                                   "type": "string",
 491 |                                   "format": "date"
 492 |                                 }
 493 |                               }
 494 |                             },
 495 |                             "last_edited_time": {
 496 |                               "type": "object",
 497 |                               "properties": {
 498 |                                 "equals": {
 499 |                                   "type": "string",
 500 |                                   "format": "date"
 501 |                                 },
 502 |                                 "before": {
 503 |                                   "type": "string",
 504 |                                   "format": "date"
 505 |                                 },
 506 |                                 "after": {
 507 |                                   "type": "string",
 508 |                                   "format": "date"
 509 |                                 },
 510 |                                 "on_or_before": {
 511 |                                   "type": "string",
 512 |                                   "format": "date"
 513 |                                 },
 514 |                                 "on_or_after": {
 515 |                                   "type": "string",
 516 |                                   "format": "date"
 517 |                                 }
 518 |                               }
 519 |                             }
 520 |                           }
 521 |                         }
 522 |                       },
 523 |                       "maxItems": 100
 524 |                     },
 525 |                     "and": {
 526 |                       "type": "array",
 527 |                       "items": {
 528 |                         "type": "object",
 529 |                         "properties": {
 530 |                           "type": "object",
 531 |                           "properties": {
 532 |                             "property": {
 533 |                               "type": "string"
 534 |                             },
 535 |                             "title": {
 536 |                               "type": "object",
 537 |                               "properties": {
 538 |                                 "equals": {
 539 |                                   "type": "string"
 540 |                                 },
 541 |                                 "does_not_equal": {
 542 |                                   "type": "string"
 543 |                                 },
 544 |                                 "contains": {
 545 |                                   "type": "string"
 546 |                                 },
 547 |                                 "does_not_contain": {
 548 |                                   "type": "string"
 549 |                                 },
 550 |                                 "starts_with": {
 551 |                                   "type": "string"
 552 |                                 },
 553 |                                 "ends_with": {
 554 |                                   "type": "string"
 555 |                                 }
 556 |                               }
 557 |                             },
 558 |                             "rich_text": {
 559 |                               "type": "object",
 560 |                               "properties": {
 561 |                                 "equals": {
 562 |                                   "type": "string"
 563 |                                 },
 564 |                                 "does_not_equal": {
 565 |                                   "type": "string"
 566 |                                 },
 567 |                                 "contains": {
 568 |                                   "type": "string"
 569 |                                 },
 570 |                                 "does_not_contain": {
 571 |                                   "type": "string"
 572 |                                 },
 573 |                                 "starts_with": {
 574 |                                   "type": "string"
 575 |                                 },
 576 |                                 "ends_with": {
 577 |                                   "type": "string"
 578 |                                 }
 579 |                               }
 580 |                             },
 581 |                             "url": {
 582 |                               "type": "object",
 583 |                               "properties": {
 584 |                                 "equals": {
 585 |                                   "type": "string"
 586 |                                 },
 587 |                                 "does_not_equal": {
 588 |                                   "type": "string"
 589 |                                 },
 590 |                                 "contains": {
 591 |                                   "type": "string"
 592 |                                 },
 593 |                                 "does_not_contain": {
 594 |                                   "type": "string"
 595 |                                 },
 596 |                                 "starts_with": {
 597 |                                   "type": "string"
 598 |                                 },
 599 |                                 "ends_with": {
 600 |                                   "type": "string"
 601 |                                 }
 602 |                               }
 603 |                             },
 604 |                             "email": {
 605 |                               "type": "object",
 606 |                               "properties": {
 607 |                                 "equals": {
 608 |                                   "type": "string"
 609 |                                 },
 610 |                                 "does_not_equal": {
 611 |                                   "type": "string"
 612 |                                 },
 613 |                                 "contains": {
 614 |                                   "type": "string"
 615 |                                 },
 616 |                                 "does_not_contain": {
 617 |                                   "type": "string"
 618 |                                 },
 619 |                                 "starts_with": {
 620 |                                   "type": "string"
 621 |                                 },
 622 |                                 "ends_with": {
 623 |                                   "type": "string"
 624 |                                 }
 625 |                               }
 626 |                             },
 627 |                             "phone_number": {
 628 |                               "type": "object",
 629 |                               "properties": {
 630 |                                 "equals": {
 631 |                                   "type": "string"
 632 |                                 },
 633 |                                 "does_not_equal": {
 634 |                                   "type": "string"
 635 |                                 },
 636 |                                 "contains": {
 637 |                                   "type": "string"
 638 |                                 },
 639 |                                 "does_not_contain": {
 640 |                                   "type": "string"
 641 |                                 },
 642 |                                 "starts_with": {
 643 |                                   "type": "string"
 644 |                                 },
 645 |                                 "ends_with": {
 646 |                                   "type": "string"
 647 |                                 }
 648 |                               }
 649 |                             },
 650 |                             "number": {
 651 |                               "type": "object",
 652 |                               "properties": {
 653 |                                 "equals": {
 654 |                                   "type": "number"
 655 |                                 },
 656 |                                 "does_not_equal": {
 657 |                                   "type": "number"
 658 |                                 },
 659 |                                 "contains": {
 660 |                                   "type": "number"
 661 |                                 },
 662 |                                 "does_not_contain": {
 663 |                                   "type": "number"
 664 |                                 },
 665 |                                 "starts_with": {
 666 |                                   "type": "number"
 667 |                                 },
 668 |                                 "ends_with": {
 669 |                                   "type": "number"
 670 |                                 }
 671 |                               }
 672 |                             },
 673 |                             "checkbox": {
 674 |                               "type": "object",
 675 |                               "properties": {
 676 |                                 "equals": {
 677 |                                   "type": "boolean"
 678 |                                 },
 679 |                                 "does_not_equal": {
 680 |                                   "type": "boolean"
 681 |                                 }
 682 |                               }
 683 |                             },
 684 |                             "select": {
 685 |                               "type": "object",
 686 |                               "properties": {
 687 |                                 "equals": {
 688 |                                   "type": "string"
 689 |                                 },
 690 |                                 "does_not_equal": {
 691 |                                   "type": "string"
 692 |                                 }
 693 |                               }
 694 |                             },
 695 |                             "multi_select": {
 696 |                               "type": "object",
 697 |                               "properties": {
 698 |                                 "contains": {
 699 |                                   "type": "string"
 700 |                                 },
 701 |                                 "does_not_contain": {
 702 |                                   "type": "string"
 703 |                                 }
 704 |                               }
 705 |                             },
 706 |                             "status": {
 707 |                               "type": "object",
 708 |                               "properties": {
 709 |                                 "equals": {
 710 |                                   "type": "string"
 711 |                                 },
 712 |                                 "does_not_equal": {
 713 |                                   "type": "string"
 714 |                                 }
 715 |                               }
 716 |                             },
 717 |                             "date": {
 718 |                               "type": "object",
 719 |                               "properties": {
 720 |                                 "equals": {
 721 |                                   "type": "string",
 722 |                                   "format": "date"
 723 |                                 },
 724 |                                 "before": {
 725 |                                   "type": "string",
 726 |                                   "format": "date"
 727 |                                 },
 728 |                                 "after": {
 729 |                                   "type": "string",
 730 |                                   "format": "date"
 731 |                                 },
 732 |                                 "on_or_before": {
 733 |                                   "type": "string",
 734 |                                   "format": "date"
 735 |                                 },
 736 |                                 "on_or_after": {
 737 |                                   "type": "string",
 738 |                                   "format": "date"
 739 |                                 }
 740 |                               }
 741 |                             },
 742 |                             "created_time": {
 743 |                               "type": "object",
 744 |                               "properties": {
 745 |                                 "equals": {
 746 |                                   "type": "string",
 747 |                                   "format": "date"
 748 |                                 },
 749 |                                 "before": {
 750 |                                   "type": "string",
 751 |                                   "format": "date"
 752 |                                 },
 753 |                                 "after": {
 754 |                                   "type": "string",
 755 |                                   "format": "date"
 756 |                                 },
 757 |                                 "on_or_before": {
 758 |                                   "type": "string",
 759 |                                   "format": "date"
 760 |                                 },
 761 |                                 "on_or_after": {
 762 |                                   "type": "string",
 763 |                                   "format": "date"
 764 |                                 }
 765 |                               }
 766 |                             },
 767 |                             "last_edited_time": {
 768 |                               "type": "object",
 769 |                               "properties": {
 770 |                                 "equals": {
 771 |                                   "type": "string",
 772 |                                   "format": "date"
 773 |                                 },
 774 |                                 "before": {
 775 |                                   "type": "string",
 776 |                                   "format": "date"
 777 |                                 },
 778 |                                 "after": {
 779 |                                   "type": "string",
 780 |                                   "format": "date"
 781 |                                 },
 782 |                                 "on_or_before": {
 783 |                                   "type": "string",
 784 |                                   "format": "date"
 785 |                                 },
 786 |                                 "on_or_after": {
 787 |                                   "type": "string",
 788 |                                   "format": "date"
 789 |                                 }
 790 |                               }
 791 |                             }
 792 |                           }
 793 |                         }
 794 |                       },
 795 |                       "maxItems": 100
 796 |                     }
 797 |                   },
 798 |                   "sorts": {
 799 |                     "type": "array",
 800 |                     "description": "When supplied, orders the results based on the provided [sort criteria](ref:post-database-query-sort).",
 801 |                     "items": {
 802 |                       "type": "object",
 803 |                       "required": [
 804 |                         "property",
 805 |                         "direction"
 806 |                       ],
 807 |                       "properties": {
 808 |                         "property": {
 809 |                           "type": "string"
 810 |                         },
 811 |                         "direction": {
 812 |                           "enum": [
 813 |                             "ascending",
 814 |                             "descending"
 815 |                           ],
 816 |                           "type": "string"
 817 |                         }
 818 |                       }
 819 |                     }
 820 |                   },
 821 |                   "start_cursor": {
 822 |                     "type": "string",
 823 |                     "description": "When supplied, returns a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results."
 824 |                   },
 825 |                   "page_size": {
 826 |                     "type": "integer",
 827 |                     "description": "The number of items from the full list desired in the response. Maximum: 100",
 828 |                     "default": 100
 829 |                   },
 830 |                   "archived": {
 831 |                     "type": "boolean"
 832 |                   },
 833 |                   "in_trash": {
 834 |                     "type": "boolean"
 835 |                   }
 836 |                 }
 837 |               }
 838 |             }
 839 |           }
 840 |         },
 841 |         "responses": {},
 842 |         "deprecated": false,
 843 |         "security": []
 844 |       }
 845 |     },
 846 |     "/v1/search": {
 847 |       "post": {
 848 |         "summary": "Search by title",
 849 |         "description": "",
 850 |         "operationId": "post-search",
 851 |         "parameters": [],
 852 |         "requestBody": {
 853 |           "content": {
 854 |             "application/json": {
 855 |               "schema": {
 856 |                 "type": "object",
 857 |                 "properties": {
 858 |                   "query": {
 859 |                     "type": "string",
 860 |                     "description": "The text that the API compares page and database titles against."
 861 |                   },
 862 |                   "sort": {
 863 |                     "type": "object",
 864 |                     "description": "A set of criteria, `direction` and `timestamp` keys, that orders the results. The **only** supported timestamp value is `\"last_edited_time\"`. Supported `direction` values are `\"ascending\"` and `\"descending\"`. If `sort` is not provided, then the most recently edited results are returned first.",
 865 |                     "properties": {
 866 |                       "direction": {
 867 |                         "type": "string",
 868 |                         "description": "The direction to sort. Possible values include `ascending` and `descending`."
 869 |                       },
 870 |                       "timestamp": {
 871 |                         "type": "string",
 872 |                         "description": "The name of the timestamp to sort against. Possible values include `last_edited_time`."
 873 |                       }
 874 |                     }
 875 |                   },
 876 |                   "filter": {
 877 |                     "type": "object",
 878 |                     "description": "A set of criteria, `value` and `property` keys, that limits the results to either only pages or only databases. Possible `value` values are `\"page\"` or `\"database\"`. The only supported `property` value is `\"object\"`.",
 879 |                     "properties": {
 880 |                       "value": {
 881 |                         "type": "string",
 882 |                         "description": "The value of the property to filter the results by.  Possible values for object type include `page` or `database`.  **Limitation**: Currently the only filter allowed is `object` which will filter by type of object (either `page` or `database`)"
 883 |                       },
 884 |                       "property": {
 885 |                         "type": "string",
 886 |                         "description": "The name of the property to filter by. Currently the only property you can filter by is the object type.  Possible values include `object`.   Limitation: Currently the only filter allowed is `object` which will filter by type of object (either `page` or `database`)"
 887 |                       }
 888 |                     }
 889 |                   },
 890 |                   "start_cursor": {
 891 |                     "type": "string",
 892 |                     "description": "A `cursor` value returned in a previous response that If supplied, limits the response to results starting after the `cursor`. If not supplied, then the first page of results is returned. Refer to [pagination](https://developers.notion.com/reference/intro#pagination) for more details."
 893 |                   },
 894 |                   "page_size": {
 895 |                     "type": "integer",
 896 |                     "description": "The number of items from the full list to include in the response. Maximum: `100`.",
 897 |                     "default": 100,
 898 |                     "format": "int32"
 899 |                   }
 900 |                 }
 901 |               }
 902 |             }
 903 |           }
 904 |         },
 905 |         "responses": {},
 906 |         "deprecated": false,
 907 |         "security": []
 908 |       }
 909 |     },
 910 |     "/v1/blocks/{block_id}/children": {
 911 |       "get": {
 912 |         "summary": "Retrieve block children",
 913 |         "description": "",
 914 |         "operationId": "get-block-children",
 915 |         "parameters": [
 916 |           {
 917 |             "name": "block_id",
 918 |             "in": "path",
 919 |             "description": "Identifier for a [block](ref:block)",
 920 |             "schema": {
 921 |               "type": "string"
 922 |             },
 923 |             "required": true
 924 |           },
 925 |           {
 926 |             "name": "start_cursor",
 927 |             "in": "query",
 928 |             "description": "If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results.",
 929 |             "schema": {
 930 |               "type": "string"
 931 |             }
 932 |           },
 933 |           {
 934 |             "name": "page_size",
 935 |             "in": "query",
 936 |             "description": "The number of items from the full list desired in the response. Maximum: 100",
 937 |             "schema": {
 938 |               "type": "integer",
 939 |               "format": "int32",
 940 |               "default": 100
 941 |             }
 942 |           }
 943 |         ],
 944 |         "responses": {},
 945 |         "deprecated": false,
 946 |         "security": []
 947 |       },
 948 |       "patch": {
 949 |         "summary": "Append block children",
 950 |         "description": "",
 951 |         "operationId": "patch-block-children",
 952 |         "parameters": [
 953 |           {
 954 |             "name": "block_id",
 955 |             "in": "path",
 956 |             "description": "Identifier for a [block](ref:block). Also accepts a [page](ref:page) ID.",
 957 |             "schema": {
 958 |               "type": "string"
 959 |             },
 960 |             "required": true
 961 |           }
 962 |         ],
 963 |         "requestBody": {
 964 |           "content": {
 965 |             "application/json": {
 966 |               "schema": {
 967 |                 "type": "object",
 968 |                 "required": [
 969 |                   "children"
 970 |                 ],
 971 |                 "properties": {
 972 |                   "children": {
 973 |                     "type": "array",
 974 |                     "items": {
 975 |                       "type": "object",
 976 |                       "properties": {
 977 |                         "paragraph": {
 978 |                           "type": "object",
 979 |                           "properties": {
 980 |                             "rich_text": {
 981 |                               "type": "array",
 982 |                               "items": {
 983 |                                 "type": "object",
 984 |                                 "properties": {
 985 |                                   "text": {
 986 |                                     "type": "object",
 987 |                                     "properties": {
 988 |                                       "content": {
 989 |                                         "type": "string"
 990 |                                       },
 991 |                                       "link": {
 992 |                                         "type": [
 993 |                                           "object",
 994 |                                           "null"
 995 |                                         ],
 996 |                                         "properties": {
 997 |                                           "url": {
 998 |                                             "type": "string"
 999 |                                           }
1000 |                                         },
1001 |                                         "required": [
1002 |                                           "url"
1003 |                                         ]
1004 |                                       }
1005 |                                     },
1006 |                                     "additionalProperties": false,
1007 |                                     "required": [
1008 |                                       "content"
1009 |                                     ]
1010 |                                   },
1011 |                                   "type": {
1012 |                                     "enum": [
1013 |                                       "text"
1014 |                                     ],
1015 |                                     "type": "string"
1016 |                                   }
1017 |                                 },
1018 |                                 "additionalProperties": false,
1019 |                                 "required": [
1020 |                                   "text"
1021 |                                 ]
1022 |                               },
1023 |                               "maxItems": 100
1024 |                             }
1025 |                           },
1026 |                           "additionalProperties": false,
1027 |                           "required": [
1028 |                             "rich_text"
1029 |                           ]
1030 |                         },
1031 |                         "bulleted_list_item": {
1032 |                           "type": "object",
1033 |                           "properties": {
1034 |                             "rich_text": {
1035 |                               "type": "array",
1036 |                               "items": {
1037 |                                 "type": "object",
1038 |                                 "properties": {
1039 |                                   "text": {
1040 |                                     "type": "object",
1041 |                                     "properties": {
1042 |                                       "content": {
1043 |                                         "type": "string"
1044 |                                       },
1045 |                                       "link": {
1046 |                                         "type": [
1047 |                                           "object",
1048 |                                           "null"
1049 |                                         ],
1050 |                                         "properties": {
1051 |                                           "url": {
1052 |                                             "type": "string"
1053 |                                           }
1054 |                                         },
1055 |                                         "required": [
1056 |                                           "url"
1057 |                                         ]
1058 |                                       }
1059 |                                     },
1060 |                                     "additionalProperties": false,
1061 |                                     "required": [
1062 |                                       "content"
1063 |                                     ]
1064 |                                   },
1065 |                                   "type": {
1066 |                                     "enum": [
1067 |                                       "text"
1068 |                                     ],
1069 |                                     "type": "string"
1070 |                                   }
1071 |                                 },
1072 |                                 "additionalProperties": false,
1073 |                                 "required": [
1074 |                                   "text"
1075 |                                 ]
1076 |                               },
1077 |                               "maxItems": 100
1078 |                             }
1079 |                           },
1080 |                           "additionalProperties": false,
1081 |                           "required": [
1082 |                             "rich_text"
1083 |                           ]
1084 |                         },
1085 |                         "type": {
1086 |                           "enum": [
1087 |                             "paragraph",
1088 |                             "bulleted_list_item"
1089 |                           ],
1090 |                           "type": "string"
1091 |                         }
1092 |                       },
1093 |                       "additionalProperties": false
1094 |                     },
1095 |                     "description": "Child content to append to a container block as an array of [block objects](ref:block)"
1096 |                   },
1097 |                   "after": {
1098 |                     "type": "string",
1099 |                     "description": "The ID of the existing block that the new block should be appended after."
1100 |                   }
1101 |                 }
1102 |               }
1103 |             }
1104 |           }
1105 |         },
1106 |         "responses": {},
1107 |         "deprecated": false,
1108 |         "security": []
1109 |       }
1110 |     },
1111 |     "/v1/blocks/{block_id}": {
1112 |       "get": {
1113 |         "summary": "Retrieve a block",
1114 |         "description": "",
1115 |         "operationId": "retrieve-a-block",
1116 |         "parameters": [
1117 |           {
1118 |             "name": "block_id",
1119 |             "in": "path",
1120 |             "description": "Identifier for a Notion block",
1121 |             "schema": {
1122 |               "type": "string"
1123 |             },
1124 |             "required": true
1125 |           }
1126 |         ],
1127 |         "responses": {},
1128 |         "deprecated": false,
1129 |         "security": []
1130 |       },
1131 |       "patch": {
1132 |         "summary": "Update a block",
1133 |         "description": "",
1134 |         "operationId": "update-a-block",
1135 |         "parameters": [
1136 |           {
1137 |             "name": "block_id",
1138 |             "in": "path",
1139 |             "description": "Identifier for a Notion block",
1140 |             "schema": {
1141 |               "type": "string"
1142 |             },
1143 |             "required": true
1144 |           }
1145 |         ],
1146 |         "requestBody": {
1147 |           "content": {
1148 |             "application/json": {
1149 |               "schema": {
1150 |                 "type": "object",
1151 |                 "properties": {
1152 |                   "type": {
1153 |                     "type": "object",
1154 |                     "description": "The [block object `type`](ref:block#block-object-keys) value with the properties to be updated. Currently only `text` (for supported block types) and `checked` (for `to_do` blocks) fields can be updated.",
1155 |                     "properties": {}
1156 |                   },
1157 |                   "archived": {
1158 |                     "type": "boolean",
1159 |                     "description": "Set to true to archive (delete) a block. Set to false to un-archive (restore) a block.",
1160 |                     "default": true
1161 |                   }
1162 |                 }
1163 |               }
1164 |             }
1165 |           }
1166 |         },
1167 |         "responses": {},
1168 |         "deprecated": false,
1169 |         "security": []
1170 |       },
1171 |       "delete": {
1172 |         "summary": "Delete a block",
1173 |         "description": "",
1174 |         "operationId": "delete-a-block",
1175 |         "parameters": [
1176 |           {
1177 |             "name": "block_id",
1178 |             "in": "path",
1179 |             "description": "Identifier for a Notion block",
1180 |             "schema": {
1181 |               "type": "string"
1182 |             },
1183 |             "required": true
1184 |           }
1185 |         ],
1186 |         "responses": {},
1187 |         "deprecated": false,
1188 |         "security": []
1189 |       }
1190 |     },
1191 |     "/v1/pages/{page_id}": {
1192 |       "get": {
1193 |         "summary": "Retrieve a page",
1194 |         "description": "",
1195 |         "operationId": "retrieve-a-page",
1196 |         "parameters": [
1197 |           {
1198 |             "name": "page_id",
1199 |             "in": "path",
1200 |             "description": "Identifier for a Notion page",
1201 |             "schema": {
1202 |               "type": "string"
1203 |             },
1204 |             "required": true
1205 |           },
1206 |           {
1207 |             "name": "filter_properties",
1208 |             "in": "query",
1209 |             "description": "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`.",
1210 |             "schema": {
1211 |               "type": "string"
1212 |             }
1213 |           }
1214 |         ],
1215 |         "responses": {},
1216 |         "deprecated": false,
1217 |         "security": []
1218 |       },
1219 |       "patch": {
1220 |         "summary": "Update page properties",
1221 |         "description": "",
1222 |         "operationId": "patch-page",
1223 |         "parameters": [
1224 |           {
1225 |             "name": "page_id",
1226 |             "in": "path",
1227 |             "description": "The identifier for the Notion page to be updated.",
1228 |             "schema": {
1229 |               "type": "string"
1230 |             },
1231 |             "required": true
1232 |           }
1233 |         ],
1234 |         "requestBody": {
1235 |           "content": {
1236 |             "application/json": {
1237 |               "schema": {
1238 |                 "type": "object",
1239 |                 "properties": {
1240 |                   "properties": {
1241 |                     "description": "The property values to update for the page. The keys are the names or IDs of the property and the values are property values. If a page property ID is not included, then it is not changed.",
1242 |                     "type": "object",
1243 |                     "properties": {
1244 |                       "title": {
1245 |                         "type": "array",
1246 |                         "items": {
1247 |                           "type": "object",
1248 |                           "properties": {
1249 |                             "text": {
1250 |                               "type": "object",
1251 |                               "properties": {
1252 |                                 "content": {
1253 |                                   "type": "string"
1254 |                                 },
1255 |                                 "link": {
1256 |                                   "type": [
1257 |                                     "object",
1258 |                                     "null"
1259 |                                   ],
1260 |                                   "properties": {
1261 |                                     "url": {
1262 |                                       "type": "string"
1263 |                                     }
1264 |                                   },
1265 |                                   "required": [
1266 |                                     "url"
1267 |                                   ]
1268 |                                 }
1269 |                               },
1270 |                               "additionalProperties": false,
1271 |                               "required": [
1272 |                                 "content"
1273 |                               ]
1274 |                             },
1275 |                             "type": {
1276 |                               "enum": [
1277 |                                 "text"
1278 |                               ],
1279 |                               "type": "string"
1280 |                             }
1281 |                           },
1282 |                           "additionalProperties": false,
1283 |                           "required": [
1284 |                             "text"
1285 |                           ]
1286 |                         },
1287 |                         "maxItems": 100
1288 |                       },
1289 |                       "type": {
1290 |                         "enum": [
1291 |                           "title"
1292 |                         ],
1293 |                         "type": "string"
1294 |                       }
1295 |                     },
1296 |                     "additionalProperties": false,
1297 |                     "required": [
1298 |                       "title"
1299 |                     ]
1300 |                   },
1301 |                   "in_trash": {
1302 |                     "type": "boolean",
1303 |                     "description": "Set to true to delete a block. Set to false to restore a block.",
1304 |                     "default": false
1305 |                   },
1306 |                   "archived": {
1307 |                     "type": "boolean"
1308 |                   },
1309 |                   "icon": {
1310 |                     "description": "A page icon for the page. Supported types are [external file object](https://developers.notion.com/reference/file-object) or [emoji object](https://developers.notion.com/reference/emoji-object).",
1311 |                     "type": "object",
1312 |                     "properties": {
1313 |                       "emoji": {
1314 |                         "type": "string"
1315 |                       }
1316 |                     },
1317 |                     "additionalProperties": false,
1318 |                     "required": [
1319 |                       "emoji"
1320 |                     ]
1321 |                   },
1322 |                   "cover": {
1323 |                     "type": "object",
1324 |                     "description": "A cover image for the page. Only [external file objects](https://developers.notion.com/reference/file-object) are supported.",
1325 |                     "properties": {
1326 |                       "external": {
1327 |                         "type": "object",
1328 |                         "properties": {
1329 |                           "url": {
1330 |                             "type": "string"
1331 |                           }
1332 |                         },
1333 |                         "additionalProperties": false,
1334 |                         "required": [
1335 |                           "url"
1336 |                         ]
1337 |                       },
1338 |                       "type": {
1339 |                         "enum": [
1340 |                           "external"
1341 |                         ],
1342 |                         "type": "string"
1343 |                       }
1344 |                     },
1345 |                     "required": [
1346 |                       "external"
1347 |                     ],
1348 |                     "additionalProperties": false
1349 |                   }
1350 |                 }
1351 |               }
1352 |             }
1353 |           }
1354 |         },
1355 |         "responses": {},
1356 |         "deprecated": false,
1357 |         "security": []
1358 |       }
1359 |     },
1360 |     "/v1/pages": {
1361 |       "post": {
1362 |         "summary": "Create a page",
1363 |         "description": "",
1364 |         "operationId": "post-page",
1365 |         "parameters": [],
1366 |         "requestBody": {
1367 |           "content": {
1368 |             "application/json": {
1369 |               "schema": {
1370 |                 "type": "object",
1371 |                 "required": [
1372 |                   "parent",
1373 |                   "properties"
1374 |                 ],
1375 |                 "properties": {
1376 |                   "parent": {
1377 |                     "type": "object",
1378 |                     "properties": {
1379 |                       "page_id": {
1380 |                         "type": "string",
1381 |                         "format": "uuid"
1382 |                       }
1383 |                     },
1384 |                     "required": [
1385 |                       "page_id"
1386 |                     ]
1387 |                   },
1388 |                   "properties": {
1389 |                     "type": "object",
1390 |                     "properties": {
1391 |                       "title": {
1392 |                         "type": "array",
1393 |                         "items": {
1394 |                           "type": "object",
1395 |                           "required": [
1396 |                             "text"
1397 |                           ],
1398 |                           "properties": {
1399 |                             "text": {
1400 |                               "type": "object",
1401 |                               "required": [
1402 |                                 "content"
1403 |                               ],
1404 |                               "properties": {
1405 |                                 "content": {
1406 |                                   "type": "string"
1407 |                                 }
1408 |                               }
1409 |                             }
1410 |                           }
1411 |                         },
1412 |                         "maxItems": 100
1413 |                       },
1414 |                       "type": {
1415 |                         "enum": [
1416 |                           "title"
1417 |                         ],
1418 |                         "type": "string"
1419 |                       }
1420 |                     },
1421 |                     "additionalProperties": false,
1422 |                     "required": [
1423 |                       "title"
1424 |                     ]
1425 |                   },
1426 |                   "children": {
1427 |                     "type": "array",
1428 |                     "description": "The content to be rendered on the new page, represented as an array of [block objects](https://developers.notion.com/reference/block).",
1429 |                     "items": {
1430 |                       "type": "string"
1431 |                     }
1432 |                   },
1433 |                   "icon": {
1434 |                     "type": "string",
1435 |                     "description": "The icon of the new page. Either an [emoji object](https://developers.notion.com/reference/emoji-object) or an [external file object](https://developers.notion.com/reference/file-object)..",
1436 |                     "format": "json"
1437 |                   },
1438 |                   "cover": {
1439 |                     "type": "string",
1440 |                     "description": "The cover image of the new page, represented as a [file object](https://developers.notion.com/reference/file-object).",
1441 |                     "format": "json"
1442 |                   }
1443 |                 }
1444 |               }
1445 |             }
1446 |           }
1447 |         },
1448 |         "responses": {},
1449 |         "deprecated": false,
1450 |         "security": []
1451 |       }
1452 |     },
1453 |     "/v1/databases": {
1454 |       "post": {
1455 |         "summary": "Create a database",
1456 |         "description": "",
1457 |         "operationId": "create-a-database",
1458 |         "parameters": [],
1459 |         "requestBody": {
1460 |           "content": {
1461 |             "application/json": {
1462 |               "schema": {
1463 |                 "type": "object",
1464 |                 "required": [
1465 |                   "parent",
1466 |                   "properties"
1467 |                 ],
1468 |                 "properties": {
1469 |                   "parent": {
1470 |                     "type": "object",
1471 |                     "properties": {
1472 |                       "type": {
1473 |                         "enum": [
1474 |                           "page_id"
1475 |                         ],
1476 |                         "type": "string"
1477 |                       },
1478 |                       "page_id": {
1479 |                         "type": "string",
1480 |                         "format": "uuid"
1481 |                       }
1482 |                     },
1483 |                     "required": [
1484 |                       "type",
1485 |                       "page_id"
1486 |                     ]
1487 |                   },
1488 |                   "properties": {
1489 |                     "type": "object",
1490 |                     "description": "Property schema of database. The keys are the names of properties as they appear in Notion and the values are [property schema objects](https://developers.notion.com/reference/property-schema-object).",
1491 |                     "additionalProperties": {
1492 |                       "oneOf": [
1493 |                         {
1494 |                           "type": "object",
1495 |                           "properties": {
1496 |                             "title": {
1497 |                               "type": "object",
1498 |                               "properties": {},
1499 |                               "additionalProperties": false
1500 |                             },
1501 |                             "description": {
1502 |                               "type": "string",
1503 |                               "maxLength": 280,
1504 |                               "minLength": 1
1505 |                             }
1506 |                           },
1507 |                           "additionalProperties": false,
1508 |                           "required": [
1509 |                             "title"
1510 |                           ]
1511 |                         }
1512 |                       ]
1513 |                     }
1514 |                   },
1515 |                   "title": {
1516 |                     "type": "array",
1517 |                     "items": {
1518 |                       "type": "object",
1519 |                       "required": [
1520 |                         "text"
1521 |                       ],
1522 |                       "properties": {
1523 |                         "text": {
1524 |                           "type": "object",
1525 |                           "properties": {
1526 |                             "content": {
1527 |                               "type": "string"
1528 |                             },
1529 |                             "link": {
1530 |                               "type": [
1531 |                                 "object",
1532 |                                 "null"
1533 |                               ],
1534 |                               "properties": {
1535 |                                 "url": {
1536 |                                   "type": "string"
1537 |                                 }
1538 |                               },
1539 |                               "required": [
1540 |                                 "url"
1541 |                               ]
1542 |                             }
1543 |                           },
1544 |                           "additionalProperties": false,
1545 |                           "required": [
1546 |                             "content"
1547 |                           ]
1548 |                         },
1549 |                         "type": {
1550 |                           "enum": [
1551 |                             "text"
1552 |                           ],
1553 |                           "type": "string"
1554 |                         }
1555 |                       },
1556 |                       "additionalProperties": false
1557 |                     },
1558 |                     "maxItems": 100
1559 |                   }
1560 |                 }
1561 |               }
1562 |             }
1563 |           }
1564 |         },
1565 |         "responses": {
1566 |           "200": {
1567 |             "description": "200",
1568 |             "content": {
1569 |               "application/json": {
1570 |                 "examples": {
1571 |                   "Result": {
1572 |                     "value": "{\n    \"object\": \"database\",\n    \"id\": \"bc1211ca-e3f1-4939-ae34-5260b16f627c\",\n    \"created_time\": \"2021-07-08T23:50:00.000Z\",\n    \"last_edited_time\": \"2021-07-08T23:50:00.000Z\",\n    \"icon\": {\n        \"type\": \"emoji\",\n        \"emoji\": \"🎉\"\n    },\n    \"cover\": {\n        \"type\": \"external\",\n        \"external\": {\n            \"url\": \"https://website.domain/images/image.png\"\n        }\n    },\n    \"url\": \"https://www.notion.so/bc1211cae3f14939ae34260b16f627c\",\n    \"title\": [\n        {\n            \"type\": \"text\",\n            \"text\": {\n                \"content\": \"Grocery List\",\n                \"link\": null\n            },\n            \"annotations\": {\n                \"bold\": false,\n                \"italic\": false,\n                \"strikethrough\": false,\n                \"underline\": false,\n                \"code\": false,\n                \"color\": \"default\"\n            },\n            \"plain_text\": \"Grocery List\",\n            \"href\": null\n        }\n    ],\n    \"properties\": {\n        \"+1\": {\n            \"id\": \"Wp%3DC\",\n            \"name\": \"+1\",\n            \"type\": \"people\",\n            \"people\": {}\n        },\n        \"In stock\": {\n            \"id\": \"fk%5EY\",\n            \"name\": \"In stock\",\n            \"type\": \"checkbox\",\n            \"checkbox\": {}\n        },\n        \"Price\": {\n            \"id\": \"evWq\",\n            \"name\": \"Price\",\n            \"type\": \"number\",\n            \"number\": {\n                \"format\": \"dollar\"\n            }\n        },\n        \"Description\": {\n            \"id\": \"V}lX\",\n            \"name\": \"Description\",\n            \"type\": \"rich_text\",\n            \"rich_text\": {}\n        },\n        \"Last ordered\": {\n            \"id\": \"eVnV\",\n            \"name\": \"Last ordered\",\n            \"type\": \"date\",\n            \"date\": {}\n        },\n        \"Meals\": {\n            \"id\": \"%7DWA~\",\n            \"name\": \"Meals\",\n            \"type\": \"relation\",\n            \"relation\": {\n                \"database_id\": \"668d797c-76fa-4934-9b05-ad288df2d136\",\n                \"single_property\": {}\n            }\n        },\n        \"Number of meals\": {\n            \"id\": \"Z\\\\Eh\",\n            \"name\": \"Number of meals\",\n            \"type\": \"rollup\",\n            \"rollup\": {\n                \"rollup_property_name\": \"Name\",\n                \"relation_property_name\": \"Meals\",\n                \"rollup_property_id\": \"title\",\n                \"relation_property_id\": \"mxp^\",\n                \"function\": \"count\"\n            }\n        },\n        \"Store availability\": {\n            \"id\": \"s}Kq\",\n            \"name\": \"Store availability\",\n            \"type\": \"multi_select\",\n            \"multi_select\": {\n                \"options\": [\n                    {\n                        \"id\": \"cb79b393-d1c1-4528-b517-c450859de766\",\n                        \"name\": \"Duc Loi Market\",\n                        \"color\": \"blue\"\n                    },\n                    {\n                        \"id\": \"58aae162-75d4-403b-a793-3bc7308e4cd2\",\n                        \"name\": \"Rainbow Grocery\",\n                        \"color\": \"gray\"\n                    },\n                    {\n                        \"id\": \"22d0f199-babc-44ff-bd80-a9eae3e3fcbf\",\n                        \"name\": \"Nijiya Market\",\n                        \"color\": \"purple\"\n                    },\n                    {\n                        \"id\": \"0d069987-ffb0-4347-bde2-8e4068003dbc\",\n                        \"name\": \"Gus's Community Market\",\n                        \"color\": \"yellow\"\n                    }\n                ]\n            }\n        },\n        \"Photo\": {\n            \"id\": \"yfiK\",\n            \"name\": \"Photo\",\n            \"type\": \"files\",\n            \"files\": {}\n        },\n        \"Food group\": {\n            \"id\": \"CM%3EH\",\n            \"name\": \"Food group\",\n            \"type\": \"select\",\n            \"select\": {\n                \"options\": [\n                    {\n                        \"id\": \"6d4523fa-88cb-4ffd-9364-1e39d0f4e566\",\n                        \"name\": \"🥦Vegetable\",\n                        \"color\": \"green\"\n                    },\n                    {\n                        \"id\": \"268d7e75-de8f-4c4b-8b9d-de0f97021833\",\n                        \"name\": \"🍎Fruit\",\n                        \"color\": \"red\"\n                    },\n                    {\n                        \"id\": \"1b234a00-dc97-489c-b987-829264cfdfef\",\n                        \"name\": \"💪Protein\",\n                        \"color\": \"yellow\"\n                    }\n                ]\n            }\n        },\n        \"Name\": {\n            \"id\": \"title\",\n            \"name\": \"Name\",\n            \"type\": \"title\",\n            \"title\": {}\n        }\n    },\n    \"parent\": {\n        \"type\": \"page_id\",\n        \"page_id\": \"98ad959b-2b6a-4774-80ee-00246fb0ea9b\"\n    },\n    \"archived\": false\n}{\n    \"object\": \"database\",\n    \"id\": \"bc1211ca-e3f1-4939-ae34-5260b16f627c\",\n    \"created_time\": \"2021-07-08T23:50:00.000Z\",\n    \"last_edited_time\": \"2021-07-08T23:50:00.000Z\",\n    \"icon\": {\n        \"type\": \"emoji\",\n        \"emoji\": \"🎉\"\n    },\n    \"cover\": {\n        \"type\": \"external\",\n        \"external\": {\n            \"url\": \"https://website.domain/images/image.png\"\n        }\n    },\n    \"url\": \"https://www.notion.so/bc1211cae3f14939ae34260b16f627c\",\n    \"title\": [\n        {\n            \"type\": \"text\",\n            \"text\": {\n                \"content\": \"Grocery List\",\n                \"link\": null\n            },\n            \"annotations\": {\n                \"bold\": false,\n                \"italic\": false,\n                \"strikethrough\": false,\n                \"underline\": false,\n                \"code\": false,\n                \"color\": \"default\"\n            },\n            \"plain_text\": \"Grocery List\",\n            \"href\": null\n        }\n    ],\n    \"properties\": {\n        \"+1\": {\n            \"id\": \"Wp%3DC\",\n            \"name\": \"+1\",\n            \"type\": \"people\",\n            \"people\": {}\n        },\n        \"In stock\": {\n            \"id\": \"fk%5EY\",\n            \"name\": \"In stock\",\n            \"type\": \"checkbox\",\n            \"checkbox\": {}\n        },\n        \"Price\": {\n            \"id\": \"evWq\",\n            \"name\": \"Price\",\n            \"type\": \"number\",\n            \"number\": {\n                \"format\": \"dollar\"\n            }\n        },\n        \"Description\": {\n            \"id\": \"V}lX\",\n            \"name\": \"Description\",\n            \"type\": \"rich_text\",\n            \"rich_text\": {}\n        },\n        \"Last ordered\": {\n            \"id\": \"eVnV\",\n            \"name\": \"Last ordered\",\n            \"type\": \"date\",\n            \"date\": {}\n        },\n        \"Meals\": {\n            \"id\": \"%7DWA~\",\n            \"name\": \"Meals\",\n            \"type\": \"relation\",\n            \"relation\": {\n                \"database_id\": \"668d797c-76fa-4934-9b05-ad288df2d136\",\n                \"synced_property_name\": \"Related to Grocery List (Meals)\"\n            }\n        },\n        \"Number of meals\": {\n            \"id\": \"Z\\\\Eh\",\n            \"name\": \"Number of meals\",\n            \"type\": \"rollup\",\n            \"rollup\": {\n                \"rollup_property_name\": \"Name\",\n                \"relation_property_name\": \"Meals\",\n                \"rollup_property_id\": \"title\",\n                \"relation_property_id\": \"mxp^\",\n                \"function\": \"count\"\n            }\n        },\n        \"Store availability\": {\n            \"id\": \"s}Kq\",\n            \"name\": \"Store availability\",\n            \"type\": \"multi_select\",\n            \"multi_select\": {\n                \"options\": [\n                    {\n                        \"id\": \"cb79b393-d1c1-4528-b517-c450859de766\",\n                        \"name\": \"Duc Loi Market\",\n                        \"color\": \"blue\"\n                    },\n                    {\n                        \"id\": \"58aae162-75d4-403b-a793-3bc7308e4cd2\",\n                        \"name\": \"Rainbow Grocery\",\n                        \"color\": \"gray\"\n                    },\n                    {\n                        \"id\": \"22d0f199-babc-44ff-bd80-a9eae3e3fcbf\",\n                        \"name\": \"Nijiya Market\",\n                        \"color\": \"purple\"\n                    },\n                    {\n                        \"id\": \"0d069987-ffb0-4347-bde2-8e4068003dbc\",\n                        \"name\": \"Gus's Community Market\",\n                        \"color\": \"yellow\"\n                    }\n                ]\n            }\n        },\n        \"Photo\": {\n            \"id\": \"yfiK\",\n            \"name\": \"Photo\",\n            \"type\": \"files\",\n            \"files\": {}\n        },\n        \"Food group\": {\n            \"id\": \"CM%3EH\",\n            \"name\": \"Food group\",\n            \"type\": \"select\",\n            \"select\": {\n                \"options\": [\n                    {\n                        \"id\": \"6d4523fa-88cb-4ffd-9364-1e39d0f4e566\",\n                        \"name\": \"🥦Vegetable\",\n                        \"color\": \"green\"\n                    },\n                    {\n                        \"id\": \"268d7e75-de8f-4c4b-8b9d-de0f97021833\",\n                        \"name\": \"🍎Fruit\",\n                        \"color\": \"red\"\n                    },\n                    {\n                        \"id\": \"1b234a00-dc97-489c-b987-829264cfdfef\",\n                        \"name\": \"💪Protein\",\n                        \"color\": \"yellow\"\n                    }\n                ]\n            }\n        },\n        \"Name\": {\n            \"id\": \"title\",\n            \"name\": \"Name\",\n            \"type\": \"title\",\n            \"title\": {}\n        }\n    },\n    \"parent\": {\n        \"type\": \"page_id\",\n        \"page_id\": \"98ad959b-2b6a-4774-80ee-00246fb0ea9b\"\n    },\n    \"archived\": false,\n    \"is_inline\": false\n}"
1573 |                   }
1574 |                 }
1575 |               }
1576 |             }
1577 |           }
1578 |         },
1579 |         "deprecated": false,
1580 |         "security": []
1581 |       }
1582 |     },
1583 |     "/v1/databases/{database_id}": {
1584 |       "patch": {
1585 |         "summary": "Update a database",
1586 |         "description": "",
1587 |         "operationId": "update-a-database",
1588 |         "parameters": [
1589 |           {
1590 |             "name": "database_id",
1591 |             "in": "path",
1592 |             "description": "identifier for a Notion database",
1593 |             "schema": {
1594 |               "type": "string"
1595 |             },
1596 |             "required": true
1597 |           }
1598 |         ],
1599 |         "requestBody": {
1600 |           "content": {
1601 |             "application/json": {
1602 |               "schema": {
1603 |                 "type": "object",
1604 |                 "properties": {
1605 |                   "title": {
1606 |                     "description": "An array of [rich text objects](https://developers.notion.com/reference/rich-text) that represents the title of the database that is displayed in the Notion UI. If omitted, then the database title remains unchanged.",
1607 |                     "type": "array",
1608 |                     "items": {
1609 |                       "type": "object",
1610 |                       "required": [
1611 |                         "text"
1612 |                       ],
1613 |                       "properties": {
1614 |                         "text": {
1615 |                           "type": "object",
1616 |                           "properties": {
1617 |                             "content": {
1618 |                               "type": "string"
1619 |                             },
1620 |                             "link": {
1621 |                               "type": [
1622 |                                 "object",
1623 |                                 "null"
1624 |                               ],
1625 |                               "properties": {
1626 |                                 "url": {
1627 |                                   "type": "string"
1628 |                                 }
1629 |                               },
1630 |                               "required": [
1631 |                                 "url"
1632 |                               ]
1633 |                             }
1634 |                           },
1635 |                           "additionalProperties": false,
1636 |                           "required": [
1637 |                             "content"
1638 |                           ]
1639 |                         },
1640 |                         "type": {
1641 |                           "enum": [
1642 |                             "text"
1643 |                           ],
1644 |                           "type": "string"
1645 |                         }
1646 |                       },
1647 |                       "additionalProperties": false
1648 |                     }
1649 |                   },
1650 |                   "description": {
1651 |                     "type": "array",
1652 |                     "items": {
1653 |                       "type": "object",
1654 |                       "required": [
1655 |                         "text"
1656 |                       ],
1657 |                       "properties": {
1658 |                         "text": {
1659 |                           "type": "object",
1660 |                           "properties": {
1661 |                             "content": {
1662 |                               "type": "string"
1663 |                             },
1664 |                             "link": {
1665 |                               "type": [
1666 |                                 "object",
1667 |                                 "null"
1668 |                               ],
1669 |                               "properties": {
1670 |                                 "url": {
1671 |                                   "type": "string"
1672 |                                 }
1673 |                               },
1674 |                               "required": [
1675 |                                 "url"
1676 |                               ]
1677 |                             }
1678 |                           },
1679 |                           "additionalProperties": false,
1680 |                           "required": [
1681 |                             "content"
1682 |                           ]
1683 |                         },
1684 |                         "type": {
1685 |                           "enum": [
1686 |                             "text"
1687 |                           ],
1688 |                           "type": "string"
1689 |                         }
1690 |                       },
1691 |                       "additionalProperties": false
1692 |                     },
1693 |                     "maxItems": 100,
1694 |                     "description": "An array of [rich text objects](https://developers.notion.com/reference/rich-text) that represents the description of the database that is displayed in the Notion UI. If omitted, then the database description remains unchanged."
1695 |                   },
1696 |                   "properties": {
1697 |                     "type": "object",
1698 |                     "description": "Property schema of database. The keys are the names of properties as they appear in Notion and the values are [property schema objects](https://developers.notion.com/reference/property-schema-object).",
1699 |                     "properties": {
1700 |                       "name": {
1701 |                         "type": "string"
1702 |                       }
1703 |                     }
1704 |                   }
1705 |                 },
1706 |                 "additionalProperties": false
1707 |               }
1708 |             }
1709 |           }
1710 |         },
1711 |         "responses": {},
1712 |         "deprecated": false,
1713 |         "security": []
1714 |       },
1715 |       "get": {
1716 |         "summary": "Retrieve a database",
1717 |         "description": "",
1718 |         "operationId": "retrieve-a-database",
1719 |         "parameters": [
1720 |           {
1721 |             "name": "database_id",
1722 |             "in": "path",
1723 |             "description": "An identifier for the Notion database.",
1724 |             "schema": {
1725 |               "type": "string"
1726 |             },
1727 |             "required": true
1728 |           }
1729 |         ],
1730 |         "responses": {
1731 |           "200": {
1732 |             "description": "200",
1733 |             "content": {
1734 |               "application/json": {
1735 |                 "examples": {
1736 |                   "Result": {
1737 |                     "value": "{\n    \"object\": \"database\",\n    \"id\": \"bc1211ca-e3f1-4939-ae34-5260b16f627c\",\n    \"created_time\": \"2021-07-08T23:50:00.000Z\",\n    \"last_edited_time\": \"2021-07-08T23:50:00.000Z\",\n    \"icon\": {\n        \"type\": \"emoji\",\n        \"emoji\": \"🎉\"\n    },\n    \"cover\": {\n        \"type\": \"external\",\n        \"external\": {\n            \"url\": \"https://website.domain/images/image.png\"\n        }\n    },\n    \"url\": \"https://www.notion.so/bc1211cae3f14939ae34260b16f627c\",\n    \"title\": [\n        {\n            \"type\": \"text\",\n            \"text\": {\n                \"content\": \"Grocery List\",\n                \"link\": null\n            },\n            \"annotations\": {\n                \"bold\": false,\n                \"italic\": false,\n                \"strikethrough\": false,\n                \"underline\": false,\n                \"code\": false,\n                \"color\": \"default\"\n            },\n            \"plain_text\": \"Grocery List\",\n            \"href\": null\n        }\n    ],\n    \"description\": [\n        {\n            \"type\": \"text\",\n            \"text\": {\n                \"content\": \"Grocery list for just kale 🥬\",\n                \"link\": null\n            },\n            \"annotations\": {\n                \"bold\": false,\n                \"italic\": false,\n                \"strikethrough\": false,\n                \"underline\": false,\n                \"code\": false,\n                \"color\": \"default\"\n            },\n            \"plain_text\": \"Grocery list for just kale 🥬\",\n            \"href\": null\n        }\n    ],\n    \"properties\": {\n        \"+1\": {\n            \"id\": \"Wp%3DC\",\n            \"name\": \"+1\",\n            \"type\": \"people\",\n            \"people\": {}\n        },\n        \"In stock\": {\n            \"id\": \"fk%5EY\",\n            \"name\": \"In stock\",\n            \"type\": \"checkbox\",\n            \"checkbox\": {}\n        },\n        \"Price\": {\n            \"id\": \"evWq\",\n            \"name\": \"Price\",\n            \"type\": \"number\",\n            \"number\": {\n                \"format\": \"dollar\"\n            }\n        },\n        \"Description\": {\n            \"id\": \"V}lX\",\n            \"name\": \"Description\",\n            \"type\": \"rich_text\",\n            \"rich_text\": {}\n        },\n        \"Last ordered\": {\n            \"id\": \"eVnV\",\n            \"name\": \"Last ordered\",\n            \"type\": \"date\",\n            \"date\": {}\n        },\n        \"Meals\": {\n            \"id\": \"%7DWA~\",\n            \"name\": \"Meals\",\n            \"type\": \"relation\",\n            \"relation\": {\n                \"database_id\": \"668d797c-76fa-4934-9b05-ad288df2d136\",\n                \"synced_property_name\": \"Related to Grocery List (Meals)\"\n            }\n        },\n        \"Number of meals\": {\n            \"id\": \"Z\\\\Eh\",\n            \"name\": \"Number of meals\",\n            \"type\": \"rollup\",\n            \"rollup\": {\n                \"rollup_property_name\": \"Name\",\n                \"relation_property_name\": \"Meals\",\n                \"rollup_property_id\": \"title\",\n                \"relation_property_id\": \"mxp^\",\n                \"function\": \"count\"\n            }\n        },\n        \"Store availability\": {\n            \"id\": \"s}Kq\",\n            \"name\": \"Store availability\",\n            \"type\": \"multi_select\",\n            \"multi_select\": {\n                \"options\": [\n                    {\n                        \"id\": \"cb79b393-d1c1-4528-b517-c450859de766\",\n                        \"name\": \"Duc Loi Market\",\n                        \"color\": \"blue\"\n                    },\n                    {\n                        \"id\": \"58aae162-75d4-403b-a793-3bc7308e4cd2\",\n                        \"name\": \"Rainbow Grocery\",\n                        \"color\": \"gray\"\n                    },\n                    {\n                        \"id\": \"22d0f199-babc-44ff-bd80-a9eae3e3fcbf\",\n                        \"name\": \"Nijiya Market\",\n                        \"color\": \"purple\"\n                    },\n                    {\n                        \"id\": \"0d069987-ffb0-4347-bde2-8e4068003dbc\",\n                        \"name\": \"Gus's Community Market\",\n                        \"color\": \"yellow\"\n                    }\n                ]\n            }\n        },\n        \"Photo\": {\n            \"id\": \"yfiK\",\n            \"name\": \"Photo\",\n            \"type\": \"files\",\n            \"files\": {}\n        },\n        \"Food group\": {\n            \"id\": \"CM%3EH\",\n            \"name\": \"Food group\",\n            \"type\": \"select\",\n            \"select\": {\n                \"options\": [\n                    {\n                        \"id\": \"6d4523fa-88cb-4ffd-9364-1e39d0f4e566\",\n                        \"name\": \"🥦Vegetable\",\n                        \"color\": \"green\"\n                    },\n                    {\n                        \"id\": \"268d7e75-de8f-4c4b-8b9d-de0f97021833\",\n                        \"name\": \"🍎Fruit\",\n                        \"color\": \"red\"\n                    },\n                    {\n                        \"id\": \"1b234a00-dc97-489c-b987-829264cfdfef\",\n                        \"name\": \"💪Protein\",\n                        \"color\": \"yellow\"\n                    }\n                ]\n            }\n        },\n        \"Name\": {\n            \"id\": \"title\",\n            \"name\": \"Name\",\n            \"type\": \"title\",\n            \"title\": {}\n        }\n    },\n    \"parent\": {\n        \"type\": \"page_id\",\n        \"page_id\": \"98ad959b-2b6a-4774-80ee-00246fb0ea9b\"\n    },\n    \"archived\": false,\n    \"is_inline\": false,\n    \"public_url\": null\n}"
1738 |                   }
1739 |                 }
1740 |               }
1741 |             }
1742 |           }
1743 |         },
1744 |         "deprecated": false,
1745 |         "security": []
1746 |       }
1747 |     },
1748 |     "/v1/pages/{page_id}/properties/{property_id}": {
1749 |       "get": {
1750 |         "summary": "Retrieve a page property item",
1751 |         "description": "",
1752 |         "operationId": "retrieve-a-page-property",
1753 |         "parameters": [
1754 |           {
1755 |             "name": "page_id",
1756 |             "in": "path",
1757 |             "description": "Identifier for a Notion page",
1758 |             "schema": {
1759 |               "type": "string"
1760 |             },
1761 |             "required": true
1762 |           },
1763 |           {
1764 |             "name": "property_id",
1765 |             "in": "path",
1766 |             "description": "Identifier for a page [property](https://developers.notion.com/reference/page#all-property-values)",
1767 |             "schema": {
1768 |               "type": "string"
1769 |             },
1770 |             "required": true
1771 |           },
1772 |           {
1773 |             "name": "page_size",
1774 |             "in": "query",
1775 |             "description": "For paginated properties. The max number of property item objects on a page. The default size is 100",
1776 |             "schema": {
1777 |               "type": "integer",
1778 |               "format": "int32"
1779 |             }
1780 |           },
1781 |           {
1782 |             "name": "start_cursor",
1783 |             "in": "query",
1784 |             "description": "For paginated properties.",
1785 |             "schema": {
1786 |               "type": "string"
1787 |             }
1788 |           }
1789 |         ],
1790 |         "responses": {
1791 |           "200": {
1792 |             "description": "200",
1793 |             "content": {
1794 |               "application/json": {
1795 |                 "examples": {
1796 |                   "Number Property Item": {
1797 |                     "value": "{\n  \"object\": \"property_item\",\n  \"id\" \"kjPO\",\n  \"type\": \"number\",\n  \"number\": 2\n}"
1798 |                   },
1799 |                   "Result": {
1800 |                     "value": "{\n    \"object\": \"list\",\n    \"results\": [\n        {\n            \"object\": \"property_item\",\n            \"id\" \"kjPO\",\n            \"type\": \"rich_text\",\n            \"rich_text\": {\n                \"type\": \"text\",\n                \"text\": {\n                    \"content\": \"Avocado \",\n                    \"link\": null\n                },\n                \"annotations\": {\n                    \"bold\": false,\n                    \"italic\": false,\n                    \"strikethrough\": false,\n                    \"underline\": false,\n                    \"code\": false,\n                    \"color\": \"default\"\n                },\n                \"plain_text\": \"Avocado \",\n                \"href\": null\n            }\n        },\n        {\n            \"object\": \"property_item\",\n            \"id\" \"ijPO\",\n            \"type\": \"rich_text\",\n            \"rich_text\": {\n                \"type\": \"mention\",\n                \"mention\": {\n                    \"type\": \"page\",\n                    \"page\": {\n                        \"id\": \"41117fd7-69a5-4694-bc07-c1e3a682c857\"\n                    }\n                },\n                \"annotations\": {\n                    \"bold\": false,\n                    \"italic\": false,\n                    \"strikethrough\": false,\n                    \"underline\": false,\n                    \"code\": false,\n                    \"color\": \"default\"\n                },\n                \"plain_text\": \"Lemons\",\n                \"href\": \"http://notion.so/41117fd769a54694bc07c1e3a682c857\"\n            }\n        },\n        {\n            \"object\": \"property_item\",\n            \"id\" \"kjPO\",\n            \"type\": \"rich_text\",\n            \"rich_text\": {\n                \"type\": \"text\",\n                \"text\": {\n                    \"content\": \" Tomato \",\n                    \"link\": null\n                },\n                \"annotations\": {\n                    \"bold\": false,\n                    \"italic\": false,\n                    \"strikethrough\": false,\n                    \"underline\": false,\n                    \"code\": false,\n                    \"color\": \"default\"\n                },\n                \"plain_text\": \" Tomato \",\n                \"href\": null\n            }\n        },\n...\n    ],\n    \"next_cursor\": \"some-next-cursor-value\",\n    \"has_more\": true,\n\t\t\"next_url\": \"http://api.notion.com/v1/pages/0e5235bf86aa4efb93aa772cce7eab71/properties/NVv^?start_cursor=some-next-cursor-value&page_size=25\",\n    \"property_item\": {\n      \"id\": \"NVv^\",\n      \"next_url\": null,\n      \"type\": \"rich_text\",\n      \"rich_text\": {}\n    }\n}"
1801 |                   },
1802 |                   "Rollup List Property Item": {
1803 |                     "value": "{\n    \"object\": \"list\",\n    \"results\": [\n        {\n            \"object\": \"property_item\",\n          \t\"id\": \"dj2l\",\n            \"type\": \"relation\",\n            \"relation\": {\n                \"id\": \"83f92c9d-523d-466e-8c1f-9bc2c25a99fe\"\n            }\n        },\n        {\n            \"object\": \"property_item\",\n          \t\"id\": \"dj2l\",\n            \"type\": \"relation\",\n            \"relation\": {\n                \"id\": \"45cfb825-3463-4891-8932-7e6d8c170630\"\n            }\n        },\n        {\n            \"object\": \"property_item\",\n          \t\"id\": \"dj2l\",\n            \"type\": \"relation\",\n            \"relation\": {\n                \"id\": \"1688be1a-a197-4f2a-9688-e528c4b56d94\"\n            }\n        }\n    ],\n    \"next_cursor\": \"some-next-cursor-value\",\n    \"has_more\": true,\n\t\t\"property_item\": {\n      \"id\": \"y}~p\",\n      \"next_url\": \"http://api.notion.com/v1/pages/0e5235bf86aa4efb93aa772cce7eab71/properties/y%7D~p?start_cursor=1QaTunT5&page_size=25\",\n      \"type\": \"rollup\",\n      \"rollup\": {\n        \"function\": \"sum\",\n        \"type\": \"incomplete\",\n        \"incomplete\": {}\n      }\n    }\n    \"type\": \"property_item\"\n}"
1804 |                   }
1805 |                 }
1806 |               }
1807 |             }
1808 |           }
1809 |         },
1810 |         "deprecated": false,
1811 |         "security": []
1812 |       }
1813 |     },
1814 |     "/v1/comments": {
1815 |       "get": {
1816 |         "summary": "Retrieve comments",
1817 |         "description": "Retrieves a list of un-resolved [Comment objects](ref:comment-object) from a page or block.",
1818 |         "operationId": "retrieve-a-comment",
1819 |         "parameters": [
1820 |           {
1821 |             "name": "block_id",
1822 |             "in": "query",
1823 |             "description": "Identifier for a Notion block or page",
1824 |             "required": true,
1825 |             "schema": {
1826 |               "type": "string"
1827 |             }
1828 |           },
1829 |           {
1830 |             "name": "start_cursor",
1831 |             "in": "query",
1832 |             "description": "If supplied, this endpoint will return a page of results starting after the cursor provided. If not supplied, this endpoint will return the first page of results.",
1833 |             "schema": {
1834 |               "type": "string"
1835 |             }
1836 |           },
1837 |           {
1838 |             "name": "page_size",
1839 |             "in": "query",
1840 |             "description": "The number of items from the full list desired in the response. Maximum: 100",
1841 |             "schema": {
1842 |               "type": "integer",
1843 |               "format": "int32"
1844 |             }
1845 |           }
1846 |         ],
1847 |         "responses": {
1848 |           "200": {
1849 |             "description": "200",
1850 |             "content": {
1851 |               "application/json": {
1852 |                 "examples": {
1853 |                   "OK": {
1854 |                     "value": "{\n    \"object\": \"list\",\n    \"results\": [\n        {\n            \"object\": \"comment\",\n            \"id\": \"94cc56ab-9f02-409d-9f99-1037e9fe502f\",\n            \"parent\": {\n                \"type\": \"page_id\",\n                \"page_id\": \"5c6a2821-6bb1-4a7e-b6e1-c50111515c3d\"\n            },\n            \"discussion_id\": \"f1407351-36f5-4c49-a13c-49f8ba11776d\",\n            \"created_time\": \"2022-07-15T16:52:00.000Z\",\n            \"last_edited_time\": \"2022-07-15T19:16:00.000Z\",\n            \"created_by\": {\n                \"object\": \"user\",\n                \"id\": \"9b15170a-9941-4297-8ee6-83fa7649a87a\"\n            },\n            \"rich_text\": [\n                {\n                    \"type\": \"text\",\n                    \"text\": {\n                        \"content\": \"Single comment\",\n                        \"link\": null\n                    },\n                    \"annotations\": {\n                        \"bold\": false,\n                        \"italic\": false,\n                        \"strikethrough\": false,\n                        \"underline\": false,\n                        \"code\": false,\n                        \"color\": \"default\"\n                    },\n                    \"plain_text\": \"Single comment\",\n                    \"href\": null\n                }\n            ]\n        }\n    ],\n    \"next_cursor\": null,\n    \"has_more\": false,\n    \"type\": \"comment\",\n    \"comment\": {}\n}"
1855 |                   }
1856 |                 }
1857 |               }
1858 |             }
1859 |           }
1860 |         },
1861 |         "deprecated": false,
1862 |         "security": []
1863 |       },
1864 |       "post": {
1865 |         "summary": "Create comment",
1866 |         "description": "Creates a comment in a page or existing discussion thread.",
1867 |         "operationId": "create-a-comment",
1868 |         "requestBody": {
1869 |           "content": {
1870 |             "application/json": {
1871 |               "schema": {
1872 |                 "type": "object",
1873 |                 "required": [
1874 |                   "parent",
1875 |                   "rich_text"
1876 |                 ],
1877 |                 "properties": {
1878 |                   "parent": {
1879 |                     "type": "object",
1880 |                     "description": "The page that contains the comment",
1881 |                     "required": [
1882 |                       "page_id"
1883 |                     ],
1884 |                     "properties": {
1885 |                       "page_id": {
1886 |                         "type": "string",
1887 |                         "description": "the page ID"
1888 |                       }
1889 |                     }
1890 |                   },
1891 |                   "rich_text": {
1892 |                     "type": "array",
1893 |                     "items": {
1894 |                       "type": "object",
1895 |                       "required": [
1896 |                         "text"
1897 |                       ],
1898 |                       "properties": {
1899 |                         "text": {
1900 |                           "type": "object",
1901 |                           "required": [
1902 |                             "content"
1903 |                           ],
1904 |                           "properties": {
1905 |                             "content": {
1906 |                               "type": "string",
1907 |                               "description": "The content of the comment"
1908 |                             }
1909 |                           }
1910 |                         }
1911 |                       }
1912 |                     }
1913 |                   }
1914 |                 }
1915 |               }
1916 |             }
1917 |           }
1918 |         },
1919 |         "responses": {
1920 |           "200": {
1921 |             "description": "200",
1922 |             "content": {
1923 |               "application/json": {
1924 |                 "examples": {
1925 |                   "Result": {
1926 |                     "value": "{\n    \"object\": \"comment\",\n    \"id\": \"b52b8ed6-e029-4707-a671-832549c09de3\",\n    \"parent\": {\n        \"type\": \"page_id\",\n        \"page_id\": \"5c6a2821-6bb1-4a7e-b6e1-c50111515c3d\"\n    },\n    \"discussion_id\": \"f1407351-36f5-4c49-a13c-49f8ba11776d\",\n    \"created_time\": \"2022-07-15T20:53:00.000Z\",\n    \"last_edited_time\": \"2022-07-15T20:53:00.000Z\",\n    \"created_by\": {\n        \"object\": \"user\",\n        \"id\": \"067dee40-6ebd-496f-b446-093c715fb5ec\"\n    },\n    \"rich_text\": [\n        {\n            \"type\": \"text\",\n            \"text\": {\n                \"content\": \"Hello world\",\n                \"link\": null\n            },\n            \"annotations\": {\n                \"bold\": false,\n                \"italic\": false,\n                \"strikethrough\": false,\n                \"underline\": false,\n                \"code\": false,\n                \"color\": \"default\"\n            },\n            \"plain_text\": \"Hello world\",\n            \"href\": null\n        }\n    ]\n}"
1927 |                   }
1928 |                 }
1929 |               }
1930 |             }
1931 |           }
1932 |         },
1933 |         "deprecated": false,
1934 |         "security": []
1935 |       }
1936 |     }
1937 |   }
1938 | }
1939 | 
```

