@react-aria/mcp 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/react-aria/src/index.js +2 -2
- package/dist/shared/src/page-manager.js +7 -1
- package/dist/shared/src/server.js +21 -10
- package/dist/shared/src/utils.js +24 -1
- package/package.json +20 -20
- package/src/index.ts +5 -3
package/README.md
CHANGED
|
@@ -109,6 +109,10 @@ Follow Windsurf MCP [documentation](https://docs.windsurf.com/windsurf/cascade/m
|
|
|
109
109
|
| `get_react_aria_page_info` | `{ page_name: string }` | Return page description and list of section titles. |
|
|
110
110
|
| `get_react_aria_page` | `{ page_name: string, section_name?: string }` | Return full page markdown, or only the specified section. |
|
|
111
111
|
|
|
112
|
+
## Privacy Policy
|
|
113
|
+
|
|
114
|
+
See [Adobe's privacy policy](https://www.adobe.com/privacy/policy.html).
|
|
115
|
+
|
|
112
116
|
## Development
|
|
113
117
|
|
|
114
118
|
### Testing locally
|
|
@@ -135,4 +139,19 @@ Update your MCP client configuration to use the local MCP server:
|
|
|
135
139
|
}
|
|
136
140
|
}
|
|
137
141
|
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Bundling
|
|
145
|
+
|
|
146
|
+
To build an [MCP Bundle (MCPB)](https://github.com/modelcontextprotocol/mcpb), first prepare the staging directory:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
yarn workspace @react-spectrum/s2-docs generate:mcpb
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Then validate and pack using the [`@anthropic-ai/mcpb`](https://www.npmjs.com/package/@anthropic-ai/mcpb) CLI (paths are printed by the script above):
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npx @anthropic-ai/mcpb validate <staging-dir>
|
|
156
|
+
npx @anthropic-ai/mcpb pack <staging-dir> <output-path>
|
|
138
157
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
import { errorToString } from '../../shared/src/utils.js';
|
|
3
|
+
import { errorToString, readPackageVersion } from '../../shared/src/utils.js';
|
|
4
4
|
import { startServer } from '../../shared/src/server.js';
|
|
5
5
|
// CLI entry for React Aria
|
|
6
6
|
(async () => {
|
|
@@ -10,7 +10,7 @@ import { startServer } from '../../shared/src/server.js';
|
|
|
10
10
|
console.log('Usage: npx @react-aria/mcp@latest\n\nStarts the MCP server for React Aria documentation.');
|
|
11
11
|
process.exit(0);
|
|
12
12
|
}
|
|
13
|
-
await startServer('react-aria',
|
|
13
|
+
await startServer('react-aria', readPackageVersion(import.meta.url));
|
|
14
14
|
}
|
|
15
15
|
catch (err) {
|
|
16
16
|
console.error(errorToString(err));
|
|
@@ -67,7 +67,13 @@ export async function resolvePageRef(library, pageName) {
|
|
|
67
67
|
return maybe;
|
|
68
68
|
}
|
|
69
69
|
const filePath = `${baseUrl}/${normalized}.md`;
|
|
70
|
-
const stub = {
|
|
70
|
+
const stub = {
|
|
71
|
+
key: normalized,
|
|
72
|
+
name: path.basename(normalized),
|
|
73
|
+
description: undefined,
|
|
74
|
+
filePath,
|
|
75
|
+
sections: []
|
|
76
|
+
};
|
|
71
77
|
pageCache.set(stub.key, stub);
|
|
72
78
|
return stub;
|
|
73
79
|
}
|
|
@@ -4,11 +4,22 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
4
4
|
import { parseSectionsFromMarkdown } from './parser.js';
|
|
5
5
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
6
6
|
import { z } from 'zod';
|
|
7
|
-
export async function startServer(library, version,
|
|
7
|
+
export async function startServer(library, version, options = {}) {
|
|
8
8
|
const server = new McpServer({
|
|
9
9
|
name: library === 's2' ? 's2-docs-server' : 'react-aria-docs-server',
|
|
10
10
|
version
|
|
11
11
|
});
|
|
12
|
+
const libraries = [library, ...(options.additionalLibraries ?? [])];
|
|
13
|
+
for (const lib of libraries) {
|
|
14
|
+
await registerLibraryDocsTools(server, lib);
|
|
15
|
+
}
|
|
16
|
+
if (options.registerAdditionalTools) {
|
|
17
|
+
await options.registerAdditionalTools(server);
|
|
18
|
+
}
|
|
19
|
+
const transport = new StdioServerTransport();
|
|
20
|
+
await server.connect(transport);
|
|
21
|
+
}
|
|
22
|
+
async function registerLibraryDocsTools(server, library) {
|
|
12
23
|
// Build page index at startup.
|
|
13
24
|
try {
|
|
14
25
|
await buildPageIndex(library);
|
|
@@ -18,9 +29,12 @@ export async function startServer(library, version, registerAdditionalTools) {
|
|
|
18
29
|
}
|
|
19
30
|
const toolPrefix = library === 's2' ? 's2' : 'react_aria';
|
|
20
31
|
server.registerTool(`list_${toolPrefix}_pages`, {
|
|
21
|
-
title: library === 's2'
|
|
32
|
+
title: library === 's2'
|
|
33
|
+
? 'List React Spectrum (@react-spectrum/s2) docs pages'
|
|
34
|
+
: 'List React Aria docs pages',
|
|
22
35
|
description: `Returns a list of available pages in the ${library} docs.`,
|
|
23
|
-
inputSchema: { includeDescription: z.boolean().optional() }
|
|
36
|
+
inputSchema: { includeDescription: z.boolean().optional() },
|
|
37
|
+
annotations: { readOnlyHint: true, openWorldHint: true }
|
|
24
38
|
}, async ({ includeDescription }) => {
|
|
25
39
|
const pages = await buildPageIndex(library);
|
|
26
40
|
const items = pages
|
|
@@ -33,7 +47,8 @@ export async function startServer(library, version, registerAdditionalTools) {
|
|
|
33
47
|
server.registerTool(`get_${toolPrefix}_page_info`, {
|
|
34
48
|
title: 'Get page info',
|
|
35
49
|
description: 'Returns page description and list of sections for a given page.',
|
|
36
|
-
inputSchema: { page_name: z.string() }
|
|
50
|
+
inputSchema: { page_name: z.string() },
|
|
51
|
+
annotations: { readOnlyHint: true, openWorldHint: true }
|
|
37
52
|
}, async ({ page_name }) => {
|
|
38
53
|
const ref = await resolvePageRef(library, page_name);
|
|
39
54
|
const info = await ensureParsedPage(ref);
|
|
@@ -47,7 +62,8 @@ export async function startServer(library, version, registerAdditionalTools) {
|
|
|
47
62
|
server.registerTool(`get_${toolPrefix}_page`, {
|
|
48
63
|
title: 'Get page markdown',
|
|
49
64
|
description: 'Returns the full markdown content for a page, or a specific section if provided.',
|
|
50
|
-
inputSchema: { page_name: z.string(), section_name: z.string().optional() }
|
|
65
|
+
inputSchema: { page_name: z.string(), section_name: z.string().optional() },
|
|
66
|
+
annotations: { readOnlyHint: true, openWorldHint: true }
|
|
51
67
|
}, async ({ page_name, section_name }) => {
|
|
52
68
|
const ref = await resolvePageRef(library, page_name);
|
|
53
69
|
let text;
|
|
@@ -68,9 +84,4 @@ export async function startServer(library, version, registerAdditionalTools) {
|
|
|
68
84
|
const snippet = lines.slice(section.startLine, section.endLine).join('\n');
|
|
69
85
|
return { content: [{ type: 'text', text: snippet }] };
|
|
70
86
|
});
|
|
71
|
-
if (registerAdditionalTools) {
|
|
72
|
-
await registerAdditionalTools(server);
|
|
73
|
-
}
|
|
74
|
-
const transport = new StdioServerTransport();
|
|
75
|
-
await server.connect(transport);
|
|
76
87
|
}
|
package/dist/shared/src/utils.js
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
|
+
import { dirname, join } from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { readFileSync } from 'fs';
|
|
4
|
+
// Resolves the version from the nearest package.json above the CLI entry point.
|
|
5
|
+
// Both the npm-published layout (dist/<lib>/src/index.js) and the .mcpb bundle
|
|
6
|
+
// layout (server/<lib>/src/index.js) place package.json three levels up.
|
|
7
|
+
export function readPackageVersion(entryUrl) {
|
|
8
|
+
const entryDir = dirname(fileURLToPath(entryUrl));
|
|
9
|
+
const pkgPath = join(entryDir, '..', '..', '..', 'package.json');
|
|
10
|
+
try {
|
|
11
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
12
|
+
if (typeof pkg.version === 'string' && pkg.version.length > 0) {
|
|
13
|
+
return pkg.version;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// fall through
|
|
18
|
+
}
|
|
19
|
+
return '0.0.0';
|
|
20
|
+
}
|
|
1
21
|
export function errorToString(err) {
|
|
2
22
|
if (err && typeof err === 'object' && 'stack' in err && typeof err.stack === 'string') {
|
|
3
23
|
return err.stack;
|
|
4
24
|
}
|
|
5
|
-
if (err &&
|
|
25
|
+
if (err &&
|
|
26
|
+
typeof err === 'object' &&
|
|
27
|
+
'message' in err &&
|
|
28
|
+
typeof err.message === 'string') {
|
|
6
29
|
return err.message;
|
|
7
30
|
}
|
|
8
31
|
try {
|
package/package.json
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-aria/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "MCP server for React Aria documentation",
|
|
5
|
-
"
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/adobe/react-spectrum"
|
|
9
|
+
},
|
|
6
10
|
"bin": "dist/react-aria/src/index.js",
|
|
11
|
+
"source": "src/index.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"src"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"main": "dist/main.js",
|
|
19
|
+
"module": "dist/module.js",
|
|
20
|
+
"types": "dist/types.d.ts",
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
7
24
|
"scripts": {
|
|
8
25
|
"prepublishOnly": "yarn build",
|
|
9
26
|
"build": "tsc -p tsconfig.json",
|
|
@@ -21,22 +38,5 @@
|
|
|
21
38
|
"engines": {
|
|
22
39
|
"node": ">=18"
|
|
23
40
|
},
|
|
24
|
-
"
|
|
25
|
-
"publishConfig": {
|
|
26
|
-
"access": "public"
|
|
27
|
-
},
|
|
28
|
-
"repository": {
|
|
29
|
-
"type": "git",
|
|
30
|
-
"url": "https://github.com/adobe/react-spectrum"
|
|
31
|
-
},
|
|
32
|
-
"files": [
|
|
33
|
-
"dist",
|
|
34
|
-
"src"
|
|
35
|
-
],
|
|
36
|
-
"sideEffects": false,
|
|
37
|
-
"main": "dist/main.js",
|
|
38
|
-
"module": "dist/module.js",
|
|
39
|
-
"types": "dist/types.d.ts",
|
|
40
|
-
"source": "src/index.ts",
|
|
41
|
-
"gitHead": "a6999bdf494a2e9c0381a5881908328bdd22ddae"
|
|
41
|
+
"gitHead": "3577a20859b9585a000010c720f6ee39c1c588cc"
|
|
42
42
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
import {errorToString} from '../../shared/src/utils.js';
|
|
3
|
+
import {errorToString, readPackageVersion} from '../../shared/src/utils.js';
|
|
4
4
|
import {startServer} from '../../shared/src/server.js';
|
|
5
5
|
|
|
6
6
|
// CLI entry for React Aria
|
|
@@ -8,10 +8,12 @@ import {startServer} from '../../shared/src/server.js';
|
|
|
8
8
|
try {
|
|
9
9
|
const arg = (process.argv[2] || '').trim();
|
|
10
10
|
if (arg === '--help' || arg === '-h' || arg === 'help') {
|
|
11
|
-
console.log(
|
|
11
|
+
console.log(
|
|
12
|
+
'Usage: npx @react-aria/mcp@latest\n\nStarts the MCP server for React Aria documentation.'
|
|
13
|
+
);
|
|
12
14
|
process.exit(0);
|
|
13
15
|
}
|
|
14
|
-
await startServer('react-aria',
|
|
16
|
+
await startServer('react-aria', readPackageVersion(import.meta.url));
|
|
15
17
|
} catch (err) {
|
|
16
18
|
console.error(errorToString(err));
|
|
17
19
|
process.exit(1);
|