@monoharada/wcf-mcp 0.7.0 → 0.9.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 CHANGED
@@ -78,7 +78,7 @@ claude mcp add wcf -- npx @monoharada/wcf-mcp
78
78
  }
79
79
  ```
80
80
 
81
- ## 提供機能(16 tools + 1 prompt + 4 resources)
81
+ ## 提供機能(16 tools + 1 prompt + 5 resources)
82
82
 
83
83
  ### ガードレール
84
84
 
@@ -242,6 +242,7 @@ claude mcp add wcf -- npx @monoharada/wcf-mcp
242
242
  | `wcf://tokens` | トークン summary(type/category/themes/sample) |
243
243
  | `wcf://guidelines/{topic}` | topic 別ガイドライン要約(`accessibility`,`css`,`patterns`,`all`) |
244
244
  | `wcf://llms-full` | `llms-full.txt` の全文 |
245
+ | `wcf://skills` | 登録済み Claude Code / Cursor / Codex スキルカタログ(skills-registry.json ベース) |
245
246
 
246
247
  ### Figma MCP との併用
247
248
 
package/core.mjs CHANGED
@@ -17,8 +17,25 @@ export const CANONICAL_PREFIX = 'dads';
17
17
  export const MAX_PREFIX_LENGTH = 64;
18
18
  export const STRUCTURED_CONTENT_DISABLE_FLAG = 'WCF_MCP_DISABLE_STRUCTURED_CONTENT';
19
19
  export const MAX_TOOL_RESULT_BYTES = 100 * 1024;
20
- export const PLUGIN_TOOL_NOTICE = 'Plugin tool (contract v1).';
21
- export const PLUGIN_CONTRACT_VERSION = '1.0.0';
20
+ export const PLUGIN_TOOL_NOTICE = 'Plugin tool (contract v1.1).';
21
+ export const PLUGIN_CONTRACT_VERSION = '1.1.0';
22
+
23
+ /**
24
+ * Convert a plugin tool's inputSchema to a passthrough Zod schema.
25
+ * Handles three cases:
26
+ * - Already a Zod schema instance (has _def or _zod) → apply .passthrough()
27
+ * - Plain object (raw shape map) → wrap with z.object().passthrough()
28
+ * - Falsy / empty → z.object({}).passthrough()
29
+ */
30
+ function toPassthroughSchema(schema) {
31
+ if (schema && (schema._def || schema._zod)) {
32
+ // Already a Zod schema — apply passthrough if it's an object type
33
+ return typeof schema.passthrough === 'function'
34
+ ? schema.passthrough()
35
+ : schema;
36
+ }
37
+ return z.object(schema ?? {}).passthrough();
38
+ }
22
39
 
23
40
  export const CATEGORY_MAP = {
24
41
  'dads-input-text': 'Form',
@@ -135,8 +152,24 @@ export const WCF_RESOURCE_URIS = Object.freeze({
135
152
  tokens: 'wcf://tokens',
136
153
  guidelinesTemplate: 'wcf://guidelines/{topic}',
137
154
  llmsFull: 'wcf://llms-full',
155
+ skills: 'wcf://skills',
138
156
  });
139
157
 
158
+ /** Normalize a skill entry to summary fields (omit compat/manifest for wcf://skills). */
159
+ function normalizeSkillSummary(s) {
160
+ return {
161
+ name: s.name,
162
+ description: s.description ?? '',
163
+ status: s.status ?? 'active',
164
+ path: s.path ?? '',
165
+ entry: s.entry ?? 'SKILL.md',
166
+ clients: Array.isArray(s.clients) ? s.clients : [],
167
+ tags: Array.isArray(s.tags) ? s.tags : [],
168
+ version: typeof s.version === 'string' ? s.version : '0.0.0',
169
+ dependencies: Array.isArray(s.dependencies) ? s.dependencies : [],
170
+ };
171
+ }
172
+
140
173
  // Unidirectional synonym table: key → expands to include these terms (DIG-09)
141
174
  // Searching "keyboard" also matches "focus", "tab" etc. but NOT reverse.
142
175
  const SYNONYM_TABLE = new Map([
@@ -722,7 +755,7 @@ function toPluginErrorMessage(name, reason) {
722
755
  * name: string,
723
756
  * description?: string,
724
757
  * inputSchema?: Record<string, unknown>,
725
- * handler?: (args: Record<string, unknown>, context: { plugin: { name: string, version: string }, helpers: { loadJsonData: Function } }) => unknown,
758
+ * handler?: (args: Record<string, unknown>, context: { plugin: { name: string, version: string }, helpers: { loadJsonData: Function, loadTextData: Function } }) => unknown,
726
759
  * staticPayload?: unknown,
727
760
  * }} WcfMcpPluginTool
728
761
  */
@@ -2137,6 +2170,33 @@ export async function createMcpServer(loadJsonData, loadValidator, options = {})
2137
2170
  },
2138
2171
  );
2139
2172
 
2173
+ // -----------------------------------------------------------------------
2174
+ // Resource: wcf://skills
2175
+ // -----------------------------------------------------------------------
2176
+ server.registerResource(
2177
+ 'wcf_skills',
2178
+ WCF_RESOURCE_URIS.skills,
2179
+ {
2180
+ title: 'WCF Skills Catalog',
2181
+ description: 'Registered Claude Code / Cursor / Codex skills from skills-registry.json.',
2182
+ mimeType: 'application/json',
2183
+ },
2184
+ async () => {
2185
+ const registry = await loadJsonData('skills-registry.json');
2186
+ if (!registry || !Array.isArray(registry.skills)) {
2187
+ throw new Error('SKILLS_REGISTRY_UNAVAILABLE: skills-registry.json is not available.');
2188
+ }
2189
+ const skills = registry.skills.map(normalizeSkillSummary);
2190
+ return {
2191
+ contents: [{
2192
+ uri: WCF_RESOURCE_URIS.skills,
2193
+ mimeType: 'application/json',
2194
+ text: JSON.stringify({ schemaVersion: registry.schemaVersion ?? 2, total: skills.length, skills }, null, 2),
2195
+ }],
2196
+ };
2197
+ },
2198
+ );
2199
+
2140
2200
  // -----------------------------------------------------------------------
2141
2201
  // Tool: get_design_system_overview
2142
2202
  // -----------------------------------------------------------------------
@@ -2232,6 +2292,10 @@ export async function createMcpServer(loadJsonData, loadValidator, options = {})
2232
2292
  uri: WCF_RESOURCE_URIS.llmsFull,
2233
2293
  purpose: 'Full LLM reference text for WCF',
2234
2294
  },
2295
+ {
2296
+ uri: WCF_RESOURCE_URIS.skills,
2297
+ purpose: 'Skills catalog snapshot',
2298
+ },
2235
2299
  ],
2236
2300
  availableTools: [
2237
2301
  { name: 'get_design_system_overview', purpose: 'This overview (start here)' },
@@ -3326,7 +3390,7 @@ export async function createMcpServer(loadJsonData, loadValidator, options = {})
3326
3390
  tool.name,
3327
3391
  {
3328
3392
  description: tool.description,
3329
- inputSchema: tool.inputSchema ?? {},
3393
+ inputSchema: toPassthroughSchema(tool.inputSchema),
3330
3394
  },
3331
3395
  async (args) => {
3332
3396
  try {
@@ -3335,6 +3399,7 @@ export async function createMcpServer(loadJsonData, loadValidator, options = {})
3335
3399
  plugin: { name: plugin.name, version: plugin.version },
3336
3400
  helpers: {
3337
3401
  loadJsonData: loadJson,
3402
+ loadTextData: loadText,
3338
3403
  buildJsonToolResponse,
3339
3404
  normalizePrefix,
3340
3405
  withPrefix,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoharada/wcf-mcp",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "MCP server for the web-components-factory design system. Provides component discovery, validation, and pattern-based UI composition without cloning the repository.",
5
5
  "type": "module",
6
6
  "bin": {
package/server.mjs CHANGED
@@ -25,6 +25,7 @@ const REPO_FILE_MAP = {
25
25
  'design-tokens.json': 'design-tokens.json',
26
26
  'guidelines-index.json': 'guidelines-index.json',
27
27
  'llms-full.txt': 'llms-full.txt',
28
+ 'skills-registry.json': 'registry/skills-registry.json',
28
29
  };
29
30
  export const DEFAULT_WCF_MCP_CONFIG = 'wcf-mcp.config.json';
30
31