Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions packages/dev/s2-docs/pages/react-aria/mcp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {Layout} from '../../src/Layout';
import {StaticTable} from '../../src/StaticTable';
import {Command} from '../../src/Command';
import {Link} from '@react-spectrum/s2';
export default Layout;

export const section = 'Guides';
export const description = 'MCP Server for React Aria';
export const tags = ['mcp', 'ai', 'documentation', 'tools'];

# MCP Server

The `@react-spectrum/mcp` package allows you to run [Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro) servers for React Aria locally. It exposes a set of tools that MCP clients can discover and call to browse the docs.

## Using with an MCP client

Add one or both servers to your MCP client configuration (the exact file and schema may depend on your client).

```js
{
"mcpServers": {
"React Aria": {
"command": "npx",
"args": ["@react-spectrum/mcp", "react-aria"]
}
}
}
```

### Cursor

<Link href="cursor://anysphere.cursor-deeplink/mcp/install?name=React%20Aria&config=eyJjb21tYW5kIjoibnB4IEByZWFjdC1zcGVjdHJ1bS9tY3AgcmVhY3QtYXJpYSJ9" aria-label="Add to Cursor">
<picture>
<source srcSet="https://cursor.com/deeplink/mcp-install-dark.svg" media="(prefers-color-scheme: light)" />
<source srcSet="https://cursor.com/deeplink/mcp-install-light.svg" media="(prefers-color-scheme: dark)" />
<img src="https://cursor.com/deeplink/mcp-install-light.svg" alt="Add to Cursor" />
</picture>
</Link>


Or follow Cursor's MCP install [guide](https://docs.cursor.com/en/context/mcp#installing-mcp-servers) and use the standard config above.

### VS Code

<Link href="vscode:mcp/install?%7B%22name%22%3A%22React%20Aria%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22%40react-spectrum%2Fmcp%22%2C%22react-aria%22%5D%7D" aria-label="Add to Visual Studio Code">
<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in Visual Studio Code" />
</Link>

Or follow VS Code's MCP install [guide](https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-an-mcp-server) and use the standard config above. You can also add servers using the VS Code CLI:

<Command command='code --add-mcp &#39;{"name":"React Aria","command":"npx","args":["@react-spectrum/mcp","react-aria"]}&#39;' />

### Claude Code

Use the Claude Code CLI to add the servers:

<Command command="claude mcp add react-aria npx @react-spectrum/mcp react-aria" />

For more information, see the [Claude Code MCP documentation](https://docs.claude.com/en/docs/claude-code/mcp).

### Codex

Create or edit the configuration file `~/.codex/config.toml` and add:

```js
[mcp_servers.react-aria]
command = "npx"
args = ["@react-spectrum/mcp", "react-aria"]
```

For more information, see the [Codex MCP documentation](https://github.com/openai/codex/blob/main/docs/config.md#mcp_servers).

### Gemini CLI

Use the Gemini CLI to add the servers:

<Command command="gemini mcp add react-aria npx @react-spectrum/mcp react-aria" />

For more information, see the [Gemini CLI MCP documentation](https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md#how-to-set-up-your-mcp-server).

### Windsurf

Follow the Windsurf MCP [documentation](https://docs.windsurf.com/windsurf/cascade/mcp) and use the standard config above.
5 changes: 3 additions & 2 deletions packages/dev/s2-docs/pages/s2/Icons.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Layout} from '../../src/Layout';
import {InstallCommand} from '../../src/InstallCommand';
import {Command} from '../../src/Command';
import {IconCards} from '../../src/IconCards';
import {IconColors} from '../../src/IconColors';
import {IconSizes} from '../../src/IconSizes';
Expand Down Expand Up @@ -116,7 +117,7 @@ Now you can import icon SVGs using the `icon:` [pipeline](https://parceljs.org/f

The `@react-spectrum/s2-icon-builder` CLI tool can be used to pre-process a folder of SVG icons into TSX files.

`npx @react-spectrum/s2-icon-builder -i 'path/to/icons/*.svg' -o 'path/to/destination'`
<Command command="npx @react-spectrum/s2-icon-builder -i 'path/to/icons/*.svg' -o 'path/to/destination'" />

This outputs a folder of TSX files with names corresponding to the input SVG files. You may rename them as you wish. To use them in your application, import them like normal components.
`import Icon from './path/to/destination/Icon';`
Expand All @@ -126,7 +127,7 @@ This outputs a folder of TSX files with names corresponding to the input SVG fil
You can also build the icons as a separate library for distribution so that multiple projects can share the same icons. Or possibly you simply do not want to output tsx files.
To do this, use the `--isLibrary` flag.

`npx @react-spectrum/s2-icon-builder -i 'path/to/icons/*.svg' -o 'path/to/destination' --isLibrary`
<Command command="npx @react-spectrum/s2-icon-builder -i 'path/to/icons/*.svg' -o 'path/to/destination' --isLibrary" />

This outputs a folder of ES modules and commonjs modules with names corresponding to the input SVG files. You may rename them as you wish. To use them in your application, import them like normal components.
`import Icon from 'library-name/path/to/destination/Icon';`
3 changes: 2 additions & 1 deletion packages/dev/s2-docs/pages/s2/Illustrations.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Layout} from '../../src/Layout';
import {InstallCommand} from '../../src/InstallCommand';
import {Command} from '../../src/Command';
import {InlineAlert, Heading, Content} from '@react-spectrum/s2';
import {IllustrationCards} from '../../src/IllustrationCards';
export default Layout;
Expand Down Expand Up @@ -54,7 +55,7 @@ Note that you must use the name `illustration` for the pipeline.

The `@react-spectrum/s2-icon-builder` CLI tool can be used to pre-process a folder of SVG illustrations into TSX files.

`npx @react-spectrum/s2-icon-builder -i 'path/to/illustrations/*.svg' --type illustration -o 'path/to/destination'`
<Command command="npx @react-spectrum/s2-icon-builder -i 'path/to/illustrations/*.svg' --type illustration -o 'path/to/destination'" />

This outputs a folder of TSX files with names corresponding to the input SVG files. You may rename them as you wish. To use them in your application, import them like normal components.
`import Illustration from './path/to/destination/Illustration';`
117 changes: 117 additions & 0 deletions packages/dev/s2-docs/pages/s2/mcp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import {Layout} from '../../src/Layout';
import {StaticTable} from '../../src/StaticTable';
import {Command} from '../../src/Command';
import {Link} from '@react-spectrum/s2';
export default Layout;

export const section = 'Guides';
export const description = 'MCP Server for React Spectrum';
export const tags = ['mcp', 'ai', 'documentation', 'tools'];

# MCP Server

The `@react-spectrum/mcp` package allows you to run [Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro) servers for React Spectrum (S2) and React Aria locally. It exposes a set of tools that MCP clients can discover and call to browse the docs.

## Using with an MCP client

Add one or both servers to your MCP client configuration (the exact file and schema may depend on your client).

```js
{
"mcpServers": {
"React Spectrum (S2)": {
"command": "npx",
"args": ["@react-spectrum/mcp", "s2"]
},
"React Aria": {
"command": "npx",
"args": ["@react-spectrum/mcp", "react-aria"]
}
}
}
```

### Cursor

React Spectrum (S2):

<Link href="cursor://anysphere.cursor-deeplink/mcp/install?name=React%20Spectrum%20(S2)&config=eyJjb21tYW5kIjoibnB4IEByZWFjdC1zcGVjdHJ1bS9tY3AgczIifQ%3D%3D" aria-label="Add to Cursor">
<picture>
<source srcSet="https://cursor.com/deeplink/mcp-install-dark.svg" media="(prefers-color-scheme: light)" />
<source srcSet="https://cursor.com/deeplink/mcp-install-light.svg" media="(prefers-color-scheme: dark)" />
<img src="https://cursor.com/deeplink/mcp-install-light.svg" alt="Add to Cursor" />
</picture>
</Link>

React Aria:

<Link href="cursor://anysphere.cursor-deeplink/mcp/install?name=React%20Aria&config=eyJjb21tYW5kIjoibnB4IEByZWFjdC1zcGVjdHJ1bS9tY3AgcmVhY3QtYXJpYSJ9" aria-label="Add to Cursor">
<picture>
<source srcSet="https://cursor.com/deeplink/mcp-install-dark.svg" media="(prefers-color-scheme: light)" />
<source srcSet="https://cursor.com/deeplink/mcp-install-light.svg" media="(prefers-color-scheme: dark)" />
<img src="https://cursor.com/deeplink/mcp-install-light.svg" alt="Add to Cursor" />
</picture>
</Link>


Or follow Cursor's MCP install [guide](https://docs.cursor.com/en/context/mcp#installing-mcp-servers) and use the standard config above.

### VS Code

React Spectrum (S2):

<Link href="vscode:mcp/install?%7B%22name%22%3A%22React%20Spectrum%20(S2)%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22%40react-spectrum%2Fmcp%22%2C%22s2%22%5D%7D" aria-label="Add to Visual Studio Code">
<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in Visual Studio Code" />
</Link>

React Aria:

<Link href="vscode:mcp/install?%7B%22name%22%3A%22React%20Aria%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22%40react-spectrum%2Fmcp%22%2C%22react-aria%22%5D%7D" aria-label="Add to Visual Studio Code">
<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in Visual Studio Code" />
</Link>

Or follow VS Code's MCP install [guide](https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-an-mcp-server) and use the standard config above. You can also add servers using the VS Code CLI:

<Command command='code --add-mcp &#39;{"name":"React Spectrum (S2)","command":"npx","args":["@react-spectrum/mcp","s2"]}&#39;' />

<Command command='code --add-mcp &#39;{"name":"React Aria","command":"npx","args":["@react-spectrum/mcp","react-aria"]}&#39;' />

### Claude Code

Use the Claude Code CLI to add the servers:

<Command command="claude mcp add react-spectrum-s2 npx @react-spectrum/mcp s2" />

<Command command="claude mcp add react-aria npx @react-spectrum/mcp react-aria" />

For more information, see the [Claude Code MCP documentation](https://docs.claude.com/en/docs/claude-code/mcp).

### Codex

Create or edit the configuration file `~/.codex/config.toml` and add:

```js
[mcp_servers.react-spectrum-s2]
command = "npx"
args = ["@react-spectrum/mcp", "s2"]

[mcp_servers.react-aria]
command = "npx"
args = ["@react-spectrum/mcp", "react-aria"]
```

For more information, see the [Codex MCP documentation](https://github.com/openai/codex/blob/main/docs/config.md#mcp_servers).

### Gemini CLI

Use the Gemini CLI to add the servers:

<Command command="gemini mcp add react-spectrum-s2 npx @react-spectrum/mcp s2" />

<Command command="gemini mcp add react-aria npx @react-spectrum/mcp react-aria" />

For more information, see the [Gemini CLI MCP documentation](https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md#how-to-set-up-your-mcp-server).

### Windsurf

Follow the Windsurf MCP [documentation](https://docs.windsurf.com/windsurf/cascade/mcp) and use the standard config above.
66 changes: 63 additions & 3 deletions packages/dev/s2-docs/scripts/generateMarkdownDocs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,37 @@ function remarkDocsComponentsToMarkdown() {
return index;
}

// Render a simple command snippet.
if (name === 'Command') {
const commandAttr = node.attributes?.find(a => a.name === 'command');
if (!commandAttr) {
parent.children.splice(index, 1);
return index;
}

let command = '';
if (commandAttr.value?.type === 'mdxJsxAttributeValueExpression') {
command = commandAttr.value.value.replace(/['"`]/g, '').trim();
} else if (typeof commandAttr.value === 'string') {
command = commandAttr.value.trim();
}

if (!command) {
parent.children.splice(index, 1);
return index;
}

const codeNode = {
type: 'code',
lang: 'bash',
meta: '',
value: command
};

parent.children.splice(index, 1, codeNode);
return index;
}

// Render an unordered list of icon names.
if (name === 'IconCards') {
const iconList = getIconNames();
Expand Down Expand Up @@ -1082,6 +1113,18 @@ function remarkDocsComponentsToMarkdown() {
}
}

// Check for aria-label attribute first
const ariaLabelAttr = node.attributes?.find(a => a.name === 'aria-label');
let ariaLabel = '';

if (ariaLabelAttr) {
if (ariaLabelAttr.value?.type === 'mdxJsxAttributeValueExpression') {
ariaLabel = ariaLabelAttr.value.value.replace(/['"`]/g, '').trim();
} else if (typeof ariaLabelAttr.value === 'string') {
ariaLabel = ariaLabelAttr.value.trim();
}
}

// Extract text content from children
const extractText = (children) => {
if (!children) {return '';}
Expand All @@ -1098,18 +1141,35 @@ function remarkDocsComponentsToMarkdown() {
.join('');
};

const linkText = extractText(node.children) || href;
const childrenText = extractText(node.children);
const linkText = ariaLabel || childrenText || href;

if (href) {
const linkNode = {
type: 'link',
url: href,
children: [{type: 'text', value: linkText}]
};
parent.children[index] = linkNode;

// If this is a flow element (block-level), wrap in paragraph to preserve spacing
if (node.type === 'mdxJsxFlowElement') {
parent.children[index] = {
type: 'paragraph',
children: [linkNode]
};
} else {
parent.children[index] = linkNode;
}
} else {
// No href, just convert to plain text
parent.children[index] = {type: 'text', value: linkText};
if (node.type === 'mdxJsxFlowElement') {
parent.children[index] = {
type: 'paragraph',
children: [{type: 'text', value: linkText}]
};
} else {
parent.children[index] = {type: 'text', value: linkText};
}
}
return;
}
Expand Down
58 changes: 58 additions & 0 deletions packages/dev/s2-docs/src/Command.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use client';

import {CopyButton} from './CopyButton';
import React from 'react';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

const container = style({
backgroundColor: 'layer-1',
marginY: 20,
borderRadius: 'xl',
display: 'flex',
flexDirection: 'column'
});

const codeWrap = style({
padding: 16
});

const codeContainer = style({
display: 'flex',
alignItems: 'center',
gap: 12,
padding: 4
});

const preStyle = style({
font: {default: 'code-xs', lg: 'code-sm'},
overflowX: 'auto',
paddingY: 8,
paddingX: 0,
margin: 0,
whiteSpace: 'pre',
flex: 1,
minWidth: 0
});

export interface CommandProps {
/** The command to display. */
command: string,
/** Optional label preceding the code block. */
label?: string
}

export function Command({command, label}: CommandProps) {
return (
<div className={container} data-example-switcher>
<div className={codeWrap}>
{label && <div className={style({font: 'body-sm', marginBottom: 8, color: 'body'})}>{label}</div>}
<div className={codeContainer}>
<pre className={preStyle}>{command}</pre>
<CopyButton ariaLabel="Copy command" tooltip="Copy command" text={command} />
</div>
</div>
</div>
);
}

export default Command;
Loading
Loading