pigment-mcp 0.3.0 → 0.4.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 +6 -6
- package/cli.js +147 -108
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
# pigment-mcp
|
|
4
4
|
|
|
5
5
|
MCP server for [Pigment](https://pigmentui.com) design systems. Your coding agent (Claude Code, Codex,
|
|
6
|
-
Cursor or any MCP client) reads tokens, rules, component specs and installation guides
|
|
7
|
-
version while it works.
|
|
6
|
+
Cursor or any MCP client) reads tokens, rules, component specs and installation guides while it works.
|
|
8
7
|
|
|
9
|
-
Every
|
|
10
|
-
|
|
8
|
+
Every design system ships inside this package, so it works offline. New systems and updates arrive with new
|
|
9
|
+
package releases.
|
|
11
10
|
|
|
12
11
|
## Connect
|
|
13
12
|
|
|
@@ -42,11 +41,12 @@ propose a plan, restyle one sample screen, then report build and visual checks.
|
|
|
42
41
|
|
|
43
42
|
| Tool | Returns |
|
|
44
43
|
| --- | --- |
|
|
45
|
-
| `list_design_systems` |
|
|
46
|
-
| `get_design_system` | The full spec of
|
|
44
|
+
| `list_design_systems` | Systems with tags and when each was last updated (`tone?`, `appearance?`) |
|
|
45
|
+
| `get_design_system` | The full spec of a system: rules, token tables, setup, verification |
|
|
47
46
|
| `get_tokens` | `tokens.css` or `tokens.json`, to copy verbatim |
|
|
48
47
|
| `get_component_spec` | One component: anatomy, variants, states, accessibility, token mapping |
|
|
49
48
|
| `get_installation_guide` | Steps and approval points for `new`, `existing` or `ongoing` |
|
|
49
|
+
| `get_changelog` | What changed, by date — to update a project that already has the system |
|
|
50
50
|
| `get_references` | Screenshots of four reference apps restyled with the system |
|
|
51
51
|
|
|
52
52
|
Requires Node 22+.
|
package/cli.js
CHANGED
|
@@ -1536,10 +1536,10 @@ var init_regexes = __esm({
|
|
|
1536
1536
|
duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
|
|
1537
1537
|
extendedDuration = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
|
|
1538
1538
|
guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
|
1539
|
-
uuid = (
|
|
1540
|
-
if (!
|
|
1539
|
+
uuid = (version2) => {
|
|
1540
|
+
if (!version2)
|
|
1541
1541
|
return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
|
|
1542
|
-
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${
|
|
1542
|
+
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version2}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
|
|
1543
1543
|
};
|
|
1544
1544
|
uuid4 = /* @__PURE__ */ uuid(4);
|
|
1545
1545
|
uuid6 = /* @__PURE__ */ uuid(6);
|
|
@@ -19777,10 +19777,10 @@ function fromJSONSchema(schema, params) {
|
|
|
19777
19777
|
} catch {
|
|
19778
19778
|
throw new Error("fromJSONSchema input is not valid JSON (possibly cyclic); use $defs/$ref for recursive schemas");
|
|
19779
19779
|
}
|
|
19780
|
-
const
|
|
19780
|
+
const version2 = detectVersion(normalized, params?.defaultTarget);
|
|
19781
19781
|
const defs = normalized.$defs || normalized.definitions || {};
|
|
19782
19782
|
const ctx = {
|
|
19783
|
-
version:
|
|
19783
|
+
version: version2,
|
|
19784
19784
|
defs,
|
|
19785
19785
|
refs: /* @__PURE__ */ new Map(),
|
|
19786
19786
|
processing: /* @__PURE__ */ new Set(),
|
|
@@ -21466,14 +21466,14 @@ function missingClientCapabilities(required2, declared) {
|
|
|
21466
21466
|
}
|
|
21467
21467
|
return Object.keys(missing).length > 0 ? missing : void 0;
|
|
21468
21468
|
}
|
|
21469
|
-
function isModernProtocolVersion(
|
|
21470
|
-
return
|
|
21469
|
+
function isModernProtocolVersion(version2) {
|
|
21470
|
+
return version2 >= FIRST_MODERN_PROTOCOL_VERSION;
|
|
21471
21471
|
}
|
|
21472
21472
|
function legacyProtocolVersions(versions) {
|
|
21473
|
-
return versions.filter((
|
|
21473
|
+
return versions.filter((version2) => !isModernProtocolVersion(version2));
|
|
21474
21474
|
}
|
|
21475
21475
|
function modernProtocolVersions(versions) {
|
|
21476
|
-
return versions.filter((
|
|
21476
|
+
return versions.filter((version2) => isModernProtocolVersion(version2));
|
|
21477
21477
|
}
|
|
21478
21478
|
function appendTextFallbackForNonObject(result) {
|
|
21479
21479
|
const sc = result.structuredContent;
|
|
@@ -23588,8 +23588,8 @@ function getWireResultSchemas() {
|
|
|
23588
23588
|
};
|
|
23589
23589
|
return wireResultSchemasMemo;
|
|
23590
23590
|
}
|
|
23591
|
-
function codecForVersion(
|
|
23592
|
-
return
|
|
23591
|
+
function codecForVersion(version2) {
|
|
23592
|
+
return version2 !== void 0 && isModernProtocolVersion(version2) ? rev2026Codec : rev2025Codec;
|
|
23593
23593
|
}
|
|
23594
23594
|
function classifiedWireEra(classification) {
|
|
23595
23595
|
if (classification.revision !== void 0) return codecForVersion(classification.revision).era;
|
|
@@ -25202,8 +25202,8 @@ var init_src_Cqbh3MYc = __esm({
|
|
|
25202
25202
|
*/
|
|
25203
25203
|
_negotiatedProtocolVersion;
|
|
25204
25204
|
static {
|
|
25205
|
-
writeNegotiatedProtocolVersion = (instance,
|
|
25206
|
-
instance._negotiatedProtocolVersion =
|
|
25205
|
+
writeNegotiatedProtocolVersion = (instance, version2) => {
|
|
25206
|
+
instance._negotiatedProtocolVersion = version2;
|
|
25207
25207
|
};
|
|
25208
25208
|
}
|
|
25209
25209
|
_supportedProtocolVersions;
|
|
@@ -33268,7 +33268,7 @@ var init_mcp_DIH4cS6P = __esm({
|
|
|
33268
33268
|
if (identity.clientInfo !== void 0) server._clientVersion = identity.clientInfo;
|
|
33269
33269
|
};
|
|
33270
33270
|
installDiscoverHandler = (server, servedModernVersions) => {
|
|
33271
|
-
const missing = servedModernVersions.filter((
|
|
33271
|
+
const missing = servedModernVersions.filter((version2) => !server._supportedProtocolVersions.includes(version2));
|
|
33272
33272
|
if (missing.length > 0) server._supportedProtocolVersions = [...server._supportedProtocolVersions, ...missing];
|
|
33273
33273
|
server.setRequestHandler("server/discover", () => server._ondiscover());
|
|
33274
33274
|
};
|
|
@@ -34680,7 +34680,7 @@ var init_src = __esm({
|
|
|
34680
34680
|
|
|
34681
34681
|
// ../content/src/index.ts
|
|
34682
34682
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
34683
|
-
import { dirname, join, resolve } from "node:path";
|
|
34683
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
34684
34684
|
function findContentRoot() {
|
|
34685
34685
|
if (process.env.PIGMENT_CONTENT_DIR) return resolve(process.env.PIGMENT_CONTENT_DIR);
|
|
34686
34686
|
let dir = process.cwd();
|
|
@@ -34705,25 +34705,31 @@ function publishedVersions(id2) {
|
|
|
34705
34705
|
if (!entry) throw new ContentError("unknown_template", `No published template "${id2}"`);
|
|
34706
34706
|
return entry.versions.filter((v) => v.status === "published").map((v) => v.version);
|
|
34707
34707
|
}
|
|
34708
|
-
function versionDir(id2,
|
|
34708
|
+
function versionDir(id2, version2) {
|
|
34709
34709
|
const versions = publishedVersions(id2);
|
|
34710
|
-
const resolvedVersion =
|
|
34710
|
+
const resolvedVersion = version2 === "latest" ? registry2().templates.find((t) => t.id === id2)?.latest : version2;
|
|
34711
34711
|
if (!resolvedVersion || !versions.includes(resolvedVersion)) {
|
|
34712
|
-
throw new ContentError("unknown_version", `"${id2}" has no published version "${
|
|
34712
|
+
throw new ContentError("unknown_version", `"${id2}" has no published version "${version2}". Available: ${versions.join(", ") || "none"}`);
|
|
34713
34713
|
}
|
|
34714
34714
|
return join(contentRoot(), "templates", id2, resolvedVersion);
|
|
34715
34715
|
}
|
|
34716
|
-
function getManifest(id2,
|
|
34717
|
-
return Manifest.parse(readJson(join(versionDir(id2,
|
|
34716
|
+
function getManifest(id2, version2) {
|
|
34717
|
+
return Manifest.parse(readJson(join(versionDir(id2, version2), "manifest.json")));
|
|
34718
34718
|
}
|
|
34719
|
-
function readArtifact(id2,
|
|
34720
|
-
const
|
|
34721
|
-
|
|
34722
|
-
|
|
34719
|
+
function readArtifact(id2, version2, rel) {
|
|
34720
|
+
const dir = versionDir(id2, version2);
|
|
34721
|
+
const file2 = join(dir, rel);
|
|
34722
|
+
if (!existsSync(file2)) throw new ContentError("unavailable_artifact", `${id2}@${version2} has no ${rel}`);
|
|
34723
|
+
return unversioned(id2, basename(dir), readFileSync(file2, "utf8"));
|
|
34723
34724
|
}
|
|
34724
|
-
function
|
|
34725
|
-
const
|
|
34726
|
-
const
|
|
34725
|
+
function unversioned(id2, version2, text2) {
|
|
34726
|
+
const name = getManifest(id2, version2).name;
|
|
34727
|
+
const date5 = (registry2().templates.find((t) => t.id === id2)?.versions.find((v) => v.version === version2)?.publishedAt ?? "").slice(0, 10);
|
|
34728
|
+
return text2.replaceAll(`${name} ${version2}`, name).replaceAll(`${id2}@${version2}`, date5 ? `${id2}, updated ${date5}` : id2).replaceAll(`"version": "${version2}",`, `"updated": "${date5}",`);
|
|
34729
|
+
}
|
|
34730
|
+
function getTokens(id2, version2) {
|
|
34731
|
+
const manifest = getManifest(id2, version2);
|
|
34732
|
+
const dir = versionDir(id2, version2);
|
|
34727
34733
|
const primitives = readJson(join(dir, manifest.artifacts.tokens.primitives));
|
|
34728
34734
|
const out = {};
|
|
34729
34735
|
for (const mode2 of ["light", "dark"]) {
|
|
@@ -34734,41 +34740,67 @@ function getTokens(id2, version3) {
|
|
|
34734
34740
|
}
|
|
34735
34741
|
return out;
|
|
34736
34742
|
}
|
|
34737
|
-
function getComponents(id2,
|
|
34738
|
-
const manifest = getManifest(id2,
|
|
34739
|
-
return ComponentIndex.parse(JSON.parse(readArtifact(id2,
|
|
34743
|
+
function getComponents(id2, version2) {
|
|
34744
|
+
const manifest = getManifest(id2, version2);
|
|
34745
|
+
return ComponentIndex.parse(JSON.parse(readArtifact(id2, version2, manifest.artifacts.components)));
|
|
34740
34746
|
}
|
|
34741
|
-
function getComponentSpec(id2,
|
|
34742
|
-
const entry = getComponents(id2,
|
|
34743
|
-
if (!entry) throw new ContentError("invalid_component", `${id2}@${
|
|
34744
|
-
if (entry.status === "unsupported" || !entry.file) return { entry, markdown: `${name} is not specified in this
|
|
34745
|
-
return { entry, markdown: readArtifact(id2,
|
|
34747
|
+
function getComponentSpec(id2, version2, name) {
|
|
34748
|
+
const entry = getComponents(id2, version2).components.find((c) => c.name === name);
|
|
34749
|
+
if (!entry) throw new ContentError("invalid_component", `${id2}@${version2} has no component "${name}"`);
|
|
34750
|
+
if (entry.status === "unsupported" || !entry.file) return { entry, markdown: `${name} is not specified in this system.` };
|
|
34751
|
+
return { entry, markdown: readArtifact(id2, version2, join("components", entry.file)) };
|
|
34746
34752
|
}
|
|
34747
|
-
function getGuide(id2,
|
|
34753
|
+
function getGuide(id2, version2, mode2) {
|
|
34748
34754
|
if (!(mode2 in GUIDE_SECTIONS)) throw new ContentError("invalid_mode", `mode must be one of ${Object.keys(GUIDE_SECTIONS).join(", ")}`);
|
|
34749
|
-
const text2 = readArtifact(id2,
|
|
34755
|
+
const text2 = readArtifact(id2, version2, getManifest(id2, version2).artifacts.instructions);
|
|
34750
34756
|
const start = text2.indexOf(GUIDE_SECTIONS[mode2]);
|
|
34751
34757
|
const rest = text2.slice(start);
|
|
34752
34758
|
const next = rest.indexOf("\n## ", 3);
|
|
34753
34759
|
const verification = text2.slice(text2.indexOf("## Verification"));
|
|
34754
34760
|
return (next > 0 ? rest.slice(0, next) : rest).trim() + "\n\n" + verification.trim();
|
|
34755
34761
|
}
|
|
34756
|
-
function getAgentMd(id2,
|
|
34757
|
-
return readArtifact(id2,
|
|
34762
|
+
function getAgentMd(id2, version2) {
|
|
34763
|
+
return readArtifact(id2, version2, join("dist", "agent.md"));
|
|
34764
|
+
}
|
|
34765
|
+
function getTokenFile(id2, version2, format) {
|
|
34766
|
+
return readArtifact(id2, version2, join("dist", `tokens.${format}`));
|
|
34758
34767
|
}
|
|
34759
|
-
function
|
|
34760
|
-
|
|
34768
|
+
function changelogEntry(id2, version2) {
|
|
34769
|
+
let md;
|
|
34770
|
+
try {
|
|
34771
|
+
md = readArtifact(id2, version2, "CHANGELOG.md").replace(/\r\n/g, "\n");
|
|
34772
|
+
} catch {
|
|
34773
|
+
return { summary: "", changes: [] };
|
|
34774
|
+
}
|
|
34775
|
+
const start = md.indexOf(`
|
|
34776
|
+
## ${version2}
|
|
34777
|
+
`);
|
|
34778
|
+
if (start < 0) return { summary: "", changes: [] };
|
|
34779
|
+
const rest = md.slice(start + version2.length + 5);
|
|
34780
|
+
const section = rest.slice(0, rest.search(/\n## |$/)).trim();
|
|
34781
|
+
const summary = (section.split(/\n\s*\n/)[0] ?? "").replace(/\s*\n\s*/g, " ").trim();
|
|
34782
|
+
const changes = [];
|
|
34783
|
+
for (const line of section.split("\n")) {
|
|
34784
|
+
if (line.startsWith("- ")) changes.push(line.slice(2).trim());
|
|
34785
|
+
else if (/^\s+\S/.test(line) && changes.length) changes[changes.length - 1] += ` ${line.trim()}`;
|
|
34786
|
+
}
|
|
34787
|
+
return { summary, changes };
|
|
34788
|
+
}
|
|
34789
|
+
function getHistory(id2) {
|
|
34790
|
+
const entry = registry2().templates.find((t) => t.id === id2);
|
|
34791
|
+
if (!entry) throw new ContentError("unknown_template", `No published template "${id2}"`);
|
|
34792
|
+
return entry.versions.filter((v) => v.status === "published").reverse().map((v) => ({ date: (v.publishedAt ?? "").slice(0, 10), ...changelogEntry(id2, v.version) }));
|
|
34761
34793
|
}
|
|
34762
|
-
function resolveVersion(id2,
|
|
34763
|
-
return getManifest(id2,
|
|
34794
|
+
function resolveVersion(id2, version2) {
|
|
34795
|
+
return getManifest(id2, version2).version;
|
|
34764
34796
|
}
|
|
34765
|
-
function getShots(id2,
|
|
34766
|
-
return shotsFor(id2, resolveVersion(id2,
|
|
34797
|
+
function getShots(id2, version2) {
|
|
34798
|
+
return shotsFor(id2, resolveVersion(id2, version2));
|
|
34767
34799
|
}
|
|
34768
|
-
function shotsFor(id2,
|
|
34800
|
+
function shotsFor(id2, version2) {
|
|
34769
34801
|
const index = join(contentRoot(), "shots.json");
|
|
34770
|
-
if (existsSync(index)) return readJson(index)[`${id2}@${
|
|
34771
|
-
const dir = join(contentRoot(), "..", "apps", "web", "public", "showcase", id2,
|
|
34802
|
+
if (existsSync(index)) return readJson(index)[`${id2}@${version2}`] ?? {};
|
|
34803
|
+
const dir = join(contentRoot(), "..", "apps", "web", "public", "showcase", id2, version2);
|
|
34772
34804
|
const shots = {};
|
|
34773
34805
|
if (!existsSync(dir)) return shots;
|
|
34774
34806
|
for (const app of readdirSync(dir)) {
|
|
@@ -34777,27 +34809,28 @@ function shotsFor(id2, version3) {
|
|
|
34777
34809
|
const files = readdirSync(join(dir, app)).filter((f) => f.endsWith(".png"));
|
|
34778
34810
|
for (const [key, re] of Object.entries({ desktopLight: /desktop-light/, desktopDark: /desktop-dark/, mobileLight: /mobile-light/, mobileDark: /mobile-dark/ })) {
|
|
34779
34811
|
const f = cover[key] ?? files.find((x) => re.test(x));
|
|
34780
|
-
if (f) shots[`${app}.${key}`] = `/showcase/${id2}/${
|
|
34812
|
+
if (f) shots[`${app}.${key}`] = `/showcase/${id2}/${version2}/${app}/${f}`;
|
|
34781
34813
|
}
|
|
34782
34814
|
}
|
|
34783
34815
|
return shots;
|
|
34784
34816
|
}
|
|
34785
34817
|
function listTemplates() {
|
|
34786
34818
|
return registry2().templates.filter((t) => t.latest).map((t) => {
|
|
34787
|
-
const
|
|
34788
|
-
const manifest = getManifest(t.id,
|
|
34789
|
-
const tokens = getTokens(t.id,
|
|
34819
|
+
const version2 = t.latest;
|
|
34820
|
+
const manifest = getManifest(t.id, version2);
|
|
34821
|
+
const tokens = getTokens(t.id, version2);
|
|
34790
34822
|
const light = tokens.light ?? tokens.dark ?? {};
|
|
34791
34823
|
const swatch = (k) => typeof light[k] === "string" ? light[k] : "#000000";
|
|
34792
34824
|
return {
|
|
34793
34825
|
id: t.id,
|
|
34794
|
-
version:
|
|
34826
|
+
version: version2,
|
|
34795
34827
|
name: manifest.name,
|
|
34796
34828
|
description: manifest.description,
|
|
34797
34829
|
tags: manifest.tags,
|
|
34798
34830
|
versions: t.versions.filter((v) => v.status === "published").map((v) => v.version),
|
|
34831
|
+
updated: (t.versions.find((v) => v.version === version2)?.publishedAt ?? "").slice(0, 10),
|
|
34799
34832
|
swatches: ["color.surface.default", "color.surface.subtle", "color.text.primary", "color.action.primary", "color.action.primaryHover"].map(swatch),
|
|
34800
|
-
shots: shotsFor(t.id,
|
|
34833
|
+
shots: shotsFor(t.id, version2)
|
|
34801
34834
|
};
|
|
34802
34835
|
});
|
|
34803
34836
|
}
|
|
@@ -34819,17 +34852,15 @@ var init_src2 = __esm({
|
|
|
34819
34852
|
});
|
|
34820
34853
|
|
|
34821
34854
|
// ../content/src/prompts.ts
|
|
34822
|
-
function specRef(id2,
|
|
34823
|
-
if (delivery === "url") return `Spec: ${SITE_URL}/s/${id2}
|
|
34824
|
-
|
|
34825
|
-
|
|
34826
|
-
|
|
34827
|
-
|
|
34828
|
-
const ref = `${id2}@${version3}`;
|
|
34829
|
-
const spec = specRef(id2, version3, delivery);
|
|
34855
|
+
function specRef(id2, delivery) {
|
|
34856
|
+
if (delivery === "url") return `Spec: ${SITE_URL}/s/${id2}/agent.md`;
|
|
34857
|
+
return "Read the spec with the Pigment MCP tools (get_design_system, get_component_spec).";
|
|
34858
|
+
}
|
|
34859
|
+
function buildPrompt(id2, mode2, delivery) {
|
|
34860
|
+
const spec = specRef(id2, delivery);
|
|
34830
34861
|
if (mode2 === "new") {
|
|
34831
34862
|
return [
|
|
34832
|
-
`Set up design system ${
|
|
34863
|
+
`Set up design system ${id2} in this codebase.`,
|
|
34833
34864
|
spec,
|
|
34834
34865
|
"First inspect the framework, styling approach and component structure, then propose an installation plan and wait for my approval.",
|
|
34835
34866
|
"Don't add libraries that don't fit the existing stack. Leave an AGENTS.md / CLAUDE.md pointer so future screens reuse the system.",
|
|
@@ -34838,7 +34869,7 @@ function buildPrompt(id2, version3, mode2, delivery) {
|
|
|
34838
34869
|
}
|
|
34839
34870
|
if (mode2 === "existing") {
|
|
34840
34871
|
return [
|
|
34841
|
-
`Apply design system ${
|
|
34872
|
+
`Apply design system ${id2} to this project.`,
|
|
34842
34873
|
spec,
|
|
34843
34874
|
"Preserve features, routes, business logic, API contracts, tests and accessibility.",
|
|
34844
34875
|
"Audit styles and components first, then propose a migration plan and wait for my approval. Restyle one screen as a sample and wait again.",
|
|
@@ -34846,7 +34877,7 @@ function buildPrompt(id2, version3, mode2, delivery) {
|
|
|
34846
34877
|
].join("\n");
|
|
34847
34878
|
}
|
|
34848
34879
|
return [
|
|
34849
|
-
`Build this with the installed design system ${
|
|
34880
|
+
`Build this with the installed design system ${id2}.`,
|
|
34850
34881
|
"Use its semantic tokens and component conventions from design-system/. Don't hard-code new style values.",
|
|
34851
34882
|
"If the spec doesn't cover something, ask me with options before deciding."
|
|
34852
34883
|
].join("\n");
|
|
@@ -34866,7 +34897,7 @@ var init_package = __esm({
|
|
|
34866
34897
|
"package.json"() {
|
|
34867
34898
|
package_default = {
|
|
34868
34899
|
name: "@pigment/mcp",
|
|
34869
|
-
version: "0.
|
|
34900
|
+
version: "0.4.1",
|
|
34870
34901
|
private: true,
|
|
34871
34902
|
type: "module",
|
|
34872
34903
|
description: "MCP server for Pigment design systems: tokens, rules, component specs and installation guides for your coding agent.",
|
|
@@ -34908,9 +34939,15 @@ function guard(fn) {
|
|
|
34908
34939
|
throw e;
|
|
34909
34940
|
}
|
|
34910
34941
|
}
|
|
34911
|
-
function
|
|
34912
|
-
const
|
|
34913
|
-
|
|
34942
|
+
function updated(systemId) {
|
|
34943
|
+
const t = listTemplates().find((x) => x.id === systemId);
|
|
34944
|
+
if (!t) throw new ContentError("unknown_template", `No published system "${systemId}". Call list_design_systems.`);
|
|
34945
|
+
return t.updated;
|
|
34946
|
+
}
|
|
34947
|
+
function specForMcp(systemId) {
|
|
34948
|
+
const date5 = updated(systemId);
|
|
34949
|
+
const md = getAgentMd(systemId, CURRENT);
|
|
34950
|
+
const index = getComponents(systemId, CURRENT).components;
|
|
34914
34951
|
const start = md.indexOf("\n## Components");
|
|
34915
34952
|
const end = start < 0 ? -1 : md.indexOf("\n## ", start + 4);
|
|
34916
34953
|
const specified = index.filter((c) => c.status !== "unsupported").map((c) => c.name);
|
|
@@ -34918,11 +34955,11 @@ function specForMcp(systemId, pinned) {
|
|
|
34918
34955
|
const chapter = [
|
|
34919
34956
|
"\n## Components\n",
|
|
34920
34957
|
`Specified: ${specified.join(", ")}. Read each with get_component_spec before building it.`,
|
|
34921
|
-
unsupported.length ? `Not specified in this
|
|
34958
|
+
unsupported.length ? `Not specified in this system: ${unsupported.join(", ")} \u2014 compose them from tokens and say so in your report.` : ""
|
|
34922
34959
|
].join("\n");
|
|
34923
34960
|
const body = start < 0 ? md : md.slice(0, start) + chapter + (end < 0 ? "" : md.slice(end));
|
|
34924
34961
|
return [
|
|
34925
|
-
`>
|
|
34962
|
+
`> Pigment system ${systemId}, updated ${date5}. Write \`${systemId}, updated ${date5}\` in design-system/VERSION.`,
|
|
34926
34963
|
"> Where this document says tokens.css or tokens.json, call get_tokens and copy the file verbatim.",
|
|
34927
34964
|
"",
|
|
34928
34965
|
body
|
|
@@ -34934,7 +34971,7 @@ function createServer() {
|
|
|
34934
34971
|
"list_design_systems",
|
|
34935
34972
|
{
|
|
34936
34973
|
title: "List design systems",
|
|
34937
|
-
description: "Browse the
|
|
34974
|
+
description: "Browse the Pigment design systems with their tone, appearance, keywords and when each was last updated. Use it to pick a system.",
|
|
34938
34975
|
inputSchema: external_exports.object({
|
|
34939
34976
|
tone: external_exports.string().optional().describe("Filter by tone: minimal, natural, soft, editorial, brutalist, technical, playful, luxury"),
|
|
34940
34977
|
appearance: external_exports.enum(["light", "dark"]).optional().describe("Only systems that support this appearance")
|
|
@@ -34942,67 +34979,76 @@ function createServer() {
|
|
|
34942
34979
|
annotations: { readOnlyHint: true }
|
|
34943
34980
|
},
|
|
34944
34981
|
async ({ tone, appearance }) => guard(() => {
|
|
34945
|
-
const items = listTemplates().filter((t) => !tone || t.tags.tone === tone).filter((t) => !appearance || t.tags.appearance.includes(appearance)).map((t) => ({ id: t.id, name: t.name,
|
|
34946
|
-
return items.length ? JSON.stringify(items, null, 2) : "No
|
|
34982
|
+
const items = listTemplates().filter((t) => !tone || t.tags.tone === tone).filter((t) => !appearance || t.tags.appearance.includes(appearance)).map((t) => ({ id: t.id, name: t.name, updated: t.updated, description: t.description, tags: t.tags, page: `${SITE_URL}/s/${t.id}` }));
|
|
34983
|
+
return items.length ? JSON.stringify(items, null, 2) : "No system matches that filter.";
|
|
34947
34984
|
})
|
|
34948
34985
|
);
|
|
34949
34986
|
server.registerTool(
|
|
34950
34987
|
"get_design_system",
|
|
34951
34988
|
{
|
|
34952
34989
|
title: "Get design system",
|
|
34953
|
-
description: "The full specification of
|
|
34954
|
-
inputSchema: external_exports.object({ id
|
|
34990
|
+
description: "The full specification of a system: character, the defining rules, color, type, spacing and motion rules, semantic and primitive token tables, setup and verification. Read it before changing any UI.",
|
|
34991
|
+
inputSchema: external_exports.object({ id }),
|
|
34955
34992
|
annotations: { readOnlyHint: true }
|
|
34956
34993
|
},
|
|
34957
|
-
async (args) => guard(() => specForMcp(args.id
|
|
34994
|
+
async (args) => guard(() => specForMcp(args.id))
|
|
34958
34995
|
);
|
|
34959
34996
|
server.registerTool(
|
|
34960
34997
|
"get_tokens",
|
|
34961
34998
|
{
|
|
34962
34999
|
title: "Get token file",
|
|
34963
35000
|
description: "The exact token values, light and dark, as tokens.css (CSS custom properties) or tokens.json. Copy the file into the project unchanged; never retype values.",
|
|
34964
|
-
inputSchema: external_exports.object({ id,
|
|
35001
|
+
inputSchema: external_exports.object({ id, format: external_exports.enum(["css", "json"]).default("css") }),
|
|
34965
35002
|
annotations: { readOnlyHint: true }
|
|
34966
35003
|
},
|
|
34967
|
-
async (args) => guard(() => getTokenFile(args.id,
|
|
35004
|
+
async (args) => guard(() => getTokenFile(args.id, CURRENT, args.format))
|
|
34968
35005
|
);
|
|
34969
35006
|
server.registerTool(
|
|
34970
35007
|
"get_component_spec",
|
|
34971
35008
|
{
|
|
34972
35009
|
title: "Get component spec",
|
|
34973
35010
|
description: "Anatomy, variants, every state, accessibility and token mapping for one component (e.g. button, table, dialog). Read it before building or restyling that component.",
|
|
34974
|
-
inputSchema: external_exports.object({ id,
|
|
35011
|
+
inputSchema: external_exports.object({ id, component: external_exports.string().describe("Component name from the Components list in get_design_system") }),
|
|
34975
35012
|
annotations: { readOnlyHint: true }
|
|
34976
35013
|
},
|
|
34977
|
-
async (args) => guard(() => getComponentSpec(args.id,
|
|
35014
|
+
async (args) => guard(() => getComponentSpec(args.id, CURRENT, args.component).markdown)
|
|
34978
35015
|
);
|
|
34979
35016
|
server.registerTool(
|
|
34980
35017
|
"get_installation_guide",
|
|
34981
35018
|
{
|
|
34982
35019
|
title: "Get installation guide",
|
|
34983
35020
|
description: "Steps, approval points and checks for one scenario: new (set up a fresh project), existing (restyle a working app without changing behavior) or ongoing (build new screens in a project that already uses the system).",
|
|
34984
|
-
inputSchema: external_exports.object({ id,
|
|
35021
|
+
inputSchema: external_exports.object({ id, mode }),
|
|
34985
35022
|
annotations: { readOnlyHint: true }
|
|
34986
35023
|
},
|
|
34987
|
-
async (args) => guard(() => getGuide(args.id,
|
|
35024
|
+
async (args) => guard(() => getGuide(args.id, CURRENT, args.mode))
|
|
35025
|
+
);
|
|
35026
|
+
server.registerTool(
|
|
35027
|
+
"get_changelog",
|
|
35028
|
+
{
|
|
35029
|
+
title: "Get changelog",
|
|
35030
|
+
description: "What changed in a system, newest first, by date. Use it to update a project: apply only the entries dated after the date in the project's design-system/VERSION.",
|
|
35031
|
+
inputSchema: external_exports.object({ id }),
|
|
35032
|
+
annotations: { readOnlyHint: true }
|
|
35033
|
+
},
|
|
35034
|
+
async (args) => guard(() => JSON.stringify(getHistory(args.id), null, 2))
|
|
34988
35035
|
);
|
|
34989
35036
|
server.registerTool(
|
|
34990
35037
|
"get_references",
|
|
34991
35038
|
{
|
|
34992
35039
|
title: "Get references",
|
|
34993
|
-
description: "Screenshots of four reference apps (dashboard, store, blog, settings) restyled with this
|
|
34994
|
-
inputSchema: external_exports.object({ id,
|
|
35040
|
+
description: "Screenshots of four reference apps (dashboard, store, blog, settings) restyled with this system by an agent \u2014 desktop and mobile, light and dark \u2014 plus links to the system page and the spec.",
|
|
35041
|
+
inputSchema: external_exports.object({ id, app: external_exports.string().optional().describe("Only one app: dashboard, commerce, blog or settings") }),
|
|
34995
35042
|
annotations: { readOnlyHint: true }
|
|
34996
35043
|
},
|
|
34997
35044
|
async (args) => guard(() => {
|
|
34998
|
-
const
|
|
34999
|
-
const shots = Object.entries(getShots(args.id, pinned)).filter(([key]) => !args.app || key.startsWith(`${args.app}.`)).map(([key, path]) => ({ view: key, url: SITE_URL + path }));
|
|
35045
|
+
const shots = Object.entries(getShots(args.id, CURRENT)).filter(([key]) => !args.app || key.startsWith(`${args.app}.`)).map(([key, path]) => ({ view: key, url: SITE_URL + path }));
|
|
35000
35046
|
return JSON.stringify(
|
|
35001
35047
|
{
|
|
35002
|
-
system:
|
|
35003
|
-
|
|
35004
|
-
|
|
35005
|
-
|
|
35048
|
+
system: args.id,
|
|
35049
|
+
updated: updated(args.id),
|
|
35050
|
+
page: `${SITE_URL}/s/${args.id}`,
|
|
35051
|
+
spec: `${SITE_URL}/s/${args.id}/agent.md`,
|
|
35006
35052
|
screenshots: shots
|
|
35007
35053
|
},
|
|
35008
35054
|
null,
|
|
@@ -35014,29 +35060,22 @@ function createServer() {
|
|
|
35014
35060
|
"apply",
|
|
35015
35061
|
{
|
|
35016
35062
|
title: "Apply a design system",
|
|
35017
|
-
description: "Install or apply a
|
|
35063
|
+
description: "Install or apply a Pigment design system with a plan, an approval step and a verification report.",
|
|
35018
35064
|
argsSchema: external_exports.object({
|
|
35019
35065
|
id: external_exports.string().describe('Design system id, e.g. "margin-notes"'),
|
|
35020
|
-
version: external_exports.string().optional().describe("Version to pin; defaults to the latest stable version"),
|
|
35021
35066
|
mode: external_exports.string().optional().describe("new, existing (default) or ongoing")
|
|
35022
35067
|
})
|
|
35023
35068
|
},
|
|
35024
|
-
({ id: systemId,
|
|
35025
|
-
const pinned = getManifest(systemId, wanted ?? "latest").version;
|
|
35069
|
+
({ id: systemId, mode: scenario }) => {
|
|
35026
35070
|
const m = mode.safeParse(scenario ?? "existing");
|
|
35027
35071
|
return {
|
|
35028
|
-
messages: [
|
|
35029
|
-
{
|
|
35030
|
-
role: "user",
|
|
35031
|
-
content: { type: "text", text: buildPrompt(systemId, pinned, m.success ? m.data : "existing", "mcp") }
|
|
35032
|
-
}
|
|
35033
|
-
]
|
|
35072
|
+
messages: [{ role: "user", content: { type: "text", text: buildPrompt(systemId, m.success ? m.data : "existing", "mcp") } }]
|
|
35034
35073
|
};
|
|
35035
35074
|
}
|
|
35036
35075
|
);
|
|
35037
35076
|
return server;
|
|
35038
35077
|
}
|
|
35039
|
-
var SERVER_VERSION, id,
|
|
35078
|
+
var SERVER_VERSION, CURRENT, id, mode, INSTRUCTIONS;
|
|
35040
35079
|
var init_server = __esm({
|
|
35041
35080
|
"src/server.ts"() {
|
|
35042
35081
|
"use strict";
|
|
@@ -35046,15 +35085,15 @@ var init_server = __esm({
|
|
|
35046
35085
|
init_zod();
|
|
35047
35086
|
init_package();
|
|
35048
35087
|
SERVER_VERSION = package_default.version;
|
|
35088
|
+
CURRENT = "latest";
|
|
35049
35089
|
id = external_exports.string().describe('Design system id, e.g. "margin-notes" (see list_design_systems)');
|
|
35050
|
-
|
|
35090
|
+
mode = external_exports.enum(["new", "existing", "ongoing"]);
|
|
35051
35091
|
INSTRUCTIONS = [
|
|
35052
|
-
"Pigment serves
|
|
35053
|
-
"
|
|
35054
|
-
"
|
|
35055
|
-
"
|
|
35092
|
+
"Pigment serves design systems for coding agents. Every tool returns the current system; there is nothing to choose or pin.",
|
|
35093
|
+
"Applying a system copies it into the project's design-system/ folder (tokens, component notes and a VERSION file naming the system and its update date).",
|
|
35094
|
+
"From then on design-system/ is the project's source of truth: build new screens from it and don't re-fetch tokens unless the user asks to update.",
|
|
35095
|
+
"To update, call get_changelog, apply only the entries dated after the date in design-system/VERSION, and then write the new date."
|
|
35056
35096
|
].join("\n");
|
|
35057
|
-
mode = external_exports.enum(["new", "existing", "ongoing"]);
|
|
35058
35097
|
}
|
|
35059
35098
|
});
|
|
35060
35099
|
|