@flareum/mcp 0.2.8 → 0.2.10

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.
@@ -8,11 +8,12 @@ export type Probe = (path: string) => boolean;
8
8
  */
9
9
  export declare const chooseStylesDir: (exists: Probe, configured?: string) => string;
10
10
  export declare const autoPullEnabled: (env: Record<string, string | undefined>) => boolean;
11
- /** Only ever the FIRST time: an existing directory is the developer's, and `flareum pull` owns updates. */
12
- export declare const needsFirstPull: (exists: Probe, dir: string) => boolean;
11
+ export declare const STAMP = ".flareum-version";
12
+ export declare const pulledVersion: (read: (path: string) => string | null, dir: string) => string | null;
13
+ export declare const needsPull: (exists: Probe, read: (path: string) => string | null, dir: string, published: string | null) => boolean;
13
14
  export type FirstPull = {
14
15
  ran: false;
15
- reason: 'disabled' | 'already-pulled';
16
+ reason: 'disabled' | 'up-to-date';
16
17
  dir: string;
17
18
  } | {
18
19
  ran: true;
@@ -28,4 +29,4 @@ export declare const firstPullReport: (outcome: FirstPull) => string | null;
28
29
  /** Writes under `root`, refusing nothing the pull already refuses (see isWritablePath). */
29
30
  export declare const fileWriter: (root: string) => (path: string, contents: string) => Promise<void>;
30
31
  export declare const configuredOut: (cwd: string, env: Record<string, string | undefined>) => string | undefined;
31
- export declare const runFirstPull: (client: Pick<FlareumClient, "files" | "file">, cwd: string, env: Record<string, string | undefined>, configuredOut?: string) => Promise<FirstPull>;
32
+ export declare const runFirstPull: (client: Pick<FlareumClient, "files" | "file" | "published">, cwd: string, env: Record<string, string | undefined>, configuredOut?: string) => Promise<FirstPull>;
@@ -29,8 +29,18 @@ export const chooseStylesDir = (exists, configured) => {
29
29
  // Opt-out, not opt-in: a project with no stylesheets is the case this exists for, and a stdio server
30
30
  // has nobody to ask at startup. Anything but an explicit off means on.
31
31
  export const autoPullEnabled = (env) => !['off', 'false', '0', 'no'].includes((env.FLAREUM_AUTO_PULL ?? '').trim().toLowerCase());
32
- /** Only ever the FIRST time: an existing directory is the developer's, and `flareum pull` owns updates. */
33
- export const needsFirstPull = (exists, dir) => !exists(dir);
32
+ // A stamp beside the files, not in config.json: config is the developer's, this is bookkeeping.
33
+ export const STAMP = '.flareum-version';
34
+ export const pulledVersion = (read, dir) => read(join(dir, STAMP))?.trim() || null;
35
+ // Pull when there is nothing here, or when what is published is not what is on disk. Connecting
36
+ // used to be a one-time event, so a project pulled once never saw another push.
37
+ export const needsPull = (exists, read, dir, published) => {
38
+ if (!exists(dir))
39
+ return true;
40
+ if (!published)
41
+ return false;
42
+ return pulledVersion(read, dir) !== published;
43
+ };
34
44
  export const firstPullReport = (outcome) => {
35
45
  // Silence is right for a start that did nothing — this prints on every server start.
36
46
  if (!outcome.ran && outcome.reason !== 'failed')
@@ -39,8 +49,11 @@ export const firstPullReport = (outcome) => {
39
49
  return `[flareum] could NOT pull the stylesheets into ${outcome.dir} — ${outcome.error}. `
40
50
  + 'The token tools still work; run `npx -p @flareum/mcp flareum pull` to retry.';
41
51
  const { written, failed } = outcome.result;
52
+ // Naming the import is the difference between 24 files on disk and 24 files that apply: nothing
53
+ // loads them until the project's global stylesheet says so.
42
54
  const head = `[flareum] no local stylesheets — pulled ${written.length} into ${outcome.dir}. `
43
- + 'Run `npx -p @flareum/mcp flareum watch` to keep them current, or set FLAREUM_AUTO_PULL=off.';
55
+ + `Import them once in your global stylesheet \`@use '${outcome.dir.replace(/^src\//, './')}/main';\` `
56
+ + '— then `npx -p @flareum/mcp flareum watch` keeps them current (FLAREUM_AUTO_PULL=off to stop).';
44
57
  return failed.length ? `${head}\n[flareum] ${failed.length} could not be written: `
45
58
  + failed.map(({ path, reason }) => `${path} — ${reason}`).join('; ') : head;
46
59
  };
@@ -65,13 +78,25 @@ export const configuredOut = (cwd, env) => {
65
78
  };
66
79
  export const runFirstPull = async (client, cwd, env, configuredOut) => {
67
80
  const exists = path => existsSync(resolve(cwd, path));
81
+ const read = (path) => {
82
+ try {
83
+ return readFileSync(resolve(cwd, path), 'utf8');
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ };
68
89
  const dir = chooseStylesDir(exists, configuredOut);
69
90
  if (!autoPullEnabled(env))
70
91
  return { ran: false, reason: 'disabled', dir };
71
- if (!needsFirstPull(exists, dir))
72
- return { ran: false, reason: 'already-pulled', dir };
73
92
  try {
74
- return { ran: true, dir, result: await pullStyles(client, fileWriter(resolve(cwd, dir))) };
93
+ const published = await client.published().then(r => r.publishedVersionId).catch(() => null);
94
+ if (!needsPull(exists, read, dir, published))
95
+ return { ran: false, reason: 'up-to-date', dir };
96
+ const result = await pullStyles(client, fileWriter(resolve(cwd, dir)));
97
+ // Stamped only after the write, so a failed pull is retried on the next connection.
98
+ await writeFile(resolve(cwd, dir, STAMP), `${result.publishedVersionId}\n`, 'utf8');
99
+ return { ran: true, dir, result };
75
100
  }
76
101
  catch (error) {
77
102
  // A project with nothing published, an expired key, no network — none of them may stop the server.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flareum/mcp",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Connect a coding agent to a Flareum project's design tokens.",
5
5
  "license": "MIT",
6
6
  "author": "Flareum",
package/skill/SKILL.md CHANGED
@@ -31,6 +31,42 @@ page, and it is worth reading in full before the first line of code.
31
31
  | Any text — a heading, a label, body copy, a pseudo-element's `content` | [references/typography.md](references/typography.md) |
32
32
  | A token name, or judging one that already exists | [references/naming.md](references/naming.md) |
33
33
 
34
+ ## Before the first token: check the stylesheets are imported
35
+
36
+ A token only resolves if the pulled stylesheets are actually loaded. `flareum pull` writes them into
37
+ the project — it does not wire them in, because which file is the global entry point is the
38
+ project's decision, not the tool's.
39
+
40
+ So the first time you use a token in a project, check the import exists, and add it if it does not.
41
+ Otherwise every `var([prefix]-…)` you write is correct and renders as nothing — the failure is
42
+ silent, and it looks like the token is wrong rather than absent.
43
+
44
+ **Find the pulled files** (`src/styles/flareum/`, or wherever `out` in `.flareum/config.json`
45
+ points), then **find the global stylesheet** — the one the app already loads for everything:
46
+
47
+ | Project | Usually |
48
+ |---|---|
49
+ | Angular | the `styles` entry in `angular.json` — commonly `src/styles.scss` |
50
+ | Vite / React / Vue | the CSS imported by the entry module — `src/main.tsx`, `src/index.css` |
51
+ | Next.js | `app/globals.css`, imported by the root layout |
52
+ | Plain | whatever the HTML `<link>`s |
53
+
54
+ Add the import at the **top**, before anything that uses a token:
55
+
56
+ ```scss
57
+ @use './styles/flareum/main'; // SCSS
58
+ ```
59
+ ```css
60
+ @import './styles/flareum/main.css'; /* plain CSS */
61
+ ```
62
+
63
+ Then confirm it resolves — build, or grep the built CSS for a `--[prefix]-` declaration. A token
64
+ that is imported but still not applying is usually the `font:` shorthand or a missing
65
+ `--line-height`; [references/typography.md](references/typography.md) covers both.
66
+
67
+ If the pulled folder does not exist at all, the project has never pulled: say so and give the
68
+ command — `npx -p @flareum/mcp flareum pull` — rather than writing tokens that cannot resolve.
69
+
34
70
  ## Reading a search result
35
71
 
36
72
  The header tells you which kind of answer you got, and they mean different things: