pigment-mcp 0.3.0 → 0.4.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/README.md +6 -6
- package/cli.js +147 -106
- 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,16 @@ 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}
|
|
34855
|
+
function specRef(id2, delivery) {
|
|
34856
|
+
if (delivery === "url") return `Spec: ${SITE_URL}/s/${id2}/agent.md`;
|
|
34824
34857
|
if (delivery === "mcp") return "Read the spec with the Pigment MCP tools (get_design_system, get_component_spec).";
|
|
34825
|
-
return `Spec:
|
|
34858
|
+
return `Spec: dist/agent.md in the ${id2} package, unzipped under ./design-packages/`;
|
|
34826
34859
|
}
|
|
34827
|
-
function buildPrompt(id2,
|
|
34828
|
-
const
|
|
34829
|
-
const spec = specRef(id2, version3, delivery);
|
|
34860
|
+
function buildPrompt(id2, mode2, delivery) {
|
|
34861
|
+
const spec = specRef(id2, delivery);
|
|
34830
34862
|
if (mode2 === "new") {
|
|
34831
34863
|
return [
|
|
34832
|
-
`Set up design system ${
|
|
34864
|
+
`Set up design system ${id2} in this codebase.`,
|
|
34833
34865
|
spec,
|
|
34834
34866
|
"First inspect the framework, styling approach and component structure, then propose an installation plan and wait for my approval.",
|
|
34835
34867
|
"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 +34870,7 @@ function buildPrompt(id2, version3, mode2, delivery) {
|
|
|
34838
34870
|
}
|
|
34839
34871
|
if (mode2 === "existing") {
|
|
34840
34872
|
return [
|
|
34841
|
-
`Apply design system ${
|
|
34873
|
+
`Apply design system ${id2} to this project.`,
|
|
34842
34874
|
spec,
|
|
34843
34875
|
"Preserve features, routes, business logic, API contracts, tests and accessibility.",
|
|
34844
34876
|
"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 +34878,7 @@ function buildPrompt(id2, version3, mode2, delivery) {
|
|
|
34846
34878
|
].join("\n");
|
|
34847
34879
|
}
|
|
34848
34880
|
return [
|
|
34849
|
-
`Build this with the installed design system ${
|
|
34881
|
+
`Build this with the installed design system ${id2}.`,
|
|
34850
34882
|
"Use its semantic tokens and component conventions from design-system/. Don't hard-code new style values.",
|
|
34851
34883
|
"If the spec doesn't cover something, ask me with options before deciding."
|
|
34852
34884
|
].join("\n");
|
|
@@ -34866,7 +34898,7 @@ var init_package = __esm({
|
|
|
34866
34898
|
"package.json"() {
|
|
34867
34899
|
package_default = {
|
|
34868
34900
|
name: "@pigment/mcp",
|
|
34869
|
-
version: "0.
|
|
34901
|
+
version: "0.4.0",
|
|
34870
34902
|
private: true,
|
|
34871
34903
|
type: "module",
|
|
34872
34904
|
description: "MCP server for Pigment design systems: tokens, rules, component specs and installation guides for your coding agent.",
|
|
@@ -34908,9 +34940,15 @@ function guard(fn) {
|
|
|
34908
34940
|
throw e;
|
|
34909
34941
|
}
|
|
34910
34942
|
}
|
|
34911
|
-
function
|
|
34912
|
-
const
|
|
34913
|
-
|
|
34943
|
+
function updated(systemId) {
|
|
34944
|
+
const t = listTemplates().find((x) => x.id === systemId);
|
|
34945
|
+
if (!t) throw new ContentError("unknown_template", `No published system "${systemId}". Call list_design_systems.`);
|
|
34946
|
+
return t.updated;
|
|
34947
|
+
}
|
|
34948
|
+
function specForMcp(systemId) {
|
|
34949
|
+
const date5 = updated(systemId);
|
|
34950
|
+
const md = getAgentMd(systemId, CURRENT);
|
|
34951
|
+
const index = getComponents(systemId, CURRENT).components;
|
|
34914
34952
|
const start = md.indexOf("\n## Components");
|
|
34915
34953
|
const end = start < 0 ? -1 : md.indexOf("\n## ", start + 4);
|
|
34916
34954
|
const specified = index.filter((c) => c.status !== "unsupported").map((c) => c.name);
|
|
@@ -34918,11 +34956,11 @@ function specForMcp(systemId, pinned) {
|
|
|
34918
34956
|
const chapter = [
|
|
34919
34957
|
"\n## Components\n",
|
|
34920
34958
|
`Specified: ${specified.join(", ")}. Read each with get_component_spec before building it.`,
|
|
34921
|
-
unsupported.length ? `Not specified in this
|
|
34959
|
+
unsupported.length ? `Not specified in this system: ${unsupported.join(", ")} \u2014 compose them from tokens and say so in your report.` : ""
|
|
34922
34960
|
].join("\n");
|
|
34923
34961
|
const body = start < 0 ? md : md.slice(0, start) + chapter + (end < 0 ? "" : md.slice(end));
|
|
34924
34962
|
return [
|
|
34925
|
-
`>
|
|
34963
|
+
`> Pigment system ${systemId}, updated ${date5}. Write \`${systemId}, updated ${date5}\` in design-system/VERSION.`,
|
|
34926
34964
|
"> Where this document says tokens.css or tokens.json, call get_tokens and copy the file verbatim.",
|
|
34927
34965
|
"",
|
|
34928
34966
|
body
|
|
@@ -34934,7 +34972,7 @@ function createServer() {
|
|
|
34934
34972
|
"list_design_systems",
|
|
34935
34973
|
{
|
|
34936
34974
|
title: "List design systems",
|
|
34937
|
-
description: "Browse the
|
|
34975
|
+
description: "Browse the Pigment design systems with their tone, appearance, keywords and when each was last updated. Use it to pick a system.",
|
|
34938
34976
|
inputSchema: external_exports.object({
|
|
34939
34977
|
tone: external_exports.string().optional().describe("Filter by tone: minimal, natural, soft, editorial, brutalist, technical, playful, luxury"),
|
|
34940
34978
|
appearance: external_exports.enum(["light", "dark"]).optional().describe("Only systems that support this appearance")
|
|
@@ -34942,67 +34980,77 @@ function createServer() {
|
|
|
34942
34980
|
annotations: { readOnlyHint: true }
|
|
34943
34981
|
},
|
|
34944
34982
|
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
|
|
34983
|
+
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}` }));
|
|
34984
|
+
return items.length ? JSON.stringify(items, null, 2) : "No system matches that filter.";
|
|
34947
34985
|
})
|
|
34948
34986
|
);
|
|
34949
34987
|
server.registerTool(
|
|
34950
34988
|
"get_design_system",
|
|
34951
34989
|
{
|
|
34952
34990
|
title: "Get design system",
|
|
34953
|
-
description: "The full specification of
|
|
34954
|
-
inputSchema: external_exports.object({ id
|
|
34991
|
+
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.",
|
|
34992
|
+
inputSchema: external_exports.object({ id }),
|
|
34955
34993
|
annotations: { readOnlyHint: true }
|
|
34956
34994
|
},
|
|
34957
|
-
async (args) => guard(() => specForMcp(args.id
|
|
34995
|
+
async (args) => guard(() => specForMcp(args.id))
|
|
34958
34996
|
);
|
|
34959
34997
|
server.registerTool(
|
|
34960
34998
|
"get_tokens",
|
|
34961
34999
|
{
|
|
34962
35000
|
title: "Get token file",
|
|
34963
35001
|
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,
|
|
35002
|
+
inputSchema: external_exports.object({ id, format: external_exports.enum(["css", "json"]).default("css") }),
|
|
34965
35003
|
annotations: { readOnlyHint: true }
|
|
34966
35004
|
},
|
|
34967
|
-
async (args) => guard(() => getTokenFile(args.id,
|
|
35005
|
+
async (args) => guard(() => getTokenFile(args.id, CURRENT, args.format))
|
|
34968
35006
|
);
|
|
34969
35007
|
server.registerTool(
|
|
34970
35008
|
"get_component_spec",
|
|
34971
35009
|
{
|
|
34972
35010
|
title: "Get component spec",
|
|
34973
35011
|
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,
|
|
35012
|
+
inputSchema: external_exports.object({ id, component: external_exports.string().describe("Component name from the Components list in get_design_system") }),
|
|
34975
35013
|
annotations: { readOnlyHint: true }
|
|
34976
35014
|
},
|
|
34977
|
-
async (args) => guard(() => getComponentSpec(args.id,
|
|
35015
|
+
async (args) => guard(() => getComponentSpec(args.id, CURRENT, args.component).markdown)
|
|
34978
35016
|
);
|
|
34979
35017
|
server.registerTool(
|
|
34980
35018
|
"get_installation_guide",
|
|
34981
35019
|
{
|
|
34982
35020
|
title: "Get installation guide",
|
|
34983
35021
|
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,
|
|
35022
|
+
inputSchema: external_exports.object({ id, mode }),
|
|
34985
35023
|
annotations: { readOnlyHint: true }
|
|
34986
35024
|
},
|
|
34987
|
-
async (args) => guard(() => getGuide(args.id,
|
|
35025
|
+
async (args) => guard(() => getGuide(args.id, CURRENT, args.mode))
|
|
35026
|
+
);
|
|
35027
|
+
server.registerTool(
|
|
35028
|
+
"get_changelog",
|
|
35029
|
+
{
|
|
35030
|
+
title: "Get changelog",
|
|
35031
|
+
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.",
|
|
35032
|
+
inputSchema: external_exports.object({ id }),
|
|
35033
|
+
annotations: { readOnlyHint: true }
|
|
35034
|
+
},
|
|
35035
|
+
async (args) => guard(() => JSON.stringify(getHistory(args.id), null, 2))
|
|
34988
35036
|
);
|
|
34989
35037
|
server.registerTool(
|
|
34990
35038
|
"get_references",
|
|
34991
35039
|
{
|
|
34992
35040
|
title: "Get references",
|
|
34993
|
-
description: "Screenshots of four reference apps (dashboard, store, blog, settings) restyled with this
|
|
34994
|
-
inputSchema: external_exports.object({ id,
|
|
35041
|
+
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, spec and offline package.",
|
|
35042
|
+
inputSchema: external_exports.object({ id, app: external_exports.string().optional().describe("Only one app: dashboard, commerce, blog or settings") }),
|
|
34995
35043
|
annotations: { readOnlyHint: true }
|
|
34996
35044
|
},
|
|
34997
35045
|
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 }));
|
|
35046
|
+
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
35047
|
return JSON.stringify(
|
|
35001
35048
|
{
|
|
35002
|
-
system:
|
|
35003
|
-
|
|
35004
|
-
|
|
35005
|
-
|
|
35049
|
+
system: args.id,
|
|
35050
|
+
updated: updated(args.id),
|
|
35051
|
+
page: `${SITE_URL}/s/${args.id}`,
|
|
35052
|
+
spec: `${SITE_URL}/s/${args.id}/agent.md`,
|
|
35053
|
+
package: `${SITE_URL}/download/${args.id}`,
|
|
35006
35054
|
screenshots: shots
|
|
35007
35055
|
},
|
|
35008
35056
|
null,
|
|
@@ -35014,29 +35062,22 @@ function createServer() {
|
|
|
35014
35062
|
"apply",
|
|
35015
35063
|
{
|
|
35016
35064
|
title: "Apply a design system",
|
|
35017
|
-
description: "Install or apply a
|
|
35065
|
+
description: "Install or apply a Pigment design system with a plan, an approval step and a verification report.",
|
|
35018
35066
|
argsSchema: external_exports.object({
|
|
35019
35067
|
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
35068
|
mode: external_exports.string().optional().describe("new, existing (default) or ongoing")
|
|
35022
35069
|
})
|
|
35023
35070
|
},
|
|
35024
|
-
({ id: systemId,
|
|
35025
|
-
const pinned = getManifest(systemId, wanted ?? "latest").version;
|
|
35071
|
+
({ id: systemId, mode: scenario }) => {
|
|
35026
35072
|
const m = mode.safeParse(scenario ?? "existing");
|
|
35027
35073
|
return {
|
|
35028
|
-
messages: [
|
|
35029
|
-
{
|
|
35030
|
-
role: "user",
|
|
35031
|
-
content: { type: "text", text: buildPrompt(systemId, pinned, m.success ? m.data : "existing", "mcp") }
|
|
35032
|
-
}
|
|
35033
|
-
]
|
|
35074
|
+
messages: [{ role: "user", content: { type: "text", text: buildPrompt(systemId, m.success ? m.data : "existing", "mcp") } }]
|
|
35034
35075
|
};
|
|
35035
35076
|
}
|
|
35036
35077
|
);
|
|
35037
35078
|
return server;
|
|
35038
35079
|
}
|
|
35039
|
-
var SERVER_VERSION, id,
|
|
35080
|
+
var SERVER_VERSION, CURRENT, id, mode, INSTRUCTIONS;
|
|
35040
35081
|
var init_server = __esm({
|
|
35041
35082
|
"src/server.ts"() {
|
|
35042
35083
|
"use strict";
|
|
@@ -35046,15 +35087,15 @@ var init_server = __esm({
|
|
|
35046
35087
|
init_zod();
|
|
35047
35088
|
init_package();
|
|
35048
35089
|
SERVER_VERSION = package_default.version;
|
|
35090
|
+
CURRENT = "latest";
|
|
35049
35091
|
id = external_exports.string().describe('Design system id, e.g. "margin-notes" (see list_design_systems)');
|
|
35050
|
-
|
|
35092
|
+
mode = external_exports.enum(["new", "existing", "ongoing"]);
|
|
35051
35093
|
INSTRUCTIONS = [
|
|
35052
|
-
"Pigment serves
|
|
35053
|
-
"
|
|
35054
|
-
"
|
|
35055
|
-
"
|
|
35094
|
+
"Pigment serves design systems for coding agents. Every tool returns the current system; there is nothing to choose or pin.",
|
|
35095
|
+
"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).",
|
|
35096
|
+
"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.",
|
|
35097
|
+
"To update, call get_changelog, apply only the entries dated after the date in design-system/VERSION, and then write the new date."
|
|
35056
35098
|
].join("\n");
|
|
35057
|
-
mode = external_exports.enum(["new", "existing", "ongoing"]);
|
|
35058
35099
|
}
|
|
35059
35100
|
});
|
|
35060
35101
|
|