@expressivecss/mcp-server 0.2.2 → 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/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/CHANGELOG.md +76 -0
- package/README.md +485 -3
- package/package.json +1 -1
- package/server.js +484 -44
- package/smoke.mjs +1221 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expressivecss-mcp",
|
|
3
3
|
"displayName": "ExpressiveCSS MCP",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "ExpressiveCSS workflow server with Setup Expert, Rules Enforcer, Creative Director, Page Arcjitect, Component Syntax Expert, and Quality Inspector.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "BaezFJ",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expressivecss-mcp",
|
|
3
3
|
"displayName": "ExpressiveCSS MCP",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "ExpressiveCSS workflow server with Setup Expert, Rules Enforcer, Creative Director, Page Arcjitect, Component Syntax Expert, and Quality Inspector.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "BaezFJ",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,81 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 - 2026-10-06
|
|
4
|
+
|
|
5
|
+
- Breaking: guidance tools now cap each result at 64 KiB of UTF-8 by
|
|
6
|
+
default. A response that used to arrive whole can now omit whole
|
|
7
|
+
units and list them in `responseBudget`. To return larger responses, set
|
|
8
|
+
`EXPRESSIVECSS_MCP_MAX_RESPONSE_BYTES` in the server's environment. The
|
|
9
|
+
limit is described in its own entry below.
|
|
10
|
+
|
|
11
|
+
- Add argument completion to the component resource templates. Both templates
|
|
12
|
+
complete canonical slugs by case-insensitive prefix, and
|
|
13
|
+
`component_guide_section` also completes section names. Aliases are not
|
|
14
|
+
matched. Results use the SDK limit of 100 values with `total` and `hasMore`.
|
|
15
|
+
Unknown template references return `-32602`. Completion reads only the
|
|
16
|
+
bundled catalogue and stays outside the response byte budget. Tool arguments
|
|
17
|
+
are not completed.
|
|
18
|
+
|
|
19
|
+
- Add versioned component guide resources for the current bundled snapshot.
|
|
20
|
+
The `component_guide` template returns a whole guide with its complete
|
|
21
|
+
contract, syntax, rules, Options and Methods. `component_guide_section`
|
|
22
|
+
returns one of those sections. `resources/list` lists every whole-guide URI.
|
|
23
|
+
Reads share the operator byte budget and deliver sections whole. A read that
|
|
24
|
+
cannot fit returns `-32001` with the section URIs that fit and the sections
|
|
25
|
+
that need a larger budget. Aliases, unknown names and unavailable snapshot
|
|
26
|
+
identities return `-32002`. Budget errors now name the URI that was read.
|
|
27
|
+
|
|
28
|
+
- Add a read-only `component_catalog` resource for the current bundled snapshot,
|
|
29
|
+
identified by framework version and contract source hash. JSON contents reuse
|
|
30
|
+
the complete compact catalogue and retain unknown consumer compatibility.
|
|
31
|
+
Reads use the existing operator byte budget and deliver every entry whole or
|
|
32
|
+
return protocol error `-32001` with a sufficient restart budget. Discovery
|
|
33
|
+
remains available under small budgets; unknown resource identities return
|
|
34
|
+
`-32002`. Existing tools, QA policy and package versions remain unchanged.
|
|
35
|
+
|
|
36
|
+
- Guidance tools enforce a configurable 64 KiB UTF-8 limit on the complete
|
|
37
|
+
serialized tool result, including text and structured content. Typed
|
|
38
|
+
`responseBudget` metadata accounts for whole-unit omissions and narrower
|
|
39
|
+
recovery requests. Indivisible guidance or accounting that cannot fit produces
|
|
40
|
+
an explicit budget error; impossible minimal results use JSON-RPC error
|
|
41
|
+
`-32001`. Setup, creative, both page aliases, syntax and catalogue share the
|
|
42
|
+
limit; QA limits and evidence behavior remain unchanged. Syntax code is whole
|
|
43
|
+
or omitted, and retained contract-prose limits have explicit disclosure.
|
|
44
|
+
|
|
45
|
+
- `component_syntax_expert` accepts `detail: "compact"` or `"detailed"`, with
|
|
46
|
+
detailed as the backward-compatible default. Compact retains complete rules,
|
|
47
|
+
identity and shared evidence while omitting contract prose and syntax examples.
|
|
48
|
+
Requested Options/Methods and explicit foundations work in both modes.
|
|
49
|
+
`includeCapabilities` overrides component capability detail, which defaults
|
|
50
|
+
off in compact and on in detailed. Effective selectors and schema-validated
|
|
51
|
+
`omittedFields` identify intentional omissions and their reasons. Retrieve
|
|
52
|
+
omitted detail through the supported selectors. Existing version/provenance
|
|
53
|
+
safety checks remain. Contract summaries retain their disclosed prose limit;
|
|
54
|
+
examples now use whole delivery or explicit budget omission.
|
|
55
|
+
|
|
56
|
+
- `component_catalog` accepts optional `query` and `limit` to search existing
|
|
57
|
+
names, aliases and compact descriptions. Exact matches precede labelled
|
|
58
|
+
heuristic matches. Search defaults to 10 results, permits at most 50 and
|
|
59
|
+
reports total/omitted counts, truncation and explicit empty results. Full
|
|
60
|
+
listings and compatibility/provenance evidence remain unchanged.
|
|
61
|
+
|
|
62
|
+
- Add read-only `component_catalog` for complete compact component listings,
|
|
63
|
+
existing aliases and runtime ownership, documentation links and bundled
|
|
64
|
+
version/source hash. Optional explicit targets receive compatibility and
|
|
65
|
+
provenance checks; omitted targets remain unchecked.
|
|
66
|
+
|
|
67
|
+
- `component_syntax_expert` accepts `sections: ["methods"]` or both `"options"`
|
|
68
|
+
and `"methods"` once each. Requested Methods return complete bundled Markdown
|
|
69
|
+
or an explicit absent-section record. Defaults and compatibility/provenance
|
|
70
|
+
evidence remain unchanged.
|
|
71
|
+
- `component_syntax_expert` accepts `sections: ["options"]` to return complete
|
|
72
|
+
bundled Options Markdown or an explicit absent-section record. Existing
|
|
73
|
+
requests omit these records; compatibility and provenance evidence are unchanged.
|
|
74
|
+
- `component_syntax_expert` returns complete component rules in source order,
|
|
75
|
+
including rules previously omitted by the eight-rule cap. Generic fallback
|
|
76
|
+
advice remains unchanged.
|
|
77
|
+
- Bundled framework guidance: ExpressiveCSS 0.12.0.
|
|
78
|
+
|
|
3
79
|
## 0.2.2 - 2026-10-01
|
|
4
80
|
|
|
5
81
|
- Semantics findings from `rules_enforcer`, `quality_inspector`, and
|
package/README.md
CHANGED
|
@@ -11,11 +11,215 @@ This folder contains a self-hosted MCP server for the ExpressiveCSS design-to-QA
|
|
|
11
11
|
|
|
12
12
|
The server bundles generated component guides, selection data, contract metadata, and the normative semantics data. All component guidance comes from this synchronized package data. A framework source checkout contributes only target-version and contract-provenance evidence, so local prose cannot replace the packaged guidance.
|
|
13
13
|
|
|
14
|
+
`component_syntax_expert` returns every rule from each found component's bundled Rules section, in source order. Guides without rule bullets retain generic authoring advice. Looking up rules does not establish component-rule conformance.
|
|
15
|
+
|
|
16
|
+
## Selectable syntax detail
|
|
17
|
+
|
|
18
|
+
`detail` accepts `"compact"` or `"detailed"` and defaults to `"detailed"`.
|
|
19
|
+
Existing request forms and defaults remain valid. Both modes retain complete
|
|
20
|
+
rules for delivered components, identity, sources, lookup results and shared
|
|
21
|
+
compatibility/provenance evidence. The aggregate budget below can omit whole
|
|
22
|
+
fields or components with explicit accounting.
|
|
23
|
+
|
|
24
|
+
| Component field | Compact | Detailed |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| `file`, `slug`, `title`, `source`, `docs`, `rules` | Included | Included |
|
|
27
|
+
| `contract`, `syntax` | Omitted | Contract summary and whole syntax example, subject to budget |
|
|
28
|
+
| `options`, `methods` | Included only when requested through `sections` | Same |
|
|
29
|
+
| `capability` | Omitted by default | Included by default |
|
|
30
|
+
|
|
31
|
+
The optional boolean `includeCapabilities` overrides the component capability
|
|
32
|
+
default in either mode. Explicit `sections` requests work in both modes and
|
|
33
|
+
retain complete documented Markdown or explicit absence. Explicit `foundations`
|
|
34
|
+
requests remain effective even with `includeCapabilities: false`; that selector
|
|
35
|
+
controls only component capability records.
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"components": ["date-picker", "autocomplete"],
|
|
40
|
+
"detail": "compact",
|
|
41
|
+
"sections": ["options", "methods"],
|
|
42
|
+
"includeCapabilities": true
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Ordinary results report effective `detail` and `includeCapabilities`. Each found
|
|
47
|
+
component adds `omittedFields`, with one record per intentionally omitted field:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"field": "syntax",
|
|
52
|
+
"reason": "compact-detail"
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Fields are reported in `contract`, `syntax`, `options`, `methods`, `capability`
|
|
57
|
+
order. Compact prose/example omissions use `compact-detail`. Unrequested API
|
|
58
|
+
sections and disabled component capability detail use `not-requested`. Requested
|
|
59
|
+
API records with `status: "absent"` and included null capability records are
|
|
60
|
+
delivered results, so they have no omission record. The syntax output schema
|
|
61
|
+
validates selector values and omission fields/reasons. Byte omissions use
|
|
62
|
+
`byte-budget`. A contract summary longer than 900 characters reports
|
|
63
|
+
`length-limit`, with its shortened prose still present. A disabled syntax tool
|
|
64
|
+
retains its shared blocked envelope and budget metadata without retrieval fields.
|
|
65
|
+
|
|
66
|
+
Recover omitted prose/examples with `detail: "detailed"`, API sections with
|
|
67
|
+
`sections`, and component capability records with `includeCapabilities: true`.
|
|
68
|
+
Version/provenance checks still block unsafe capability data. Detail selection
|
|
69
|
+
does not change compatibility or missing-name lookup. Budget omissions make
|
|
70
|
+
delivery partial or erroneous. Text and structured content describe the same result.
|
|
71
|
+
|
|
72
|
+
Detailed output retains the contract summary limit of 900 characters with
|
|
73
|
+
explicit disclosure. Read the linked component documentation for full contract
|
|
74
|
+
prose; increasing the byte budget does not remove this summary limit. Syntax
|
|
75
|
+
examples, rules and requested API sections are whole or explicitly omitted.
|
|
76
|
+
Generic fallback advice remains nonnormative, and retrieval does not verify
|
|
77
|
+
consumer interaction, visual or accessibility behavior.
|
|
78
|
+
|
|
79
|
+
## Aggregate response budget and recovery
|
|
80
|
+
|
|
81
|
+
`EXPRESSIVECSS_MCP_MAX_RESPONSE_BYTES` defaults to 65,536 bytes, or 64 KiB.
|
|
82
|
+
Set it in the server's environment to a positive safe integer in decimal digits.
|
|
83
|
+
Empty values, zero, signed numbers, fractions, whitespace, exponents and unsafe
|
|
84
|
+
integers fail startup. Clients cannot override this operator setting.
|
|
85
|
+
|
|
86
|
+
The budget applies to `setup_expert`, `creative_director`, `page_architect`,
|
|
87
|
+
`page_arcjitect`, `component_syntax_expert` and `component_catalog`, including
|
|
88
|
+
disabled-tool and SDK validation-error results. `rules_enforcer` and
|
|
89
|
+
`quality_inspector` retain their existing QA limits and evidence behavior.
|
|
90
|
+
The [catalogue resource](#versioned-catalogue-resource) and
|
|
91
|
+
[component resources](#versioned-component-resources) use the same setting to
|
|
92
|
+
bound successful resource-read results, with complete delivery or a protocol
|
|
93
|
+
error. Discovery lists are outside the content budget.
|
|
94
|
+
|
|
95
|
+
The exact measurement is `Buffer.byteLength(JSON.stringify(result), 'utf8')`.
|
|
96
|
+
It counts the entire wire tool-result object, including JSON escapes, text,
|
|
97
|
+
structured content, metadata and `isError`. These tools use compact JSON text
|
|
98
|
+
and duplicate the same payload in structured content. The outer JSON-RPC
|
|
99
|
+
envelope and stdio framing are excluded. A final transport check covers errors
|
|
100
|
+
the SDK creates before or after a handler runs.
|
|
101
|
+
|
|
102
|
+
Affected structured results add `responseBudget`:
|
|
103
|
+
|
|
104
|
+
| Field | Meaning |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `maxBytes` | Effective operator budget. |
|
|
107
|
+
| `delivery` | `complete`, `partial` or `error` for the requested projection. |
|
|
108
|
+
| `omissions` | Every byte-omitted unit, with its identity, `reason: "byte-budget"` and recovery index. |
|
|
109
|
+
| `recoveries` | Typed retry requests or advice to increase the operator budget. |
|
|
110
|
+
|
|
111
|
+
Syntax omission identities include original request position and name, canonical
|
|
112
|
+
slug when known and field when applicable. Delivered components have
|
|
113
|
+
`requestIndex` for repeated or mixed known/unknown requests. Selector omissions
|
|
114
|
+
remain in `found[].omittedFields`; budget omissions also identify fields there.
|
|
115
|
+
Unknown components, absent API sections and blocked capabilities retain their
|
|
116
|
+
existing distinct meanings. `foundCount` and catalogue `count` count only
|
|
117
|
+
delivered records.
|
|
118
|
+
|
|
119
|
+
Reduction is deterministic. Syntax drops whole optional capability records,
|
|
120
|
+
contract summaries and examples before whole requested Options/Methods, then
|
|
121
|
+
whole components and foundations. It works backwards through each collection
|
|
122
|
+
so retained records preserve their original order. A delivered component always
|
|
123
|
+
retains all its rules in source order. Catalogue and creative reductions remove
|
|
124
|
+
whole trailing entries while preserving ranking. Page architecture and its
|
|
125
|
+
skeleton are indivisible. Setup checks can fail explicitly when they cannot fit.
|
|
126
|
+
Compatibility, provenance, performed checks and evidence limits remain truthful.
|
|
127
|
+
Budget omissions never imply complete coverage or browser approval.
|
|
128
|
+
|
|
129
|
+
For `delivery: "partial"`, execute a referenced recovery request:
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"action": "retry",
|
|
134
|
+
"request": {
|
|
135
|
+
"name": "component_syntax_expert",
|
|
136
|
+
"arguments": {
|
|
137
|
+
"projectRoot": "/absolute/path/to/project",
|
|
138
|
+
"workflowId": "example-workflow",
|
|
139
|
+
"components": ["autocomplete"],
|
|
140
|
+
"detail": "compact",
|
|
141
|
+
"includeCapabilities": false,
|
|
142
|
+
"sections": ["methods"]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Catalogue recovery uses an exact slug query with `limit: 1`, preserving any
|
|
149
|
+
explicit target. It omits the optional workflow correlation ID because
|
|
150
|
+
catalogue retrieval has no workflow state. Search-limit omissions and byte
|
|
151
|
+
omissions have separate accounting. Catalogue tool recovery adds no pagination
|
|
152
|
+
and does not require resource support in the client.
|
|
153
|
+
|
|
154
|
+
Creative recovery reranks a concise goal naming the omitted component with
|
|
155
|
+
`maxSuggestions: 1`, preserving target and workflow context. Ranking scores and
|
|
156
|
+
explanations can change with the narrower goal. The server offers this request
|
|
157
|
+
only when it returns the named suggestion whole within the same budget.
|
|
158
|
+
|
|
159
|
+
If an indivisible unit or the complete omission accounting cannot fit,
|
|
160
|
+
`delivery: "error"` and `isError: true` advise an operator budget increase.
|
|
161
|
+
Error results can retain whole reference records but make no successful-delivery
|
|
162
|
+
claim. If even a minimal truthful result with essential evidence cannot fit,
|
|
163
|
+
the server returns JSON-RPC error `-32001` with no tool-result object. The
|
|
164
|
+
protocol error envelope is outside the tool-result budget. Do not retry that
|
|
165
|
+
failure expecting same-budget success. Increase the server setting and restart,
|
|
166
|
+
then repeat the request. A budget of 1 is valid and exercises this failure path.
|
|
167
|
+
|
|
168
|
+
## Requested runtime API sections
|
|
169
|
+
|
|
170
|
+
To request documented runtime Options, add `sections: ["options"]`:
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"components": ["date-picker", "cards"],
|
|
175
|
+
"sections": ["options"]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Each found component adds an `options` record. A documented section returns
|
|
180
|
+
`{ "status": "documented", "markdown": "..." }` with its complete bundled Markdown
|
|
181
|
+
body, including tables and nested guidance. Datepicker includes its visibility
|
|
182
|
+
and docked-display options. A missing or empty section returns
|
|
183
|
+
`{ "status": "absent", "markdown": null }`; this means the bundled guide has no
|
|
184
|
+
documented Options section, not that the component has no configuration.
|
|
185
|
+
Cards is one such guide.
|
|
186
|
+
|
|
187
|
+
To request documented runtime Methods, use `sections: ["methods"]`. Select both
|
|
188
|
+
sections with `sections: ["options", "methods"]`:
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"components": ["autocomplete", "cards"],
|
|
193
|
+
"sections": ["options", "methods"]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Each found component adds a `methods` record when selected. Documented Methods
|
|
198
|
+
return their complete bundled Markdown in the same `{ "status": "documented",
|
|
199
|
+
"markdown": "..." }` shape. Autocomplete includes `.destroy()` and its cleanup
|
|
200
|
+
guidance. A missing or empty Methods section returns `{ "status": "absent",
|
|
201
|
+
"markdown": null }`. This describes the guide's documentation; it does not
|
|
202
|
+
establish that the runtime has no methods. Cards reports absence.
|
|
203
|
+
|
|
204
|
+
Existing requests such as `{ "components": ["date-picker"] }` retain their fields.
|
|
205
|
+
Omitting `sections` or using `sections: []` omits both optional records. Options-only
|
|
206
|
+
selection omits `methods`; Methods-only selection omits `options`. The selector
|
|
207
|
+
accepts either supported name once, or both in either order with the same result.
|
|
208
|
+
Unknown names, duplicate entries and arrays over two entries are rejected.
|
|
209
|
+
Component and foundation request limits remain unchanged. Unknown component names
|
|
210
|
+
keep their existing `missing` result.
|
|
211
|
+
|
|
212
|
+
Requested Options and Methods remain bundled reference data when target-version or
|
|
213
|
+
provenance checks block a result. They do not change compatibility, capability
|
|
214
|
+
evidence or availability, and do not verify runtime or accessibility behavior.
|
|
215
|
+
|
|
14
216
|
A resolved version matching the bundled contract reports `documentationMode: "bundled"` and `bundledContractSafe: true`. `documentationSources.bundled` identifies the contract version and source hash. This resolver does not verify the public website, so `currentDocsSafe` and `documentationSources.current.available` remain false even on a match. Use matching bundled guidance, installed sources, or a proven release tag for version-specific claims.
|
|
15
217
|
|
|
16
218
|
## Material capability evidence
|
|
17
219
|
|
|
18
|
-
`component_syntax_expert` adds a scoped `capability` record to each found component
|
|
220
|
+
`component_syntax_expert` adds a scoped `capability` record to each found component
|
|
221
|
+
when component capability detail is enabled. Detailed mode enables it by default;
|
|
222
|
+
compact mode omits it by default. `includeCapabilities` overrides either default.
|
|
19
223
|
For foundations, pass `foundations: ["typography", "shape", "motion"]`; component
|
|
20
224
|
names are optional for this request. Results distinguish documented scope,
|
|
21
225
|
pinned source review, feature/integration gaps, mapped checks and recorded results.
|
|
@@ -29,6 +233,276 @@ does not rerun tests or re-review sources. The optional Markdown
|
|
|
29
233
|
[roadmap](https://github.com/BaezFJ/ExpressiveCSS/blob/master/skills/expressivecss/references/capability-roadmap.md) and packaged
|
|
30
234
|
`capability-roadmap.json` come from the same catalogue.
|
|
31
235
|
|
|
236
|
+
## Component catalogue
|
|
237
|
+
|
|
238
|
+
Call `component_catalog` with `{}` to list every component in the server's
|
|
239
|
+
current bundle. No design goal or component name is required. To also check a
|
|
240
|
+
consumer project, supply an explicit target:
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
{ "projectRoot": "/absolute/path/to/consumer" }
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
An optional `workflowId` associates the result with other tool calls. `entries`
|
|
247
|
+
are sorted by canonical `slug`, and `count` reports their total. Each entry has:
|
|
248
|
+
|
|
249
|
+
| Field | Source and meaning |
|
|
250
|
+
| --- | --- |
|
|
251
|
+
| `slug`, `title` | Canonical guide name and title. Pass the slug to `component_syntax_expert`. |
|
|
252
|
+
| `description` | First nonempty decision `useWhen` string, then `jobs`, or null. |
|
|
253
|
+
| `aliases` | Existing decision aliases, or an empty array. These describe the component; they do not extend exact syntax lookup. |
|
|
254
|
+
| `runtime` | Existing runtime ownership value, or null. |
|
|
255
|
+
| `docs` | Bundled guide's documentation link, or null. |
|
|
256
|
+
|
|
257
|
+
The result includes `contractVersion`, `sourceHash` and `guideSource: "bundled"`
|
|
258
|
+
to identify the shipped snapshot. It contains compact metadata, with no full
|
|
259
|
+
syntax, rules, runtime API sections or capability records. Retrieve guidance
|
|
260
|
+
through `component_syntax_expert`. Listing includes component guides only;
|
|
261
|
+
foundation guidance remains available through that tool's `foundations` selector.
|
|
262
|
+
|
|
263
|
+
Without `projectRoot`, listing reports `status: "available"` and
|
|
264
|
+
`contractCompatibility: "unknown"`. It does not inspect the working directory
|
|
265
|
+
or a CLI project-root default. `contractProvenance: "bundled-verified"` concerns
|
|
266
|
+
the packaged snapshot, and `uncheckedAreas` names target compatibility and
|
|
267
|
+
provenance as unperformed checks. With an explicit target, existing version and
|
|
268
|
+
provenance checks can return `status: "blocked"`. The complete reference entries
|
|
269
|
+
remain available with the same bundled version and hash.
|
|
270
|
+
|
|
271
|
+
`coverageStatus: "complete-bundled-catalogue"` describes delivery of all entries.
|
|
272
|
+
It does not establish consumer compatibility, browser behavior or accessibility
|
|
273
|
+
approval. Calls are read-only and execute no project scripts.
|
|
274
|
+
|
|
275
|
+
### Search the catalogue
|
|
276
|
+
|
|
277
|
+
Supply `query` to search canonical slugs, titles, aliases and compact descriptions:
|
|
278
|
+
|
|
279
|
+
```json
|
|
280
|
+
{ "query": "navbar", "limit": 1 }
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
This discovers `app-bar` with `matchType: "exact-alias"`. Pass the returned
|
|
284
|
+
canonical slug to `component_syntax_expert`; search does not expand that tool's
|
|
285
|
+
alias lookup. Search also accepts exact names such as `app-bar` and descriptive
|
|
286
|
+
queries such as `screen-level actions`.
|
|
287
|
+
|
|
288
|
+
`query` accepts at most 256 characters before trimming and rejects empty or
|
|
289
|
+
whitespace-only strings. `limit` must be an integer from 1 through 50 and defaults
|
|
290
|
+
to 10 for search. Without `query`, the tool still returns the entire catalogue;
|
|
291
|
+
a valid supplied limit has no effect on listing.
|
|
292
|
+
|
|
293
|
+
Names use the existing case-insensitive normalization: runs of characters other
|
|
294
|
+
than ASCII letters and digits become hyphens, with leading/trailing hyphens removed.
|
|
295
|
+
Search sorts exact slug/title matches first, exact aliases second, then heuristic
|
|
296
|
+
matches. Within each group, entries are sorted by canonical slug. A heuristic
|
|
297
|
+
match contains every normalized query token somewhere in the searchable fields,
|
|
298
|
+
including one- and two-character tokens. Tokens can match partial words or span
|
|
299
|
+
fields. These suggestions do not establish which component a design requires.
|
|
300
|
+
Queries that normalize to no tokens return no matches. Full guide bodies,
|
|
301
|
+
capability records and extra decision descriptions are not searched.
|
|
302
|
+
|
|
303
|
+
Search entries retain the listing metadata and add `matchType`, which is
|
|
304
|
+
`exact-name`, `exact-alias` or `heuristic`. Each component appears once with its
|
|
305
|
+
strongest match type. Search results also include:
|
|
306
|
+
|
|
307
|
+
| Field | Meaning |
|
|
308
|
+
| --- | --- |
|
|
309
|
+
| `query`, `limit` | Trimmed query and effective search limit. |
|
|
310
|
+
| `count`, `totalMatches` | Number delivered and total matches before limiting. |
|
|
311
|
+
| `omittedCount`, `truncated` | Matches omitted by the search result-count limit, separately from the byte budget. |
|
|
312
|
+
| `coverageStatus` | `complete-search-results` for all matches, or `partial-search-results` when the limit omitted matches. |
|
|
313
|
+
|
|
314
|
+
For example, `{"query":"no-catalogue-match-zzzz"}` returns `entries: []`,
|
|
315
|
+
zero counts, `truncated: false` and complete search coverage. If a query returns
|
|
316
|
+
more than its limit, increase `limit` up to 50 or narrow the query to retrieve
|
|
317
|
+
omitted entries. Search coverage concerns matching entries, not the whole
|
|
318
|
+
catalogue. Further byte omissions appear in `responseBudget`; `count` reflects
|
|
319
|
+
the records actually delivered and coverage becomes `partial-response-budget`
|
|
320
|
+
or `response-budget-error` when necessary.
|
|
321
|
+
|
|
322
|
+
Search retains the listing's bundled version/hash and optional-target evidence.
|
|
323
|
+
An omitted target leaves compatibility unknown; an incompatible explicit target
|
|
324
|
+
remains blocked while reference matches stay available. Empty results and
|
|
325
|
+
truncation do not change compatibility outcomes.
|
|
326
|
+
|
|
327
|
+
## Versioned catalogue resource
|
|
328
|
+
|
|
329
|
+
Clients with resource support can discover and read the current bundled snapshot
|
|
330
|
+
over the same stdio connection. The resource is named `component_catalog` and
|
|
331
|
+
has MIME type `application/json`. Use the advertised URI:
|
|
332
|
+
|
|
333
|
+
```js
|
|
334
|
+
const { resources } = await client.listResources();
|
|
335
|
+
const catalogue = resources.find((resource) => resource.name === 'component_catalog');
|
|
336
|
+
const result = await client.readResource({ uri: catalogue.uri });
|
|
337
|
+
const snapshot = JSON.parse(result.contents[0].text);
|
|
338
|
+
console.log(snapshot.contractVersion, snapshot.sourceHash, snapshot.entries);
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
The URI format is
|
|
342
|
+
`expressivecss://catalogue/<framework-version>/<source-hash>`. The framework
|
|
343
|
+
version is a URI-encoded path segment and the complete hash comes from the
|
|
344
|
+
shipped contract. It identifies those contract sources; it is not a digest of
|
|
345
|
+
the serialized resource text. Only the current shipped bundle is available.
|
|
346
|
+
The URI's version and hash agree with `contractVersion` and `sourceHash` in JSON.
|
|
347
|
+
There is no unversioned `latest` alias, historical lookup or search selector.
|
|
348
|
+
Resource reads require the exact advertised URI.
|
|
349
|
+
Unknown versions/hashes, query/fragment selectors and unrelated URIs return
|
|
350
|
+
resource-not-found error `-32002`. Invalid request parameters fail through the
|
|
351
|
+
SDK's request validation. The installed SDK 1.31.0 reports request-schema
|
|
352
|
+
failures with protocol error `-32603`.
|
|
353
|
+
|
|
354
|
+
Successful reads return one text item with that URI and JSON MIME type. The
|
|
355
|
+
JSON has `schemaVersion: 1`, `entries`, `count`, `contractVersion`, `sourceHash`
|
|
356
|
+
and `guideSource: "bundled"`. Entries contain the same compact fields and slug
|
|
357
|
+
ordering as a complete unfiltered catalogue tool result. They contain no full
|
|
358
|
+
component guide or capability dump. Tool-only stage/workflow and search fields
|
|
359
|
+
are absent. Resource operations do not depend on tool skip flags.
|
|
360
|
+
|
|
361
|
+
The JSON retains catalogue evidence fields: `status`, `checksPerformed`,
|
|
362
|
+
`evidenceSources`, `uncheckedAreas`, `contractCompatibility`,
|
|
363
|
+
`contractProvenance`, `contractProvenanceDetails`, `coverageStatus` and
|
|
364
|
+
`blockedChecks`. Compatibility is always `unknown`; `bundled-verified`
|
|
365
|
+
provenance concerns the packaged snapshot. Reads inspect no consumer files,
|
|
366
|
+
ignore the working directory and CLI project-root default, and execute no
|
|
367
|
+
project scripts or components. Complete catalogue coverage does not establish
|
|
368
|
+
consumer compatibility, browser behavior or accessibility approval.
|
|
369
|
+
|
|
370
|
+
### Resource-read budget and recovery
|
|
371
|
+
|
|
372
|
+
Successful resource reads share `EXPRESSIVECSS_MCP_MAX_RESPONSE_BYTES`, default
|
|
373
|
+
65,536 UTF-8 bytes. Measure the entire final `resources/read` result with
|
|
374
|
+
`Buffer.byteLength(JSON.stringify(result), 'utf8')`. This includes the contents
|
|
375
|
+
array, URI, MIME type, escaped JSON text, metadata and any SDK-added result
|
|
376
|
+
fields. The outer JSON-RPC envelope and stdio framing are excluded. Resource
|
|
377
|
+
JSON includes `responseBudget` with the effective `maxBytes`,
|
|
378
|
+
`delivery: "complete"` and empty `omissions`/`recoveries` arrays.
|
|
379
|
+
|
|
380
|
+
Every successful read delivers every entry whole. If that cannot fit, the
|
|
381
|
+
server returns JSON-RPC error `-32001` without a successful resource result.
|
|
382
|
+
Error data has `uri`, `maxBytes`, `requiredBytes` and
|
|
383
|
+
`setting: "EXPRESSIVECSS_MCP_MAX_RESPONSE_BYTES"`. The required size includes
|
|
384
|
+
the retry budget field's own bytes. Set the operator setting to at least
|
|
385
|
+
`requiredBytes`, restart the server and read the same advertised URI to
|
|
386
|
+
retrieve the complete catalogue. For example, in a contributor checkout:
|
|
387
|
+
|
|
388
|
+
```sh
|
|
389
|
+
# Replace 100000 with the requiredBytes from the error.
|
|
390
|
+
EXPRESSIVECSS_MCP_MAX_RESPONSE_BYTES=100000 node mcp/expressivecss/server.js
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
In an MCP client configuration, update that server's environment and reconnect
|
|
394
|
+
instead. A narrower catalogue tool query remains an option when only one entry
|
|
395
|
+
is needed, but it does not recover the whole resource at the same small budget.
|
|
396
|
+
Protocol errors are outside the successful-result budget, including budget 1.
|
|
397
|
+
`resources/list`, `resources/templates/list` and `tools/list` are discovery
|
|
398
|
+
operations outside this content budget; resource discovery remains available
|
|
399
|
+
when a read cannot fit. Subscription support is not advertised.
|
|
400
|
+
|
|
401
|
+
## Versioned component resources
|
|
402
|
+
|
|
403
|
+
Component guides are available as resources of the same bundled snapshot. Two
|
|
404
|
+
templates appear in `resources/templates/list`, both with MIME type
|
|
405
|
+
`application/json`:
|
|
406
|
+
|
|
407
|
+
| Template | URI |
|
|
408
|
+
| --- | --- |
|
|
409
|
+
| `component_guide` | `expressivecss://components/<framework-version>/<source-hash>/{slug}` |
|
|
410
|
+
| `component_guide_section` | `expressivecss://components/<framework-version>/<source-hash>/{slug}/{section}` |
|
|
411
|
+
|
|
412
|
+
The version and hash are fixed to the shipped contract, as in the catalogue
|
|
413
|
+
URI. `resources/list` lists one whole-guide URI per bundled component, sorted by
|
|
414
|
+
slug, after the catalogue. Section URIs are not listed. Build them from the
|
|
415
|
+
template with a canonical slug and one of `contract`, `syntax`, `rules`,
|
|
416
|
+
`options` or `methods`:
|
|
417
|
+
|
|
418
|
+
```js
|
|
419
|
+
const { resourceTemplates } = await client.listResourceTemplates();
|
|
420
|
+
const section = resourceTemplates.find((template) => template.name === 'component_guide_section');
|
|
421
|
+
const uri = section.uriTemplate.replace('{slug}', 'date-picker').replace('{section}', 'options');
|
|
422
|
+
const options = JSON.parse((await client.readResource({ uri })).contents[0].text).options;
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
Every read returns one text item with JSON containing `schemaVersion: 1`,
|
|
426
|
+
`slug`, `title`, `docs` (the documentation page, as in catalogue entries),
|
|
427
|
+
`repositorySource` (the page source in the repository), `contractVersion`,
|
|
428
|
+
`sourceHash` and `guideSource: "bundled"`. A whole-guide read adds all five
|
|
429
|
+
sections. A section read adds `section` and only that section's field:
|
|
430
|
+
|
|
431
|
+
- `contract` is the complete Contract text. The syntax tool shortens long
|
|
432
|
+
contracts to 900 characters; resources do not.
|
|
433
|
+
- `syntax` is `{ language, example }`, the same as detailed syntax tool output.
|
|
434
|
+
- `rules` is the complete ordered rule list returned by the syntax tool.
|
|
435
|
+
- `options` and `methods` are `{ status, markdown }`. A guide without that
|
|
436
|
+
section returns `status: "absent"` and `markdown: null`.
|
|
437
|
+
|
|
438
|
+
The JSON carries the same evidence fields as the catalogue resource.
|
|
439
|
+
Compatibility is always `unknown`, and `coverageStatus` is
|
|
440
|
+
`complete-bundled-guide` or `complete-bundled-guide-section`. Reads inspect no
|
|
441
|
+
consumer files, ignore the working directory, CLI project-root default and tool
|
|
442
|
+
skip flags, and execute no project scripts or components.
|
|
443
|
+
|
|
444
|
+
Reads accept only the exact URIs the templates describe. Catalogue aliases such
|
|
445
|
+
as `datepicker`, case variants, unknown slugs or sections, other versions or
|
|
446
|
+
hashes, extra or empty segments, trailing slashes, percent-encoded variants and
|
|
447
|
+
query or fragment selectors return `-32002`. Use `component_catalog` to resolve
|
|
448
|
+
an alias to its canonical slug, or [complete](#complete-resource-arguments) a
|
|
449
|
+
slug prefix.
|
|
450
|
+
|
|
451
|
+
### Component read budget and recovery
|
|
452
|
+
|
|
453
|
+
Component reads use the [resource-read budget](#resource-read-budget-and-recovery)
|
|
454
|
+
and its measurement. A successful read always delivers every requested section
|
|
455
|
+
whole. If a read does not fit, the server returns `-32001` with no contents.
|
|
456
|
+
The error data has `uri`, `maxBytes`, `requiredBytes`, `setting`,
|
|
457
|
+
`recoveries` and `unrecoverableSections`:
|
|
458
|
+
|
|
459
|
+
- For a whole-guide URI, `recoveries` lists the section URIs whose complete
|
|
460
|
+
reads fit the current budget, in section order. Read those on the same
|
|
461
|
+
connection. `unrecoverableSections` names the sections that do not fit.
|
|
462
|
+
- For a section URI, `recoveries` is empty and `unrecoverableSections` names
|
|
463
|
+
that section. Its `requiredBytes` is the budget that section needs.
|
|
464
|
+
|
|
465
|
+
Restart with `EXPRESSIVECSS_MCP_MAX_RESPONSE_BYTES` of at least `requiredBytes`
|
|
466
|
+
to read a URI that cannot fit. The largest bundled guide fits the default
|
|
467
|
+
budget, so section recovery matters only under a smaller operator budget.
|
|
468
|
+
|
|
469
|
+
### Complete resource arguments
|
|
470
|
+
|
|
471
|
+
The server advertises the `completions` capability. `completion/complete`
|
|
472
|
+
completes `slug` on both component templates and `section` on
|
|
473
|
+
`component_guide_section`. Pass the exact `uriTemplate` string from
|
|
474
|
+
`resources/templates/list` as `ref.uri`:
|
|
475
|
+
|
|
476
|
+
```js
|
|
477
|
+
const { resourceTemplates } = await client.listResourceTemplates();
|
|
478
|
+
const guide = resourceTemplates.find((template) => template.name === 'component_guide');
|
|
479
|
+
await client.complete({ ref: { type: 'ref/resource', uri: guide.uriTemplate }, argument: { name: 'slug', value: 'ca' } });
|
|
480
|
+
// { completion: { values: ['cards', 'carousel'], total: 2, hasMore: false } }
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
A value matches names that start with it, ignoring case. Slugs come back in
|
|
484
|
+
`resources/list` order, and an empty value returns all of them. Sections come
|
|
485
|
+
back in the order `contract`, `syntax`, `rules`, `options`, `methods`, whatever
|
|
486
|
+
slug `context.arguments` holds. Only canonical slugs match, so `datepicker`
|
|
487
|
+
returns no values while `date` returns `date-picker`. The SDK returns at most
|
|
488
|
+
100 values, with `total` matches and `hasMore` set when more matched. Every
|
|
489
|
+
current result fits.
|
|
490
|
+
|
|
491
|
+
- A value with no matches returns `values: []`, `total: 0` and
|
|
492
|
+
`hasMore: false`.
|
|
493
|
+
- Other argument names, such as `version`, and the fixed catalogue URI return
|
|
494
|
+
`values: []` and `hasMore: false` without `total`.
|
|
495
|
+
- A `ref.uri` that is not one of the two current template strings, such as
|
|
496
|
+
another version or hash, returns `-32602`. So does a `ref/prompt` reference,
|
|
497
|
+
because the server has no prompts.
|
|
498
|
+
|
|
499
|
+
Completion uses the bundled catalogue loaded at startup. It reads no project
|
|
500
|
+
files and runs no commands, and it stays outside the
|
|
501
|
+
[content budget](#resource-read-budget-and-recovery) like resource listing.
|
|
502
|
+
Completion covers resource template arguments only. MCP does not complete tool
|
|
503
|
+
arguments, so `component_syntax_expert` and other tools still need canonical
|
|
504
|
+
names or aliases, which `component_catalog` lists.
|
|
505
|
+
|
|
32
506
|
## Run it locally
|
|
33
507
|
|
|
34
508
|
The server supports Node `^22.22.2 || ^24.15.0 || >=26.0.0`, matching its `jsdom` runtime dependency.
|
|
@@ -59,14 +533,15 @@ npm test
|
|
|
59
533
|
| `creative_director` | Suggests components from the generated decision catalogue, with uncertain fuzzy matches labelled as fallback |
|
|
60
534
|
| `page_arcjitect` | Workflow stage returning page sections, landmarks, and a semantic skeleton |
|
|
61
535
|
| `page_architect` | Conventional spelling for the same page architecture tool; component names must resolve exactly |
|
|
62
|
-
| `component_syntax_expert` | Returns
|
|
536
|
+
| `component_syntax_expert` | Returns complete rules, selectable syntax/capability detail and requested documented Options and Methods for components |
|
|
537
|
+
| `component_catalog` | Lists or searches compact bundled component metadata with labelled matches, result limits, snapshot identity and optional target compatibility checks |
|
|
63
538
|
| `quality_inspector` | Runs scoped static checks and optional commands (`npm run typecheck`, `npm run test`), then names every uninspected review area |
|
|
64
539
|
|
|
65
540
|
Static findings are heuristic and require source or runtime confirmation before remediation. A clean static check is reported as `staticStatus: "heuristic_pass"`; any overall MCP `pass` applies only to `checksPerformed`. Neither proves visual hierarchy, responsive rendering, focus behavior, motion, contrast, screen-reader announcements, or component-rule conformance unless separate evidence covers those areas. Read `uncheckedAreas`, `blockedChecks`, `coverageStatus`, `contractCompatibility`, and `contractProvenance` before using a result in a finish review.
|
|
66
541
|
|
|
67
542
|
`creative_director` and both page architect spellings resolve the target ExpressiveCSS version before reading current contract guidance. They return no recommendations or architecture when the version is mismatched or unresolved, when local contract provenance is missing, stale, invalid, or divergent from the bundled package contract, or when an architecture request contains an inexact component name. Fuzzy creative matches remain labelled `confidence: "fallback"`; page architecture never accepts them silently.
|
|
68
543
|
|
|
69
|
-
|
|
544
|
+
When checking a framework source target, the server accepts only the generated contract's canonical source list. It resolves the real project and source paths, rejects symbolic links and non-regular files, and caps each source at 2 MiB and the set at 8 MiB. It recomputes provenance for each target-project check in manifest order with the generator's SHA-256 input format, `source path + NUL + file content + NUL`. The verified local manifest must also match the bundled package's framework version and source hash because the MCP serves bundled guidance. Contract-dependent output is blocked when the source set is invalid, missing, oversized, stale, or divergent. Invalid source paths never produce a computed hash. Generated data shipped in this package reports `contractProvenance: "bundled-verified"` because package consumers do not receive the framework source files.
|
|
70
545
|
|
|
71
546
|
Static inspection uses descriptor-level, no-follow bounded reads and rechecks file identity after each read. It caps files at 2 MiB each and 16 MiB per request by default, stops after 200 issues per file or 1,000 per request, and applies a five-second scan budget. Any unread, changed, over-budget, or partially scanned file appears under `filesUninspected`, which prevents a pass.
|
|
72
547
|
|
|
@@ -136,6 +611,7 @@ network limits, evidence handling, and bounded repair workflow.
|
|
|
136
611
|
|
|
137
612
|
## Environment variables
|
|
138
613
|
|
|
614
|
+
- `EXPRESSIVECSS_MCP_MAX_RESPONSE_BYTES`, default `65536`.
|
|
139
615
|
- `EXPRESSIVECSS_MCP_MAX_COMPONENT_RESPONSE_CHARS`
|
|
140
616
|
- `EXPRESSIVECSS_MCP_MAX_COMPONENT_SKIPS`
|
|
141
617
|
- `EXPRESSIVECSS_MCP_QA_MAX_FILES`
|
|
@@ -152,6 +628,11 @@ network limits, evidence handling, and bounded repair workflow.
|
|
|
152
628
|
|
|
153
629
|
Set any skip flag to `true` to disable that stage from doing work.
|
|
154
630
|
|
|
631
|
+
`EXPRESSIVECSS_MCP_MAX_COMPONENT_RESPONSE_CHARS` is retained for configuration
|
|
632
|
+
compatibility and the legacy `maxCharactersPerComponent` metadata. It no longer
|
|
633
|
+
clips syntax examples and does not bound tool results. Use the byte setting for
|
|
634
|
+
aggregate guidance limits. QA command-output limits remain separate.
|
|
635
|
+
|
|
155
636
|
Command execution is denied by default. To let `quality_inspector` honor `runCommands: true`, the MCP operator must set `EXPRESSIVECSS_MCP_ALLOWED_COMMAND_ROOTS` when launching the server. Use platform path separators for multiple roots, or a JSON array of absolute roots:
|
|
156
637
|
|
|
157
638
|
```text
|
|
@@ -172,6 +653,7 @@ The real `projectRoot` must equal or be contained by one of those roots. A tool
|
|
|
172
653
|
"command": "npx",
|
|
173
654
|
"args": ["-y", "@expressivecss/mcp-server@latest"],
|
|
174
655
|
"env": {
|
|
656
|
+
"EXPRESSIVECSS_MCP_MAX_RESPONSE_BYTES": "65536",
|
|
175
657
|
"EXPRESSIVECSS_MCP_MAX_COMPONENT_RESPONSE_CHARS": "24000",
|
|
176
658
|
"EXPRESSIVECSS_MCP_MAX_COMPONENT_SKIPS": "7",
|
|
177
659
|
"EXPRESSIVECSS_MCP_QA_MAX_FILES": "300",
|