@lism-css/mcp 0.23.0 → 0.26.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.ja.md +15 -15
- package/README.md +5 -5
- package/dist/data/docs-index.json +185 -159
- package/dist/data/guides/SKILL.md +164 -228
- package/dist/data/guides/antipatterns-layout.md +271 -0
- package/dist/data/guides/antipatterns.md +121 -196
- package/dist/data/guides/base-styles.md +10 -9
- package/dist/data/guides/components-core.md +27 -9
- package/dist/data/guides/components-ui.md +30 -51
- package/dist/data/guides/css-rules.md +104 -107
- package/dist/data/guides/customize.md +10 -7
- package/dist/data/guides/naming.md +22 -41
- package/dist/data/guides/primitive-class.md +5 -5
- package/dist/data/guides/primitives/a--decorator.md +2 -28
- package/dist/data/guides/primitives/a--divider.md +1 -52
- package/dist/data/guides/primitives/a--icon.md +2 -76
- package/dist/data/guides/primitives/a--spacer.md +1 -49
- package/dist/data/guides/primitives/l--autoColumns.md +7 -54
- package/dist/data/guides/primitives/l--box.md +1 -21
- package/dist/data/guides/primitives/l--center.md +6 -39
- package/dist/data/guides/primitives/l--cluster.md +6 -26
- package/dist/data/guides/primitives/l--columns.md +7 -56
- package/dist/data/guides/primitives/l--flex.md +5 -62
- package/dist/data/guides/primitives/l--flow.md +11 -72
- package/dist/data/guides/primitives/l--frame.md +7 -78
- package/dist/data/guides/primitives/l--grid.md +5 -56
- package/dist/data/guides/primitives/l--stack.md +5 -44
- package/dist/data/guides/primitives/l--switchColumns.md +8 -53
- package/dist/data/guides/primitives/l--tileGrid.md +7 -44
- package/dist/data/guides/primitives/l--withSide.md +9 -79
- package/dist/data/guides/property-class/all-props.md +246 -0
- package/dist/data/guides/property-class/bd.md +6 -71
- package/dist/data/guides/property-class/hov.md +14 -73
- package/dist/data/guides/property-class/max-sz.md +3 -39
- package/dist/data/guides/property-class.md +33 -250
- package/dist/data/guides/references/authoring.md +246 -0
- package/dist/data/guides/references/page-sections.md +99 -0
- package/dist/data/guides/references/verification.md +75 -0
- package/dist/data/guides/responsive.md +44 -15
- package/dist/data/guides/set-class.md +2 -12
- package/dist/data/guides/tokens.md +20 -16
- package/dist/data/guides/trait-class/has--gutter.md +3 -31
- package/dist/data/guides/trait-class/has--mask.md +3 -36
- package/dist/data/guides/trait-class/has--snap.md +3 -34
- package/dist/data/guides/trait-class/has--transition.md +3 -41
- package/dist/data/guides/trait-class/is--boxLink.md +2 -63
- package/dist/data/guides/trait-class/is--container.md +2 -29
- package/dist/data/guides/trait-class/is--layer.md +1 -57
- package/dist/data/guides/trait-class/is--wrapper.md +3 -56
- package/dist/data/guides/trait-class.md +8 -8
- package/dist/data/guides/utility-class.md +1 -1
- package/dist/data/meta.js +4 -3
- package/dist/index.js +4 -1
- package/dist/lib/load-markdown.d.ts +4 -0
- package/dist/lib/load-markdown.js +10 -0
- package/dist/lib/response.d.ts +5 -0
- package/dist/lib/response.js +15 -2
- package/dist/lib/schemas.d.ts +35 -0
- package/dist/lib/schemas.js +13 -0
- package/dist/lib/search.d.ts +2 -0
- package/dist/lib/search.js +56 -4
- package/dist/lib/types.d.ts +5 -21
- package/dist/lib/version.d.ts +2 -0
- package/dist/lib/version.js +8 -0
- package/dist/tools/convert-css.js +37 -14
- package/dist/tools/get-component.js +2 -2
- package/dist/tools/get-guide.d.ts +2 -0
- package/dist/tools/get-guide.js +41 -18
- package/dist/tools/get-overview.js +2 -2
- package/dist/tools/get-props-system.js +8 -6
- package/dist/tools/get-tokens.js +2 -2
- package/dist/tools/search-docs.js +13 -7
- package/package.json +21 -6
package/dist/lib/search.js
CHANGED
|
@@ -67,7 +67,7 @@ function scoreEntry(entry, queryTokens) {
|
|
|
67
67
|
return score;
|
|
68
68
|
}
|
|
69
69
|
export function searchDocs(entries, query, options) {
|
|
70
|
-
const { category, limit = 10, cssPropertyMap } = options ?? {};
|
|
70
|
+
const { category, limit = 10, cssPropertyMap, guideTopics } = options ?? {};
|
|
71
71
|
// CSSプロパティ名・Property Class記法をLism prop名に展開してからトークナイズ
|
|
72
72
|
const expandedQuery = expandQuery(query, cssPropertyMap);
|
|
73
73
|
const queryTokens = tokenize(expandedQuery);
|
|
@@ -85,15 +85,67 @@ export function searchDocs(entries, query, options) {
|
|
|
85
85
|
.filter(({ score }) => score > 0)
|
|
86
86
|
.sort((a, b) => b.score - a.score)
|
|
87
87
|
.slice(0, limit);
|
|
88
|
-
const DOCS_BASE_URL = 'https://lism-css.com/docs';
|
|
89
88
|
return scored.map(({ entry, score }) => ({
|
|
90
89
|
sourcePath: entry.sourcePath,
|
|
91
|
-
url:
|
|
90
|
+
url: slugToPageUrl(sourcePathToUrlSlug(entry.sourcePath)),
|
|
92
91
|
heading: entry.title,
|
|
93
92
|
snippet: entry.snippet,
|
|
94
93
|
score,
|
|
94
|
+
nextTool: getNextTool(entry, guideTopics),
|
|
95
95
|
}));
|
|
96
96
|
}
|
|
97
|
+
const SITE_BASE_URL = 'https://lism-css.com';
|
|
98
|
+
/**
|
|
99
|
+
* URL スラッグを公開ページの URL に変換する。
|
|
100
|
+
* `ui/` 配下はサイト直下(`/ui/...`)、それ以外は `/docs/` 配下で公開される
|
|
101
|
+
* (apps/docs の `getPostUrl` と同じルーティング規則)。
|
|
102
|
+
*/
|
|
103
|
+
function slugToPageUrl(slug) {
|
|
104
|
+
return slug.startsWith('ui/') ? `${SITE_BASE_URL}/${slug}/` : `${SITE_BASE_URL}/docs/${slug}/`;
|
|
105
|
+
}
|
|
106
|
+
/** `sourcePath`(拡張子なし)の末尾セグメントを返す(例: `primitives/l--flex` → `l--flex`) */
|
|
107
|
+
function getBasename(withoutExt) {
|
|
108
|
+
const parts = withoutExt.split('/');
|
|
109
|
+
return parts[parts.length - 1];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 検索結果のページを詳しく見るための推奨フォローアップツール呼び出しを返す。
|
|
113
|
+
* sourcePath による判定をカテゴリによる判定より優先する。
|
|
114
|
+
*/
|
|
115
|
+
function getNextTool(entry, guideTopics) {
|
|
116
|
+
const withoutExt = entry.sourcePath.replace(/\.mdx$/, '');
|
|
117
|
+
const basename = getBasename(withoutExt);
|
|
118
|
+
// sourcePath ベースの判定(category より優先)
|
|
119
|
+
if (withoutExt === 'core-components/lism-props') {
|
|
120
|
+
return 'get_props_system()';
|
|
121
|
+
}
|
|
122
|
+
if (withoutExt.startsWith('primitives/') || withoutExt.startsWith('trait-class/')) {
|
|
123
|
+
return `get_component(name: "${basename}")`;
|
|
124
|
+
}
|
|
125
|
+
if (withoutExt === 'property-class') {
|
|
126
|
+
return 'get_guide(topic: "property-class")';
|
|
127
|
+
}
|
|
128
|
+
if (withoutExt.startsWith('property-class/')) {
|
|
129
|
+
return `get_props_system(prop: "${basename}")`;
|
|
130
|
+
}
|
|
131
|
+
// ui/block-examples/(Chat, Timeline 等)と ui/components/(Card, Hero 等)は、
|
|
132
|
+
// パッケージが提供するコンポーネントではなく Lism CSS での実装例ページなので get_component では解決できない。
|
|
133
|
+
// 詳細が必要な場合は検索結果の url を参照してもらう。
|
|
134
|
+
if (withoutExt.startsWith('ui/block-examples/') || withoutExt.startsWith('ui/components/')) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
// category ベースの判定
|
|
138
|
+
switch (entry.category) {
|
|
139
|
+
case 'core-components':
|
|
140
|
+
return `get_component(name: "${basename}")`;
|
|
141
|
+
case 'ui':
|
|
142
|
+
return `get_component(name: "${basename}", package: "@lism-css/ui")`;
|
|
143
|
+
case 'guide':
|
|
144
|
+
return guideTopics?.has(basename) ? `get_guide(topic: "${basename}")` : null;
|
|
145
|
+
default:
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
97
149
|
/**
|
|
98
150
|
* `sourcePath`(実 MDX ファイルの相対パス)を公開 URL のスラッグに変換する。
|
|
99
151
|
*
|
|
@@ -112,7 +164,7 @@ export function searchDocs(entries, query, options) {
|
|
|
112
164
|
* `ui/DummyText.mdx` → `ui/dummytext`
|
|
113
165
|
*/
|
|
114
166
|
const PRESERVE_CASE_PREFIXES = ['primitives/', 'trait-class/'];
|
|
115
|
-
function sourcePathToUrlSlug(sourcePath) {
|
|
167
|
+
export function sourcePathToUrlSlug(sourcePath) {
|
|
116
168
|
const withoutExt = sourcePath.replace(/\.mdx$/, '');
|
|
117
169
|
return PRESERVE_CASE_PREFIXES.some((prefix) => withoutExt.startsWith(prefix)) ? withoutExt : withoutExt.toLowerCase();
|
|
118
170
|
}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export interface SearchResult {
|
|
7
|
-
sourcePath: string;
|
|
8
|
-
url: string;
|
|
9
|
-
heading: string;
|
|
10
|
-
snippet: string;
|
|
11
|
-
score: number;
|
|
12
|
-
}
|
|
13
|
-
export interface DocsEntry {
|
|
14
|
-
sourcePath: string;
|
|
15
|
-
title: string;
|
|
16
|
-
description: string;
|
|
17
|
-
category: string;
|
|
18
|
-
headings: string[];
|
|
19
|
-
keywords: string[];
|
|
20
|
-
snippet: string;
|
|
21
|
-
}
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { MetaInfoSchema, DocsEntrySchema, SearchResultSchema } from './schemas.js';
|
|
3
|
+
export type MetaInfo = z.infer<typeof MetaInfoSchema>;
|
|
4
|
+
export type SearchResult = z.infer<typeof SearchResultSchema>;
|
|
5
|
+
export type DocsEntry = z.infer<typeof DocsEntrySchema>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
// src/lib/(開発時)と dist/lib/(ビルド後)のどちらから見ても package.json は 2 つ上の階層にある
|
|
6
|
+
const pkgPath = resolve(__dirname, '..', '..', 'package.json');
|
|
7
|
+
/** package.json の version(サーバーが名乗るバージョンの単一情報源) */
|
|
8
|
+
export const packageVersion = JSON.parse(readFileSync(pkgPath, 'utf-8')).version;
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { loadPropsMarkdown } from '../lib/load-markdown.js';
|
|
3
3
|
import { parsePropRows } from '../lib/markdown-utils.js';
|
|
4
|
+
import { MetaInfoSchema } from '../lib/schemas.js';
|
|
4
5
|
import { success, error, READ_ONLY_ANNOTATIONS } from '../lib/response.js';
|
|
6
|
+
/** 変換結果の1行 */
|
|
7
|
+
const ConversionEntrySchema = z.object({
|
|
8
|
+
css: z.string(),
|
|
9
|
+
lismProp: z.string().nullable(),
|
|
10
|
+
suggestedValue: z.string().nullable(),
|
|
11
|
+
availableTokens: z.array(z.string()).nullable(),
|
|
12
|
+
confidence: z.enum(['exact', 'approximate', 'unmapped']),
|
|
13
|
+
note: z.string(),
|
|
14
|
+
});
|
|
15
|
+
/** コンポーネント提案 */
|
|
16
|
+
const ComponentSuggestionSchema = z.object({
|
|
17
|
+
name: z.string(),
|
|
18
|
+
reason: z.string(),
|
|
19
|
+
implicitCss: z.array(z.string()),
|
|
20
|
+
});
|
|
5
21
|
// ----------------------------------------------------------------
|
|
6
22
|
// CSS パース
|
|
7
23
|
// ----------------------------------------------------------------
|
|
@@ -9,7 +25,7 @@ import { success, error, READ_ONLY_ANNOTATIONS } from '../lib/response.js';
|
|
|
9
25
|
function detectAtRules(cssText) {
|
|
10
26
|
const atRuleMatch = cssText.match(/^@(\w[\w-]*)/m);
|
|
11
27
|
if (atRuleMatch) {
|
|
12
|
-
return `@${atRuleMatch[1]}
|
|
28
|
+
return `@${atRuleMatch[1]} rules are not supported. Provide plain CSS declarations (property: value;) only.`;
|
|
13
29
|
}
|
|
14
30
|
return null;
|
|
15
31
|
}
|
|
@@ -124,7 +140,7 @@ function detectComponent(declarations) {
|
|
|
124
140
|
if (display === 'flex' && (flexDirection === 'column' || flexDirection === 'column-reverse')) {
|
|
125
141
|
return {
|
|
126
142
|
name: 'Stack',
|
|
127
|
-
reason: 'display: flex + flex-direction: column → Stack
|
|
143
|
+
reason: 'display: flex + flex-direction: column → Stack (vertical flex)',
|
|
128
144
|
implicitCss: ['display: flex', 'flex-direction: column'],
|
|
129
145
|
};
|
|
130
146
|
}
|
|
@@ -132,7 +148,7 @@ function detectComponent(declarations) {
|
|
|
132
148
|
if (display === 'grid' && placeItems === 'center') {
|
|
133
149
|
return {
|
|
134
150
|
name: 'Center',
|
|
135
|
-
reason: 'display: grid + place-items: center → Center
|
|
151
|
+
reason: 'display: grid + place-items: center → Center (centered grid)',
|
|
136
152
|
implicitCss: ['display: grid', 'place-items: center'],
|
|
137
153
|
};
|
|
138
154
|
}
|
|
@@ -140,7 +156,7 @@ function detectComponent(declarations) {
|
|
|
140
156
|
if (display === 'flex') {
|
|
141
157
|
return {
|
|
142
158
|
name: 'Flex',
|
|
143
|
-
reason: 'display: flex → Flex
|
|
159
|
+
reason: 'display: flex → Flex component',
|
|
144
160
|
implicitCss: ['display: flex'],
|
|
145
161
|
};
|
|
146
162
|
}
|
|
@@ -148,7 +164,7 @@ function detectComponent(declarations) {
|
|
|
148
164
|
if (display === 'grid') {
|
|
149
165
|
return {
|
|
150
166
|
name: 'Grid',
|
|
151
|
-
reason: 'display: grid → Grid
|
|
167
|
+
reason: 'display: grid → Grid component',
|
|
152
168
|
implicitCss: ['display: grid'],
|
|
153
169
|
};
|
|
154
170
|
}
|
|
@@ -206,6 +222,13 @@ export function registerConvertCss(server) {
|
|
|
206
222
|
.string()
|
|
207
223
|
.describe('CSS code to convert. Accepts a full rule block with selector (e.g. ".foo { padding: 1rem; }") or bare declarations (e.g. "padding: 1rem; font-size: 16px;"). @media and other at-rules are not supported.'),
|
|
208
224
|
},
|
|
225
|
+
outputSchema: {
|
|
226
|
+
meta: MetaInfoSchema,
|
|
227
|
+
conversions: z.array(ConversionEntrySchema),
|
|
228
|
+
suggestedComponent: ComponentSuggestionSchema.nullable(),
|
|
229
|
+
example: z.string(),
|
|
230
|
+
tip: z.string(),
|
|
231
|
+
},
|
|
209
232
|
annotations: READ_ONLY_ANNOTATIONS,
|
|
210
233
|
}, ({ css }) => {
|
|
211
234
|
try {
|
|
@@ -214,12 +237,12 @@ export function registerConvertCss(server) {
|
|
|
214
237
|
if (atRuleError) {
|
|
215
238
|
return error(atRuleError);
|
|
216
239
|
}
|
|
217
|
-
const md =
|
|
240
|
+
const md = loadPropsMarkdown();
|
|
218
241
|
const mappings = buildMappings(md);
|
|
219
242
|
const cssPropertyMap = buildCssPropertyMap(mappings);
|
|
220
243
|
const declarations = parseCssDeclarations(css);
|
|
221
244
|
if (declarations.length === 0) {
|
|
222
|
-
return error('CSS
|
|
245
|
+
return error('No CSS declarations found. Provide CSS in "property: value;" format.');
|
|
223
246
|
}
|
|
224
247
|
// 各宣言を変換
|
|
225
248
|
const conversions = declarations.map((decl) => {
|
|
@@ -231,7 +254,7 @@ export function registerConvertCss(server) {
|
|
|
231
254
|
suggestedValue: null,
|
|
232
255
|
availableTokens: null,
|
|
233
256
|
confidence: 'unmapped',
|
|
234
|
-
note: 'Lism
|
|
257
|
+
note: 'No matching Lism prop. Specify it directly via the style attribute.',
|
|
235
258
|
};
|
|
236
259
|
}
|
|
237
260
|
const suggested = suggestValue(mapping, decl.value);
|
|
@@ -243,10 +266,10 @@ export function registerConvertCss(server) {
|
|
|
243
266
|
availableTokens: mapping.presetValues.length > 0 ? mapping.presetValues : null,
|
|
244
267
|
confidence: suggested ? 'exact' : 'approximate',
|
|
245
268
|
note: suggested
|
|
246
|
-
?
|
|
269
|
+
? `Use token value '${suggested}' (category: ${category})`
|
|
247
270
|
: mapping.presetValues.length > 0
|
|
248
|
-
?
|
|
249
|
-
:
|
|
271
|
+
? `Custom value. Available tokens: ${mapping.presetValues.join(', ')} (category: ${category})`
|
|
272
|
+
: `Use as a custom value (category: ${category})`,
|
|
250
273
|
};
|
|
251
274
|
});
|
|
252
275
|
// コンポーネント検出
|
|
@@ -257,11 +280,11 @@ export function registerConvertCss(server) {
|
|
|
257
280
|
conversions,
|
|
258
281
|
suggestedComponent,
|
|
259
282
|
example,
|
|
260
|
-
tip: '
|
|
283
|
+
tip: 'Values that do not match a token can be set as CSS variables via the style attribute (e.g. style="--p: 1rem"). Use get_props_system for details on each prop.',
|
|
261
284
|
});
|
|
262
285
|
}
|
|
263
286
|
catch (e) {
|
|
264
|
-
return error(`CSS
|
|
287
|
+
return error(`CSS conversion failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
265
288
|
}
|
|
266
289
|
});
|
|
267
290
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { getGuideFilenames, loadMarkdown } from '../lib/load-markdown.js';
|
|
3
3
|
import { findComponentByHeading, findComponentInTables } from '../lib/markdown-utils.js';
|
|
4
|
-
import { markdownResponse,
|
|
4
|
+
import { markdownResponse, loadFailureError, notFound, READ_ONLY_ANNOTATIONS } from '../lib/response.js';
|
|
5
5
|
/** 入力を正規化してエイリアス検索のキーに変換する。
|
|
6
6
|
* `<Flex>` / `Flex` / `l--flex` / `flex` をすべて `flex` に揃える。 */
|
|
7
7
|
function normalizeComponentKey(input) {
|
|
@@ -171,7 +171,7 @@ export function registerGetComponent(server) {
|
|
|
171
171
|
});
|
|
172
172
|
}
|
|
173
173
|
catch (e) {
|
|
174
|
-
return
|
|
174
|
+
return loadFailureError('component data', e);
|
|
175
175
|
}
|
|
176
176
|
});
|
|
177
177
|
}
|
package/dist/tools/get-guide.js
CHANGED
|
@@ -1,32 +1,55 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { loadMarkdown } from '../lib/load-markdown.js';
|
|
3
|
-
import { markdownResponse,
|
|
3
|
+
import { markdownResponse, loadFailureError, READ_ONLY_ANNOTATIONS } from '../lib/response.js';
|
|
4
|
+
// files に複数指定したトピックは結合して返す。
|
|
5
|
+
// MCP クライアントは Markdown 内の相対リンクを辿れないため、分冊ファイルは本体に結合する。
|
|
4
6
|
const GUIDE_TOPICS = {
|
|
5
|
-
overview: {
|
|
6
|
-
tokens: {
|
|
7
|
-
'property-class': {
|
|
7
|
+
overview: { files: ['SKILL.md'], label: 'Framework overview, packages, implementation rules' },
|
|
8
|
+
tokens: { files: ['tokens.md'], label: 'Design tokens (spacing, colors, font sizes, etc.)' },
|
|
9
|
+
'property-class': {
|
|
10
|
+
files: ['property-class.md', 'property-class/all-props.md', 'property-class/bd.md', 'property-class/hov.md', 'property-class/max-sz.md'],
|
|
11
|
+
label: 'Property Class system, all props reference table, border (bd) / hover (hov) / max-sz details',
|
|
12
|
+
},
|
|
8
13
|
'components-core': {
|
|
9
|
-
|
|
14
|
+
files: ['components-core.md'],
|
|
10
15
|
label: 'Core component system (Lism, Box, Flex, Stack, Grid, etc.)',
|
|
11
16
|
},
|
|
12
17
|
'components-ui': {
|
|
13
|
-
|
|
18
|
+
files: ['components-ui.md'],
|
|
14
19
|
label: 'UI components (Accordion, Modal, Tabs, Button, etc.)',
|
|
15
20
|
},
|
|
16
|
-
'base-styles': {
|
|
17
|
-
'set-class': {
|
|
21
|
+
'base-styles': { files: ['base-styles.md'], label: 'Base styling, reset CSS, HTML element styles' },
|
|
22
|
+
'set-class': { files: ['set-class.md'], label: 'Set classes (set--plain, set--bxsh, set--hov, etc.)' },
|
|
18
23
|
'primitive-class': {
|
|
19
|
-
|
|
20
|
-
label: 'Primitive class prefixes (
|
|
24
|
+
files: ['primitive-class.md'],
|
|
25
|
+
label: 'Primitive class prefixes (l--, a--), with column-layout primitive selection guide',
|
|
26
|
+
},
|
|
27
|
+
'trait-class': {
|
|
28
|
+
files: ['trait-class.md'],
|
|
29
|
+
label: 'Trait classes (is--, has--): declarative role/feature classes in the lism-trait layer',
|
|
30
|
+
},
|
|
31
|
+
'utility-class': { files: ['utility-class.md'], label: 'Utility classes (u--trim, u--cbox, etc.)' },
|
|
32
|
+
'css-rules': { files: ['css-rules.md'], label: 'CSS methodology, layer structure, Block Class (b--) / Custom Class (c--), naming conventions' },
|
|
33
|
+
naming: {
|
|
34
|
+
files: ['naming.md'],
|
|
35
|
+
label: 'Naming conventions: CSS variable / class naming rules, {prop} and {value} abbreviation rules',
|
|
36
|
+
},
|
|
37
|
+
responsive: { files: ['responsive.md'], label: 'Responsive design, breakpoints, container queries' },
|
|
38
|
+
customize: {
|
|
39
|
+
files: ['customize.md'],
|
|
40
|
+
label: 'Customization: @layer opt-out, SCSS settings, lism.config.js, CSS purge',
|
|
21
41
|
},
|
|
22
|
-
'utility-class': { file: 'utility-class.md', label: 'Utility classes (u--trim, u--cbox, etc.)' },
|
|
23
|
-
'css-rules': { file: 'css-rules.md', label: 'CSS methodology, layer structure, naming conventions' },
|
|
24
|
-
responsive: { file: 'responsive.md', label: 'Responsive design, breakpoints, container queries' },
|
|
25
42
|
antipatterns: {
|
|
26
|
-
|
|
27
|
-
label: 'AI code-generation antipatterns: token typos, prop type mistakes
|
|
43
|
+
files: ['antipatterns.md'],
|
|
44
|
+
label: 'AI code-generation antipatterns (values / style declarations): px hardcoding, token typos, keycolor misuse, prop type mistakes',
|
|
45
|
+
},
|
|
46
|
+
'antipatterns-layout': {
|
|
47
|
+
files: ['antipatterns-layout.md'],
|
|
48
|
+
label: 'AI code-generation antipatterns (structure / layout / responsive): layout choice errors, responsive omissions, is-- misuse, naming mistakes',
|
|
28
49
|
},
|
|
29
50
|
};
|
|
51
|
+
/** get_guide が受理するトピックキーの集合。search.ts の nextTool 判定で利用する。 */
|
|
52
|
+
export const GUIDE_TOPIC_KEYS = new Set(Object.keys(GUIDE_TOPICS));
|
|
30
53
|
const TOPIC_DESCRIPTION = Object.entries(GUIDE_TOPICS)
|
|
31
54
|
.map(([key, { label }]) => `- ${key}: ${label}`)
|
|
32
55
|
.join('\n');
|
|
@@ -42,11 +65,11 @@ export function registerGetGuide(server) {
|
|
|
42
65
|
annotations: READ_ONLY_ANNOTATIONS,
|
|
43
66
|
}, ({ topic }) => {
|
|
44
67
|
try {
|
|
45
|
-
const {
|
|
46
|
-
return markdownResponse(loadMarkdown(file));
|
|
68
|
+
const { files } = GUIDE_TOPICS[topic];
|
|
69
|
+
return markdownResponse(files.map((file) => loadMarkdown(file)).join('\n\n'));
|
|
47
70
|
}
|
|
48
71
|
catch (e) {
|
|
49
|
-
return
|
|
72
|
+
return loadFailureError(`guide "${topic}"`, e);
|
|
50
73
|
}
|
|
51
74
|
});
|
|
52
75
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loadMarkdown } from '../lib/load-markdown.js';
|
|
2
2
|
import { extractSection } from '../lib/markdown-utils.js';
|
|
3
|
-
import { markdownResponse,
|
|
3
|
+
import { markdownResponse, loadFailureError, READ_ONLY_ANNOTATIONS } from '../lib/response.js';
|
|
4
4
|
/**
|
|
5
5
|
* SKILL.md を中核に、css-rules.md の Layer 構造セクションと
|
|
6
6
|
* responsive.md のブレイクポイントセクションを付加して返す。
|
|
@@ -34,7 +34,7 @@ export function registerGetOverview(server) {
|
|
|
34
34
|
return markdownResponse(buildOverviewMarkdown());
|
|
35
35
|
}
|
|
36
36
|
catch (e) {
|
|
37
|
-
return
|
|
37
|
+
return loadFailureError('overview data', e);
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { loadPropsMarkdown } from '../lib/load-markdown.js';
|
|
3
3
|
import { parsePropRows } from '../lib/markdown-utils.js';
|
|
4
4
|
import { parsePropClassName } from '../lib/search.js';
|
|
5
|
-
import { markdownResponse,
|
|
5
|
+
import { markdownResponse, loadFailureError, notFound, READ_ONLY_ANNOTATIONS } from '../lib/response.js';
|
|
6
6
|
/** cssProperty フィールドからコア名を抽出("--hl 変数のみ" → "--hl") */
|
|
7
7
|
function normalizeCssProperty(raw) {
|
|
8
8
|
return raw
|
|
@@ -26,7 +26,7 @@ export function registerGetPropsSystem(server) {
|
|
|
26
26
|
annotations: READ_ONLY_ANNOTATIONS,
|
|
27
27
|
}, ({ prop }) => {
|
|
28
28
|
try {
|
|
29
|
-
const md =
|
|
29
|
+
const md = loadPropsMarkdown();
|
|
30
30
|
// prop 未指定: 全文を返す
|
|
31
31
|
if (!prop) {
|
|
32
32
|
return markdownResponse(md);
|
|
@@ -44,13 +44,15 @@ export function registerGetPropsSystem(server) {
|
|
|
44
44
|
});
|
|
45
45
|
if (matched.length === 0) {
|
|
46
46
|
const availableProps = rows.map((r) => `${r.prop} (${r.cssProperty})`);
|
|
47
|
-
return notFound(`"${prop}"
|
|
47
|
+
return notFound(`No prop matches "${prop}". Search by Lism prop name (e.g. "p", "fz") or CSS property name (e.g. "padding", "font-size").`, {
|
|
48
|
+
availableProps,
|
|
49
|
+
});
|
|
48
50
|
}
|
|
49
51
|
// 一致したセクション名のユニーク一覧を取得
|
|
50
52
|
const sections = [...new Set(matched.map((r) => r.sectionName))];
|
|
51
53
|
// property-class.md から対象セクションを抽出して結合
|
|
52
54
|
const lines = md.split('\n');
|
|
53
|
-
const resultParts = [`##
|
|
55
|
+
const resultParts = [`## Search results: "${prop}"\n`];
|
|
54
56
|
for (const sectionName of sections) {
|
|
55
57
|
// セクション内の一致する行だけを含む簡易 Markdown を生成
|
|
56
58
|
const sectionRows = matched.filter((r) => r.sectionName === sectionName);
|
|
@@ -67,7 +69,7 @@ export function registerGetPropsSystem(server) {
|
|
|
67
69
|
return markdownResponse(resultParts.join('\n\n'));
|
|
68
70
|
}
|
|
69
71
|
catch (e) {
|
|
70
|
-
return
|
|
72
|
+
return loadFailureError('props system data', e);
|
|
71
73
|
}
|
|
72
74
|
});
|
|
73
75
|
}
|
package/dist/tools/get-tokens.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { loadMarkdown } from '../lib/load-markdown.js';
|
|
2
|
-
import { markdownResponse,
|
|
2
|
+
import { markdownResponse, loadFailureError, READ_ONLY_ANNOTATIONS } from '../lib/response.js';
|
|
3
3
|
export function registerGetTokens(server) {
|
|
4
4
|
server.registerTool('get_tokens', {
|
|
5
5
|
description: 'Get design tokens (colors, spacing, font sizes, shadows, etc.) used in lism-css. Returns the full token reference including CSS variable names and available values.\n' +
|
|
@@ -12,7 +12,7 @@ export function registerGetTokens(server) {
|
|
|
12
12
|
return markdownResponse(loadMarkdown('tokens.md'));
|
|
13
13
|
}
|
|
14
14
|
catch (e) {
|
|
15
|
-
return
|
|
15
|
+
return loadFailureError('tokens data', e);
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
18
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { loadJSON } from '../lib/load-data.js';
|
|
3
|
-
import {
|
|
4
|
-
import { DocsEntrySchema } from '../lib/schemas.js';
|
|
3
|
+
import { loadPropsMarkdown } from '../lib/load-markdown.js';
|
|
4
|
+
import { DocsEntrySchema, MetaInfoSchema, SearchResultSchema } from '../lib/schemas.js';
|
|
5
5
|
import { parsePropRows } from '../lib/markdown-utils.js';
|
|
6
6
|
import { searchDocs } from '../lib/search.js';
|
|
7
|
-
import { success,
|
|
7
|
+
import { success, loadFailureError, READ_ONLY_ANNOTATIONS } from '../lib/response.js';
|
|
8
|
+
import { GUIDE_TOPIC_KEYS } from './get-guide.js';
|
|
8
9
|
const DOC_CATEGORIES = ['all', 'core-components', 'primitives', 'property-class', 'ui', 'guide'];
|
|
9
10
|
/**
|
|
10
11
|
* property-class.md のテーブルから CSSプロパティ名 → Lism prop名 のマップを構築する。
|
|
@@ -27,22 +28,27 @@ export function registerSearchDocs(server) {
|
|
|
27
28
|
description: "Search lism-css documentation by keyword. Returns matching pages with relevance scores. Supports CSS property names (e.g. 'font-size', 'padding') which are automatically expanded to corresponding lism prop names.\n" +
|
|
28
29
|
'Use this when you cannot find information with other tools, or to discover available components, features, and guides by keyword.\n' +
|
|
29
30
|
'Do NOT use this as your first step — prefer get_component for a known component, get_props_system for a known prop, or get_guide for a specific topic. This is a fallback search tool.\n' +
|
|
30
|
-
'Returns JSON with search results including page URLs and relevance scores.',
|
|
31
|
+
'Returns JSON with search results including page URLs and relevance scores. Each result includes a nextTool field with the recommended follow-up tool call for fetching that page in detail.',
|
|
31
32
|
inputSchema: {
|
|
32
33
|
query: z.string().describe('Search query (keywords separated by spaces). CSS property names like "font-size" are also accepted.'),
|
|
33
34
|
category: z.enum(DOC_CATEGORIES).default('all').describe('Filter by documentation category.'),
|
|
34
35
|
limit: z.number().int().min(1).max(20).default(10).describe('Maximum number of results to return.'),
|
|
35
36
|
},
|
|
37
|
+
outputSchema: {
|
|
38
|
+
meta: MetaInfoSchema,
|
|
39
|
+
query: z.string(),
|
|
40
|
+
results: z.array(SearchResultSchema),
|
|
41
|
+
},
|
|
36
42
|
annotations: READ_ONLY_ANNOTATIONS,
|
|
37
43
|
}, ({ query, category, limit }) => {
|
|
38
44
|
try {
|
|
39
45
|
const entries = loadJSON('docs-index.json', z.array(DocsEntrySchema));
|
|
40
|
-
const cssPropertyMap = buildCssPropertyMapFromMarkdown(
|
|
41
|
-
const results = searchDocs(entries, query, { category, limit, cssPropertyMap });
|
|
46
|
+
const cssPropertyMap = buildCssPropertyMapFromMarkdown(loadPropsMarkdown());
|
|
47
|
+
const results = searchDocs(entries, query, { category, limit, cssPropertyMap, guideTopics: GUIDE_TOPIC_KEYS });
|
|
42
48
|
return success({ query, results });
|
|
43
49
|
}
|
|
44
50
|
catch (e) {
|
|
45
|
-
return
|
|
51
|
+
return loadFailureError('docs search index', e);
|
|
46
52
|
}
|
|
47
53
|
});
|
|
48
54
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lism-css/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "MCP server for lism-css documentation and API reference.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"modelcontextprotocol",
|
|
8
|
+
"lism-css",
|
|
9
|
+
"css",
|
|
10
|
+
"documentation"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://lism-css.com/",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/lism-css/lism-css/tree/main/packages/mcp"
|
|
16
|
+
},
|
|
5
17
|
"type": "module",
|
|
6
18
|
"bin": {
|
|
7
|
-
"mcp": "./bin/lism-mcp.mjs"
|
|
19
|
+
"lism-mcp": "./bin/lism-mcp.mjs"
|
|
8
20
|
},
|
|
9
21
|
"main": "./dist/index.js",
|
|
10
22
|
"files": [
|
|
@@ -12,15 +24,18 @@
|
|
|
12
24
|
"bin"
|
|
13
25
|
],
|
|
14
26
|
"dependencies": {
|
|
15
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
16
28
|
"zod": "^3.25.76"
|
|
17
29
|
},
|
|
18
30
|
"devDependencies": {
|
|
19
|
-
"@types/node": "^25.
|
|
20
|
-
"typescript": "^5.
|
|
21
|
-
"vitest": "^4.1.
|
|
31
|
+
"@types/node": "^25.9.4",
|
|
32
|
+
"typescript": "^5.9.3",
|
|
33
|
+
"vitest": "^4.1.10"
|
|
22
34
|
},
|
|
23
35
|
"license": "MIT",
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
},
|
|
24
39
|
"scripts": {
|
|
25
40
|
"format": "prettier --write . --ignore-path ../../.prettierignore",
|
|
26
41
|
"build": "tsc -p tsconfig.build.json && cp src/data/docs-index.json dist/data/ && rm -rf dist/data/guides && cp -r ../../skills/lism-css-guide dist/data/guides",
|