@starklab/stark-mcp 0.2.1 → 0.3.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/src/server.js CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  getLayoutSchema,
13
13
  validateLayout,
14
14
  getGenerationProtocol,
15
+ whispererContext,
15
16
  } from './data.js';
16
17
 
17
18
  const json = (value) => ({ content: [{ type: 'text', text: JSON.stringify(value, null, 2) }] });
@@ -169,5 +170,35 @@ export function createServer() {
169
170
  wrap(() => getGenerationProtocol())
170
171
  );
171
172
 
173
+ server.registerTool(
174
+ 'whisperer_context',
175
+ {
176
+ title: 'Ground an answer about the design system',
177
+ description:
178
+ 'Everything a model needs to answer one question about Stark: the rules to answer under and ' +
179
+ 'the facts to answer from — every component with its props per platform, every token with ' +
180
+ 'its value, dark value, alias chain and React Native name — with the components and tokens ' +
181
+ 'the question names expanded in full. The same brain behind Whisperer, the concierge in ' +
182
+ "Stark Dominion. Put the result in the system prompt and answer the question from it alone. " +
183
+ 'Returns prose, not JSON.',
184
+ inputSchema: {
185
+ question: z.string().describe('What is being asked about the design system, verbatim'),
186
+ context: z
187
+ .array(z.string())
188
+ .optional()
189
+ .describe('The prior turns of the conversation, newest first, so a follow-up keeps its subject'),
190
+ },
191
+ },
192
+ // Not `wrap`: the answer is a system prompt, and a system prompt is text —
193
+ // a JSON-encoded string would hand the client every newline as `\n`.
194
+ async ({ question, context }) => {
195
+ try {
196
+ return { content: [{ type: 'text', text: whispererContext(question, context ?? []).text }] };
197
+ } catch (err) {
198
+ return error(err instanceof Error ? err.message : String(err));
199
+ }
200
+ }
201
+ );
202
+
172
203
  return server;
173
204
  }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Types for whisperer.js — the shared Whisperer brain. TypeScript consumers
3
+ * (Dominion) resolve this file ahead of the .js it sits beside.
4
+ */
5
+
6
+ export interface UsageDoc {
7
+ dos?: string[];
8
+ donts?: string[];
9
+ codeExample?: string;
10
+ }
11
+
12
+ export interface NativeUsageProp {
13
+ name: string;
14
+ type: string;
15
+ default?: string;
16
+ required?: boolean | string;
17
+ description?: string;
18
+ }
19
+
20
+ export interface NativeUsageDoc extends UsageDoc {
21
+ props?: NativeUsageProp[];
22
+ }
23
+
24
+ export interface PropMapEntry {
25
+ react: string;
26
+ type?: string;
27
+ values?: Record<string, string>;
28
+ transform?: string;
29
+ description?: string;
30
+ componentProp?: boolean;
31
+ }
32
+
33
+ export interface ManifestComponent {
34
+ name: string;
35
+ slug: string;
36
+ status: string;
37
+ description: string;
38
+ platforms?: string[];
39
+ usage?: UsageDoc | null;
40
+ nativeUsage?: NativeUsageDoc | null;
41
+ props?: { web?: { propMap?: PropMapEntry[] } | null } | null;
42
+ tokens?: Record<string, unknown> | null;
43
+ }
44
+
45
+ export interface PropEntry {
46
+ name: string;
47
+ hasDefault?: boolean;
48
+ defaultSource?: string;
49
+ rest?: boolean;
50
+ }
51
+
52
+ export interface SignaturePlatform {
53
+ package?: string;
54
+ components?: Record<string, { props?: PropEntry[] }>;
55
+ }
56
+
57
+ export interface TokenMeta {
58
+ value: unknown;
59
+ type: string;
60
+ layer: 'primitive' | 'semantic' | 'component' | null;
61
+ alias: string | null;
62
+ description: string | null;
63
+ rn: { name: string; module: string } | null;
64
+ }
65
+
66
+ export interface WhispererData {
67
+ manifest: { components: ManifestComponent[] };
68
+ catalog: { platforms: Record<string, { exports: Record<string, { kind: string }> }> };
69
+ componentProps: { platforms: { web?: SignaturePlatform; native?: SignaturePlatform } };
70
+ tokenMeta: Record<string, TokenMeta>;
71
+ tokenDark: Record<string, unknown>;
72
+ }
73
+
74
+ export interface Grounding {
75
+ /** The grounding block, ready to sit under the system prompt. */
76
+ text: string;
77
+ /** The components whose full detail the block carries. */
78
+ components: string[];
79
+ /** The subset the question itself named. */
80
+ named: string[];
81
+ /** The tokens the question named outright. */
82
+ tokens: string[];
83
+ }
84
+
85
+ export interface Whisperer {
86
+ /** Where each platform's components are imported from. */
87
+ PACKAGES: { web: string | null; native: string | null };
88
+ /** The grounding block for one question; `context` is the prior turns, newest first. */
89
+ buildGrounding(question: string, context?: string[]): Grounding;
90
+ /** Every component the text names, in reading order, uncapped. */
91
+ componentsNamedIn(text: string): { name: string; platforms: string[] }[];
92
+ isKnownComponent(name: string): boolean;
93
+ /** Whether a token name (with or without its leading `--`) exists. */
94
+ isKnownToken(name: string): boolean;
95
+ /** Every token the text names, as CSS name or React Native export. */
96
+ tokensInQuestion(text: string): string[];
97
+ }
98
+
99
+ /** The grounding functions, built over one set of generated files. */
100
+ export function createWhisperer(data: WhispererData): Whisperer;
101
+
102
+ /**
103
+ * The design-system rules the grounding is handed to a model under. A
104
+ * surface appends its own rules — how it renders, what it can see.
105
+ */
106
+ export const WHISPERER_SYSTEM_PROMPT: string;