myoperator-mcp 0.0.3 → 0.0.5

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.
Files changed (3) hide show
  1. package/README.md +49 -1
  2. package/dist/index.js +446 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -14,7 +14,12 @@ npx myoperator-mcp
14
14
 
15
15
  ### Cursor (One-Click Install)
16
16
 
17
- [**Install in Cursor**](cursor://anysphere.cursor-deeplink/mcp/install?name=myoperator&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm15b3BlcmF0b3ItbWNwIl19)
17
+ [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.png)](cursor://anysphere.cursor-deeplink/mcp/install?name=myoperator&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm15b3BlcmF0b3ItbWNwIl19)
18
+
19
+ > **Note:** The button above works when viewing this README locally or in an app that supports `cursor://` links. If it doesn't work, copy this link and paste in your browser:
20
+ > ```
21
+ > cursor://anysphere.cursor-deeplink/mcp/install?name=myoperator&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm15b3BlcmF0b3ItbWNwIl19
22
+ > ```
18
23
 
19
24
  Or manually edit `~/.cursor/mcp.json`:
20
25
 
@@ -96,8 +101,10 @@ Or use Command Palette → "MCP: Add Server"
96
101
  | `list-components` | List all available components with descriptions |
97
102
  | `get-component-metadata` | Get props, variants, dependencies for a component |
98
103
  | `get-component-examples` | Get React code examples |
104
+ | `get-component-source` | **NEW** Get full source code (copy/paste ready) |
99
105
  | `list-design-tokens` | List design tokens (colors, spacing, radius, typography) |
100
106
  | `get-component-accessibility` | Get accessibility guidelines and ARIA attributes |
107
+ | `get-installation-info` | **NEW** Get npm package info and setup instructions |
101
108
 
102
109
  ---
103
110
 
@@ -143,6 +150,20 @@ Once installed, ask your AI assistant:
143
150
 
144
151
  > "What keyboard shortcuts does the Table support?"
145
152
 
153
+ ### Source Code (NEW)
154
+
155
+ > "Give me the full Button component source code"
156
+
157
+ > "Get the utils.ts file I need"
158
+
159
+ > "Get the CSS styles for the design system"
160
+
161
+ ### Installation
162
+
163
+ > "How do I install myOperator UI?"
164
+
165
+ > "What are the dependencies I need?"
166
+
146
167
  ---
147
168
 
148
169
  ## Components
@@ -221,6 +242,33 @@ Output: {
221
242
  }
222
243
  ```
223
244
 
245
+ ### `get-component-source`
246
+
247
+ Get full source code for a component (copy/paste ready).
248
+
249
+ ```
250
+ Input: { componentName: "button" } // or "utils" or "css"
251
+ Output: {
252
+ component, file path, dependencies,
253
+ installCommand,
254
+ sourceCode (full implementation)
255
+ }
256
+ ```
257
+
258
+ ### `get-installation-info`
259
+
260
+ Get npm package info and setup instructions.
261
+
262
+ ```
263
+ Input: (none)
264
+ Output: {
265
+ packageName, npmUrl,
266
+ quickStart commands,
267
+ manualInstallation steps,
268
+ dependencies
269
+ }
270
+ ```
271
+
224
272
  ---
225
273
 
226
274
  ## Development
package/dist/index.js CHANGED
@@ -7,6 +7,266 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
7
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
8
 
9
9
  // src/data/metadata.ts
10
+ var componentSourceCode = {
11
+ button: `import * as React from "react"
12
+ import { Slot } from "@radix-ui/react-slot"
13
+ import { cva, type VariantProps } from "class-variance-authority"
14
+ import { Loader2 } from "lucide-react"
15
+
16
+ import { cn } from "@/lib/utils"
17
+
18
+ const buttonVariants = cva(
19
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
20
+ {
21
+ variants: {
22
+ variant: {
23
+ default: "bg-[#343E55] text-white hover:bg-[#343E55]/90",
24
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
25
+ outline: "border border-[#343E55] bg-transparent text-[#343E55] hover:bg-[#343E55] hover:text-white",
26
+ secondary: "bg-[#343E55]/20 text-[#343E55] hover:bg-[#343E55]/30",
27
+ ghost: "hover:bg-[#343E55]/10 hover:text-[#343E55]",
28
+ link: "text-[#343E55] underline-offset-4 hover:underline",
29
+ },
30
+ size: {
31
+ default: "py-2.5 px-4",
32
+ sm: "py-2 px-3 text-xs",
33
+ lg: "py-3 px-6",
34
+ icon: "p-2.5",
35
+ },
36
+ },
37
+ defaultVariants: {
38
+ variant: "default",
39
+ size: "default",
40
+ },
41
+ }
42
+ )
43
+
44
+ export interface ButtonProps
45
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
46
+ VariantProps<typeof buttonVariants> {
47
+ asChild?: boolean
48
+ leftIcon?: React.ReactNode
49
+ rightIcon?: React.ReactNode
50
+ loading?: boolean
51
+ loadingText?: string
52
+ }
53
+
54
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
55
+ ({ className, variant, size, asChild = false, leftIcon, rightIcon, loading = false, loadingText, children, disabled, ...props }, ref) => {
56
+ const Comp = asChild ? Slot : "button"
57
+ return (
58
+ <Comp
59
+ className={cn(buttonVariants({ variant, size, className }))}
60
+ ref={ref}
61
+ disabled={disabled || loading}
62
+ {...props}
63
+ >
64
+ {loading ? (
65
+ <>
66
+ <Loader2 className="animate-spin" />
67
+ {loadingText || children}
68
+ </>
69
+ ) : (
70
+ <>
71
+ {leftIcon}
72
+ {children}
73
+ {rightIcon}
74
+ </>
75
+ )}
76
+ </Comp>
77
+ )
78
+ }
79
+ )
80
+ Button.displayName = "Button"
81
+
82
+ export { Button, buttonVariants }`,
83
+ badge: `import * as React from "react"
84
+ import { cva, type VariantProps } from "class-variance-authority"
85
+
86
+ import { cn } from "@/lib/utils"
87
+
88
+ const badgeVariants = cva(
89
+ "inline-flex items-center justify-center rounded-full text-sm font-semibold transition-colors whitespace-nowrap",
90
+ {
91
+ variants: {
92
+ variant: {
93
+ active: "bg-[#E5FFF5] text-[#00A651]",
94
+ failed: "bg-[#FFECEC] text-[#FF3B3B]",
95
+ disabled: "bg-[#F3F5F6] text-[#6B7280]",
96
+ default: "bg-[#F3F5F6] text-[#333333]",
97
+ },
98
+ size: {
99
+ default: "px-3 py-1",
100
+ sm: "px-2 py-0.5 text-xs",
101
+ lg: "px-4 py-1.5",
102
+ },
103
+ },
104
+ defaultVariants: {
105
+ variant: "default",
106
+ size: "default",
107
+ },
108
+ }
109
+ )
110
+
111
+ export interface BadgeProps
112
+ extends React.HTMLAttributes<HTMLDivElement>,
113
+ VariantProps<typeof badgeVariants> {
114
+ leftIcon?: React.ReactNode
115
+ rightIcon?: React.ReactNode
116
+ }
117
+
118
+ const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
119
+ ({ className, variant, size, leftIcon, rightIcon, children, ...props }, ref) => {
120
+ return (
121
+ <div
122
+ className={cn(badgeVariants({ variant, size, className }), "gap-1")}
123
+ ref={ref}
124
+ {...props}
125
+ >
126
+ {leftIcon && <span className="[&_svg]:size-3">{leftIcon}</span>}
127
+ {children}
128
+ {rightIcon && <span className="[&_svg]:size-3">{rightIcon}</span>}
129
+ </div>
130
+ )
131
+ }
132
+ )
133
+ Badge.displayName = "Badge"
134
+
135
+ export { Badge, badgeVariants }`,
136
+ tag: `import * as React from "react"
137
+ import { cva, type VariantProps } from "class-variance-authority"
138
+
139
+ import { cn } from "@/lib/utils"
140
+
141
+ const tagVariants = cva(
142
+ "inline-flex items-center justify-center rounded text-sm transition-colors",
143
+ {
144
+ variants: {
145
+ variant: {
146
+ default: "bg-[#F3F4F6] text-[#333333]",
147
+ primary: "bg-[#343E55]/10 text-[#343E55]",
148
+ secondary: "bg-[#E5E7EB] text-[#374151]",
149
+ success: "bg-[#E5FFF5] text-[#00A651]",
150
+ warning: "bg-[#FFF8E5] text-[#F59E0B]",
151
+ error: "bg-[#FFECEC] text-[#FF3B3B]",
152
+ },
153
+ size: {
154
+ default: "px-2 py-1",
155
+ sm: "px-1.5 py-0.5 text-xs",
156
+ lg: "px-3 py-1.5",
157
+ },
158
+ interactive: {
159
+ true: "cursor-pointer hover:bg-[#E5E7EB] active:bg-[#D1D5DB]",
160
+ false: "",
161
+ },
162
+ selected: {
163
+ true: "ring-2 ring-[#343E55] ring-offset-1",
164
+ false: "",
165
+ },
166
+ },
167
+ defaultVariants: {
168
+ variant: "default",
169
+ size: "default",
170
+ interactive: false,
171
+ selected: false,
172
+ },
173
+ }
174
+ )
175
+
176
+ export interface TagProps
177
+ extends React.HTMLAttributes<HTMLSpanElement>,
178
+ VariantProps<typeof tagVariants> {
179
+ label?: string
180
+ interactive?: boolean
181
+ selected?: boolean
182
+ }
183
+
184
+ const Tag = React.forwardRef<HTMLSpanElement, TagProps>(
185
+ ({ className, variant, size, interactive, selected, label, children, ...props }, ref) => {
186
+ return (
187
+ <span
188
+ className={cn(tagVariants({ variant, size, interactive, selected, className }))}
189
+ ref={ref}
190
+ role={interactive ? "button" : undefined}
191
+ tabIndex={interactive ? 0 : undefined}
192
+ aria-selected={selected}
193
+ {...props}
194
+ >
195
+ {label && <span className="font-semibold mr-1">{label}</span>}
196
+ <span className="font-normal">{children}</span>
197
+ </span>
198
+ )
199
+ }
200
+ )
201
+ Tag.displayName = "Tag"
202
+
203
+ export { Tag, tagVariants }`
204
+ };
205
+ var utilsSourceCode = `import { type ClassValue, clsx } from "clsx"
206
+ import { twMerge } from "tailwind-merge"
207
+
208
+ export function cn(...inputs: ClassValue[]) {
209
+ return twMerge(clsx(inputs))
210
+ }`;
211
+ var cssStyles = `@tailwind base;
212
+ @tailwind components;
213
+ @tailwind utilities;
214
+
215
+ @layer base {
216
+ :root {
217
+ --background: 0 0% 100%;
218
+ --foreground: 222.2 84% 4.9%;
219
+ --card: 0 0% 100%;
220
+ --card-foreground: 222.2 84% 4.9%;
221
+ --popover: 0 0% 100%;
222
+ --popover-foreground: 222.2 84% 4.9%;
223
+ --primary: 222.2 47.4% 11.2%;
224
+ --primary-foreground: 210 40% 98%;
225
+ --secondary: 210 40% 96.1%;
226
+ --secondary-foreground: 222.2 47.4% 11.2%;
227
+ --muted: 210 40% 96.1%;
228
+ --muted-foreground: 215.4 16.3% 46.9%;
229
+ --accent: 210 40% 96.1%;
230
+ --accent-foreground: 222.2 47.4% 11.2%;
231
+ --destructive: 0 84.2% 60.2%;
232
+ --destructive-foreground: 210 40% 98%;
233
+ --border: 214.3 31.8% 91.4%;
234
+ --input: 214.3 31.8% 91.4%;
235
+ --ring: 222.2 84% 4.9%;
236
+ --radius: 0.5rem;
237
+ }
238
+
239
+ .dark {
240
+ --background: 222.2 84% 4.9%;
241
+ --foreground: 210 40% 98%;
242
+ --card: 222.2 84% 4.9%;
243
+ --card-foreground: 210 40% 98%;
244
+ --popover: 222.2 84% 4.9%;
245
+ --popover-foreground: 210 40% 98%;
246
+ --primary: 210 40% 98%;
247
+ --primary-foreground: 222.2 47.4% 11.2%;
248
+ --secondary: 217.2 32.6% 17.5%;
249
+ --secondary-foreground: 210 40% 98%;
250
+ --muted: 217.2 32.6% 17.5%;
251
+ --muted-foreground: 215 20.2% 65.1%;
252
+ --accent: 217.2 32.6% 17.5%;
253
+ --accent-foreground: 210 40% 98%;
254
+ --destructive: 0 62.8% 30.6%;
255
+ --destructive-foreground: 210 40% 98%;
256
+ --border: 217.2 32.6% 17.5%;
257
+ --input: 217.2 32.6% 17.5%;
258
+ --ring: 212.7 26.8% 83.9%;
259
+ }
260
+ }
261
+
262
+ @layer base {
263
+ * {
264
+ @apply border-border;
265
+ }
266
+ body {
267
+ @apply bg-background text-foreground;
268
+ }
269
+ }`;
10
270
  var componentMetadata = {
11
271
  button: {
12
272
  name: "Button",
@@ -1276,17 +1536,202 @@ function registerGetComponentAccessibility(server) {
1276
1536
  );
1277
1537
  }
1278
1538
 
1539
+ // src/server/tools/get-component-source.ts
1540
+ import { z as z5 } from "zod";
1541
+ function registerGetComponentSource(server) {
1542
+ server.tool(
1543
+ "get-component-source",
1544
+ "Get the full source code for a myOperator UI component (copy/paste ready)",
1545
+ {
1546
+ componentName: z5.string().describe(
1547
+ "The name of the component (e.g., 'button', 'badge', 'tag') or 'utils' for the cn() helper or 'css' for styles"
1548
+ )
1549
+ },
1550
+ async ({ componentName }) => {
1551
+ const name = componentName.toLowerCase();
1552
+ if (name === "utils" || name === "cn") {
1553
+ return {
1554
+ content: [
1555
+ {
1556
+ type: "text",
1557
+ text: JSON.stringify(
1558
+ {
1559
+ file: "lib/utils.ts",
1560
+ description: "Utility function for merging Tailwind classes",
1561
+ dependencies: ["clsx", "tailwind-merge"],
1562
+ installCommand: "npm install clsx tailwind-merge",
1563
+ sourceCode: utilsSourceCode
1564
+ },
1565
+ null,
1566
+ 2
1567
+ )
1568
+ }
1569
+ ]
1570
+ };
1571
+ }
1572
+ if (name === "css" || name === "styles") {
1573
+ return {
1574
+ content: [
1575
+ {
1576
+ type: "text",
1577
+ text: JSON.stringify(
1578
+ {
1579
+ file: "index.css",
1580
+ description: "CSS styles with Tailwind and design tokens",
1581
+ dependencies: ["tailwindcss"],
1582
+ sourceCode: cssStyles
1583
+ },
1584
+ null,
1585
+ 2
1586
+ )
1587
+ }
1588
+ ]
1589
+ };
1590
+ }
1591
+ const sourceCode = componentSourceCode[name];
1592
+ if (!sourceCode) {
1593
+ const availableComponents = [
1594
+ ...Object.keys(componentSourceCode),
1595
+ "utils",
1596
+ "css"
1597
+ ].join(", ");
1598
+ return {
1599
+ content: [
1600
+ {
1601
+ type: "text",
1602
+ text: `Error: Source code for "${componentName}" not found. Available: ${availableComponents}`
1603
+ }
1604
+ ],
1605
+ isError: true
1606
+ };
1607
+ }
1608
+ const dependenciesMap = {
1609
+ button: [
1610
+ "@radix-ui/react-slot",
1611
+ "class-variance-authority",
1612
+ "clsx",
1613
+ "tailwind-merge",
1614
+ "lucide-react"
1615
+ ],
1616
+ badge: ["class-variance-authority", "clsx", "tailwind-merge"],
1617
+ tag: ["class-variance-authority", "clsx", "tailwind-merge"]
1618
+ };
1619
+ const dependencies = dependenciesMap[name] || [];
1620
+ return {
1621
+ content: [
1622
+ {
1623
+ type: "text",
1624
+ text: JSON.stringify(
1625
+ {
1626
+ component: name,
1627
+ file: `components/ui/${name}.tsx`,
1628
+ dependencies,
1629
+ installCommand: dependencies.length > 0 ? `npm install ${dependencies.join(" ")}` : null,
1630
+ requiredFiles: [
1631
+ {
1632
+ path: "lib/utils.ts",
1633
+ note: "Required for cn() function - use get-component-source with 'utils' to get this file"
1634
+ }
1635
+ ],
1636
+ sourceCode
1637
+ },
1638
+ null,
1639
+ 2
1640
+ )
1641
+ }
1642
+ ]
1643
+ };
1644
+ }
1645
+ );
1646
+ }
1647
+
1648
+ // src/server/tools/get-installation-info.ts
1649
+ function registerGetInstallationInfo(server) {
1650
+ server.tool(
1651
+ "get-installation-info",
1652
+ "Get installation instructions and npm package info for myOperator UI",
1653
+ {},
1654
+ async () => {
1655
+ const installationInfo = {
1656
+ packageName: "myoperator-ui",
1657
+ npmUrl: "https://www.npmjs.com/package/myoperator-ui",
1658
+ description: "CLI for adding myOperator UI components to your project",
1659
+ quickStart: {
1660
+ step1: "npx myoperator-ui init",
1661
+ step2: "npx myoperator-ui add button",
1662
+ description: "Initialize project and add components via CLI"
1663
+ },
1664
+ manualInstallation: {
1665
+ description: "If you prefer to manually add components:",
1666
+ steps: [
1667
+ {
1668
+ step: 1,
1669
+ title: "Install dependencies",
1670
+ command: "npm install class-variance-authority clsx tailwind-merge"
1671
+ },
1672
+ {
1673
+ step: 2,
1674
+ title: "Create utils file",
1675
+ path: "lib/utils.ts",
1676
+ note: "Use get-component-source with 'utils' to get the code"
1677
+ },
1678
+ {
1679
+ step: 3,
1680
+ title: "Add CSS styles",
1681
+ path: "index.css or globals.css",
1682
+ note: "Use get-component-source with 'css' to get the styles"
1683
+ },
1684
+ {
1685
+ step: 4,
1686
+ title: "Copy component",
1687
+ path: "components/ui/[component].tsx",
1688
+ note: "Use get-component-source with component name to get the code"
1689
+ }
1690
+ ]
1691
+ },
1692
+ peerDependencies: {
1693
+ react: "^18.0.0",
1694
+ "react-dom": "^18.0.0",
1695
+ tailwindcss: "^3.4.0"
1696
+ },
1697
+ optionalDependencies: {
1698
+ "@radix-ui/react-slot": "For Button asChild prop",
1699
+ "@radix-ui/react-dropdown-menu": "For DropdownMenu component",
1700
+ "lucide-react": "For icons"
1701
+ },
1702
+ tailwindConfig: {
1703
+ note: "Add these to your tailwind.config.js",
1704
+ content: ["./components/**/*.{ts,tsx}"],
1705
+ plugins: ["tailwindcss-animate"]
1706
+ },
1707
+ repository: "https://github.com/Ankish8/storybook-npm",
1708
+ documentation: "https://storybook-npm.vercel.app"
1709
+ };
1710
+ return {
1711
+ content: [
1712
+ {
1713
+ type: "text",
1714
+ text: JSON.stringify(installationInfo, null, 2)
1715
+ }
1716
+ ]
1717
+ };
1718
+ }
1719
+ );
1720
+ }
1721
+
1279
1722
  // src/server/index.ts
1280
1723
  function createServer() {
1281
1724
  const server = new McpServer({
1282
1725
  name: "myoperator-mcp",
1283
- version: "0.0.1"
1726
+ version: "0.0.5"
1284
1727
  });
1285
1728
  registerListComponents(server);
1286
1729
  registerGetComponentMetadata(server);
1287
1730
  registerGetComponentExamples(server);
1731
+ registerGetComponentSource(server);
1288
1732
  registerListDesignTokens(server);
1289
1733
  registerGetComponentAccessibility(server);
1734
+ registerGetInstallationInfo(server);
1290
1735
  return server;
1291
1736
  }
1292
1737
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myoperator-mcp",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "MCP server for myOperator UI components - enables AI assistants to access component metadata, examples, and design tokens",
5
5
  "type": "module",
6
6
  "bin": "./dist/index.js",