Skip to content

Commit 619559b

Browse files
Copilotabernier
andauthored
Add MCP server with page-tagged documentation, dynamic resources, and comprehensive tests (#531)
* Initial plan * Add page tag wrapping and MCP server implementation Co-authored-by: abernier <[email protected]> * Update pnpm-lock.yaml with new dependencies Co-authored-by: abernier <[email protected]> * Add MCP README and format code with prettier Co-authored-by: abernier <[email protected]> * Add XML attribute escaping for security Co-authored-by: abernier <[email protected]> * Add implementation summary documentation Co-authored-by: abernier <[email protected]> * Add /mcp SSE route for remote MCP server access Co-authored-by: abernier <[email protected]> * Fix CSS selector injection vulnerability in MCP servers Co-authored-by: abernier <[email protected]> * Remove stdio MCP server, keep only HTTP/SSE endpoint Co-authored-by: abernier <[email protected]> * Reuse libs registry from page.tsx for MCP server Co-authored-by: abernier <[email protected]> * Optimize registry: move URL mapping to module scope Co-authored-by: abernier <[email protected]> * Refactor MCP server to use mcp-handler for better Vercel integration Co-authored-by: abernier <[email protected]> * Optimize MCP route by extracting library names to constant Co-authored-by: abernier <[email protected]> * Remove registry adapter, use libs directly from page.tsx Co-authored-by: abernier <[email protected]> * Remove docs files, add MCP section to introduction, use xmlbuilder2 Co-authored-by: abernier <[email protected]> * Optimize XML generation and clarify curl example Co-authored-by: abernier <[email protected]> * Remove hardcoded list of supported libraries from docs Co-authored-by: abernier <[email protected]> * Remove duplicate URL mapping, use library URLs directly Co-authored-by: abernier <[email protected]> * Support internal routes by prepending docs.pmnd.rs base URL Co-authored-by: abernier <[email protected]> * Rename MCP server to pmndrs-docs Co-authored-by: abernier <[email protected]> * Fix TypeScript errors and update pnpm-lock.yaml Co-authored-by: abernier <[email protected]> * Add dynamic export directive to exclude /mcp from static export Co-authored-by: abernier <[email protected]> * Exclude /mcp route from static export builds Co-authored-by: abernier <[email protected]> * Fix static export compatibility for /mcp route Co-authored-by: abernier <[email protected]> * Add prebuild script to remove /mcp route in static export mode Co-authored-by: abernier <[email protected]> * Revert MCP route to simpler version from commit 58ad8da Co-authored-by: abernier <[email protected]> * Add local MCP server for offline documentation access Co-authored-by: abernier <[email protected]> * Refactor MCP servers to share business logic via mcp-tools module Co-authored-by: abernier <[email protected]> * Convert all MCP code to TypeScript (.ts/.mts) Co-authored-by: abernier <[email protected]> * Revert to commit 16b4878: remove local MCP server and shared logic Co-authored-by: abernier <[email protected]> * Remove node-fetch dependency, use native fetch Co-authored-by: abernier <[email protected]> * Simplify prebuild script to use plain shell command Co-authored-by: abernier <[email protected]> * Update pnpm-lock.yaml after removing node-fetch dependency Co-authored-by: abernier <[email protected]> * Remove basePath option from mcp-handler configuration Co-authored-by: abernier <[email protected]> * Move MCP server to /api/[transport] route with basePath configuration Co-authored-by: abernier <[email protected]> * Remove unnecessary prebuild script - Next.js auto-excludes /api routes from static exports Co-authored-by: abernier <[email protected]> * Test and remove prebuild script - Next.js auto-excludes /api routes Co-authored-by: abernier <[email protected]> * Add postbuild script to restore API directory after static export Co-authored-by: abernier <[email protected]> * Replace prebuild/postbuild with unified build script using mv instead of rm Co-authored-by: abernier <[email protected]> * Replace external build script with oneliner in package.json Co-authored-by: abernier <[email protected]> * Simplify build script: use tmp/api-backup instead of complex trap logic Co-authored-by: abernier <[email protected]> * Fix build script to preserve next build exit status Co-authored-by: abernier <[email protected]> * Simplify build script by removing redundant || true statements Co-authored-by: abernier <[email protected]> * Fix CI: remove obsolete bin entry from package.json Co-authored-by: abernier <[email protected]> * build.sh * . * Rename build.sh to next-build.sh Co-authored-by: abernier <[email protected]> * Remove redundant .api-backup from .gitignore Co-authored-by: abernier <[email protected]> * Add explanatory header to next-build.sh script Co-authored-by: abernier <[email protected]> * Refactor next-build.sh to use if statements and IS_EXPORT variable Co-authored-by: abernier <[email protected]> * Update MCP config example to use @modelcontextprotocol/client-sse Co-authored-by: abernier <[email protected]> * Add skill.md manifest and register as MCP resource Co-authored-by: abernier <[email protected]> * Convert skill.md to dynamic route with libs integration Co-authored-by: abernier <[email protected]> * Replace list_pages tool with docs://{lib}/index resource template Co-authored-by: abernier <[email protected]> * Update MCP documentation to reflect resource templates Co-authored-by: abernier <[email protected]> * Update skill.md to reflect resource template architecture Co-authored-by: abernier <[email protected]> * Fix TypeScript errors in MCP resource registration Co-authored-by: abernier <[email protected]> * Add force-static directive to skill.md route Co-authored-by: abernier <[email protected]> * Remove .js extensions from TypeScript imports Co-authored-by: abernier <[email protected]> * Fix resource template registration API usage Co-authored-by: abernier <[email protected]> * Replace resource template with list_pages tool Co-authored-by: abernier <[email protected]> * Replace list_pages tool with dynamic resource registration Co-authored-by: abernier <[email protected]> * Add MCP server declaration to llms.txt Co-authored-by: abernier <[email protected]> * docs_url * Add as const to libs and use SUPPORTED_LIBRARY_NAMES type Co-authored-by: abernier <[email protected]> * . * Filter MCP server to only support pmndrs.github.io libraries Co-authored-by: abernier <[email protected]> * Support libraries with local paths (starting with /) in MCP server Co-authored-by: abernier <[email protected]> * Use current server URL for local paths instead of hardcoding Co-authored-by: abernier <[email protected]> * . * Remove redundant library validation check (zod already validates) Co-authored-by: abernier <[email protected]> * Remove redundant URL validation in resource registration Co-authored-by: abernier <[email protected]> * doc * doc * debug * debug * baseUrl() * . * -type-fest * Add comprehensive tests for MCP route using vitest and MSW Co-authored-by: abernier <[email protected]> * . * -skill route * . * docs(changeset): mcp support * get_page_content tests * . * . * . * . * . * . * . * . * cache * . --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: abernier <[email protected]> Co-authored-by: Antoine BERNIER <[email protected]>
1 parent 326dd2e commit 619559b

File tree

13 files changed

+1901
-78
lines changed

13 files changed

+1901
-78
lines changed

.changeset/neat-lions-bet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@pmndrs/docs': minor
3+
---
4+
5+
mcp support

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ node_modules/
1717
.next/
1818
.DS_Store
1919
.secrets
20+
tmp/api-backup
2021

2122
build/
2223
dist/

docs/getting-started/introduction.mdx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ We implement [m3 design system](https://m3.material.io/styles/color/system/overv
103103
104104
</details>
105105

106-
## dev
106+
## Usage
107+
108+
### dev
107109

108110
```sh
109111
$ (
@@ -118,7 +120,7 @@ $ (
118120
export NEXT_PUBLIC_LIBNAME_DOTSUFFIX_HREF="https://docs.pmnd.rs"
119121
export BASE_PATH=
120122
export DIST_DIR=
121-
export OUTPUT=export
123+
export OUTPUT=
122124
export HOME_REDIRECT=
123125
export MDX_BASEURL=http://localhost:$_PORT
124126
export SOURCECODE_BASEURL="vscode://file$(pwd)"
@@ -152,7 +154,7 @@ Then go to: http://localhost:3000
152154
> [!TIP]
153155
> If `HOME_REDIRECT=` empty, `/` will not redirect, and instead displays an index of libraries.
154156
155-
## build
157+
### build
156158

157159
```sh
158160
$ (
@@ -202,7 +204,7 @@ $ (
202204

203205
http://localhost:3000
204206

205-
## Docker
207+
### Docker
206208

207209
```sh
208210
$ docker build -t pmndrs-docs .
@@ -294,4 +296,10 @@ These URLs are linked in the HTML header as:
294296
```html
295297
<link rel="alternate" type="text/plain" href="/llms.txt" />
296298
<link rel="alternate" type="text/plain" href="/llms-full.txt" />
299+
```
300+
301+
## MCP Server
302+
303+
```sh
304+
$ npx -y @modelcontextprotocol/inspector
297305
```

next-build.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/sh
2+
#
3+
# Next.js build wrapper for static export compatibility
4+
#
5+
# When building in export mode (OUTPUT=export), Next.js cannot handle Route Handlers
6+
# (route.ts files) as they require server runtime. This script temporarily moves the
7+
# /api directory during the build, then restores it afterward to preserve the source.
8+
#
9+
# Usage:
10+
# OUTPUT=export npm run build # Static export (GitHub Pages)
11+
# npm run build # Server build (Vercel)
12+
13+
# Check if we're building in export mode
14+
if [ "$OUTPUT" = "export" ]; then
15+
IS_EXPORT=true
16+
else
17+
IS_EXPORT=false
18+
fi
19+
20+
# Move API directory if building for export
21+
if [ "$IS_EXPORT" = "true" ]; then
22+
mkdir -p tmp
23+
mv src/app/api tmp/api-backup
24+
fi
25+
26+
# Run Next.js build
27+
next build
28+
STATUS=$?
29+
30+
# Restore API directory if it was moved
31+
if [ "$IS_EXPORT" = "true" ]; then
32+
mv tmp/api-backup src/app/api
33+
fi
34+
35+
exit $STATUS

package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"husky": "^9.1.7",
3333
"lint-staged": "^15.2.10",
3434
"minimist": "^1.2.8",
35+
"msw": "^2.12.8",
3536
"postcss": "^8.4.45",
3637
"prettier": "^3.3.3",
3738
"prettier-plugin-organize-imports": "^4.0.0",
@@ -51,11 +52,13 @@
5152
"@codesandbox/sandpack-react": "^2.20.0",
5253
"@fontsource/inconsolata": "^5.2.8",
5354
"@fontsource/inter": "^5.2.8",
55+
"@modelcontextprotocol/sdk": "^1.25.2",
5456
"@octokit/core": "^6.1.2",
5557
"@radix-ui/react-collapsible": "^1.1.0",
5658
"@radix-ui/react-dialog": "^1.1.1",
5759
"@radix-ui/react-visually-hidden": "^1.2.4",
5860
"@tailwindcss/aspect-ratio": "^0.4.2",
61+
"cheerio": "^1.0.0",
5962
"class-variance-authority": "^0.7.1",
6063
"clsx": "^2.1.1",
6164
"cmdk": "^1.1.1",
@@ -64,6 +67,7 @@
6467
"lodash-es": "^4.17.21",
6568
"lucide-react": "^0.563.0",
6669
"match-sorter": "^6.3.4",
70+
"mcp-handler": "^1.0.7",
6771
"mermaid": "^11.12.2",
6872
"next": "^16.1.3",
6973
"next-mdx-remote": "^5.0.0",
@@ -77,12 +81,14 @@
7781
"remark-gfm": "^4.0.1",
7882
"sanitize-html": "^2.17.0",
7983
"tailwind-merge": "^3.4.0",
80-
"unist-util-visit": "^5.0.0"
84+
"unist-util-visit": "^5.0.0",
85+
"xmlbuilder2": "^3.1.1",
86+
"zod": "^3.24.1"
8187
},
8288
"scripts": {
8389
"dev": "NODE_OPTIONS='--inspect' next",
8490
"start": "next start",
85-
"build": "next build",
91+
"build": "./next-build.sh",
8692
"format": "prettier -w src/",
8793
"lint": "eslint src/**/*.{ts,tsx} && prettier . --check",
8894
"prepare": "husky && (test -f scripts/copy-fonts.sh && sh scripts/copy-fonts.sh || true)",

playwright.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { defineConfig, devices } from '@playwright/test'
55
*/
66
export default defineConfig({
77
testDir: './src/app',
8+
testIgnore: '**/route.test.ts',
89
use: {
910
baseURL: 'http://localhost:3000',
1011
},

0 commit comments

Comments
 (0)