@atomixstudio/mcp 0.1.1 → 1.0.1
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 +72 -288
- package/dist/index.d.ts +1 -201
- package/dist/index.js +1288 -2740
- package/dist/index.js.map +1 -1
- package/package.json +31 -32
- package/data/component-tokens-snapshot.json +0 -659
- package/data/tenants/default.json +0 -73
- package/scripts/sync-component-tokens.cjs +0 -974
- package/scripts/sync-component-tokens.js +0 -678
- package/src/ai-rules-generator.ts +0 -1144
- package/src/component-tokens.ts +0 -702
- package/src/index.ts +0 -1155
- package/src/tenant-store.ts +0 -436
- package/src/tokens.ts +0 -208
- package/src/user-tokens.ts +0 -268
- package/src/utils.ts +0 -465
- package/tests/stress-test.cjs +0 -907
- package/tsconfig.json +0 -21
- package/tsup.config.ts +0 -16
package/src/user-tokens.ts
DELETED
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Tokens Fetcher
|
|
3
|
-
* -------------------
|
|
4
|
-
* Fetches user-specific design system tokens from Atomix API.
|
|
5
|
-
*
|
|
6
|
-
* Used when MCP server is run with --ds-id flag to serve a user's
|
|
7
|
-
* custom design system instead of Atomix's internal tokens.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// ============================================
|
|
11
|
-
// TYPES
|
|
12
|
-
// ============================================
|
|
13
|
-
|
|
14
|
-
export interface UserDesignSystem {
|
|
15
|
-
id: string;
|
|
16
|
-
name: string;
|
|
17
|
-
tokens: Record<string, unknown>;
|
|
18
|
-
governance?: {
|
|
19
|
-
rules: string[];
|
|
20
|
-
categories?: Record<string, string[]>;
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface FetchUserDSOptions {
|
|
25
|
-
/** User's design system ID */
|
|
26
|
-
dsId: string;
|
|
27
|
-
/** API key for authentication */
|
|
28
|
-
apiKey?: string;
|
|
29
|
-
/** Base URL for the Atomix API (default: https://atomix.design) */
|
|
30
|
-
baseUrl?: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface UserDSMeta {
|
|
34
|
-
id: string;
|
|
35
|
-
name: string;
|
|
36
|
-
publishedAt?: number;
|
|
37
|
-
updatedAt?: number;
|
|
38
|
-
version?: number;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface UserDSResponse {
|
|
42
|
-
success: boolean;
|
|
43
|
-
tokens?: Record<string, unknown>;
|
|
44
|
-
governance?: UserDesignSystem['governance'];
|
|
45
|
-
meta?: UserDSMeta;
|
|
46
|
-
error?: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ============================================
|
|
50
|
-
// API ENDPOINTS
|
|
51
|
-
// ============================================
|
|
52
|
-
|
|
53
|
-
const DEFAULT_BASE_URL = 'https://atomixstudio.eu';
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Fetch user's design system tokens from Atomix API
|
|
57
|
-
*
|
|
58
|
-
* @param options - Fetch options including dsId and apiKey
|
|
59
|
-
* @returns User's tokens and governance rules
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```ts
|
|
63
|
-
* const { tokens, governance } = await fetchUserDesignSystem({
|
|
64
|
-
* dsId: 'abc123',
|
|
65
|
-
* apiKey: 'user-api-key'
|
|
66
|
-
* });
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export async function fetchUserDesignSystem(
|
|
70
|
-
options: FetchUserDSOptions
|
|
71
|
-
): Promise<UserDSResponse> {
|
|
72
|
-
const { dsId, apiKey, baseUrl = DEFAULT_BASE_URL } = options;
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
const headers: Record<string, string> = {
|
|
76
|
-
'Content-Type': 'application/json',
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
if (apiKey) {
|
|
80
|
-
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Fetch tokens
|
|
84
|
-
const tokensResponse = await fetch(`${baseUrl}/api/ds/${dsId}/tokens`, {
|
|
85
|
-
method: 'GET',
|
|
86
|
-
headers,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
if (!tokensResponse.ok) {
|
|
90
|
-
const error = await tokensResponse.text();
|
|
91
|
-
return {
|
|
92
|
-
success: false,
|
|
93
|
-
error: `Failed to fetch tokens: ${tokensResponse.status} ${error}`,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const tokensData = await tokensResponse.json() as {
|
|
98
|
-
tokens?: Record<string, unknown>;
|
|
99
|
-
meta?: UserDSMeta;
|
|
100
|
-
} | Record<string, unknown>;
|
|
101
|
-
|
|
102
|
-
// Extract metadata
|
|
103
|
-
const meta: UserDSMeta | undefined = 'meta' in tokensData && tokensData.meta
|
|
104
|
-
? tokensData.meta as UserDSMeta
|
|
105
|
-
: undefined;
|
|
106
|
-
|
|
107
|
-
// Fetch governance rules
|
|
108
|
-
let governance: UserDesignSystem['governance'] | undefined;
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
const rulesResponse = await fetch(`${baseUrl}/api/ds/${dsId}/rules`, {
|
|
112
|
-
method: 'GET',
|
|
113
|
-
headers,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
if (rulesResponse.ok) {
|
|
117
|
-
const rulesData = await rulesResponse.json() as UserDesignSystem['governance'];
|
|
118
|
-
governance = rulesData;
|
|
119
|
-
}
|
|
120
|
-
} catch {
|
|
121
|
-
// Governance is optional, continue without it
|
|
122
|
-
console.error('[atomix-mcp] Could not fetch governance rules, continuing without them');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Extract tokens - handle both { tokens: {...} } and direct {...} formats
|
|
126
|
-
const tokens = 'tokens' in tokensData && tokensData.tokens
|
|
127
|
-
? tokensData.tokens as Record<string, unknown>
|
|
128
|
-
: tokensData as Record<string, unknown>;
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
success: true,
|
|
132
|
-
tokens,
|
|
133
|
-
governance,
|
|
134
|
-
meta,
|
|
135
|
-
};
|
|
136
|
-
} catch (error) {
|
|
137
|
-
return {
|
|
138
|
-
success: false,
|
|
139
|
-
error: `Network error: ${error instanceof Error ? error.message : String(error)}`,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Validate API key format
|
|
146
|
-
*/
|
|
147
|
-
export function isValidApiKey(key: unknown): key is string {
|
|
148
|
-
if (typeof key !== 'string') return false;
|
|
149
|
-
// API keys should be at least 20 characters (UUID-ish)
|
|
150
|
-
return key.length >= 20;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Validate design system ID format
|
|
155
|
-
*/
|
|
156
|
-
export function isValidDsId(id: unknown): id is string {
|
|
157
|
-
if (typeof id !== 'string') return false;
|
|
158
|
-
// DS IDs should be non-empty strings
|
|
159
|
-
return id.length > 0;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// ============================================
|
|
163
|
-
// CLI ARGUMENT PARSING
|
|
164
|
-
// ============================================
|
|
165
|
-
|
|
166
|
-
export interface CLIArgs {
|
|
167
|
-
/** User's design system ID */
|
|
168
|
-
dsId?: string;
|
|
169
|
-
/** API key for authentication */
|
|
170
|
-
apiKey?: string;
|
|
171
|
-
/** Tenant ID (legacy, mapped to dsId) */
|
|
172
|
-
tenant?: string;
|
|
173
|
-
/** Base URL for the Atomix API */
|
|
174
|
-
baseUrl?: string;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Parse command line arguments for user DS mode
|
|
179
|
-
*
|
|
180
|
-
* Supported args:
|
|
181
|
-
* - --ds-id <id>: User's design system ID
|
|
182
|
-
* - --api-key <key>: API key for authentication
|
|
183
|
-
* - --tenant <id>: Legacy tenant ID (mapped to dsId)
|
|
184
|
-
* - --base-url <url>: Custom API base URL
|
|
185
|
-
*
|
|
186
|
-
* @param argv - Command line arguments (default: process.argv)
|
|
187
|
-
* @returns Parsed CLI arguments
|
|
188
|
-
*/
|
|
189
|
-
export function parseCLIArgs(argv: string[] = process.argv): CLIArgs {
|
|
190
|
-
const args: CLIArgs = {};
|
|
191
|
-
|
|
192
|
-
for (let i = 0; i < argv.length; i++) {
|
|
193
|
-
const arg = argv[i];
|
|
194
|
-
const next = argv[i + 1];
|
|
195
|
-
|
|
196
|
-
switch (arg) {
|
|
197
|
-
case '--ds-id':
|
|
198
|
-
if (next && !next.startsWith('--')) {
|
|
199
|
-
args.dsId = next;
|
|
200
|
-
i++;
|
|
201
|
-
}
|
|
202
|
-
break;
|
|
203
|
-
|
|
204
|
-
case '--api-key':
|
|
205
|
-
if (next && !next.startsWith('--')) {
|
|
206
|
-
args.apiKey = next;
|
|
207
|
-
i++;
|
|
208
|
-
}
|
|
209
|
-
break;
|
|
210
|
-
|
|
211
|
-
case '--tenant':
|
|
212
|
-
// Legacy support: map tenant to dsId
|
|
213
|
-
if (next && !next.startsWith('--')) {
|
|
214
|
-
args.tenant = next;
|
|
215
|
-
args.dsId = args.dsId || next;
|
|
216
|
-
i++;
|
|
217
|
-
}
|
|
218
|
-
break;
|
|
219
|
-
|
|
220
|
-
case '--base-url':
|
|
221
|
-
if (next && !next.startsWith('--')) {
|
|
222
|
-
args.baseUrl = next;
|
|
223
|
-
i++;
|
|
224
|
-
}
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return args;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Check if CLI args indicate user DS mode
|
|
234
|
-
*/
|
|
235
|
-
export function isUserDSMode(args: CLIArgs): boolean {
|
|
236
|
-
return Boolean(args.dsId);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// ============================================
|
|
240
|
-
// TOKEN TRANSFORMATION
|
|
241
|
-
// ============================================
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Transform user DS tokens to match the structure expected by MCP server.
|
|
245
|
-
*
|
|
246
|
-
* User DS tokens come in the StoredDesignSystem format from InstantDB.
|
|
247
|
-
* This transforms them to the flat primitives structure used by MCP tools.
|
|
248
|
-
*
|
|
249
|
-
* @param userTokens - User's tokens from InstantDB
|
|
250
|
-
* @returns Tokens in MCP-compatible format
|
|
251
|
-
*/
|
|
252
|
-
export function transformUserTokens(
|
|
253
|
-
userTokens: Record<string, unknown>
|
|
254
|
-
): Record<string, unknown> {
|
|
255
|
-
// If tokens are already in the right format, return as-is
|
|
256
|
-
if (userTokens.colors && userTokens.typography && userTokens.spacing) {
|
|
257
|
-
return userTokens;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// If tokens have a 'tokens' wrapper, unwrap it
|
|
261
|
-
if (typeof userTokens.tokens === 'object' && userTokens.tokens !== null) {
|
|
262
|
-
return userTokens.tokens as Record<string, unknown>;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Return as-is and let the MCP tools handle the structure
|
|
266
|
-
return userTokens;
|
|
267
|
-
}
|
|
268
|
-
|