skill-registry-mcp 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ /**
2
+ * SkillRegistryClient - handles API calls to the Skill Registry API
3
+ * Implements session-level deduplication for find_skill
4
+ * Implements LRU offline cache and health polling with exponential backoff
5
+ */
6
+ import type { Namespace } from './config.js';
7
+ export interface ClientOptions {
8
+ apiKey: string;
9
+ baseUrl: string;
10
+ namespace: Namespace;
11
+ /** Override the skills directory (defaults to ~/.claude/skills). Used in tests. */
12
+ skillsDir?: string;
13
+ }
14
+ export interface FindSkillInput {
15
+ query: string;
16
+ bundle_id?: string;
17
+ }
18
+ export interface SubmitFeedbackInput {
19
+ match_id: string;
20
+ skill_id: string;
21
+ result: 'success' | 'failure' | 'partial';
22
+ score: number;
23
+ }
24
+ export interface SkillRegistryClient {
25
+ findSkill(input: FindSkillInput): Promise<string>;
26
+ listBundles(): Promise<string>;
27
+ submitFeedback(input: SubmitFeedbackInput): Promise<string>;
28
+ /** Clean up background resources (health polling timer). */
29
+ destroy?: () => void;
30
+ }
31
+ /**
32
+ * Create a new SkillRegistryClient instance with its own session dedup state.
33
+ */
34
+ export declare function createSkillRegistryClient(options: ClientOptions): SkillRegistryClient;
35
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAM5C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,SAAS,CAAA;IACpB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;IACzC,KAAK,EAAE,MAAM,CAAA;CACd;AA4BD,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACjD,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9B,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3D,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AA6CD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,aAAa,GAAG,mBAAmB,CAmVrF"}
package/dist/client.js ADDED
@@ -0,0 +1,366 @@
1
+ /**
2
+ * SkillRegistryClient - handles API calls to the Skill Registry API
3
+ * Implements session-level deduplication for find_skill
4
+ * Implements LRU offline cache and health polling with exponential backoff
5
+ */
6
+ import { mkdir, writeFile, readFile } from 'fs/promises';
7
+ import { existsSync } from 'fs';
8
+ import { join, dirname } from 'path';
9
+ import { homedir } from 'os';
10
+ // LRU cache constants
11
+ const LRU_MAX_SIZE = 50;
12
+ const HEALTH_POLL_INITIAL_MS = 5000;
13
+ const HEALTH_POLL_MAX_MS = 60000;
14
+ /**
15
+ * Minimal LRU cache using a Map (insertion order + re-insertion on access).
16
+ * Key is query.trim().toLowerCase(). Max size is LRU_MAX_SIZE.
17
+ */
18
+ class LRUCache {
19
+ map = new Map();
20
+ maxSize;
21
+ constructor(maxSize) {
22
+ this.maxSize = maxSize;
23
+ }
24
+ get(key) {
25
+ if (!this.map.has(key))
26
+ return undefined;
27
+ // Re-insert to mark as recently used
28
+ const value = this.map.get(key);
29
+ this.map.delete(key);
30
+ this.map.set(key, value);
31
+ return value;
32
+ }
33
+ set(key, value) {
34
+ if (this.map.has(key)) {
35
+ this.map.delete(key);
36
+ }
37
+ this.map.set(key, value);
38
+ // Evict oldest (first) entry if over capacity
39
+ if (this.map.size > this.maxSize) {
40
+ const firstKey = this.map.keys().next().value;
41
+ this.map.delete(firstKey);
42
+ }
43
+ }
44
+ has(key) {
45
+ return this.map.has(key);
46
+ }
47
+ }
48
+ /**
49
+ * Create a new SkillRegistryClient instance with its own session dedup state.
50
+ */
51
+ export function createSkillRegistryClient(options) {
52
+ const { apiKey, baseUrl, namespace } = options;
53
+ const skillsDir = options.skillsDir ?? join(homedir(), '.claude', 'skills');
54
+ // Session-level deduplication: tracks skill_ids already returned in this client instance
55
+ const returnedSkillIds = new Set();
56
+ // LRU offline cache: key = query.trim().toLowerCase(), value = AGENT.md content string
57
+ const offlineCache = new LRUCache(LRU_MAX_SIZE);
58
+ // Offline state tracking
59
+ let isOffline = false;
60
+ let healthPollTimer = null;
61
+ let currentPollIntervalMs = HEALTH_POLL_INITIAL_MS;
62
+ /**
63
+ * Start health polling with exponential backoff.
64
+ * Only starts if not already polling.
65
+ */
66
+ function startHealthPolling() {
67
+ if (healthPollTimer !== null)
68
+ return;
69
+ currentPollIntervalMs = HEALTH_POLL_INITIAL_MS;
70
+ scheduleHealthPoll();
71
+ }
72
+ function scheduleHealthPoll() {
73
+ healthPollTimer = setTimeout(async () => {
74
+ healthPollTimer = null;
75
+ await pollHealth();
76
+ }, currentPollIntervalMs);
77
+ }
78
+ async function pollHealth() {
79
+ try {
80
+ const response = await fetch(`${baseUrl}/v1/health`, {
81
+ method: 'GET',
82
+ headers: { Authorization: `Bearer ${apiKey}` },
83
+ });
84
+ if (response.ok) {
85
+ let data = {};
86
+ try {
87
+ data = (await response.json());
88
+ }
89
+ catch {
90
+ // ignore parse errors
91
+ }
92
+ if (data.status === 'ok' || data.status === 'degraded') {
93
+ // Cloud is back
94
+ isOffline = false;
95
+ healthPollTimer = null;
96
+ currentPollIntervalMs = HEALTH_POLL_INITIAL_MS;
97
+ return;
98
+ }
99
+ }
100
+ }
101
+ catch {
102
+ // Health check failed - still offline
103
+ }
104
+ // Still offline: schedule next poll with exponential backoff
105
+ currentPollIntervalMs = Math.min(currentPollIntervalMs * 2, HEALTH_POLL_MAX_MS);
106
+ scheduleHealthPoll();
107
+ }
108
+ /**
109
+ * Stop health polling and clean up timer.
110
+ */
111
+ function stopHealthPolling() {
112
+ if (healthPollTimer !== null) {
113
+ clearTimeout(healthPollTimer);
114
+ healthPollTimer = null;
115
+ }
116
+ }
117
+ async function findSkill(input) {
118
+ const cacheKey = input.query.trim().toLowerCase();
119
+ // If offline, try cache first
120
+ if (isOffline) {
121
+ const cached = offlineCache.get(cacheKey);
122
+ if (cached !== undefined) {
123
+ return cached;
124
+ }
125
+ return '当前处于离线模式,未找到缓存结果。错误码:OFFLINE_CACHE_MISS';
126
+ }
127
+ const body = {
128
+ query: input.query,
129
+ namespace,
130
+ };
131
+ if (input.bundle_id) {
132
+ body.bundle_id = input.bundle_id;
133
+ }
134
+ let response;
135
+ try {
136
+ response = await fetch(`${baseUrl}/v1/match`, {
137
+ method: 'POST',
138
+ headers: {
139
+ 'Content-Type': 'application/json',
140
+ Authorization: `Bearer ${apiKey}`,
141
+ },
142
+ body: JSON.stringify(body),
143
+ });
144
+ }
145
+ catch (err) {
146
+ // Network error - switch to offline mode
147
+ isOffline = true;
148
+ startHealthPolling();
149
+ // Try cache
150
+ const cached = offlineCache.get(cacheKey);
151
+ if (cached !== undefined) {
152
+ return cached;
153
+ }
154
+ return '当前处于离线模式,未找到缓存结果。错误码:OFFLINE_CACHE_MISS';
155
+ }
156
+ if (response.status === 401) {
157
+ return '认证失败:API Key 无效或未授权,请检查 SKILL_REGISTRY_API_KEY 环境变量。';
158
+ }
159
+ if (response.status === 429) {
160
+ return '请求超限:已超过 API 调用频率限制,请稍后重试。';
161
+ }
162
+ if (!response.ok) {
163
+ return `API 请求失败:HTTP ${response.status}`;
164
+ }
165
+ let data;
166
+ try {
167
+ data = (await response.json());
168
+ }
169
+ catch {
170
+ return 'API 返回数据格式错误';
171
+ }
172
+ if (!data.skills || data.skills.length === 0) {
173
+ return '未找到匹配的 skill';
174
+ }
175
+ const skill = data.skills[0];
176
+ // Session-level deduplication check
177
+ if (returnedSkillIds.has(skill.skill_id)) {
178
+ // Extract skill name from content (first line H1 header) or fall back to skill_id
179
+ const skillName = extractSkillName(skill.content, skill.skill_id);
180
+ return `[${skillName}] 已在当前 session 中提供,请参考之前的上下文`;
181
+ }
182
+ // Mark this skill as returned in the current session
183
+ returnedSkillIds.add(skill.skill_id);
184
+ // If this is a Script type skill, attempt to download scripts
185
+ if (skill.type === 'Script' && skill.name && skill.scripts && skill.scripts.length > 0) {
186
+ const warnings = await downloadScripts(skill);
187
+ const finalContent = warnings.length > 0
188
+ ? skill.content + '\n\n' + warnings.join('\n')
189
+ : skill.content;
190
+ // Cache the content (even Script skills)
191
+ offlineCache.set(cacheKey, finalContent);
192
+ return finalContent;
193
+ }
194
+ // Cache the result (AC1)
195
+ offlineCache.set(cacheKey, skill.content);
196
+ return skill.content;
197
+ }
198
+ /**
199
+ * Download script files for a Script-type skill.
200
+ * Returns an array of warning strings (empty if all downloads succeeded).
201
+ */
202
+ async function downloadScripts(skill) {
203
+ const skillName = skill.name;
204
+ const skillDir = join(skillsDir, skillName);
205
+ const versionFile = join(skillDir, '.version');
206
+ // Check if local version matches remote version (skip download if same)
207
+ if (skill.version && existsSync(versionFile)) {
208
+ try {
209
+ const localVersion = await readFile(versionFile, 'utf8');
210
+ if (localVersion.trim() === skill.version.trim()) {
211
+ // Same version, skip download
212
+ return [];
213
+ }
214
+ }
215
+ catch {
216
+ // Cannot read version file, proceed with download
217
+ }
218
+ }
219
+ // Ensure skill directory exists
220
+ try {
221
+ await mkdir(skillDir, { recursive: true });
222
+ }
223
+ catch {
224
+ return ['[WARN] 脚本文件下载失败,请手动下载或重新调用'];
225
+ }
226
+ const warnings = [];
227
+ for (const filename of skill.scripts) {
228
+ const scriptUrl = `${baseUrl}/v1/skills/${skill.skill_id}/scripts/${filename}`;
229
+ let scriptResponse;
230
+ try {
231
+ scriptResponse = await fetch(scriptUrl, {
232
+ headers: {
233
+ Authorization: `Bearer ${apiKey}`,
234
+ },
235
+ });
236
+ }
237
+ catch (err) {
238
+ // Network error
239
+ warnings.push('[WARN] 脚本文件下载失败,请手动下载或重新调用');
240
+ continue;
241
+ }
242
+ if (scriptResponse.status === 404) {
243
+ warnings.push('[WARN] 脚本文件不存在,请联系 skill 维护者');
244
+ continue;
245
+ }
246
+ if (!scriptResponse.ok) {
247
+ warnings.push('[WARN] 脚本文件下载失败,请手动下载或重新调用');
248
+ continue;
249
+ }
250
+ try {
251
+ const scriptContent = await scriptResponse.arrayBuffer();
252
+ const scriptPath = join(skillDir, filename);
253
+ // Ensure subdirectory exists if filename contains path separators
254
+ await mkdir(dirname(scriptPath), { recursive: true });
255
+ await writeFile(scriptPath, Buffer.from(scriptContent));
256
+ }
257
+ catch {
258
+ warnings.push('[WARN] 脚本文件下载失败,请手动下载或重新调用');
259
+ continue;
260
+ }
261
+ }
262
+ // Write version file if all downloads succeeded (no warnings)
263
+ if (warnings.length === 0 && skill.version) {
264
+ try {
265
+ await writeFile(versionFile, skill.version);
266
+ }
267
+ catch {
268
+ // Non-critical: ignore version file write failure
269
+ }
270
+ }
271
+ return warnings;
272
+ }
273
+ async function listBundles() {
274
+ let response;
275
+ try {
276
+ response = await fetch(`${baseUrl}/v1/bundles`, {
277
+ method: 'GET',
278
+ headers: {
279
+ Authorization: `Bearer ${apiKey}`,
280
+ },
281
+ });
282
+ }
283
+ catch (err) {
284
+ return `网络错误:无法连接到 Skill Registry API。${String(err)}`;
285
+ }
286
+ if (response.status === 401) {
287
+ return '认证失败:API Key 无效或未授权。';
288
+ }
289
+ if (!response.ok) {
290
+ return `API 请求失败:HTTP ${response.status}`;
291
+ }
292
+ let data;
293
+ try {
294
+ data = (await response.json());
295
+ }
296
+ catch {
297
+ return 'API 返回数据格式错误';
298
+ }
299
+ if (!data.bundles || data.bundles.length === 0) {
300
+ return '暂无可用的 bundle';
301
+ }
302
+ // Format as plain text
303
+ const lines = ['Bundle 列表:', ''];
304
+ for (const bundle of data.bundles) {
305
+ lines.push(`Bundle ID: ${bundle.bundle_id}`);
306
+ lines.push(`名称: ${bundle.name}`);
307
+ if (bundle.description) {
308
+ lines.push(`描述: ${bundle.description}`);
309
+ }
310
+ lines.push(`命名空间: ${bundle.namespace}`);
311
+ lines.push(`Skill 数量: ${bundle.skill_count}`);
312
+ lines.push('');
313
+ }
314
+ return lines.join('\n').trimEnd();
315
+ }
316
+ async function submitFeedback(input) {
317
+ let response;
318
+ try {
319
+ response = await fetch(`${baseUrl}/v1/feedback`, {
320
+ method: 'POST',
321
+ headers: {
322
+ 'Content-Type': 'application/json',
323
+ Authorization: `Bearer ${apiKey}`,
324
+ },
325
+ body: JSON.stringify(input),
326
+ });
327
+ }
328
+ catch (err) {
329
+ return `网络错误:无法连接到 Skill Registry API。${String(err)}`;
330
+ }
331
+ if (response.status === 401) {
332
+ return '认证失败:API Key 无效或未授权,请检查 SKILL_REGISTRY_API_KEY 环境变量。';
333
+ }
334
+ if (response.status === 400) {
335
+ let errorBody = {};
336
+ try {
337
+ errorBody = (await response.json());
338
+ }
339
+ catch {
340
+ // ignore JSON parse failure
341
+ }
342
+ const errorCode = String(errorBody.error ?? 'UNKNOWN_ERROR');
343
+ const errorMsg = String(errorBody.message ?? '');
344
+ return `反馈提交失败:${errorCode}${errorMsg ? ' - ' + errorMsg : ''}`;
345
+ }
346
+ if (!response.ok) {
347
+ return `API 请求失败:HTTP ${response.status}`;
348
+ }
349
+ return '反馈已提交';
350
+ }
351
+ function destroy() {
352
+ stopHealthPolling();
353
+ }
354
+ return { findSkill, listBundles, submitFeedback, destroy };
355
+ }
356
+ /**
357
+ * Extract skill name from AGENT.md content (first H1 heading) or fall back to skill_id.
358
+ */
359
+ function extractSkillName(content, skillId) {
360
+ const match = content.match(/^#\s+(.+)$/m);
361
+ if (match) {
362
+ return match[1].trim();
363
+ }
364
+ return skillId;
365
+ }
366
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Configuration parsing and validation for MCP server
3
+ */
4
+ export type Namespace = 'private' | 'public' | 'all';
5
+ export interface McpConfig {
6
+ namespace: Namespace;
7
+ }
8
+ export interface EnvConfig {
9
+ apiKey: string;
10
+ }
11
+ /**
12
+ * Parse command-line arguments for the MCP server.
13
+ * Supports: --namespace <private|public|all>
14
+ */
15
+ export declare function parseArgs(args: string[]): McpConfig;
16
+ /**
17
+ * Validate required environment variables.
18
+ * Throws with descriptive error if SKILL_REGISTRY_API_KEY is not set.
19
+ */
20
+ export declare function validateEnv(): EnvConfig;
21
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAA;AAEpD,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAA;CACf;AAID;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAoBnD;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,SAAS,CASvC"}
package/dist/config.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Configuration parsing and validation for MCP server
3
+ */
4
+ const VALID_NAMESPACES = ['private', 'public', 'all'];
5
+ /**
6
+ * Parse command-line arguments for the MCP server.
7
+ * Supports: --namespace <private|public|all>
8
+ */
9
+ export function parseArgs(args) {
10
+ let namespace = 'all';
11
+ for (let i = 0; i < args.length; i++) {
12
+ if (args[i] === '--namespace') {
13
+ const value = args[i + 1];
14
+ if (!value) {
15
+ throw new Error('--namespace requires a value');
16
+ }
17
+ if (!VALID_NAMESPACES.includes(value)) {
18
+ throw new Error(`Invalid namespace value: "${value}". Must be one of: ${VALID_NAMESPACES.join(', ')}`);
19
+ }
20
+ namespace = value;
21
+ i++; // skip the value
22
+ }
23
+ }
24
+ return { namespace };
25
+ }
26
+ /**
27
+ * Validate required environment variables.
28
+ * Throws with descriptive error if SKILL_REGISTRY_API_KEY is not set.
29
+ */
30
+ export function validateEnv() {
31
+ const apiKey = process.env.SKILL_REGISTRY_API_KEY;
32
+ if (!apiKey) {
33
+ throw new Error('SKILL_REGISTRY_API_KEY environment variable is required but not set. ' +
34
+ 'Please set it before starting the MCP server.');
35
+ }
36
+ return { apiKey };
37
+ }
38
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,gBAAgB,GAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;AAElE;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,IAAI,SAAS,GAAc,KAAK,CAAA;IAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACzB,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;YACjD,CAAC;YACD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAkB,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,KAAK,CACb,6BAA6B,KAAK,sBAAsB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtF,CAAA;YACH,CAAC;YACD,SAAS,GAAG,KAAkB,CAAA;YAC9B,CAAC,EAAE,CAAA,CAAC,iBAAiB;QACvB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,CAAA;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAA;IACjD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,uEAAuE;YACvE,+CAA+C,CAChD,CAAA;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,CAAA;AACnB,CAAC"}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @skill-registry/mcp - MCP Server entry point
4
+ *
5
+ * Usage:
6
+ * skill-registry-mcp --namespace <private|public|all>
7
+ *
8
+ * Environment variables:
9
+ * SKILL_REGISTRY_API_KEY (required) API key for Skill Registry
10
+ * SKILL_REGISTRY_BASE_URL (optional) Base URL, defaults to https://api.skill-registry.dev
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
package/dist/index.js ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @skill-registry/mcp - MCP Server entry point
4
+ *
5
+ * Usage:
6
+ * skill-registry-mcp --namespace <private|public|all>
7
+ *
8
+ * Environment variables:
9
+ * SKILL_REGISTRY_API_KEY (required) API key for Skill Registry
10
+ * SKILL_REGISTRY_BASE_URL (optional) Base URL, defaults to https://api.skill-registry.dev
11
+ */
12
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
13
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
14
+ import { z } from 'zod';
15
+ import { appendFileSync } from 'node:fs';
16
+ import { parseArgs, validateEnv } from './config.js';
17
+ import { createSkillRegistryClient } from './client.js';
18
+ import { FIND_SKILL_DESCRIPTION, LIST_BUNDLES_DESCRIPTION, SUBMIT_FEEDBACK_DESCRIPTION, } from './tools.js';
19
+ const LOG_FILE = '/tmp/skill-registry-mcp.log';
20
+ function log(msg) {
21
+ appendFileSync(LOG_FILE, `[${new Date().toISOString()}] ${msg}\n`);
22
+ }
23
+ async function main() {
24
+ // Validate required env vars (will throw and exit if missing)
25
+ let envConfig;
26
+ try {
27
+ envConfig = validateEnv();
28
+ }
29
+ catch (err) {
30
+ console.error(`[skill-registry-mcp] Error: ${String(err)}`);
31
+ process.exit(1);
32
+ }
33
+ // Parse CLI args
34
+ let mcpConfig;
35
+ try {
36
+ mcpConfig = parseArgs(process.argv.slice(2));
37
+ }
38
+ catch (err) {
39
+ console.error(`[skill-registry-mcp] Error: ${String(err)}`);
40
+ process.exit(1);
41
+ }
42
+ const baseUrl = process.env.SKILL_REGISTRY_BASE_URL ?? 'https://api.skill-registry.dev';
43
+ // Create API client (with session-level dedup)
44
+ const client = createSkillRegistryClient({
45
+ apiKey: envConfig.apiKey,
46
+ baseUrl,
47
+ namespace: mcpConfig.namespace,
48
+ });
49
+ // Create MCP server
50
+ const server = new McpServer({
51
+ name: 'skill-registry',
52
+ version: '0.0.1',
53
+ }, {
54
+ instructions: '你是一个有技能库加持的编程助手。' +
55
+ '当用户要求实现功能、修复 bug、重构代码或执行编码任务时,' +
56
+ '先调用 find_skill 搜索是否有可复用的 skill,按返回的 AGENT.md 执行任务。' +
57
+ '任务完成后调用 submit_feedback 提交反馈。' +
58
+ '如果 find_skill 无匹配结果,正常编码即可。',
59
+ });
60
+ // Register find_skill tool
61
+ server.tool('find_skill', FIND_SKILL_DESCRIPTION, {
62
+ query: z.string().describe('搜索查询文本,描述你需要的 skill 功能(最多 1000 字符)'),
63
+ bundle_id: z.string().optional().describe('(可选)限定在指定 bundle 中搜索'),
64
+ }, async ({ query, bundle_id }) => {
65
+ log(`find_skill called | query="${query}" bundle_id=${bundle_id ?? 'none'}`);
66
+ const result = await client.findSkill({ query, bundle_id });
67
+ log(`find_skill result | length=${result.length}`);
68
+ return {
69
+ content: [{ type: 'text', text: result }],
70
+ };
71
+ });
72
+ // Register list_bundles tool
73
+ server.tool('list_bundles', LIST_BUNDLES_DESCRIPTION, {}, async () => {
74
+ log('list_bundles called');
75
+ const result = await client.listBundles();
76
+ log(`list_bundles result | length=${result.length}`);
77
+ return {
78
+ content: [{ type: 'text', text: result }],
79
+ };
80
+ });
81
+ // Register submit_feedback tool
82
+ server.tool('submit_feedback', SUBMIT_FEEDBACK_DESCRIPTION, {
83
+ match_id: z.string().describe('find_skill 返回的 match_id(UUID)'),
84
+ skill_id: z.string().describe('使用的 skill ID'),
85
+ result: z.enum(['success', 'failure', 'partial']).describe('执行结果:success、failure 或 partial'),
86
+ score: z.number().int().min(1).max(3).describe('有用程度评分:1(无帮助)、2(一般)、3(非常有帮助)'),
87
+ }, async ({ match_id, skill_id, result, score }) => {
88
+ log(`submit_feedback called | match_id=${match_id} skill_id=${skill_id} result=${result} score=${score}`);
89
+ const text = await client.submitFeedback({ match_id, skill_id, result, score });
90
+ log(`submit_feedback done`);
91
+ return {
92
+ content: [{ type: 'text', text }],
93
+ };
94
+ });
95
+ // Start stdio transport
96
+ const transport = new StdioServerTransport();
97
+ await server.connect(transport);
98
+ log('MCP server started');
99
+ }
100
+ main().catch((err) => {
101
+ console.error('[skill-registry-mcp] Fatal error:', err);
102
+ process.exit(1);
103
+ });
104
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}