skilldb 0.4.3 → 0.5.2

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/dist/mcp.js CHANGED
@@ -125,16 +125,22 @@ var args = process.argv.slice(2);
125
125
  var apiKeyIdx = args.indexOf("--api-key");
126
126
  var apiKey = apiKeyIdx >= 0 ? args[apiKeyIdx + 1] : resolveApiKey();
127
127
  var baseUrl = args.includes("--base-url") ? args[args.indexOf("--base-url") + 1] : void 0;
128
+ var hasApiKey = !!apiKey;
128
129
  var client = new SkillDBClient({ apiKey, baseUrl });
130
+ if (!hasApiKey) {
131
+ process.stderr.write(
132
+ "\n\u26A0\uFE0F SkillDB MCP: No API key configured.\n You can search and browse skills, but full content requires a Pro key.\n Get a free key at: https://skilldb.dev/api-access\n Then run: claude mcp remove skilldb && claude mcp add skilldb -- skilldb-mcp --api-key YOUR_KEY\n\n"
133
+ );
134
+ }
129
135
  var server = new McpServer({
130
136
  name: "skilldb",
131
- version: "0.4.0"
137
+ version: "0.5.2"
132
138
  });
133
139
  server.registerTool(
134
140
  "skilldb_search",
135
141
  {
136
142
  title: "Search SkillDB Skills",
137
- description: "Search the SkillDB library of 5,000+ AI agent skills by keyword. Returns skill metadata including name, description, pack, category, and line count. Use this to find relevant skills for any coding task.",
143
+ description: "Search the SkillDB library of 5,000+ AI agent skills by keyword. Returns skill metadata (name, description, pack, category, line count). Without an API key, only metadata is returned. With a key, full skill content is included. Get a free key at skilldb.dev/api-access.",
138
144
  inputSchema: z.object({
139
145
  query: z.string().describe("Search query (e.g. 'code review', 'react hooks', 'security')"),
140
146
  category: z.string().optional().describe("Filter by category name"),
@@ -150,14 +156,25 @@ server.registerTool(
150
156
  limit: Math.min(limit || 10, 50),
151
157
  includeContent: !!apiKey
152
158
  });
153
- const text = res.skills.length === 0 ? `No skills found for "${query}".` : res.skills.map(
159
+ const noKey = !hasApiKey;
160
+ const text = res.skills.length === 0 ? `No skills found for "${query}".` : (noKey ? `\u26A0\uFE0F **No API key configured** \u2014 showing metadata only. Full skill content (instructions, patterns, code examples) requires a free API key.
161
+ \u{1F449} Get yours in 30 seconds: https://skilldb.dev/api-access
162
+ \u{1F449} Then: \`claude mcp remove skilldb && claude mcp add skilldb -- skilldb-mcp --api-key YOUR_KEY\`
163
+
164
+ ---
165
+
166
+ ` : "") + res.skills.map(
154
167
  (s, i) => `${i + 1}. **${s.title}** (${s.pack})
155
168
  ${s.description}
156
- ID: ${s.id} | ${s.lines} lines | Category: ${s.category}${s.content ? "\n Content: " + s.content.substring(0, 200) + "..." : ""}`
169
+ ID: \`${s.id}\` | ${s.lines} lines | Category: ${s.category}` + (s.content ? `
170
+ \u2705 Full content available (${s.lines} lines)` : `
171
+ \u{1F512} Content locked \u2014 needs API key`)
157
172
  ).join("\n\n") + `
158
173
 
159
174
  ---
160
- Found ${res.pagination.total} total results. Showing ${res.skills.length}.`;
175
+ Found ${res.pagination.total} total results. Showing ${res.skills.length}.` + (noKey ? `
176
+
177
+ \u{1F511} **To unlock full content:** Get a free API key at https://skilldb.dev/api-access` : "");
161
178
  return { content: [{ type: "text", text }] };
162
179
  } catch (e) {
163
180
  return { content: [{ type: "text", text: `Error: ${e.message}` }], isError: true };
@@ -168,7 +185,7 @@ server.registerTool(
168
185
  "skilldb_get",
169
186
  {
170
187
  title: "Get Skill Content",
171
- description: "Retrieve the full content of a specific SkillDB skill by its ID. Returns the complete markdown skill file with instructions, best practices, and patterns that can be used as agent context. Requires a Pro or Studio API key for full content.",
188
+ description: "Retrieve a SkillDB skill by ID. Without an API key: returns metadata + description only. With an API key: returns the FULL markdown content (instructions, patterns, best practices). Get a free key at skilldb.dev/api-access for full access.",
172
189
  inputSchema: z.object({
173
190
  id: z.string().describe("Skill ID (e.g. 'software-skills/code-review.md')")
174
191
  })
@@ -176,15 +193,27 @@ server.registerTool(
176
193
  async ({ id }) => {
177
194
  try {
178
195
  const skill = await client.get(id);
179
- const text = skill.content ? `# ${skill.title}
196
+ let text;
197
+ if (skill.content) {
198
+ text = `# ${skill.title}
180
199
  **Pack:** ${skill.pack} | **Category:** ${skill.category} | **Lines:** ${skill.lines}
181
200
 
182
- ${skill.content}` : `# ${skill.title}
201
+ ${skill.content}`;
202
+ } else {
203
+ text = `# ${skill.title}
183
204
  **Pack:** ${skill.pack} | **Category:** ${skill.category} | **Lines:** ${skill.lines}
184
205
 
185
206
  ${skill.description}
186
207
 
187
- _Full content requires a Pro API key. Get one at https://skilldb.dev/api-access_`;
208
+ ---
209
+ \u26A0\uFE0F **Full content not available** \u2014 you're seeing metadata only.
210
+
211
+ To load the complete ${skill.lines}-line skill with instructions, patterns, and best practices:
212
+ 1. Get a free API key at https://skilldb.dev/api-access
213
+ 2. Reconfigure: \`claude mcp remove skilldb && claude mcp add skilldb -- skilldb-mcp --api-key YOUR_KEY\`
214
+
215
+ Free keys get 100 calls/month. Pro ($9/mo) gets unlimited access.`;
216
+ }
188
217
  return { content: [{ type: "text", text }] };
189
218
  } catch (e) {
190
219
  return { content: [{ type: "text", text: `Error: ${e.message}` }], isError: true };
@@ -320,6 +349,120 @@ Use \`skilldb_search\` to explore individual skills within each pack.`;
320
349
  return { content: [{ type: "text", text }] };
321
350
  }
322
351
  );
352
+ server.registerTool(
353
+ "skilldb_purge",
354
+ {
355
+ title: "Purge Cached Skills",
356
+ description: "Remove cached SkillDB skills from the local .skilldb/ directory to free disk space. By default removes inactive skills + slim summaries. Use 'all' to clear everything, or 'inactive' to only remove unused skills.",
357
+ inputSchema: z.object({
358
+ mode: z.enum(["default", "all", "inactive", "slim"]).optional().default("default").describe("What to purge: 'default' (inactive + slim), 'all' (everything), 'inactive' (unused only), 'slim' (summaries only)"),
359
+ dryRun: z.boolean().optional().default(false).describe("Preview what would be removed without deleting")
360
+ })
361
+ },
362
+ async ({ mode, dryRun }) => {
363
+ try {
364
+ const fs2 = await import("fs");
365
+ const path2 = await import("path");
366
+ const cwd = process.cwd();
367
+ const skilldbDir = path2.join(cwd, ".skilldb");
368
+ const skillsDir = path2.join(skilldbDir, "skills");
369
+ const activeDir = path2.join(skilldbDir, "active");
370
+ const slimDir = path2.join(skilldbDir, "slim");
371
+ if (!fs2.existsSync(skilldbDir)) {
372
+ return { content: [{ type: "text", text: "No .skilldb/ directory found. Run `skilldb init` first." }] };
373
+ }
374
+ const collectSkills = (dir) => {
375
+ const skills = [];
376
+ if (!fs2.existsSync(dir)) return skills;
377
+ for (const pack of fs2.readdirSync(dir, { withFileTypes: true })) {
378
+ if (!pack.isDirectory()) continue;
379
+ for (const file of fs2.readdirSync(path2.join(dir, pack.name))) {
380
+ if (file.endsWith(".md")) skills.push(`${pack.name}/${file}`);
381
+ }
382
+ }
383
+ return skills;
384
+ };
385
+ const allSkills = collectSkills(skillsDir);
386
+ const activeSkills = new Set(collectSkills(activeDir));
387
+ const inactiveSkills = allSkills.filter((s) => !activeSkills.has(s));
388
+ const slimSkills = collectSkills(slimDir);
389
+ let toPurge = [];
390
+ let purgeSlim = false;
391
+ if (mode === "all") {
392
+ toPurge = [...allSkills];
393
+ purgeSlim = true;
394
+ } else if (mode === "inactive") {
395
+ toPurge = inactiveSkills;
396
+ } else if (mode === "slim") {
397
+ purgeSlim = true;
398
+ } else {
399
+ toPurge = inactiveSkills;
400
+ purgeSlim = true;
401
+ }
402
+ if (dryRun) {
403
+ const lines = [
404
+ `## Purge Preview (dry run)`,
405
+ `- Skills to remove: ${toPurge.length}`,
406
+ `- Slim summaries to remove: ${purgeSlim ? slimSkills.length : 0}`,
407
+ `- Active skills kept: ${activeSkills.size}`,
408
+ "",
409
+ ...toPurge.slice(0, 30).map((s) => ` - ${s}`),
410
+ toPurge.length > 30 ? ` ... and ${toPurge.length - 30} more` : ""
411
+ ];
412
+ return { content: [{ type: "text", text: lines.filter(Boolean).join("\n") }] };
413
+ }
414
+ let removed = 0;
415
+ let bytesFreed = 0;
416
+ for (const skillId of toPurge) {
417
+ const [pack, file] = skillId.split("/");
418
+ const filePath = path2.join(skillsDir, pack, file);
419
+ if (fs2.existsSync(filePath)) {
420
+ bytesFreed += fs2.statSync(filePath).size;
421
+ fs2.unlinkSync(filePath);
422
+ removed++;
423
+ }
424
+ const packDir = path2.join(skillsDir, pack);
425
+ if (fs2.existsSync(packDir) && fs2.readdirSync(packDir).length === 0) {
426
+ fs2.rmdirSync(packDir);
427
+ }
428
+ }
429
+ let slimRemoved = 0;
430
+ if (purgeSlim && fs2.existsSync(slimDir)) {
431
+ for (const pack of fs2.readdirSync(slimDir, { withFileTypes: true })) {
432
+ if (!pack.isDirectory()) continue;
433
+ const packPath = path2.join(slimDir, pack.name);
434
+ for (const file of fs2.readdirSync(packPath)) {
435
+ const fp = path2.join(packPath, file);
436
+ bytesFreed += fs2.statSync(fp).size;
437
+ fs2.unlinkSync(fp);
438
+ slimRemoved++;
439
+ }
440
+ if (fs2.readdirSync(packPath).length === 0) fs2.rmdirSync(packPath);
441
+ }
442
+ }
443
+ if (mode === "all" && fs2.existsSync(activeDir)) {
444
+ for (const pack of fs2.readdirSync(activeDir, { withFileTypes: true })) {
445
+ if (!pack.isDirectory()) continue;
446
+ const packPath = path2.join(activeDir, pack.name);
447
+ for (const file of fs2.readdirSync(packPath)) {
448
+ fs2.unlinkSync(path2.join(packPath, file));
449
+ }
450
+ fs2.rmdirSync(packPath);
451
+ }
452
+ }
453
+ const text = [
454
+ `## Purge Complete`,
455
+ `- Skills removed: ${removed}`,
456
+ `- Slim summaries removed: ${slimRemoved}`,
457
+ `- Space freed: ${(bytesFreed / 1024).toFixed(0)} KB`,
458
+ `- Active skills kept: ${mode === "all" ? 0 : activeSkills.size}`
459
+ ].join("\n");
460
+ return { content: [{ type: "text", text }] };
461
+ } catch (e) {
462
+ return { content: [{ type: "text", text: `Error: ${e.message}` }], isError: true };
463
+ }
464
+ }
465
+ );
323
466
  var transport = new StdioServerTransport();
324
467
  await server.connect(transport);
325
468
  //# sourceMappingURL=mcp.js.map
package/dist/mcp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mcp.ts","../src/config.ts","../src/client.ts"],"sourcesContent":["/**\n * SkillDB MCP Server\n *\n * Model Context Protocol server that exposes SkillDB skills\n * to any MCP-compatible AI coding tool (Claude Code, Cursor,\n * Windsurf, VS Code Copilot, and 30+ others).\n *\n * Installation:\n * claude mcp add skilldb -- npx skilldb-mcp\n * # or with API key:\n * claude mcp add skilldb -- npx skilldb-mcp --api-key sk_live_xxx\n *\n * Cursor (settings.json):\n * { \"mcpServers\": { \"skilldb\": { \"command\": \"npx\", \"args\": [\"skilldb-mcp\"] } } }\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { SkillDBClient } from \"./client.js\";\nimport { resolveApiKey } from \"./config.js\";\n\n// Parse CLI args for API key\nconst args = process.argv.slice(2);\nconst apiKeyIdx = args.indexOf(\"--api-key\");\nconst apiKey = apiKeyIdx >= 0 ? args[apiKeyIdx + 1] : resolveApiKey();\nconst baseUrl = args.includes(\"--base-url\")\n ? args[args.indexOf(\"--base-url\") + 1]\n : undefined;\n\nconst client = new SkillDBClient({ apiKey, baseUrl });\n\nconst server = new McpServer({\n name: \"skilldb\",\n version: \"0.4.0\",\n});\n\n// ─── Tool: Search Skills ───\nserver.registerTool(\n \"skilldb_search\",\n {\n title: \"Search SkillDB Skills\",\n description:\n \"Search the SkillDB library of 5,000+ AI agent skills by keyword. Returns skill metadata including name, description, pack, category, and line count. Use this to find relevant skills for any coding task.\",\n inputSchema: z.object({\n query: z.string().describe(\"Search query (e.g. 'code review', 'react hooks', 'security')\"),\n category: z.string().optional().describe(\"Filter by category name\"),\n pack: z.string().optional().describe(\"Filter by pack name\"),\n limit: z.number().optional().default(10).describe(\"Max results (1-50)\"),\n }),\n },\n async ({ query, category, pack, limit }) => {\n try {\n const res = await client.search(query, {\n category,\n pack,\n limit: Math.min(limit || 10, 50),\n includeContent: !!apiKey,\n });\n\n const text = res.skills.length === 0\n ? `No skills found for \"${query}\".`\n : res.skills\n .map(\n (s, i) =>\n `${i + 1}. **${s.title}** (${s.pack})\\n ${s.description}\\n ID: ${s.id} | ${s.lines} lines | Category: ${s.category}${s.content ? \"\\n Content: \" + s.content.substring(0, 200) + \"...\" : \"\"}`\n )\n .join(\"\\n\\n\") +\n `\\n\\n---\\nFound ${res.pagination.total} total results. Showing ${res.skills.length}.`;\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Tool: Get Skill Content ───\nserver.registerTool(\n \"skilldb_get\",\n {\n title: \"Get Skill Content\",\n description:\n \"Retrieve the full content of a specific SkillDB skill by its ID. Returns the complete markdown skill file with instructions, best practices, and patterns that can be used as agent context. Requires a Pro or Studio API key for full content.\",\n inputSchema: z.object({\n id: z.string().describe(\"Skill ID (e.g. 'software-skills/code-review.md')\"),\n }),\n },\n async ({ id }) => {\n try {\n const skill = await client.get(id);\n const text = skill.content\n ? `# ${skill.title}\\n**Pack:** ${skill.pack} | **Category:** ${skill.category} | **Lines:** ${skill.lines}\\n\\n${skill.content}`\n : `# ${skill.title}\\n**Pack:** ${skill.pack} | **Category:** ${skill.category} | **Lines:** ${skill.lines}\\n\\n${skill.description}\\n\\n_Full content requires a Pro API key. Get one at https://skilldb.dev/api-access_`;\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Tool: List Skills ───\nserver.registerTool(\n \"skilldb_list\",\n {\n title: \"List SkillDB Skills\",\n description:\n \"Browse all available skills with optional filtering by category or pack. Use this to explore what's available in the SkillDB library.\",\n inputSchema: z.object({\n category: z.string().optional().describe(\"Filter by category (e.g. 'Software Engineering', 'Security')\"),\n pack: z.string().optional().describe(\"Filter by pack (e.g. 'software-skills', 'react-patterns-skills')\"),\n sort: z.enum([\"name\", \"-name\", \"lines\", \"-lines\", \"pack\", \"category\"]).optional().describe(\"Sort order\"),\n limit: z.number().optional().default(20).describe(\"Max results (1-100)\"),\n offset: z.number().optional().default(0).describe(\"Pagination offset\"),\n }),\n },\n async ({ category, pack, sort, limit, offset }) => {\n try {\n const res = await client.list({ category, pack, sort, limit, offset });\n\n const text = res.skills.length === 0\n ? \"No skills found with those filters.\"\n : `## SkillDB Skills${category ? ` — ${category}` : \"\"}${pack ? ` — ${pack}` : \"\"}\\n\\n` +\n res.skills\n .map((s) => `- **${s.title}** (${s.id}) — ${s.lines} lines\\n ${s.description}`)\n .join(\"\\n\") +\n `\\n\\n---\\n${res.pagination.total} total | Showing ${res.skills.length} (offset ${offset || 0})\\nCategories: ${res.meta.categories.join(\", \")}`;\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Tool: Suggest / Autocomplete ───\nserver.registerTool(\n \"skilldb_suggest\",\n {\n title: \"Suggest Skills\",\n description:\n \"Get autocomplete suggestions for skill names. Fast, lightweight — useful for quick lookups.\",\n inputSchema: z.object({\n query: z.string().min(2).describe(\"Partial skill name (min 2 chars)\"),\n }),\n },\n async ({ query }) => {\n try {\n const res = await client.suggest(query);\n const text = res.suggestions.length === 0\n ? `No suggestions for \"${query}\".`\n : res.suggestions\n .map((s) => `- **${s.title}** (${s.pack} / ${s.category})\\n ID: ${s.id}`)\n .join(\"\\n\");\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Tool: Recommend Skills for Project ───\nserver.registerTool(\n \"skilldb_recommend\",\n {\n title: \"Recommend Skills for Project\",\n description:\n \"Analyze the current project context and recommend relevant SkillDB skill packs. Provide information about the tech stack (languages, frameworks, tools) and get tailored skill pack recommendations.\",\n inputSchema: z.object({\n technologies: z.array(z.string()).describe(\"Technologies in your project (e.g. ['react', 'typescript', 'docker', 'postgresql'])\"),\n role: z.string().optional().describe(\"Your role or focus area (e.g. 'frontend', 'backend', 'devops', 'security')\"),\n }),\n },\n async ({ technologies, role }) => {\n // Map technologies to known skill packs\n const TECH_MAP: Record<string, string[]> = {\n react: [\"react-patterns-skills\", \"web-polish-skills\"],\n vue: [\"vue-skills\", \"web-polish-skills\"],\n angular: [\"angular-skills\", \"web-polish-skills\"],\n svelte: [\"svelte-skills\", \"web-polish-skills\"],\n next: [\"react-patterns-skills\", \"web-polish-skills\"],\n typescript: [\"typescript-skills\"],\n javascript: [\"software-skills\", \"typescript-skills\"],\n python: [\"python-skills\"],\n rust: [\"rust-skills\"],\n go: [\"go-skills\"],\n java: [\"java-skills\"],\n docker: [\"devops-skills\", \"docker-skills\"],\n kubernetes: [\"devops-skills\", \"infrastructure-skills\"],\n aws: [\"cloud-skills\", \"infrastructure-skills\"],\n gcp: [\"cloud-skills\"],\n azure: [\"cloud-skills\"],\n postgresql: [\"database-skills\", \"sql-skills\"],\n mongodb: [\"database-skills\"],\n redis: [\"database-skills\"],\n graphql: [\"api-design-skills\"],\n rest: [\"api-design-skills\"],\n express: [\"nodejs-skills\", \"api-design-skills\"],\n fastify: [\"nodejs-skills\"],\n nestjs: [\"nodejs-skills\", \"api-design-skills\"],\n prisma: [\"database-skills\"],\n \"react-native\": [\"react-native-skills\", \"mobile-skills\"],\n flutter: [\"mobile-skills\"],\n openai: [\"ai-agent-skills\", \"prompt-engineering-skills\"],\n langchain: [\"ai-agent-skills\", \"llm-skills\"],\n claude: [\"ai-agent-skills\", \"prompt-engineering-skills\"],\n };\n\n const ROLE_MAP: Record<string, string[]> = {\n frontend: [\"css-skills\", \"web-polish-skills\", \"typescript-skills\"],\n backend: [\"software-skills\", \"api-design-skills\", \"database-skills\"],\n devops: [\"devops-skills\", \"ci-cd-skills\", \"infrastructure-skills\"],\n security: [\"security-skills\", \"appsec-skills\", \"auth-skills\"],\n fullstack: [\"software-skills\", \"react-patterns-skills\", \"api-design-skills\"],\n data: [\"data-engineering-skills\", \"sql-skills\", \"analytics-skills\"],\n mobile: [\"mobile-skills\", \"react-native-skills\"],\n ai: [\"ai-agent-skills\", \"prompt-engineering-skills\", \"llm-skills\"],\n };\n\n const recommended = new Set<string>([\"software-skills\"]); // always recommend baseline\n for (const tech of technologies) {\n const key = tech.toLowerCase().replace(/[^a-z]/g, \"\");\n for (const [pattern, packs] of Object.entries(TECH_MAP)) {\n if (key.includes(pattern) || pattern.includes(key)) {\n packs.forEach((p) => recommended.add(p));\n }\n }\n }\n if (role) {\n const rolePacks = ROLE_MAP[role.toLowerCase()] || [];\n rolePacks.forEach((p) => recommended.add(p));\n }\n\n const packList = [...recommended];\n const text =\n `## Recommended Skill Packs\\n\\n` +\n `Based on: ${technologies.join(\", \")}${role ? ` (${role})` : \"\"}\\n\\n` +\n packList.map((p) => `- \\`${p}\\` — install with \\`skilldb add ${p}\\``).join(\"\\n\") +\n `\\n\\n**Install all:** \\`${packList.map((p) => `skilldb add ${p}`).join(\" && \")}\\`\\n` +\n `\\nUse \\`skilldb_search\\` to explore individual skills within each pack.`;\n\n return { content: [{ type: \"text\", text }] };\n }\n);\n\n// ─── Start server ───\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst RC_FILE = '.skilldbrc';\n\nexport const DEFAULT_BASE_URL = 'https://skilldb.dev/api/v1';\n\ninterface RcConfig {\n apiKey?: string;\n}\n\nfunction readJson(filePath: string): RcConfig | null {\n try {\n const raw = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve API key from (in priority order):\n * 1. SKILLDB_API_KEY env var\n * 2. .skilldbrc in project root (cwd)\n * 3. ~/.skilldbrc in home dir\n */\nexport function resolveApiKey(): string | undefined {\n if (process.env.SKILLDB_API_KEY) {\n return process.env.SKILLDB_API_KEY;\n }\n\n const projectRc = path.join(process.cwd(), RC_FILE);\n const projectConfig = readJson(projectRc);\n if (projectConfig?.apiKey) return projectConfig.apiKey;\n\n const homeRc = path.join(os.homedir(), RC_FILE);\n const homeConfig = readJson(homeRc);\n if (homeConfig?.apiKey) return homeConfig.apiKey;\n\n return undefined;\n}\n\n/**\n * Resolve base URL from env or default.\n */\nexport function resolveBaseUrl(): string {\n return process.env.SKILLDB_API_URL || DEFAULT_BASE_URL;\n}\n\n/**\n * Save API key to ~/.skilldbrc (user-wide) or project .skilldbrc.\n */\nexport function saveApiKey(apiKey: string, global = true): string {\n const target = global\n ? path.join(os.homedir(), RC_FILE)\n : path.join(process.cwd(), RC_FILE);\n\n const existing = readJson(target) || {};\n fs.writeFileSync(target, JSON.stringify({ ...existing, apiKey }, null, 2) + '\\n', 'utf-8');\n return target;\n}\n","import type { ClientConfig, Skill, SkillsResponse, SearchOptions } from './types.js';\nimport { resolveApiKey, resolveBaseUrl } from './config.js';\n\nexport class SkillDBClient {\n private apiKey?: string;\n private baseUrl: string;\n\n constructor(config?: ClientConfig) {\n this.apiKey = config?.apiKey ?? resolveApiKey();\n this.baseUrl = config?.baseUrl ?? resolveBaseUrl();\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.apiKey) {\n h['Authorization'] = `Bearer ${this.apiKey}`;\n }\n return h;\n }\n\n private async request<T>(endpoint: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${this.baseUrl}${endpoint}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== '') url.searchParams.set(k, v);\n }\n }\n\n const res = await fetch(url.toString(), { headers: this.headers() });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({}));\n const msg = (body as Record<string, string>).error || `HTTP ${res.status}`;\n throw new Error(msg);\n }\n\n return res.json() as Promise<T>;\n }\n\n /** Search skills by keyword. */\n async search(query: string, options?: Omit<SearchOptions, 'search'>): Promise<SkillsResponse> {\n return this.request<SkillsResponse>('/skills', {\n search: query,\n category: options?.category ?? '',\n pack: options?.pack ?? '',\n sort: options?.sort ?? '',\n limit: String(options?.limit ?? 20),\n offset: String(options?.offset ?? 0),\n include_content: options?.includeContent ? 'true' : '',\n });\n }\n\n /** List skills with optional filters and sorting. */\n async list(options?: SearchOptions): Promise<SkillsResponse> {\n return this.request<SkillsResponse>('/skills', {\n category: options?.category ?? '',\n pack: options?.pack ?? '',\n search: options?.search ?? '',\n sort: options?.sort ?? '',\n limit: String(options?.limit ?? 50),\n offset: String(options?.offset ?? 0),\n include_content: options?.includeContent ? 'true' : '',\n });\n }\n\n /** Get a single skill by ID (e.g. \"software-skills/code-review.md\"). */\n async get(id: string): Promise<Skill> {\n const encoded = encodeURIComponent(id);\n const res = await this.request<Skill | { skill: Skill }>(`/skills/${encoded}`, {\n include_content: 'true',\n });\n // Handle both direct and wrapped responses\n return 'skill' in res ? res.skill : res;\n }\n\n /** Batch retrieve multiple skills by IDs (max 50). */\n async batch(ids: string[]): Promise<SkillsResponse> {\n return this.request<SkillsResponse>('/skills', {\n ids: ids.slice(0, 50).join(','),\n include_content: 'true',\n });\n }\n\n /** Get search autocomplete suggestions. */\n async suggest(query: string): Promise<{ suggestions: Array<{ title: string; pack: string; category: string; id: string }> }> {\n return this.request('/skills/suggest', { q: query });\n }\n\n /** Validate that the configured API key works. */\n async validate(): Promise<boolean> {\n try {\n const url = `${this.baseUrl}/keys/usage`;\n const res = await fetch(url, { headers: this.headers() });\n return res.ok;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/mcp.ts","../src/config.ts","../src/client.ts"],"sourcesContent":["/**\n * SkillDB MCP Server\n *\n * Model Context Protocol server that exposes SkillDB skills\n * to any MCP-compatible AI coding tool (Claude Code, Cursor,\n * Windsurf, VS Code Copilot, and 30+ others).\n *\n * Installation:\n * claude mcp add skilldb -- npx skilldb-mcp\n * # or with API key:\n * claude mcp add skilldb -- npx skilldb-mcp --api-key sk_live_xxx\n *\n * Cursor (settings.json):\n * { \"mcpServers\": { \"skilldb\": { \"command\": \"npx\", \"args\": [\"skilldb-mcp\"] } } }\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { SkillDBClient } from \"./client.js\";\nimport { resolveApiKey } from \"./config.js\";\n\n// Parse CLI args for API key\nconst args = process.argv.slice(2);\nconst apiKeyIdx = args.indexOf(\"--api-key\");\nconst apiKey = apiKeyIdx >= 0 ? args[apiKeyIdx + 1] : resolveApiKey();\nconst baseUrl = args.includes(\"--base-url\")\n ? args[args.indexOf(\"--base-url\") + 1]\n : undefined;\n\nconst hasApiKey = !!apiKey;\nconst client = new SkillDBClient({ apiKey, baseUrl });\n\n// Warn on startup if no API key\nif (!hasApiKey) {\n process.stderr.write(\n \"\\n⚠️ SkillDB MCP: No API key configured.\\n\" +\n \" You can search and browse skills, but full content requires a Pro key.\\n\" +\n \" Get a free key at: https://skilldb.dev/api-access\\n\" +\n \" Then run: claude mcp remove skilldb && claude mcp add skilldb -- skilldb-mcp --api-key YOUR_KEY\\n\\n\"\n );\n}\n\nconst server = new McpServer({\n name: \"skilldb\",\n version: \"0.5.2\",\n});\n\n// ─── Tool: Search Skills ───\nserver.registerTool(\n \"skilldb_search\",\n {\n title: \"Search SkillDB Skills\",\n description:\n \"Search the SkillDB library of 5,000+ AI agent skills by keyword. Returns skill metadata (name, description, pack, category, line count). Without an API key, only metadata is returned. With a key, full skill content is included. Get a free key at skilldb.dev/api-access.\",\n inputSchema: z.object({\n query: z.string().describe(\"Search query (e.g. 'code review', 'react hooks', 'security')\"),\n category: z.string().optional().describe(\"Filter by category name\"),\n pack: z.string().optional().describe(\"Filter by pack name\"),\n limit: z.number().optional().default(10).describe(\"Max results (1-50)\"),\n }),\n },\n async ({ query, category, pack, limit }) => {\n try {\n const res = await client.search(query, {\n category,\n pack,\n limit: Math.min(limit || 10, 50),\n includeContent: !!apiKey,\n });\n\n const noKey = !hasApiKey;\n const text = res.skills.length === 0\n ? `No skills found for \"${query}\".`\n : (noKey ? `⚠️ **No API key configured** — showing metadata only. Full skill content (instructions, patterns, code examples) requires a free API key.\\n👉 Get yours in 30 seconds: https://skilldb.dev/api-access\\n👉 Then: \\`claude mcp remove skilldb && claude mcp add skilldb -- skilldb-mcp --api-key YOUR_KEY\\`\\n\\n---\\n\\n` : '') +\n res.skills\n .map(\n (s, i) =>\n `${i + 1}. **${s.title}** (${s.pack})\\n ${s.description}\\n ID: \\`${s.id}\\` | ${s.lines} lines | Category: ${s.category}` +\n (s.content ? `\\n ✅ Full content available (${s.lines} lines)` : `\\n 🔒 Content locked — needs API key`)\n )\n .join(\"\\n\\n\") +\n `\\n\\n---\\nFound ${res.pagination.total} total results. Showing ${res.skills.length}.` +\n (noKey ? `\\n\\n🔑 **To unlock full content:** Get a free API key at https://skilldb.dev/api-access` : '');\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Tool: Get Skill Content ───\nserver.registerTool(\n \"skilldb_get\",\n {\n title: \"Get Skill Content\",\n description:\n \"Retrieve a SkillDB skill by ID. Without an API key: returns metadata + description only. With an API key: returns the FULL markdown content (instructions, patterns, best practices). Get a free key at skilldb.dev/api-access for full access.\",\n inputSchema: z.object({\n id: z.string().describe(\"Skill ID (e.g. 'software-skills/code-review.md')\"),\n }),\n },\n async ({ id }) => {\n try {\n const skill = await client.get(id);\n let text: string;\n if (skill.content) {\n text = `# ${skill.title}\\n**Pack:** ${skill.pack} | **Category:** ${skill.category} | **Lines:** ${skill.lines}\\n\\n${skill.content}`;\n } else {\n text = `# ${skill.title}\\n**Pack:** ${skill.pack} | **Category:** ${skill.category} | **Lines:** ${skill.lines}\\n\\n${skill.description}\\n\\n` +\n `---\\n` +\n `⚠️ **Full content not available** — you're seeing metadata only.\\n\\n` +\n `To load the complete ${skill.lines}-line skill with instructions, patterns, and best practices:\\n` +\n `1. Get a free API key at https://skilldb.dev/api-access\\n` +\n `2. Reconfigure: \\`claude mcp remove skilldb && claude mcp add skilldb -- skilldb-mcp --api-key YOUR_KEY\\`\\n\\n` +\n `Free keys get 100 calls/month. Pro ($9/mo) gets unlimited access.`;\n }\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Tool: List Skills ───\nserver.registerTool(\n \"skilldb_list\",\n {\n title: \"List SkillDB Skills\",\n description:\n \"Browse all available skills with optional filtering by category or pack. Use this to explore what's available in the SkillDB library.\",\n inputSchema: z.object({\n category: z.string().optional().describe(\"Filter by category (e.g. 'Software Engineering', 'Security')\"),\n pack: z.string().optional().describe(\"Filter by pack (e.g. 'software-skills', 'react-patterns-skills')\"),\n sort: z.enum([\"name\", \"-name\", \"lines\", \"-lines\", \"pack\", \"category\"]).optional().describe(\"Sort order\"),\n limit: z.number().optional().default(20).describe(\"Max results (1-100)\"),\n offset: z.number().optional().default(0).describe(\"Pagination offset\"),\n }),\n },\n async ({ category, pack, sort, limit, offset }) => {\n try {\n const res = await client.list({ category, pack, sort, limit, offset });\n\n const text = res.skills.length === 0\n ? \"No skills found with those filters.\"\n : `## SkillDB Skills${category ? ` — ${category}` : \"\"}${pack ? ` — ${pack}` : \"\"}\\n\\n` +\n res.skills\n .map((s) => `- **${s.title}** (${s.id}) — ${s.lines} lines\\n ${s.description}`)\n .join(\"\\n\") +\n `\\n\\n---\\n${res.pagination.total} total | Showing ${res.skills.length} (offset ${offset || 0})\\nCategories: ${res.meta.categories.join(\", \")}`;\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Tool: Suggest / Autocomplete ───\nserver.registerTool(\n \"skilldb_suggest\",\n {\n title: \"Suggest Skills\",\n description:\n \"Get autocomplete suggestions for skill names. Fast, lightweight — useful for quick lookups.\",\n inputSchema: z.object({\n query: z.string().min(2).describe(\"Partial skill name (min 2 chars)\"),\n }),\n },\n async ({ query }) => {\n try {\n const res = await client.suggest(query);\n const text = res.suggestions.length === 0\n ? `No suggestions for \"${query}\".`\n : res.suggestions\n .map((s) => `- **${s.title}** (${s.pack} / ${s.category})\\n ID: ${s.id}`)\n .join(\"\\n\");\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Tool: Recommend Skills for Project ───\nserver.registerTool(\n \"skilldb_recommend\",\n {\n title: \"Recommend Skills for Project\",\n description:\n \"Analyze the current project context and recommend relevant SkillDB skill packs. Provide information about the tech stack (languages, frameworks, tools) and get tailored skill pack recommendations.\",\n inputSchema: z.object({\n technologies: z.array(z.string()).describe(\"Technologies in your project (e.g. ['react', 'typescript', 'docker', 'postgresql'])\"),\n role: z.string().optional().describe(\"Your role or focus area (e.g. 'frontend', 'backend', 'devops', 'security')\"),\n }),\n },\n async ({ technologies, role }) => {\n // Map technologies to known skill packs\n const TECH_MAP: Record<string, string[]> = {\n react: [\"react-patterns-skills\", \"web-polish-skills\"],\n vue: [\"vue-skills\", \"web-polish-skills\"],\n angular: [\"angular-skills\", \"web-polish-skills\"],\n svelte: [\"svelte-skills\", \"web-polish-skills\"],\n next: [\"react-patterns-skills\", \"web-polish-skills\"],\n typescript: [\"typescript-skills\"],\n javascript: [\"software-skills\", \"typescript-skills\"],\n python: [\"python-skills\"],\n rust: [\"rust-skills\"],\n go: [\"go-skills\"],\n java: [\"java-skills\"],\n docker: [\"devops-skills\", \"docker-skills\"],\n kubernetes: [\"devops-skills\", \"infrastructure-skills\"],\n aws: [\"cloud-skills\", \"infrastructure-skills\"],\n gcp: [\"cloud-skills\"],\n azure: [\"cloud-skills\"],\n postgresql: [\"database-skills\", \"sql-skills\"],\n mongodb: [\"database-skills\"],\n redis: [\"database-skills\"],\n graphql: [\"api-design-skills\"],\n rest: [\"api-design-skills\"],\n express: [\"nodejs-skills\", \"api-design-skills\"],\n fastify: [\"nodejs-skills\"],\n nestjs: [\"nodejs-skills\", \"api-design-skills\"],\n prisma: [\"database-skills\"],\n \"react-native\": [\"react-native-skills\", \"mobile-skills\"],\n flutter: [\"mobile-skills\"],\n openai: [\"ai-agent-skills\", \"prompt-engineering-skills\"],\n langchain: [\"ai-agent-skills\", \"llm-skills\"],\n claude: [\"ai-agent-skills\", \"prompt-engineering-skills\"],\n };\n\n const ROLE_MAP: Record<string, string[]> = {\n frontend: [\"css-skills\", \"web-polish-skills\", \"typescript-skills\"],\n backend: [\"software-skills\", \"api-design-skills\", \"database-skills\"],\n devops: [\"devops-skills\", \"ci-cd-skills\", \"infrastructure-skills\"],\n security: [\"security-skills\", \"appsec-skills\", \"auth-skills\"],\n fullstack: [\"software-skills\", \"react-patterns-skills\", \"api-design-skills\"],\n data: [\"data-engineering-skills\", \"sql-skills\", \"analytics-skills\"],\n mobile: [\"mobile-skills\", \"react-native-skills\"],\n ai: [\"ai-agent-skills\", \"prompt-engineering-skills\", \"llm-skills\"],\n };\n\n const recommended = new Set<string>([\"software-skills\"]); // always recommend baseline\n for (const tech of technologies) {\n const key = tech.toLowerCase().replace(/[^a-z]/g, \"\");\n for (const [pattern, packs] of Object.entries(TECH_MAP)) {\n if (key.includes(pattern) || pattern.includes(key)) {\n packs.forEach((p) => recommended.add(p));\n }\n }\n }\n if (role) {\n const rolePacks = ROLE_MAP[role.toLowerCase()] || [];\n rolePacks.forEach((p) => recommended.add(p));\n }\n\n const packList = [...recommended];\n const text =\n `## Recommended Skill Packs\\n\\n` +\n `Based on: ${technologies.join(\", \")}${role ? ` (${role})` : \"\"}\\n\\n` +\n packList.map((p) => `- \\`${p}\\` — install with \\`skilldb add ${p}\\``).join(\"\\n\") +\n `\\n\\n**Install all:** \\`${packList.map((p) => `skilldb add ${p}`).join(\" && \")}\\`\\n` +\n `\\nUse \\`skilldb_search\\` to explore individual skills within each pack.`;\n\n return { content: [{ type: \"text\", text }] };\n }\n);\n\n// ─── Tool: Purge Cached Skills ───\nserver.registerTool(\n \"skilldb_purge\",\n {\n title: \"Purge Cached Skills\",\n description:\n \"Remove cached SkillDB skills from the local .skilldb/ directory to free disk space. By default removes inactive skills + slim summaries. Use 'all' to clear everything, or 'inactive' to only remove unused skills.\",\n inputSchema: z.object({\n mode: z.enum([\"default\", \"all\", \"inactive\", \"slim\"]).optional().default(\"default\")\n .describe(\"What to purge: 'default' (inactive + slim), 'all' (everything), 'inactive' (unused only), 'slim' (summaries only)\"),\n dryRun: z.boolean().optional().default(false).describe(\"Preview what would be removed without deleting\"),\n }),\n },\n async ({ mode, dryRun }) => {\n try {\n const fs = await import(\"fs\");\n const path = await import(\"path\");\n const cwd = process.cwd();\n const skilldbDir = path.join(cwd, \".skilldb\");\n const skillsDir = path.join(skilldbDir, \"skills\");\n const activeDir = path.join(skilldbDir, \"active\");\n const slimDir = path.join(skilldbDir, \"slim\");\n\n if (!fs.existsSync(skilldbDir)) {\n return { content: [{ type: \"text\", text: \"No .skilldb/ directory found. Run `skilldb init` first.\" }] };\n }\n\n // Collect skills\n const collectSkills = (dir: string): string[] => {\n const skills: string[] = [];\n if (!fs.existsSync(dir)) return skills;\n for (const pack of fs.readdirSync(dir, { withFileTypes: true })) {\n if (!pack.isDirectory()) continue;\n for (const file of fs.readdirSync(path.join(dir, pack.name))) {\n if (file.endsWith(\".md\")) skills.push(`${pack.name}/${file}`);\n }\n }\n return skills;\n };\n\n const allSkills = collectSkills(skillsDir);\n const activeSkills = new Set(collectSkills(activeDir));\n const inactiveSkills = allSkills.filter(s => !activeSkills.has(s));\n const slimSkills = collectSkills(slimDir);\n\n let toPurge: string[] = [];\n let purgeSlim = false;\n\n if (mode === \"all\") {\n toPurge = [...allSkills];\n purgeSlim = true;\n } else if (mode === \"inactive\") {\n toPurge = inactiveSkills;\n } else if (mode === \"slim\") {\n purgeSlim = true;\n } else {\n toPurge = inactiveSkills;\n purgeSlim = true;\n }\n\n if (dryRun) {\n const lines = [\n `## Purge Preview (dry run)`,\n `- Skills to remove: ${toPurge.length}`,\n `- Slim summaries to remove: ${purgeSlim ? slimSkills.length : 0}`,\n `- Active skills kept: ${activeSkills.size}`,\n \"\",\n ...toPurge.slice(0, 30).map(s => ` - ${s}`),\n toPurge.length > 30 ? ` ... and ${toPurge.length - 30} more` : \"\",\n ];\n return { content: [{ type: \"text\", text: lines.filter(Boolean).join(\"\\n\") }] };\n }\n\n // Actually purge\n let removed = 0;\n let bytesFreed = 0;\n for (const skillId of toPurge) {\n const [pack, file] = skillId.split(\"/\");\n const filePath = path.join(skillsDir, pack, file);\n if (fs.existsSync(filePath)) {\n bytesFreed += fs.statSync(filePath).size;\n fs.unlinkSync(filePath);\n removed++;\n }\n const packDir = path.join(skillsDir, pack);\n if (fs.existsSync(packDir) && fs.readdirSync(packDir).length === 0) {\n fs.rmdirSync(packDir);\n }\n }\n\n let slimRemoved = 0;\n if (purgeSlim && fs.existsSync(slimDir)) {\n for (const pack of fs.readdirSync(slimDir, { withFileTypes: true })) {\n if (!pack.isDirectory()) continue;\n const packPath = path.join(slimDir, pack.name);\n for (const file of fs.readdirSync(packPath)) {\n const fp = path.join(packPath, file);\n bytesFreed += fs.statSync(fp).size;\n fs.unlinkSync(fp);\n slimRemoved++;\n }\n if (fs.readdirSync(packPath).length === 0) fs.rmdirSync(packPath);\n }\n }\n\n if (mode === \"all\" && fs.existsSync(activeDir)) {\n for (const pack of fs.readdirSync(activeDir, { withFileTypes: true })) {\n if (!pack.isDirectory()) continue;\n const packPath = path.join(activeDir, pack.name);\n for (const file of fs.readdirSync(packPath)) {\n fs.unlinkSync(path.join(packPath, file));\n }\n fs.rmdirSync(packPath);\n }\n }\n\n const text = [\n `## Purge Complete`,\n `- Skills removed: ${removed}`,\n `- Slim summaries removed: ${slimRemoved}`,\n `- Space freed: ${(bytesFreed / 1024).toFixed(0)} KB`,\n `- Active skills kept: ${mode === \"all\" ? 0 : activeSkills.size}`,\n ].join(\"\\n\");\n\n return { content: [{ type: \"text\", text }] };\n } catch (e) {\n return { content: [{ type: \"text\", text: `Error: ${(e as Error).message}` }], isError: true };\n }\n }\n);\n\n// ─── Start server ───\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst RC_FILE = '.skilldbrc';\n\nexport const DEFAULT_BASE_URL = 'https://skilldb.dev/api/v1';\n\ninterface RcConfig {\n apiKey?: string;\n}\n\nfunction readJson(filePath: string): RcConfig | null {\n try {\n const raw = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve API key from (in priority order):\n * 1. SKILLDB_API_KEY env var\n * 2. .skilldbrc in project root (cwd)\n * 3. ~/.skilldbrc in home dir\n */\nexport function resolveApiKey(): string | undefined {\n if (process.env.SKILLDB_API_KEY) {\n return process.env.SKILLDB_API_KEY;\n }\n\n const projectRc = path.join(process.cwd(), RC_FILE);\n const projectConfig = readJson(projectRc);\n if (projectConfig?.apiKey) return projectConfig.apiKey;\n\n const homeRc = path.join(os.homedir(), RC_FILE);\n const homeConfig = readJson(homeRc);\n if (homeConfig?.apiKey) return homeConfig.apiKey;\n\n return undefined;\n}\n\n/**\n * Resolve base URL from env or default.\n */\nexport function resolveBaseUrl(): string {\n return process.env.SKILLDB_API_URL || DEFAULT_BASE_URL;\n}\n\n/**\n * Save API key to ~/.skilldbrc (user-wide) or project .skilldbrc.\n */\nexport function saveApiKey(apiKey: string, global = true): string {\n const target = global\n ? path.join(os.homedir(), RC_FILE)\n : path.join(process.cwd(), RC_FILE);\n\n const existing = readJson(target) || {};\n fs.writeFileSync(target, JSON.stringify({ ...existing, apiKey }, null, 2) + '\\n', 'utf-8');\n return target;\n}\n","import type { ClientConfig, Skill, SkillsResponse, SearchOptions } from './types.js';\nimport { resolveApiKey, resolveBaseUrl } from './config.js';\n\nexport class SkillDBClient {\n private apiKey?: string;\n private baseUrl: string;\n\n constructor(config?: ClientConfig) {\n this.apiKey = config?.apiKey ?? resolveApiKey();\n this.baseUrl = config?.baseUrl ?? resolveBaseUrl();\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.apiKey) {\n h['Authorization'] = `Bearer ${this.apiKey}`;\n }\n return h;\n }\n\n private async request<T>(endpoint: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${this.baseUrl}${endpoint}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== '') url.searchParams.set(k, v);\n }\n }\n\n const res = await fetch(url.toString(), { headers: this.headers() });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({}));\n const msg = (body as Record<string, string>).error || `HTTP ${res.status}`;\n throw new Error(msg);\n }\n\n return res.json() as Promise<T>;\n }\n\n /** Search skills by keyword. */\n async search(query: string, options?: Omit<SearchOptions, 'search'>): Promise<SkillsResponse> {\n return this.request<SkillsResponse>('/skills', {\n search: query,\n category: options?.category ?? '',\n pack: options?.pack ?? '',\n sort: options?.sort ?? '',\n limit: String(options?.limit ?? 20),\n offset: String(options?.offset ?? 0),\n include_content: options?.includeContent ? 'true' : '',\n });\n }\n\n /** List skills with optional filters and sorting. */\n async list(options?: SearchOptions): Promise<SkillsResponse> {\n return this.request<SkillsResponse>('/skills', {\n category: options?.category ?? '',\n pack: options?.pack ?? '',\n search: options?.search ?? '',\n sort: options?.sort ?? '',\n limit: String(options?.limit ?? 50),\n offset: String(options?.offset ?? 0),\n include_content: options?.includeContent ? 'true' : '',\n });\n }\n\n /** Get a single skill by ID (e.g. \"software-skills/code-review.md\"). */\n async get(id: string): Promise<Skill> {\n const encoded = encodeURIComponent(id);\n const res = await this.request<Skill | { skill: Skill }>(`/skills/${encoded}`, {\n include_content: 'true',\n });\n // Handle both direct and wrapped responses\n return 'skill' in res ? res.skill : res;\n }\n\n /** Batch retrieve multiple skills by IDs (max 50). */\n async batch(ids: string[]): Promise<SkillsResponse> {\n return this.request<SkillsResponse>('/skills', {\n ids: ids.slice(0, 50).join(','),\n include_content: 'true',\n });\n }\n\n /** Get search autocomplete suggestions. */\n async suggest(query: string): Promise<{ suggestions: Array<{ title: string; pack: string; category: string; id: string }> }> {\n return this.request('/skills/suggest', { q: query });\n }\n\n /** Validate that the configured API key works. */\n async validate(): Promise<boolean> {\n try {\n const url = `${this.baseUrl}/keys/usage`;\n const res = await fetch(url, { headers: this.headers() });\n return res.ok;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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","names":["fs","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skilldb",
3
- "version": "0.4.3",
3
+ "version": "0.5.2",
4
4
  "description": "SDK and CLI for SkillDB — discover, install, and manage AI agent skills",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",