Add Apple Design docs and resource previews#49
Conversation
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
📝 WalkthroughWalkthroughThis PR adds Apple Design/HIG support to the MCP server: new schemas and tools for searching design docs, fetching content, listing/downloading resources, returning examples, exposing cached resources, and handling Apple Design URLs and redirects. ChangesApple Design Docs Feature
Estimated code review effort: 5 (Critical) | ~120 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Pull request overview
This PR adds Apple Design support to the Apple Developer Documentation MCP server, including new tools for searching and reading Human Interface Guidelines (HIG) and Apple Design pages, listing Design Resources, downloading Apple-hosted resource files into an MCP-exposed cache, and returning visual previews as MCP image blocks.
Changes:
- Introduces new Apple Design tools (
search_apple_design_docs,get_apple_design_content,list_apple_design_resources,download_apple_design_resource,get_apple_design_examples) and wires them into the server/tool handler layer. - Adds a new Design docs implementation with HTML parsing, HIG JSON formatting, resource catalog parsing, manual redirect validation, byte limits, and a local cache exposed via MCP
resources/listandresources/read. - Expands tests to cover the new tools, resource handlers, redirect handling, and response format validation (including
imageandresource_linkblocks).
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/utils/url-converter.test.ts | Adds coverage for HIG URL → design JSON API conversion and Apple Design URL detection. |
| tests/tools/handlers.test.ts | Extends tool handler tests for new Apple Design tool routes and argument defaults. |
| tests/tools/design-docs.test.ts | New comprehensive test suite for HIG formatting, HTML parsing, resource catalog parsing, downloads, caching, redirects, and examples. |
| tests/response-format.test.ts | Updates response-format validation to accept image/resource_link/resource blocks and adds Apple Design tool validation. |
| tests/index.test.ts | Verifies server registers MCP resources handlers and exposes Apple Design public methods. |
| src/utils/url-converter.ts | Adds convertToDesignJsonApiUrl and isAppleDesignUrl; integrates design conversion into convertToJsonApiUrl. |
| src/utils/http-client.ts | Adds manual redirect support (redirect, allowManualRedirect) so Design fetches can validate redirects safely. |
| src/utils/constants.ts | Adds cache TTL/size constants and Apple Design URL constants. |
| src/utils/cache.ts | Adds in-memory caches for Design content and Design resources. |
| src/tools/handlers.ts | Extends tool dispatch for Apple Design tools and updates handler return type to CallToolResult. |
| src/tools/design-docs.ts | New Apple Design implementation: search, content fetch/formatting, resource catalog, downloads/cache, examples, and MCP resources support. |
| src/tools/definitions.ts | Adds MCP tool definitions and schemas for the five Apple Design tools. |
| src/schemas/index.ts | Exports the new Apple Design zod schemas. |
| src/schemas/design.schema.ts | Defines zod schemas for Apple Design tool inputs. |
| src/index.ts | Wires in Design tools, delegates /design/... URLs, and adds MCP resources/list/resources/read handlers. |
| src/tests/http-client-headers-integration.test.ts | Adds test ensuring redirect options are passed through to fetch. |
| README.md | Documents Apple Design/HIG features, usage examples, and new tools. |
| pnpm-workspace.yaml | Updates workspace config and adds build-allowlist entries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@kimsungwhee I made this PR to add Apple design docs to the MCP. If you have time I would love if you could take a look :) thanks for making this MCP! |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (4)
src/utils/http-client.ts (1)
240-256: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueDocument the manual-redirect assumption
This path depends onredirect: 'manual'exposing the actual 3xx status andLocationheader; add a short note so future changes don’t assume browser-style opaque redirects.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/utils/http-client.ts` around lines 240 - 256, The manual-redirect branch in http-client’s redirect handling should be documented to make the 3xx/Location-header assumption explicit. Add a short comment near isAllowedManualRedirect and the return response path explaining that allowManualRedirect relies on fetch running with redirect: 'manual' so response.status and Location remain accessible. Keep the note close to the pool.markSuccess/pool.markFailure logic and the redirect check so future changes to HttpClient don’t assume browser-style opaque redirects.src/schemas/design.schema.ts (1)
14-14: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePrefer Zod v4 top-level
z.url()over deprecated.string().url().Zod v4 deprecated the chained string-format methods (
.string().url(),.string().email(), etc.) in favor of top-level functions (z.url()). The chained form still works but is marked for removal in a future major version.♻️ Suggested refactor
export const getAppleDesignContentSchema = z.object({ - url: z.string().url().describe('Apple Design URL to read'), + url: z.url().describe('Apple Design URL to read'), });Apply the same substitution at
downloadAppleDesignResourceSchema.url(line 28) andgetAppleDesignExamplesSchema.url(line 34).Also applies to: 28-28, 34-34
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/schemas/design.schema.ts` at line 14, Update the URL fields in the Apple design schemas to use Zod v4 top-level z.url() instead of the deprecated z.string().url() chain. Apply this change in the relevant schema definitions identified by design.schema.ts, including the url properties in the main schema, downloadAppleDesignResourceSchema, and getAppleDesignExamplesSchema, so all URL validation uses the modern API consistently.src/index.ts (1)
216-275: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winInconsistent error handling for new Apple Design methods.
Unlike
searchAppleDocs/getAppleDocContent(manual try/catch →createToolErrorResponse/createStandardErrorResponse) or other methods usingthis.handleAsyncOperation(...), these five new methods forward directly to thehandle*AppleDesign*functions with no local error handling. Errors thrown by those handlers (e.g.handleDownloadAppleDesignResourcethrows a plainErrorwhen neitherresourceIdnorurlis supplied) will only be caught by the generic catch-all insetupTools()'sCallToolRequestSchemahandler, which produces a bareError: ${message}string without the tool-specific suggestions thatcreateToolErrorResponseprovides for the rest of the toolset.♻️ Example fix pattern for one method (repeat for the others)
public async downloadAppleDesignResource( resourceId?: string, url?: string, maxBytes?: number, ) { - return await handleDownloadAppleDesignResource({ - resourceId, - url, - maxBytes, - }); + try { + return await handleDownloadAppleDesignResource({ + resourceId, + url, + maxBytes, + }); + } catch (error) { + if (error && typeof error === 'object' && 'type' in error) { + return createToolErrorResponse(error as any, 'downloadAppleDesignResource') as CallToolResult; + } + return createStandardErrorResponse(error, 'downloadAppleDesignResource') as CallToolResult; + } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/index.ts` around lines 216 - 275, The new Apple Design methods in handleSearchAppleDesignDocs, handleGetAppleDesignContent, handleListAppleDesignResources, handleDownloadAppleDesignResource, and handleGetAppleDesignExamples bypass the tool’s normal error handling path. Wrap each method in the same pattern used by searchAppleDocs/getAppleDocContent or route them through this.handleAsyncOperation so thrown errors are converted into createToolErrorResponse/createStandardErrorResponse instead of falling through to the generic setupTools catch-all. Ensure any validation errors from the handle*AppleDesign* functions return tool-specific, user-friendly messages.tests/tools/design-docs.test.ts (1)
265-327: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider adding a collision-path test for
parseDesignResourcesHtml.The "keep resource IDs stable when same-label resources reorder" test (Lines 502-553) verifies stability across reordering, but doesn't exercise the
seenResourceIdsdedup map thatparseDesignResourcesHtmlmaintains for exact duplicate category/platform/title/format/URL combinations. Adding a case with two truly identical grid-items would validate the collision-suffix behavior that underpins the "stable IDs" guarantee called out in the PR objectives.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/tools/design-docs.test.ts` around lines 265 - 327, Add a test coverage case around parseDesignResourcesHtml that uses two truly identical grid items so the seenResourceIds dedup path is exercised. Update the Apple Design document formatting test suite to assert the collision-suffix behavior for duplicate category/platform/title/format/URL combinations, alongside the existing reorder-stability test, so the stable ID guarantee is verified for exact duplicates.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/tools/design-docs.ts`:
- Around line 2104-2109: The cache write path in the open/writeFile/close flow
can leave behind an orphaned file if writeFile throws after the wx file is
created. Update the logic around the fileHandle write in the design-docs cache
writer to keep track of filePath, catch write failures, remove the partially
written file with rm(..., { force: true }), and then rethrow so the caller still
sees the error.
- Around line 953-965: The query preview path in `design-docs.ts` is still
collecting too many candidates because `filterDesignResources()` does not honor
`args.limit`. Update the `args.query` handling in this block to cap the filtered
`resources` before pushing preview URLs into `candidates`, or add an explicit
attempt limit in this loop so only up to `limit` query-derived previews are
enqueued.
- Around line 1882-1895: In the redirect-handling flow around
isRedirectResponse, make sure any response that is not returned to the caller
has its body explicitly consumed or canceled before the code follows the
redirect or throws on MAX_APPLE_DESIGN_REDIRECTS. Update the logic in the
redirect loop to cancel the current response body on the early-exit paths,
including the non-final redirect branch and the over-limit error path, so
repeated calls do not রেখে open sockets/resources. Use the existing response,
currentUrl, and getAppleDesignRedirectUrl flow as the place to add the cleanup.
- Around line 1276-1278: Clamp the parsed heading level before using it in the
markdown heading renderer in design-docs.ts. In the logic that computes level
and returns the heading string, ensure the value derived from getNumber(record,
'level') and headingLevel is normalized to the 1..6 range before passing it to
'#'.repeat(), so invalid or negative JSON values cannot throw or generate
malformed headings.
---
Nitpick comments:
In `@src/index.ts`:
- Around line 216-275: The new Apple Design methods in
handleSearchAppleDesignDocs, handleGetAppleDesignContent,
handleListAppleDesignResources, handleDownloadAppleDesignResource, and
handleGetAppleDesignExamples bypass the tool’s normal error handling path. Wrap
each method in the same pattern used by searchAppleDocs/getAppleDocContent or
route them through this.handleAsyncOperation so thrown errors are converted into
createToolErrorResponse/createStandardErrorResponse instead of falling through
to the generic setupTools catch-all. Ensure any validation errors from the
handle*AppleDesign* functions return tool-specific, user-friendly messages.
In `@src/schemas/design.schema.ts`:
- Line 14: Update the URL fields in the Apple design schemas to use Zod v4
top-level z.url() instead of the deprecated z.string().url() chain. Apply this
change in the relevant schema definitions identified by design.schema.ts,
including the url properties in the main schema,
downloadAppleDesignResourceSchema, and getAppleDesignExamplesSchema, so all URL
validation uses the modern API consistently.
In `@src/utils/http-client.ts`:
- Around line 240-256: The manual-redirect branch in http-client’s redirect
handling should be documented to make the 3xx/Location-header assumption
explicit. Add a short comment near isAllowedManualRedirect and the return
response path explaining that allowManualRedirect relies on fetch running with
redirect: 'manual' so response.status and Location remain accessible. Keep the
note close to the pool.markSuccess/pool.markFailure logic and the redirect check
so future changes to HttpClient don’t assume browser-style opaque redirects.
In `@tests/tools/design-docs.test.ts`:
- Around line 265-327: Add a test coverage case around parseDesignResourcesHtml
that uses two truly identical grid items so the seenResourceIds dedup path is
exercised. Update the Apple Design document formatting test suite to assert the
collision-suffix behavior for duplicate category/platform/title/format/URL
combinations, alongside the existing reorder-stability test, so the stable ID
guarantee is verified for exact duplicates.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c092c4c4-adfc-4537-9706-c4ebdb32ca00
📒 Files selected for processing (18)
README.mdpnpm-workspace.yamlsrc/__tests__/http-client-headers-integration.test.tssrc/index.tssrc/schemas/design.schema.tssrc/schemas/index.tssrc/tools/definitions.tssrc/tools/design-docs.tssrc/tools/handlers.tssrc/utils/cache.tssrc/utils/constants.tssrc/utils/http-client.tssrc/utils/url-converter.tstests/index.test.tstests/response-format.test.tstests/tools/design-docs.test.tstests/tools/handlers.test.tstests/utils/url-converter.test.ts
Summary
This change adds Apple Design support to the MCP server.
The server can now read Human Interface Guidelines pages, parse Apple Design pages, discover Design Resources, download direct Apple-hosted resource files, and return visual examples as MCP image blocks.
Change
The new Design tools search HIG JSON references, parse Apple Design HTML pages, list resource catalog entries with stable IDs, and fetch examples as MCP
imagecontent blocks.Direct Apple-hosted downloads are cached outside the repository, returned as MCP
resource_linkblocks, and exposed throughresources/listandresources/readas blob resources.The HIG formatter renders common Apple content blocks, including headings, paragraphs, emphasis, strong text, references, images, lists, link grids, tables, asides, tabs, alerts, supported platforms, and change logs.
External Figma, Sketch web, and
sketch://links remain catalog metadata and preview sources. The server does not attempt authenticated browser downloads for them.Hardening
Apple Design fetches now validate manual redirects, enforce byte limits for content, previews, and downloads, bound aggregate cache size, use exclusive cache writes, reuse in-flight same-URL downloads, and avoid inlining large downloaded images.
Resource IDs include stable item data and a URL hash so same-label resource entries do not drift when Apple reorders the catalog.
Testing
pnpm installpnpm test --runInBandpassed with 32 suites and 529 tests.pnpm run buildpassed.pnpm run lintexited 0 with warnings only.git diff --checkpassed.I ran a live MCP stdio end-to-end check against
node dist/index.jswith current Apple endpoints and a temporary cache directory.The live check verified
initializedeclaresresources: {},tools/listexposes the five Apple Design tools,get_apple_design_contentreads the live Layout HIG page, andget_apple_doc_contentdelegates/design/...URLs to the Design content path.The live check also verified
search_apple_design_docs,list_apple_design_resources,get_apple_design_examples,download_apple_design_resource,resources/list, andresources/read.get_apple_design_examplesreturned a realimage/pngMCP image block.download_apple_design_resourcedownloaded a live Apple Design preview image, returned aresource_link, andresources/readreturned blob content for the cached image.I visually opened the downloaded preview image. It rendered correctly as an Apple Design UIKit thumbnail with three iPhone mockups.
Review
I ran blind Codex review subagents through tmux using
codex execin read-only mode, with no prior conversation context in the prompts.Loops 45 through 100 covered repeated bug-focused and security-focused reviews. Reported findings were fixed, verified locally, and reviewed again. The final loop 100 results were clean: bug review found no bugs, and security review found no issues.
Summary by CodeRabbit