@castandcrew/spotlight-mcp 0.1.4 → 0.1.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.
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  import { guardedIndex } from './_guard.js';
3
3
  export function registerGetToken(server) {
4
- server.tool('get_token', 'Get details for a Spotlight design token: its value, category, and which components use it.', { name: z.string().describe('Token name, e.g. "--space-md", "--color-background-positive"') }, async ({ name }) => {
4
+ server.tool('get_token', 'Get details for a Spotlight design token: its default (light/:root) value, category, which components use it, ' +
5
+ 'and its variants — the dark-theme value (.spotlight_theme-dark), interactive-state values, etc.', { name: z.string().describe('Token name, e.g. "--space-md", "--color-background-positive"') }, async ({ name }) => {
5
6
  const { index, error } = guardedIndex('get_token', 'tokens');
6
7
  if (error)
7
8
  return error;
@@ -1 +1 @@
1
- {"version":3,"file":"get_token.js","sourceRoot":"","sources":["../../src/tools/get_token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,IAAI,CACT,WAAW,EACX,6FAA6F,EAC7F,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC,EAAE,EAC7F,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC7D,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CACjD,CAAC;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,IAAI,yBAAyB,KAAK,CAAC,MAAM,CAAC,MAAM,wEAAwE,EAAE,CAAC;gBAC9K,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC3E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"get_token.js","sourceRoot":"","sources":["../../src/tools/get_token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,IAAI,CACT,WAAW,EACX,gHAAgH;QAChH,iGAAiG,EACjG,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC,EAAE,EAC7F,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC7D,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CACjD,CAAC;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,IAAI,yBAAyB,KAAK,CAAC,MAAM,CAAC,MAAM,wEAAwE,EAAE,CAAC;gBAC9K,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC3E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -4,30 +4,56 @@ import { guardedIndex } from './_guard.js';
4
4
  import { searchOrPerTerm } from './_fuzzy.js';
5
5
  import { expandWithSynonyms } from './_synonyms.js';
6
6
  export function registerSearchTokens(server) {
7
- server.tool('search_tokens', 'Search Spotlight design tokens by name, description, or category.', {
7
+ server.tool('search_tokens', 'Search Spotlight design tokens by name, description, category, or value (light and dark). ' +
8
+ 'Returns purpose-named semantic tokens; pass includeRefs to also get raw palette/scale steps.', {
8
9
  query: z.string().describe('Semantic description, e.g. "large spacing", "positive color", "border radius"'),
9
- category: z.string().optional().describe('Filter by category: "spacing", "color-semantic", "typography", etc.'),
10
+ category: z.string().optional().describe('Substring filter on the token category: "color-background", "color-text", "color-border", "color-content", ' +
11
+ '"space", "size", "border-radius", "text-size", "text-weight", "text-line-height". ' +
12
+ 'Layers (semantic/foundation/ref) are not categories — leave this out to search all tokens.'),
10
13
  limit: z.number().optional().default(10).describe('Max results to return (default 10)'),
11
- }, async ({ query, category, limit }) => {
14
+ includeRefs: z.boolean().optional().default(false)
15
+ .describe('Also return ref-layer tokens (numbered palette/scale steps like --color-system-100). Default false.'),
16
+ }, async ({ query, category, limit, includeRefs }) => {
12
17
  const { index, error } = guardedIndex('search_tokens', 'tokens');
13
18
  if (error)
14
19
  return error;
15
- const tokens = category
16
- ? index.tokens.filter(t => t.category.toLowerCase().includes(category.toLowerCase()))
17
- : index.tokens;
20
+ // A query that spells a token name is a lookup: let it reach ref tokens too.
21
+ const refsOk = includeRefs || query.includes('--');
22
+ const tokens = index.tokens.filter(t => (refsOk || t.layer !== 'ref') &&
23
+ (!category || t.category.toLowerCase().includes(category.toLowerCase())));
18
24
  const fuse = new Fuse(tokens, {
19
- keys: ['name', 'useCase', 'description', 'category', 'variant', 'property'],
25
+ keys: [
26
+ 'name', 'useCase', 'description', 'category', 'variant', 'property',
27
+ { name: 'value', weight: 0.5 }, { name: 'variants.value', weight: 0.5 },
28
+ ],
20
29
  threshold: 0.4,
21
30
  ignoreLocation: true,
22
31
  includeScore: true,
23
32
  });
24
33
  const expandedQuery = expandWithSynonyms(query);
25
- const results = searchOrPerTerm(fuse, expandedQuery, limit).map(r => ({
34
+ // With ~700 semantic tokens many results tie at a perfect Fuse score (the
35
+ // query fuzzy-matches a useCase/description), and ties come back in index
36
+ // order — so "page background" buried --color-background-page under
37
+ // interactive-selected tokens. Within a score bucket, prefer results whose
38
+ // *name* spells more of the query's terms. Only a tie-break: a global
39
+ // name-term sort would rank --text-p-spacing-* over --space-lg for
40
+ // "large spacing" just because "spacing" is in the name.
41
+ const terms = expandedQuery.toLowerCase().split(/\s+/).filter(t => t.length >= 3);
42
+ const nameHits = (name) => terms.filter(t => name.toLowerCase().includes(t)).length;
43
+ const bucket = (score) => Math.round((score ?? 1) * 100);
44
+ const results = searchOrPerTerm(fuse, expandedQuery, Math.max(limit * 5, 50))
45
+ .sort((a, b) => bucket(a.score) - bucket(b.score) || nameHits(b.item.name) - nameHits(a.item.name))
46
+ .slice(0, limit)
47
+ .map(r => ({
26
48
  name: r.item.name,
27
49
  value: r.item.value,
28
50
  category: r.item.category,
29
51
  layer: r.item.layer,
30
52
  useCase: r.item.useCase,
53
+ ...(r.item.description && { description: r.item.description }),
54
+ ...(r.item.variants?.some(v => v.appliesTo.includes('.spotlight_theme-dark')) && {
55
+ darkValue: r.item.variants.find(v => v.appliesTo.includes('.spotlight_theme-dark')).value,
56
+ }),
31
57
  score: r.score,
32
58
  }));
33
59
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"search_tokens.js","sourceRoot":"","sources":["../../src/tools/search_tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpD,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,eAAe,EACf,mEAAmE,EACnE;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+EAA+E,CAAC;QAC3G,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qEAAqE,CAAC;QAC/G,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,oCAAoC,CAAC;KACxF,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;QACnC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QACjE,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,MAAM,GAAG,QAAQ;YACrB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;YACrF,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;QAEjB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE;YAC5B,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,CAAC;YAC3E,SAAS,EAAE,GAAG;YACd,cAAc,EAAE,IAAI;YACpB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;YACjB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;YACnB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ;YACzB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;YACnB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO;YACvB,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC,CAAC,CAAC;QACJ,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC7E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"search_tokens.js","sourceRoot":"","sources":["../../src/tools/search_tokens.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -71,6 +71,17 @@ export interface Token {
71
71
  appliesTo?: string[];
72
72
  /** Human-readable intent derived from the name formula — "what to use this for". */
73
73
  useCase?: string;
74
+ /**
75
+ * Other values the same name resolves to under other selectors — the dark
76
+ * theme (`.spotlight_theme-dark`), interactive states, emphasis classes.
77
+ * `value` is always the default (`:root`) value; see SPT-1896.
78
+ */
79
+ variants?: TokenVariant[];
80
+ }
81
+ export interface TokenVariant {
82
+ /** Selectors under which this value applies, e.g. [".spotlight_theme-dark"]. */
83
+ appliesTo: string[];
84
+ value: string;
74
85
  }
75
86
  export interface Pattern {
76
87
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@castandcrew/spotlight-mcp",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "MCP server for the Spotlight Design System",
5
5
  "repository": {
6
6
  "type": "git",