Skip to content

feat(API): [PF-3167] Add component-index.json API endpoint for MCP#221

Merged
wise-king-sullyman merged 1 commit intopatternfly:mainfrom
jpuzz0:PF-3167-pf-api-mcp-integration
Mar 9, 2026
Merged

feat(API): [PF-3167] Add component-index.json API endpoint for MCP#221
wise-king-sullyman merged 1 commit intopatternfly:mainfrom
jpuzz0:PF-3167-pf-api-mcp-integration

Conversation

@jpuzz0
Copy link
Contributor

@jpuzz0 jpuzz0 commented Mar 3, 2026

Summary

  • Adds a new static API endpoint (/api/component-index.json) that aggregates component metadata from the build-time API index and props.json
    • Includes: component names, sections, available tabs, props/CSS availability, example counts
    • Updates automatically on each doc-core deployment
  • Soon to be consumed by @patternfly/patternfly-mcp to power component search, documentation lookup, and schema tools without hardcoded data

Summary by CodeRabbit

  • New Features
    • Added a new versioned API endpoint that serves a comprehensive component index in JSON.
    • The index includes sections, pages, tabs, example counts, CSS availability, and whether prop documentation exists.
    • Picks a single representative entry per component name and returns the latest version's data for consumers.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

Walkthrough

Adds a new Astro API route that builds a versioned component index JSON by reading the API index and optional props.json, iterating latest-version sections/pages/tabs, and aggregating example counts, CSS presence, and props availability per component.

Changes

Cohort / File(s) Summary
Component Index API Route
src/pages/api/component-index.json.ts
New API route exporting GET and prerender, defines ComponentIndex type, reads getApiIndex, optionally loads props.json, converts page names to PascalCase, aggregates per-component metadata (section, page, tabs, exampleCount, hasCss, hasProps), handles duplicates and errors, returns 500 on failure.

Sequence Diagram

sequenceDiagram
    participant Client
    participant APIRoute as Component Index API
    participant FileSystem as File System (props.json)
    participant ApiIndex as getApiIndex
    participant Aggregator as Data Aggregator

    Client->>APIRoute: GET /api/component-index.json
    APIRoute->>FileSystem: Read props.json (optional)
    alt props.json exists
        FileSystem-->>APIRoute: Props data
        APIRoute->>APIRoute: Extract component names
    else props.json missing
        FileSystem-->>APIRoute: ENOENT
        APIRoute->>APIRoute: Continue without props
    end
    APIRoute->>ApiIndex: Fetch API index
    ApiIndex-->>APIRoute: Index with versions & sections
    APIRoute->>APIRoute: Select latest version, validate
    APIRoute->>Aggregator: Iterate sections/pages/tabs
    loop per page/tab
        Aggregator->>Aggregator: Sum example counts
        Aggregator->>Aggregator: Check CSS entries
        Aggregator->>Aggregator: Check props availability (PascalCase)
    end
    Aggregator-->>APIRoute: Component metadata map
    APIRoute-->>Client: ComponentIndex JSON
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • wise-king-sullyman
  • dlabaj
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a new component-index.json API endpoint for MCP integration, with reference to the ticket PF-3167.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Signed-off-by: Jeff Puzzo <jpuzzo@redhat.com>
@jpuzz0 jpuzz0 force-pushed the PF-3167-pf-api-mcp-integration branch from 4697420 to abdafc5 Compare March 3, 2026 19:23
@jpuzz0 jpuzz0 changed the title [PF-3167] Add component-index.json API endpoint for MCP feat(API): [PF-3167] Add component-index.json API endpoint for MCP Mar 3, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/pages/api/component-index.json.ts (1)

47-51: Add a warning when props.json is missing.

Line 48 handles ENOENT silently. This makes hasProps degrade to all-false without visibility, which is hard to detect in build logs.

Proposed improvement
   } catch (error) {
     if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
       throw error
     }
+    console.warn('[component-index] props.json not found; hasProps will be false for all components')
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/api/component-index.json.ts` around lines 47 - 51, The catch
swallowing ENOENT hides missing props.json files; update the catch in the
component index generation (the block that checks (error as
NodeJS.ErrnoException).code !== 'ENOENT') to log a warning when ENOENT occurs
(include the component path/name and that props.json is missing) instead of
silently ignoring it so hasProps consumers can be diagnosed; use the existing
logging mechanism (e.g., processLogger.warn or console.warn) and include the
error message/stack for context while still not throwing for ENOENT.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/api/component-index.json.ts`:
- Around line 43-46: The regex propsSuffixPattern currently matches "Props"
anywhere, causing names like "hasProps" to be treated as prop interfaces; change
the pattern used in the componentNamesWithProps computation to only match names
that end with "Props" (e.g., make propsSuffixPattern a suffix-anchored,
case-insensitive regex) so the Object.keys(propsData).filter((name) =>
!propsSuffixPattern.test(name)) logic only strips true "*Props" interfaces;
update the symbol propsSuffixPattern in the file where componentNamesWithProps
and propsData are used.

---

Nitpick comments:
In `@src/pages/api/component-index.json.ts`:
- Around line 47-51: The catch swallowing ENOENT hides missing props.json files;
update the catch in the component index generation (the block that checks (error
as NodeJS.ErrnoException).code !== 'ENOENT') to log a warning when ENOENT occurs
(include the component path/name and that props.json is missing) instead of
silently ignoring it so hasProps consumers can be diagnosed; use the existing
logging mechanism (e.g., processLogger.warn or console.warn) and include the
error message/stack for context while still not throwing for ENOENT.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 309bd28 and 4697420.

📒 Files selected for processing (1)
  • src/pages/api/component-index.json.ts

Comment on lines +43 to +46
const propsSuffixPattern = /Props/i
componentNamesWithProps = new Set(
Object.keys(propsData).filter((name) => !propsSuffixPattern.test(name)),
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Anchor the Props filter to suffix-only matching.

Line 43 uses /Props/i, which filters any key containing “Props” anywhere, not just interface names ending with Props. That can misclassify hasProps.

Proposed fix
-    const propsSuffixPattern = /Props/i
+    const propsSuffixPattern = /Props$/
     componentNamesWithProps = new Set(
       Object.keys(propsData).filter((name) => !propsSuffixPattern.test(name)),
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/api/component-index.json.ts` around lines 43 - 46, The regex
propsSuffixPattern currently matches "Props" anywhere, causing names like
"hasProps" to be treated as prop interfaces; change the pattern used in the
componentNamesWithProps computation to only match names that end with "Props"
(e.g., make propsSuffixPattern a suffix-anchored, case-insensitive regex) so the
Object.keys(propsData).filter((name) => !propsSuffixPattern.test(name)) logic
only strips true "*Props" interfaces; update the symbol propsSuffixPattern in
the file where componentNamesWithProps and propsData are used.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/pages/api/component-index.json.ts (1)

24-30: Edge case: consecutive hyphens produce empty segments.

If a page name contains consecutive hyphens (e.g., "some--page"), split('-') yields empty strings that become empty segments in the result. This is unlikely given your naming conventions, but worth noting.

Optional defensive fix
 function pageToPascalCase(page: string): string {
   return removeSubsection(page)
     .split('-')
+    .filter(Boolean)
     .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
     .join('')
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/api/component-index.json.ts` around lines 24 - 30, The
pageToPascalCase function can produce empty segments when page contains
consecutive hyphens; update pageToPascalCase (which calls removeSubsection) to
filter out empty strings after split('-') before mapping/capitalizing so only
non-empty words are transformed and joined, ensuring inputs like "some--page"
become "SomePage" instead of introducing empty segments.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/pages/api/component-index.json.ts`:
- Around line 24-30: The pageToPascalCase function can produce empty segments
when page contains consecutive hyphens; update pageToPascalCase (which calls
removeSubsection) to filter out empty strings after split('-') before
mapping/capitalizing so only non-empty words are transformed and joined,
ensuring inputs like "some--page" become "SomePage" instead of introducing empty
segments.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4697420 and abdafc5.

📒 Files selected for processing (1)
  • src/pages/api/component-index.json.ts

Copy link
Contributor

@wise-king-sullyman wise-king-sullyman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@wise-king-sullyman wise-king-sullyman merged commit 5af44e5 into patternfly:main Mar 9, 2026
4 checks passed
@github-actions
Copy link

github-actions bot commented Mar 9, 2026

🎉 This PR is included in version 1.21.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants