@movable/ui-mcp 1.0.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 +158 -0
- package/data/categories.json +49 -0
- package/data/components.json +218 -0
- package/data/eslint-rules.json +7 -0
- package/data/stories.json +800 -0
- package/data/theme.json +68 -0
- package/data/tokens.json +892 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +667 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# @movable/ui-mcp
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server that exposes @movable/ui component information to AI assistants.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
Run the MCP server directly without installation:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @movable/ui-mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
This server allows AI coding assistants like Claude Code, Cursor, and others to discover and understand the components available in @movable/ui without manually searching through source files.
|
|
16
|
+
|
|
17
|
+
## Available Tools
|
|
18
|
+
|
|
19
|
+
| Tool | Description |
|
|
20
|
+
|------|-------------|
|
|
21
|
+
| `list_components` | Lists all exported components from @movable/ui |
|
|
22
|
+
| `get_component` | Gets detailed info for a specific component (props, JSDoc) |
|
|
23
|
+
| `get_theme` | Gets theme configuration (palette, typography, component overrides) |
|
|
24
|
+
| `get_design_tokens` | Gets design tokens by category with resolved hex values |
|
|
25
|
+
| `get_component_example` | Gets code examples from Storybook stories |
|
|
26
|
+
| `search_components` | Searches components by keyword or category |
|
|
27
|
+
| `get_eslint_rules` | Gets available ESLint rules from @movable/ui/eslint-plugin |
|
|
28
|
+
|
|
29
|
+
## Configuration
|
|
30
|
+
|
|
31
|
+
### Claude Code
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
claude mcp add movable-ui -- npx -y @movable/ui-mcp
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then restart Claude Code and run `/mcp` to verify the server is connected.
|
|
38
|
+
|
|
39
|
+
#### Auto-approve MCP Tools
|
|
40
|
+
|
|
41
|
+
By default, Claude Code will ask for permission each time an MCP tool is used. To auto-approve all movable-ui tools, add to your `~/.claude/settings.json`:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"permissions": {
|
|
46
|
+
"allow": [
|
|
47
|
+
"mcp__movable-ui__*"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### VS Code / Cursor
|
|
54
|
+
|
|
55
|
+
Add to `.vscode/mcp.json` in your project:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"servers": {
|
|
60
|
+
"movable-ui": {
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": ["-y", "@movable/ui-mcp"]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Local Development
|
|
69
|
+
|
|
70
|
+
If you're developing the MCP server itself:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Clone the repo
|
|
74
|
+
git clone git@github.com:movableink/ui.git
|
|
75
|
+
cd ui/mcp-server
|
|
76
|
+
|
|
77
|
+
# Install dependencies
|
|
78
|
+
npm install
|
|
79
|
+
|
|
80
|
+
# Extract data and build
|
|
81
|
+
npm run build
|
|
82
|
+
|
|
83
|
+
# Run locally
|
|
84
|
+
npm start
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Development Scripts
|
|
88
|
+
|
|
89
|
+
| Script | Description |
|
|
90
|
+
|--------|-------------|
|
|
91
|
+
| `npm run extract-data` | Extract component/token data from source files |
|
|
92
|
+
| `npm run build` | Extract data and compile TypeScript |
|
|
93
|
+
| `npm run dev` | Watch mode for TypeScript compilation |
|
|
94
|
+
| `npm start` | Run the compiled server |
|
|
95
|
+
|
|
96
|
+
### How It Works
|
|
97
|
+
|
|
98
|
+
The MCP server operates in two modes:
|
|
99
|
+
|
|
100
|
+
1. **npx mode (bundled data)**: When installed via npx, the server uses pre-extracted JSON data files bundled with the package. This allows it to run anywhere without access to the source repo.
|
|
101
|
+
|
|
102
|
+
2. **Local development mode**: When running from a cloned repo, the server can read directly from source files for the most up-to-date information.
|
|
103
|
+
|
|
104
|
+
### Data Extraction
|
|
105
|
+
|
|
106
|
+
The `extract-data` script parses the UI source files and generates:
|
|
107
|
+
|
|
108
|
+
- `data/components.json` - Component metadata and props
|
|
109
|
+
- `data/tokens.json` - Design tokens with resolved hex values
|
|
110
|
+
- `data/theme.json` - Theme configuration
|
|
111
|
+
- `data/stories.json` - Storybook story metadata
|
|
112
|
+
- `data/categories.json` - Component categories
|
|
113
|
+
- `data/eslint-rules.json` - ESLint rule metadata
|
|
114
|
+
|
|
115
|
+
## Testing
|
|
116
|
+
|
|
117
|
+
Test the server manually using JSON-RPC over stdin:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Initialize
|
|
121
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' | npx @movable/ui-mcp
|
|
122
|
+
|
|
123
|
+
# List tools
|
|
124
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | npx @movable/ui-mcp
|
|
125
|
+
|
|
126
|
+
# Call a tool
|
|
127
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_design_tokens","arguments":{"category":"blue"}}}' | npx @movable/ui-mcp
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Publishing
|
|
131
|
+
|
|
132
|
+
The package is published to npm as `@movable/ui-mcp` via GitHub Actions.
|
|
133
|
+
|
|
134
|
+
### Automatic Publishing
|
|
135
|
+
|
|
136
|
+
The MCP server is automatically published when changes are pushed to `main` in:
|
|
137
|
+
- `mcp-server/src/**/*.ts` - MCP server source
|
|
138
|
+
- `mcp-server/scripts/**/*.ts` - Data extraction scripts
|
|
139
|
+
- `src/components/**/*` - UI components (affects extracted data)
|
|
140
|
+
- `src/theme/**/*.ts` - Theme definitions (affects extracted data)
|
|
141
|
+
- `stories/**/*.stories.tsx` - Storybook stories (affects extracted data)
|
|
142
|
+
- `eslint-plugin-ui/src/rules/**/*.ts` - ESLint rules (affects extracted data)
|
|
143
|
+
|
|
144
|
+
### Manual Publishing
|
|
145
|
+
|
|
146
|
+
To manually trigger a release:
|
|
147
|
+
|
|
148
|
+
1. Go to [Actions > Release MCP Server to NPM](https://github.com/movableink/ui/actions/workflows/release-mcp-server.yml)
|
|
149
|
+
2. Click "Run workflow"
|
|
150
|
+
3. Select release type (release or prerelease)
|
|
151
|
+
4. Optionally override the version increment
|
|
152
|
+
|
|
153
|
+
> **Note:** Do not publish manually via `npm publish`. Always use the GitHub Action to ensure consistent releases.
|
|
154
|
+
|
|
155
|
+
## Related
|
|
156
|
+
|
|
157
|
+
- [GitHub Issue #501](https://github.com/movableink/ui/issues/501) - npx support implementation
|
|
158
|
+
- [GitHub Issue #500](https://github.com/movableink/ui/issues/500) - Design tokens hex value resolution
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"inputs": [
|
|
3
|
+
"InkTextField",
|
|
4
|
+
"InkSelect",
|
|
5
|
+
"InkCheckboxGroup",
|
|
6
|
+
"InkRadioGroup",
|
|
7
|
+
"InkSwitch",
|
|
8
|
+
"InkRadioTiles"
|
|
9
|
+
],
|
|
10
|
+
"toggles": [
|
|
11
|
+
"InkToggleText",
|
|
12
|
+
"InkToggleTextGroup",
|
|
13
|
+
"InkToggleIcon",
|
|
14
|
+
"InkToggleIconGroup"
|
|
15
|
+
],
|
|
16
|
+
"feedback": [
|
|
17
|
+
"InkSnackbar",
|
|
18
|
+
"InkHighlightAlert",
|
|
19
|
+
"InkEmptyState"
|
|
20
|
+
],
|
|
21
|
+
"layout": [
|
|
22
|
+
"InkPaper",
|
|
23
|
+
"InkCard",
|
|
24
|
+
"InkDrawer",
|
|
25
|
+
"InkPersistentFilterDrawer"
|
|
26
|
+
],
|
|
27
|
+
"dialogs": [
|
|
28
|
+
"InkDialog"
|
|
29
|
+
],
|
|
30
|
+
"headers": [
|
|
31
|
+
"InkPageHeader",
|
|
32
|
+
"InkWorkflowHeader",
|
|
33
|
+
"HeaderMetadata",
|
|
34
|
+
"HeaderSubtitle",
|
|
35
|
+
"LinkBreadcrumbs",
|
|
36
|
+
"PageHeaderActionButtons"
|
|
37
|
+
],
|
|
38
|
+
"data-display": [
|
|
39
|
+
"InkDataGrid",
|
|
40
|
+
"InkDataGridEmpty",
|
|
41
|
+
"InkAttributeList",
|
|
42
|
+
"InkImage",
|
|
43
|
+
"InkChart"
|
|
44
|
+
],
|
|
45
|
+
"chips": [
|
|
46
|
+
"InkChip",
|
|
47
|
+
"InkChipGroup"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "DemoComponent",
|
|
4
|
+
"exportName": "DemoComponent",
|
|
5
|
+
"path": "src/components/DemoComponent",
|
|
6
|
+
"props": "type DemoComponentProps = {\n stringToDisplay: string;\n}"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "InkChip",
|
|
10
|
+
"exportName": "InkChip",
|
|
11
|
+
"path": "src/components/Chip",
|
|
12
|
+
"category": "chips"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "InkChipGroup",
|
|
16
|
+
"exportName": "InkChipGroup",
|
|
17
|
+
"path": "src/components/ChipGroup",
|
|
18
|
+
"category": "chips"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "InkDialog",
|
|
22
|
+
"exportName": "InkDialog",
|
|
23
|
+
"path": "src/components/Dialog",
|
|
24
|
+
"category": "dialogs"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "InkPersistentFilterDrawer",
|
|
28
|
+
"exportName": "InkPersistentFilterDrawer",
|
|
29
|
+
"path": "src/components/PersistentFilterDrawer",
|
|
30
|
+
"category": "layout"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "HeaderMetadata",
|
|
34
|
+
"exportName": "HeaderMetadata",
|
|
35
|
+
"path": "src/components/Header",
|
|
36
|
+
"category": "headers"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "LinkBreadcrumbs",
|
|
40
|
+
"exportName": "LinkBreadcrumbs",
|
|
41
|
+
"path": "src/components/Header",
|
|
42
|
+
"category": "headers"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "InkPageHeader",
|
|
46
|
+
"exportName": "InkPageHeader",
|
|
47
|
+
"path": "src/components/Header",
|
|
48
|
+
"category": "headers"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "InkWorkflowHeader",
|
|
52
|
+
"exportName": "InkWorkflowHeader",
|
|
53
|
+
"path": "src/components/Header",
|
|
54
|
+
"category": "headers"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "PageHeaderActionButtons",
|
|
58
|
+
"exportName": "PageHeaderActionButtons",
|
|
59
|
+
"path": "src/components/Header",
|
|
60
|
+
"category": "headers"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "HeaderSubtitle",
|
|
64
|
+
"exportName": "HeaderSubtitle",
|
|
65
|
+
"path": "src/components/Header",
|
|
66
|
+
"category": "headers"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "InkPaper",
|
|
70
|
+
"exportName": "InkPaper",
|
|
71
|
+
"path": "src/components/surfaces",
|
|
72
|
+
"category": "layout"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "InkRadioTiles",
|
|
76
|
+
"exportName": "InkRadioTiles",
|
|
77
|
+
"path": "src/components/InkRadioTiles",
|
|
78
|
+
"category": "inputs"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "InkToggleText",
|
|
82
|
+
"exportName": "InkToggleText",
|
|
83
|
+
"path": "src/components/InkToggleText",
|
|
84
|
+
"category": "toggles"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "InkToggleTextGroup",
|
|
88
|
+
"exportName": "InkToggleTextGroup",
|
|
89
|
+
"path": "src/components/InkToggleTextGroup",
|
|
90
|
+
"category": "toggles"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "InkToggleIcon",
|
|
94
|
+
"exportName": "InkToggleIcon",
|
|
95
|
+
"path": "src/components/InkToggleIcon",
|
|
96
|
+
"category": "toggles"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "InkToggleIconGroup",
|
|
100
|
+
"exportName": "InkToggleIconGroup",
|
|
101
|
+
"path": "src/components/InkToggleIconGroup",
|
|
102
|
+
"category": "toggles"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "InkEmptyState",
|
|
106
|
+
"exportName": "InkEmptyState",
|
|
107
|
+
"path": "src/components/InkEmptyState",
|
|
108
|
+
"category": "feedback"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "InkAttributeList",
|
|
112
|
+
"exportName": "InkAttributeList",
|
|
113
|
+
"path": "src/components/InkAttributeList",
|
|
114
|
+
"category": "data-display"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "InkImage",
|
|
118
|
+
"exportName": "InkImage",
|
|
119
|
+
"path": "src/components/InkImage",
|
|
120
|
+
"category": "data-display"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"name": "InkDrawer",
|
|
124
|
+
"exportName": "InkDrawer",
|
|
125
|
+
"path": "src/components/InkDrawer",
|
|
126
|
+
"category": "layout"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "InkSnackbar",
|
|
130
|
+
"exportName": "* (barrel export)",
|
|
131
|
+
"path": "src/components/InkSnackbar"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"name": "InkCheckboxGroup",
|
|
135
|
+
"exportName": "* (barrel export)",
|
|
136
|
+
"path": "src/components/InkCheckboxGroup"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"name": "InkRadioGroup",
|
|
140
|
+
"exportName": "* (barrel export)",
|
|
141
|
+
"path": "src/components/InkRadioGroup"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "InkSwitch",
|
|
145
|
+
"exportName": "* (barrel export)",
|
|
146
|
+
"path": "src/components/InkSwitch"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "InkTextField",
|
|
150
|
+
"exportName": "* (barrel export)",
|
|
151
|
+
"path": "src/components/InkTextField"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"name": "InkSelect",
|
|
155
|
+
"exportName": "* (barrel export)",
|
|
156
|
+
"path": "src/components/InkSelect"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"name": "InternalUseOnlyLabel",
|
|
160
|
+
"exportName": "InternalUseOnlyLabel",
|
|
161
|
+
"path": "src/components/InternalUseOnlyIndicators"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "InternalUseOnlyAlert",
|
|
165
|
+
"exportName": "InternalUseOnlyAlert",
|
|
166
|
+
"path": "src/components/InternalUseOnlyIndicators"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"name": "InkChart",
|
|
170
|
+
"exportName": "InkChart",
|
|
171
|
+
"path": "src/components/InkChart",
|
|
172
|
+
"category": "data-display"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"name": "InkCard",
|
|
176
|
+
"exportName": "InkCard",
|
|
177
|
+
"path": "src/components/InkCard",
|
|
178
|
+
"category": "layout"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"name": "InkGridToolBar",
|
|
182
|
+
"exportName": "InkGridToolBar",
|
|
183
|
+
"path": "src/components/InkGridToolBar"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"name": "InkDataGrid",
|
|
187
|
+
"exportName": "InkDataGrid",
|
|
188
|
+
"path": "src/components/InkDataGrid",
|
|
189
|
+
"category": "data-display"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"name": "InkDataGridEmpty",
|
|
193
|
+
"exportName": "InkDataGridEmpty",
|
|
194
|
+
"path": "src/components/InkDataGrid",
|
|
195
|
+
"category": "data-display"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"name": "InkDataGridTextWrapCell",
|
|
199
|
+
"exportName": "InkDataGridTextWrapCell",
|
|
200
|
+
"path": "src/components/InkDataGrid"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"name": "createEmptyColumns",
|
|
204
|
+
"exportName": "createEmptyColumns",
|
|
205
|
+
"path": "src/components/InkDataGrid"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"name": "createTextWrapColumn",
|
|
209
|
+
"exportName": "createTextWrapColumn",
|
|
210
|
+
"path": "src/components/InkDataGrid"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "InkHighlightAlert",
|
|
214
|
+
"exportName": "InkHighlightAlert",
|
|
215
|
+
"path": "src/components/Alert",
|
|
216
|
+
"category": "feedback"
|
|
217
|
+
}
|
|
218
|
+
]
|