@skillsmith/mcp-server 0.1.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/dist/.tsbuildinfo +1 -0
- package/dist/src/__tests__/get-skill.test.d.ts +6 -0
- package/dist/src/__tests__/get-skill.test.d.ts.map +1 -0
- package/dist/src/__tests__/get-skill.test.js +88 -0
- package/dist/src/__tests__/get-skill.test.js.map +1 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.d.ts +7 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.js +304 -0
- package/dist/src/__tests__/middleware/errorFormatter.test.js.map +1 -0
- package/dist/src/__tests__/middleware/license.test.d.ts +7 -0
- package/dist/src/__tests__/middleware/license.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/license.test.js +500 -0
- package/dist/src/__tests__/middleware/license.test.js.map +1 -0
- package/dist/src/__tests__/search.test.d.ts +6 -0
- package/dist/src/__tests__/search.test.d.ts.map +1 -0
- package/dist/src/__tests__/search.test.js +86 -0
- package/dist/src/__tests__/search.test.js.map +1 -0
- package/dist/src/__tests__/test-utils.d.ts +19 -0
- package/dist/src/__tests__/test-utils.d.ts.map +1 -0
- package/dist/src/__tests__/test-utils.js +87 -0
- package/dist/src/__tests__/test-utils.js.map +1 -0
- package/dist/src/context/index.d.ts +19 -0
- package/dist/src/context/index.d.ts.map +1 -0
- package/dist/src/context/index.js +25 -0
- package/dist/src/context/index.js.map +1 -0
- package/dist/src/context/project-detector.d.ts +145 -0
- package/dist/src/context/project-detector.d.ts.map +1 -0
- package/dist/src/context/project-detector.js +321 -0
- package/dist/src/context/project-detector.js.map +1 -0
- package/dist/src/context.d.ts +100 -0
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +157 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/core-shim.d.ts +7 -0
- package/dist/src/core-shim.d.ts.map +1 -0
- package/dist/src/core-shim.js +9 -0
- package/dist/src/core-shim.js.map +1 -0
- package/dist/src/health/healthCheck.d.ts +88 -0
- package/dist/src/health/healthCheck.d.ts.map +1 -0
- package/dist/src/health/healthCheck.js +117 -0
- package/dist/src/health/healthCheck.js.map +1 -0
- package/dist/src/health/index.d.ts +21 -0
- package/dist/src/health/index.d.ts.map +1 -0
- package/dist/src/health/index.js +21 -0
- package/dist/src/health/index.js.map +1 -0
- package/dist/src/health/readinessCheck.d.ts +139 -0
- package/dist/src/health/readinessCheck.d.ts.map +1 -0
- package/dist/src/health/readinessCheck.js +266 -0
- package/dist/src/health/readinessCheck.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +178 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/index.test.d.ts +2 -0
- package/dist/src/index.test.d.ts.map +1 -0
- package/dist/src/index.test.js +43 -0
- package/dist/src/index.test.js.map +1 -0
- package/dist/src/logger.d.ts +26 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +179 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/middleware/__tests__/csp.test.d.ts +2 -0
- package/dist/src/middleware/__tests__/csp.test.d.ts.map +1 -0
- package/dist/src/middleware/__tests__/csp.test.js +389 -0
- package/dist/src/middleware/__tests__/csp.test.js.map +1 -0
- package/dist/src/middleware/csp.d.ts +87 -0
- package/dist/src/middleware/csp.d.ts.map +1 -0
- package/dist/src/middleware/csp.js +273 -0
- package/dist/src/middleware/csp.js.map +1 -0
- package/dist/src/middleware/degradation.d.ts +99 -0
- package/dist/src/middleware/degradation.d.ts.map +1 -0
- package/dist/src/middleware/degradation.js +315 -0
- package/dist/src/middleware/degradation.js.map +1 -0
- package/dist/src/middleware/errorFormatter.d.ts +119 -0
- package/dist/src/middleware/errorFormatter.d.ts.map +1 -0
- package/dist/src/middleware/errorFormatter.js +294 -0
- package/dist/src/middleware/errorFormatter.js.map +1 -0
- package/dist/src/middleware/index.d.ts +10 -0
- package/dist/src/middleware/index.d.ts.map +1 -0
- package/dist/src/middleware/index.js +14 -0
- package/dist/src/middleware/index.js.map +1 -0
- package/dist/src/middleware/license.d.ts +161 -0
- package/dist/src/middleware/license.d.ts.map +1 -0
- package/dist/src/middleware/license.js +281 -0
- package/dist/src/middleware/license.js.map +1 -0
- package/dist/src/middleware/toolFeatureMapping.d.ts +36 -0
- package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -0
- package/dist/src/middleware/toolFeatureMapping.js +90 -0
- package/dist/src/middleware/toolFeatureMapping.js.map +1 -0
- package/dist/src/onboarding/first-run.d.ts +64 -0
- package/dist/src/onboarding/first-run.d.ts.map +1 -0
- package/dist/src/onboarding/first-run.js +77 -0
- package/dist/src/onboarding/first-run.js.map +1 -0
- package/dist/src/onboarding/index.d.ts +7 -0
- package/dist/src/onboarding/index.d.ts.map +1 -0
- package/dist/src/onboarding/index.js +7 -0
- package/dist/src/onboarding/index.js.map +1 -0
- package/dist/src/suggestions/index.d.ts +21 -0
- package/dist/src/suggestions/index.d.ts.map +1 -0
- package/dist/src/suggestions/index.js +20 -0
- package/dist/src/suggestions/index.js.map +1 -0
- package/dist/src/suggestions/suggestion-engine.d.ts +185 -0
- package/dist/src/suggestions/suggestion-engine.d.ts.map +1 -0
- package/dist/src/suggestions/suggestion-engine.js +352 -0
- package/dist/src/suggestions/suggestion-engine.js.map +1 -0
- package/dist/src/suggestions/types.d.ts +88 -0
- package/dist/src/suggestions/types.d.ts.map +1 -0
- package/dist/src/suggestions/types.js +21 -0
- package/dist/src/suggestions/types.js.map +1 -0
- package/dist/src/tools/analyze.d.ts +151 -0
- package/dist/src/tools/analyze.d.ts.map +1 -0
- package/dist/src/tools/analyze.js +205 -0
- package/dist/src/tools/analyze.js.map +1 -0
- package/dist/src/tools/compare.d.ts +149 -0
- package/dist/src/tools/compare.d.ts.map +1 -0
- package/dist/src/tools/compare.js +464 -0
- package/dist/src/tools/compare.js.map +1 -0
- package/dist/src/tools/get-skill.d.ts +116 -0
- package/dist/src/tools/get-skill.d.ts.map +1 -0
- package/dist/src/tools/get-skill.js +224 -0
- package/dist/src/tools/get-skill.js.map +1 -0
- package/dist/src/tools/index.d.ts +20 -0
- package/dist/src/tools/index.d.ts.map +1 -0
- package/dist/src/tools/index.js +20 -0
- package/dist/src/tools/index.js.map +1 -0
- package/dist/src/tools/install.d.ts +122 -0
- package/dist/src/tools/install.d.ts.map +1 -0
- package/dist/src/tools/install.js +314 -0
- package/dist/src/tools/install.js.map +1 -0
- package/dist/src/tools/recommend.d.ts +171 -0
- package/dist/src/tools/recommend.d.ts.map +1 -0
- package/dist/src/tools/recommend.js +325 -0
- package/dist/src/tools/recommend.js.map +1 -0
- package/dist/src/tools/search.d.ts +121 -0
- package/dist/src/tools/search.d.ts.map +1 -0
- package/dist/src/tools/search.js +249 -0
- package/dist/src/tools/search.js.map +1 -0
- package/dist/src/tools/suggest.d.ts +181 -0
- package/dist/src/tools/suggest.d.ts.map +1 -0
- package/dist/src/tools/suggest.js +342 -0
- package/dist/src/tools/suggest.js.map +1 -0
- package/dist/src/tools/uninstall.d.ts +123 -0
- package/dist/src/tools/uninstall.d.ts.map +1 -0
- package/dist/src/tools/uninstall.js +250 -0
- package/dist/src/tools/uninstall.js.map +1 -0
- package/dist/src/tools/validate.d.ts +122 -0
- package/dist/src/tools/validate.d.ts.map +1 -0
- package/dist/src/tools/validate.js +497 -0
- package/dist/src/tools/validate.js.map +1 -0
- package/dist/src/utils/installed-skills.d.ts +101 -0
- package/dist/src/utils/installed-skills.d.ts.map +1 -0
- package/dist/src/utils/installed-skills.js +220 -0
- package/dist/src/utils/installed-skills.js.map +1 -0
- package/dist/src/utils/validation.d.ts +76 -0
- package/dist/src/utils/validation.d.ts.map +1 -0
- package/dist/src/utils/validation.js +153 -0
- package/dist/src/utils/validation.js.map +1 -0
- package/dist/src/webhooks/index.d.ts +8 -0
- package/dist/src/webhooks/index.d.ts.map +1 -0
- package/dist/src/webhooks/index.js +9 -0
- package/dist/src/webhooks/index.js.map +1 -0
- package/dist/src/webhooks/webhook-endpoint.d.ts +149 -0
- package/dist/src/webhooks/webhook-endpoint.d.ts.map +1 -0
- package/dist/src/webhooks/webhook-endpoint.js +339 -0
- package/dist/src/webhooks/webhook-endpoint.js.map +1 -0
- package/dist/tests/compare.test.d.ts +6 -0
- package/dist/tests/compare.test.d.ts.map +1 -0
- package/dist/tests/compare.test.js +225 -0
- package/dist/tests/compare.test.js.map +1 -0
- package/dist/tests/context/project-detector.test.d.ts +6 -0
- package/dist/tests/context/project-detector.test.d.ts.map +1 -0
- package/dist/tests/context/project-detector.test.js +719 -0
- package/dist/tests/context/project-detector.test.js.map +1 -0
- package/dist/tests/e2e/compare.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/compare.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/compare.e2e.test.js +286 -0
- package/dist/tests/e2e/compare.e2e.test.js.map +1 -0
- package/dist/tests/e2e/install-flow.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/install-flow.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/install-flow.e2e.test.js +209 -0
- package/dist/tests/e2e/install-flow.e2e.test.js.map +1 -0
- package/dist/tests/e2e/recommend.e2e.test.d.ts +12 -0
- package/dist/tests/e2e/recommend.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/recommend.e2e.test.js +347 -0
- package/dist/tests/e2e/recommend.e2e.test.js.map +1 -0
- package/dist/tests/e2e/skill-flow.e2e.test.d.ts +10 -0
- package/dist/tests/e2e/skill-flow.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/skill-flow.e2e.test.js +280 -0
- package/dist/tests/e2e/skill-flow.e2e.test.js.map +1 -0
- package/dist/tests/e2e/suggest.e2e.test.d.ts +13 -0
- package/dist/tests/e2e/suggest.e2e.test.d.ts.map +1 -0
- package/dist/tests/e2e/suggest.e2e.test.js +347 -0
- package/dist/tests/e2e/suggest.e2e.test.js.map +1 -0
- package/dist/tests/e2e/utils/baseline-collector.d.ts +107 -0
- package/dist/tests/e2e/utils/baseline-collector.d.ts.map +1 -0
- package/dist/tests/e2e/utils/baseline-collector.js +211 -0
- package/dist/tests/e2e/utils/baseline-collector.js.map +1 -0
- package/dist/tests/e2e/utils/hardcoded-detector.d.ts +46 -0
- package/dist/tests/e2e/utils/hardcoded-detector.d.ts.map +1 -0
- package/dist/tests/e2e/utils/hardcoded-detector.js +255 -0
- package/dist/tests/e2e/utils/hardcoded-detector.js.map +1 -0
- package/dist/tests/e2e/utils/index.d.ts +7 -0
- package/dist/tests/e2e/utils/index.d.ts.map +1 -0
- package/dist/tests/e2e/utils/index.js +7 -0
- package/dist/tests/e2e/utils/index.js.map +1 -0
- package/dist/tests/e2e/utils/linear-reporter.d.ts +60 -0
- package/dist/tests/e2e/utils/linear-reporter.d.ts.map +1 -0
- package/dist/tests/e2e/utils/linear-reporter.js +232 -0
- package/dist/tests/e2e/utils/linear-reporter.js.map +1 -0
- package/dist/tests/health.test.d.ts +9 -0
- package/dist/tests/health.test.d.ts.map +1 -0
- package/dist/tests/health.test.js +308 -0
- package/dist/tests/health.test.js.map +1 -0
- package/dist/tests/integration/analyze.integration.test.d.ts +2 -0
- package/dist/tests/integration/analyze.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/analyze.integration.test.js +244 -0
- package/dist/tests/integration/analyze.integration.test.js.map +1 -0
- package/dist/tests/integration/compare.integration.test.d.ts +2 -0
- package/dist/tests/integration/compare.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/compare.integration.test.js +120 -0
- package/dist/tests/integration/compare.integration.test.js.map +1 -0
- package/dist/tests/integration/fixtures/test-skills.d.ts +62 -0
- package/dist/tests/integration/fixtures/test-skills.d.ts.map +1 -0
- package/dist/tests/integration/fixtures/test-skills.js +644 -0
- package/dist/tests/integration/fixtures/test-skills.js.map +1 -0
- package/dist/tests/integration/get-skill.integration.test.d.ts +6 -0
- package/dist/tests/integration/get-skill.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/get-skill.integration.test.js +203 -0
- package/dist/tests/integration/get-skill.integration.test.js.map +1 -0
- package/dist/tests/integration/github-api.integration.test.d.ts +14 -0
- package/dist/tests/integration/github-api.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/github-api.integration.test.js +190 -0
- package/dist/tests/integration/github-api.integration.test.js.map +1 -0
- package/dist/tests/integration/install.integration.test.d.ts +6 -0
- package/dist/tests/integration/install.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/install.integration.test.js +282 -0
- package/dist/tests/integration/install.integration.test.js.map +1 -0
- package/dist/tests/integration/recommend.integration.test.d.ts +2 -0
- package/dist/tests/integration/recommend.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/recommend.integration.test.js +215 -0
- package/dist/tests/integration/recommend.integration.test.js.map +1 -0
- package/dist/tests/integration/search.integration.test.d.ts +6 -0
- package/dist/tests/integration/search.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/search.integration.test.js +229 -0
- package/dist/tests/integration/search.integration.test.js.map +1 -0
- package/dist/tests/integration/setup.d.ts +71 -0
- package/dist/tests/integration/setup.d.ts.map +1 -0
- package/dist/tests/integration/setup.js +124 -0
- package/dist/tests/integration/setup.js.map +1 -0
- package/dist/tests/integration/uninstall.integration.test.d.ts +6 -0
- package/dist/tests/integration/uninstall.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/uninstall.integration.test.js +296 -0
- package/dist/tests/integration/uninstall.integration.test.js.map +1 -0
- package/dist/tests/integration/validate.integration.test.d.ts +2 -0
- package/dist/tests/integration/validate.integration.test.d.ts.map +1 -0
- package/dist/tests/integration/validate.integration.test.js +181 -0
- package/dist/tests/integration/validate.integration.test.js.map +1 -0
- package/dist/tests/onboarding/first-run.test.d.ts +7 -0
- package/dist/tests/onboarding/first-run.test.d.ts.map +1 -0
- package/dist/tests/onboarding/first-run.test.js +258 -0
- package/dist/tests/onboarding/first-run.test.js.map +1 -0
- package/dist/tests/performance/search-performance.test.d.ts +10 -0
- package/dist/tests/performance/search-performance.test.d.ts.map +1 -0
- package/dist/tests/performance/search-performance.test.js +218 -0
- package/dist/tests/performance/search-performance.test.js.map +1 -0
- package/dist/tests/recommend.test.d.ts +6 -0
- package/dist/tests/recommend.test.d.ts.map +1 -0
- package/dist/tests/recommend.test.js +208 -0
- package/dist/tests/recommend.test.js.map +1 -0
- package/dist/tests/suggestions/suggestion-engine.test.d.ts +6 -0
- package/dist/tests/suggestions/suggestion-engine.test.d.ts.map +1 -0
- package/dist/tests/suggestions/suggestion-engine.test.js +448 -0
- package/dist/tests/suggestions/suggestion-engine.test.js.map +1 -0
- package/dist/tests/test-utils.d.ts +74 -0
- package/dist/tests/test-utils.d.ts.map +1 -0
- package/dist/tests/test-utils.js +98 -0
- package/dist/tests/test-utils.js.map +1 -0
- package/dist/tests/tools.test.d.ts +5 -0
- package/dist/tests/tools.test.d.ts.map +1 -0
- package/dist/tests/tools.test.js +138 -0
- package/dist/tests/tools.test.js.map +1 -0
- package/dist/tests/unit/installed-skills.test.d.ts +6 -0
- package/dist/tests/unit/installed-skills.test.d.ts.map +1 -0
- package/dist/tests/unit/installed-skills.test.js +285 -0
- package/dist/tests/unit/installed-skills.test.js.map +1 -0
- package/dist/tests/unit/logger.test.d.ts +6 -0
- package/dist/tests/unit/logger.test.d.ts.map +1 -0
- package/dist/tests/unit/logger.test.js +281 -0
- package/dist/tests/unit/logger.test.js.map +1 -0
- package/dist/tests/validate.test.d.ts +5 -0
- package/dist/tests/validate.test.d.ts.map +1 -0
- package/dist/tests/validate.test.js +303 -0
- package/dist/tests/validate.test.js.map +1 -0
- package/dist/tests/webhooks/proxy-trust.security.test.d.ts +8 -0
- package/dist/tests/webhooks/proxy-trust.security.test.d.ts.map +1 -0
- package/dist/tests/webhooks/proxy-trust.security.test.js +145 -0
- package/dist/tests/webhooks/proxy-trust.security.test.js.map +1 -0
- package/dist/tests/webhooks/rate-limiter.security.test.d.ts +8 -0
- package/dist/tests/webhooks/rate-limiter.security.test.d.ts.map +1 -0
- package/dist/tests/webhooks/rate-limiter.security.test.js +122 -0
- package/dist/tests/webhooks/rate-limiter.security.test.js.map +1 -0
- package/dist/vitest.config.d.ts +6 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +13 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview MCP Skill Recommend Tool for suggesting relevant skills
|
|
3
|
+
* @module @skillsmith/mcp-server/tools/recommend
|
|
4
|
+
* @see SMI-741: Add MCP Tool skill_recommend
|
|
5
|
+
* @see SMI-602: Integrate semantic matching with EmbeddingService
|
|
6
|
+
* @see SMI-604: Add trigger phrase overlap detection
|
|
7
|
+
*
|
|
8
|
+
* Provides skill recommendations based on:
|
|
9
|
+
* - Currently installed skills (semantic similarity)
|
|
10
|
+
* - Optional project context (semantic matching)
|
|
11
|
+
* - Codebase analysis (framework detection)
|
|
12
|
+
* - Overlap detection (avoid similar skills)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Basic recommendation
|
|
16
|
+
* const results = await executeRecommend({
|
|
17
|
+
* installed_skills: ['anthropic/commit'],
|
|
18
|
+
* limit: 5
|
|
19
|
+
* }, toolContext);
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Recommendation with project context
|
|
23
|
+
* const results = await executeRecommend({
|
|
24
|
+
* installed_skills: ['anthropic/commit'],
|
|
25
|
+
* project_context: 'React frontend with Jest testing',
|
|
26
|
+
* limit: 10
|
|
27
|
+
* }, toolContext);
|
|
28
|
+
*/
|
|
29
|
+
import { z } from 'zod';
|
|
30
|
+
import { SkillMatcher, OverlapDetector } from '@skillsmith/core';
|
|
31
|
+
import { getInstalledSkills } from '../utils/installed-skills.js';
|
|
32
|
+
/**
|
|
33
|
+
* Zod schema for recommend tool input validation
|
|
34
|
+
*/
|
|
35
|
+
export const recommendInputSchema = z.object({
|
|
36
|
+
/** Currently installed skill IDs */
|
|
37
|
+
installed_skills: z.array(z.string()).min(0).default([]),
|
|
38
|
+
/** Optional project description for context-aware recommendations */
|
|
39
|
+
project_context: z.string().optional(),
|
|
40
|
+
/** Maximum recommendations to return (default 5) */
|
|
41
|
+
limit: z.number().min(1).max(50).default(5),
|
|
42
|
+
/** Enable overlap detection (default true) */
|
|
43
|
+
detect_overlap: z.boolean().default(true),
|
|
44
|
+
/** Minimum similarity threshold (0-1, default 0.3) */
|
|
45
|
+
min_similarity: z.number().min(0).max(1).default(0.3),
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* MCP tool schema definition for skill_recommend
|
|
49
|
+
*/
|
|
50
|
+
export const recommendToolSchema = {
|
|
51
|
+
name: 'skill_recommend',
|
|
52
|
+
description: 'Recommend skills based on currently installed skills and optional project context. Uses semantic similarity to find relevant skills. Auto-detects installed skills from ~/.claude/skills/ if not provided.',
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
installed_skills: {
|
|
57
|
+
type: 'array',
|
|
58
|
+
items: { type: 'string' },
|
|
59
|
+
description: 'Currently installed skill IDs (e.g., ["anthropic/commit", "community/jest-helper"]). If empty, auto-detects from ~/.claude/skills/',
|
|
60
|
+
},
|
|
61
|
+
project_context: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
description: 'Optional project description for context-aware recommendations (e.g., "React frontend with Jest testing")',
|
|
64
|
+
},
|
|
65
|
+
limit: {
|
|
66
|
+
type: 'number',
|
|
67
|
+
description: 'Maximum recommendations to return (default 5, max 50)',
|
|
68
|
+
minimum: 1,
|
|
69
|
+
maximum: 50,
|
|
70
|
+
default: 5,
|
|
71
|
+
},
|
|
72
|
+
detect_overlap: {
|
|
73
|
+
type: 'boolean',
|
|
74
|
+
description: 'Enable overlap detection to filter similar skills (default true)',
|
|
75
|
+
default: true,
|
|
76
|
+
},
|
|
77
|
+
min_similarity: {
|
|
78
|
+
type: 'number',
|
|
79
|
+
description: 'Minimum similarity threshold (0-1, default 0.3)',
|
|
80
|
+
minimum: 0,
|
|
81
|
+
maximum: 1,
|
|
82
|
+
default: 0.3,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
required: [],
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Map database trust tier to MCP trust tier
|
|
90
|
+
*/
|
|
91
|
+
function mapTrustTierFromDb(dbTier) {
|
|
92
|
+
switch (dbTier) {
|
|
93
|
+
case 'verified':
|
|
94
|
+
return 'verified';
|
|
95
|
+
case 'community':
|
|
96
|
+
return 'community';
|
|
97
|
+
case 'experimental':
|
|
98
|
+
return 'standard';
|
|
99
|
+
case 'unknown':
|
|
100
|
+
default:
|
|
101
|
+
return 'unverified';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Transform a database skill to SkillData format for matching
|
|
106
|
+
*/
|
|
107
|
+
function transformSkillToMatchData(skill) {
|
|
108
|
+
// Generate trigger phrases from name and first few tags
|
|
109
|
+
const triggerPhrases = [
|
|
110
|
+
skill.name,
|
|
111
|
+
`use ${skill.name}`,
|
|
112
|
+
`${skill.name} help`,
|
|
113
|
+
...skill.tags.slice(0, 3).map((tag) => `${tag} ${skill.name}`),
|
|
114
|
+
];
|
|
115
|
+
return {
|
|
116
|
+
id: skill.id,
|
|
117
|
+
name: skill.name,
|
|
118
|
+
description: skill.description || '',
|
|
119
|
+
triggerPhrases,
|
|
120
|
+
keywords: skill.tags,
|
|
121
|
+
qualityScore: Math.round((skill.qualityScore ?? 0.5) * 100),
|
|
122
|
+
trustTier: mapTrustTierFromDb(skill.trustTier),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Load skills from database via ToolContext
|
|
127
|
+
* Returns skills transformed to SkillData format for matching
|
|
128
|
+
*/
|
|
129
|
+
async function loadSkillsFromDatabase(context, limit = 500) {
|
|
130
|
+
const result = context.skillRepository.findAll(limit, 0);
|
|
131
|
+
return result.items.map(transformSkillToMatchData);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Execute skill recommendation based on installed skills and context.
|
|
135
|
+
*
|
|
136
|
+
* Uses semantic similarity to find skills that complement the user's
|
|
137
|
+
* current installation. When project context is provided, it's used
|
|
138
|
+
* to improve recommendation relevance. Overlap detection prevents
|
|
139
|
+
* recommending skills that are too similar to installed ones.
|
|
140
|
+
*
|
|
141
|
+
* @param input - Recommendation parameters
|
|
142
|
+
* @returns Promise resolving to recommendation response
|
|
143
|
+
* @throws {SkillsmithError} When validation fails
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* const response = await executeRecommend({
|
|
147
|
+
* installed_skills: ['anthropic/commit'],
|
|
148
|
+
* project_context: 'React TypeScript frontend',
|
|
149
|
+
* limit: 5
|
|
150
|
+
* }, toolContext);
|
|
151
|
+
* console.log(response.recommendations[0].reason);
|
|
152
|
+
*/
|
|
153
|
+
export async function executeRecommend(input, context) {
|
|
154
|
+
const startTime = performance.now();
|
|
155
|
+
// Validate input with Zod
|
|
156
|
+
const validated = recommendInputSchema.parse(input);
|
|
157
|
+
let { installed_skills } = validated;
|
|
158
|
+
const { project_context, limit, detect_overlap, min_similarity } = validated;
|
|
159
|
+
// SMI-906: Auto-detect installed skills from ~/.claude/skills/ if not provided
|
|
160
|
+
const autoDetected = installed_skills.length === 0;
|
|
161
|
+
if (autoDetected) {
|
|
162
|
+
installed_skills = await getInstalledSkills();
|
|
163
|
+
}
|
|
164
|
+
// Load skills from database (limit to reasonable number for performance)
|
|
165
|
+
// Use 500 as default to balance coverage vs performance
|
|
166
|
+
const skillDatabase = await loadSkillsFromDatabase(context, 500);
|
|
167
|
+
// Initialize matcher with fallback mode for now (real embeddings in production)
|
|
168
|
+
const matcher = new SkillMatcher({
|
|
169
|
+
useFallback: true, // Use mock embeddings for consistent behavior
|
|
170
|
+
minSimilarity: min_similarity,
|
|
171
|
+
qualityWeight: 0.3,
|
|
172
|
+
});
|
|
173
|
+
// Get installed skill data
|
|
174
|
+
const installedSkillData = skillDatabase.filter((s) => installed_skills.some((id) => id.toLowerCase() === s.id.toLowerCase()));
|
|
175
|
+
// SMI-907: Extract installed skill names for name-based overlap detection
|
|
176
|
+
// This filters skills with semantically similar names (e.g., "docker" filters "docker-compose")
|
|
177
|
+
const installedNames = installed_skills.map((id) => {
|
|
178
|
+
// Extract the skill name from the ID (e.g., "community/docker" -> "docker")
|
|
179
|
+
const idName = id.split('/').pop()?.toLowerCase() || '';
|
|
180
|
+
// Also check if any installed skill data has a matching name
|
|
181
|
+
const skillData = installedSkillData.find((s) => s.id.toLowerCase() === id.toLowerCase());
|
|
182
|
+
return {
|
|
183
|
+
idName,
|
|
184
|
+
skillName: skillData?.name.toLowerCase() || idName,
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
// Filter out already installed skills AND semantically similar names from candidates
|
|
188
|
+
const candidates = skillDatabase.filter((s) => {
|
|
189
|
+
const skillName = s.name.toLowerCase();
|
|
190
|
+
const skillIdName = s.id.split('/').pop()?.toLowerCase() || '';
|
|
191
|
+
// Exclude if exact ID match (case-insensitive)
|
|
192
|
+
if (installed_skills.some((id) => id.toLowerCase() === s.id.toLowerCase())) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
// SMI-907: Exclude if name is contained in or contains installed skill name
|
|
196
|
+
// This prevents recommending "docker-compose" when "docker" is installed
|
|
197
|
+
for (const installed of installedNames) {
|
|
198
|
+
const { idName, skillName: installedSkillName } = installed;
|
|
199
|
+
if (!idName && !installedSkillName)
|
|
200
|
+
continue;
|
|
201
|
+
// Check name containment both ways
|
|
202
|
+
if ((installedSkillName && skillName.includes(installedSkillName)) ||
|
|
203
|
+
(installedSkillName && installedSkillName.includes(skillName)) ||
|
|
204
|
+
(idName && skillIdName.includes(idName)) ||
|
|
205
|
+
(idName && idName.includes(skillIdName))) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return true;
|
|
210
|
+
});
|
|
211
|
+
let overlapFiltered = 0;
|
|
212
|
+
// Apply overlap detection if enabled and there are installed skills
|
|
213
|
+
let filteredCandidates = candidates;
|
|
214
|
+
if (detect_overlap && installedSkillData.length > 0) {
|
|
215
|
+
const overlapDetector = new OverlapDetector({
|
|
216
|
+
useFallback: true,
|
|
217
|
+
overlapThreshold: 0.6,
|
|
218
|
+
phraseThreshold: 0.75,
|
|
219
|
+
});
|
|
220
|
+
const filterResult = await overlapDetector.filterByOverlap(candidates, installedSkillData);
|
|
221
|
+
filteredCandidates = filterResult.accepted;
|
|
222
|
+
overlapFiltered = filterResult.rejected.length;
|
|
223
|
+
overlapDetector.close();
|
|
224
|
+
}
|
|
225
|
+
// Build query from installed skills and project context
|
|
226
|
+
let query = '';
|
|
227
|
+
if (installedSkillData.length > 0) {
|
|
228
|
+
query = installedSkillData
|
|
229
|
+
.map((s) => `${s.name} ${s.description} ${s.keywords?.join(' ') || ''}`)
|
|
230
|
+
.join(' ');
|
|
231
|
+
}
|
|
232
|
+
if (project_context) {
|
|
233
|
+
query = query ? `${query} ${project_context}` : project_context;
|
|
234
|
+
}
|
|
235
|
+
if (!query) {
|
|
236
|
+
query = 'general development productivity tools';
|
|
237
|
+
}
|
|
238
|
+
// Find similar skills using semantic matching
|
|
239
|
+
const matchResults = await matcher.findSimilarSkills(query, filteredCandidates, limit);
|
|
240
|
+
// Transform to response format
|
|
241
|
+
const recommendations = matchResults.map((result) => {
|
|
242
|
+
const skill = result.skill;
|
|
243
|
+
return {
|
|
244
|
+
skill_id: skill.id,
|
|
245
|
+
name: skill.name,
|
|
246
|
+
reason: result.matchReason,
|
|
247
|
+
similarity_score: result.similarityScore,
|
|
248
|
+
trust_tier: skill.trustTier,
|
|
249
|
+
quality_score: skill.qualityScore ?? 50,
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
const endTime = performance.now();
|
|
253
|
+
matcher.close();
|
|
254
|
+
return {
|
|
255
|
+
recommendations,
|
|
256
|
+
candidates_considered: candidates.length,
|
|
257
|
+
overlap_filtered: overlapFiltered,
|
|
258
|
+
context: {
|
|
259
|
+
installed_count: installed_skills.length,
|
|
260
|
+
has_project_context: !!project_context,
|
|
261
|
+
using_semantic_matching: true,
|
|
262
|
+
auto_detected: autoDetected,
|
|
263
|
+
},
|
|
264
|
+
timing: {
|
|
265
|
+
totalMs: Math.round(endTime - startTime),
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Format recommendations for terminal display
|
|
271
|
+
*/
|
|
272
|
+
export function formatRecommendations(response) {
|
|
273
|
+
const lines = [];
|
|
274
|
+
lines.push('\n=== Skill Recommendations ===\n');
|
|
275
|
+
if (response.recommendations.length === 0) {
|
|
276
|
+
lines.push('No recommendations found.');
|
|
277
|
+
lines.push('');
|
|
278
|
+
lines.push('Suggestions:');
|
|
279
|
+
lines.push(' - Try adding more installed skills for better matching');
|
|
280
|
+
lines.push(' - Provide a project context for more relevant results');
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
lines.push(`Found ${response.recommendations.length} recommendation(s):\n`);
|
|
284
|
+
response.recommendations.forEach((rec, index) => {
|
|
285
|
+
const trustBadge = getTrustBadge(rec.trust_tier);
|
|
286
|
+
lines.push(`${index + 1}. ${rec.name} ${trustBadge}`);
|
|
287
|
+
lines.push(` Score: ${rec.quality_score}/100 | Relevance: ${Math.round(rec.similarity_score * 100)}%`);
|
|
288
|
+
lines.push(` ${rec.reason}`);
|
|
289
|
+
lines.push(` ID: ${rec.skill_id}`);
|
|
290
|
+
lines.push('');
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
lines.push('---');
|
|
294
|
+
lines.push(`Candidates considered: ${response.candidates_considered}`);
|
|
295
|
+
if (response.overlap_filtered > 0) {
|
|
296
|
+
lines.push(`Filtered for overlap: ${response.overlap_filtered}`);
|
|
297
|
+
}
|
|
298
|
+
if (response.context.auto_detected) {
|
|
299
|
+
lines.push(`Installed skills: ${response.context.installed_count} (auto-detected from ~/.claude/skills/)`);
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
lines.push(`Installed skills: ${response.context.installed_count}`);
|
|
303
|
+
}
|
|
304
|
+
lines.push(`Semantic matching: ${response.context.using_semantic_matching ? 'enabled' : 'disabled'}`);
|
|
305
|
+
lines.push(`Completed in ${response.timing.totalMs}ms`);
|
|
306
|
+
return lines.join('\n');
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get trust badge for display
|
|
310
|
+
*/
|
|
311
|
+
function getTrustBadge(tier) {
|
|
312
|
+
switch (tier) {
|
|
313
|
+
case 'verified':
|
|
314
|
+
return '[VERIFIED]';
|
|
315
|
+
case 'community':
|
|
316
|
+
return '[COMMUNITY]';
|
|
317
|
+
case 'standard':
|
|
318
|
+
return '[STANDARD]';
|
|
319
|
+
case 'unverified':
|
|
320
|
+
return '[UNVERIFIED]';
|
|
321
|
+
default:
|
|
322
|
+
return '[UNKNOWN]';
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=recommend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommend.js","sourceRoot":"","sources":["../../../src/tools/recommend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview MCP Search Tool for Claude Code skill discovery
|
|
3
|
+
* @module @skillsmith/mcp-server/tools/search
|
|
4
|
+
* @see {@link https://github.com/wrsmith108/skillsmith|Skillsmith Repository}
|
|
5
|
+
* @see SMI-789: Wire search tool to SearchService
|
|
6
|
+
*
|
|
7
|
+
* Provides skill search functionality with support for:
|
|
8
|
+
* - Full-text search across skill names, descriptions, and authors
|
|
9
|
+
* - Category filtering (development, testing, devops, etc.)
|
|
10
|
+
* - Trust tier filtering (verified, community, standard, unverified)
|
|
11
|
+
* - Minimum quality score filtering
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Basic search with context
|
|
15
|
+
* const results = await executeSearch({ query: 'commit' }, context);
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Search with filters
|
|
19
|
+
* const results = await executeSearch({
|
|
20
|
+
* query: 'test',
|
|
21
|
+
* category: 'testing',
|
|
22
|
+
* trust_tier: 'verified',
|
|
23
|
+
* min_score: 80
|
|
24
|
+
* }, context);
|
|
25
|
+
*/
|
|
26
|
+
import { type MCPSearchResponse as SearchResponse } from '@skillsmith/core';
|
|
27
|
+
import type { ToolContext } from '../context.js';
|
|
28
|
+
/**
|
|
29
|
+
* Search tool schema for MCP
|
|
30
|
+
*/
|
|
31
|
+
export declare const searchToolSchema: {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
inputSchema: {
|
|
35
|
+
type: "object";
|
|
36
|
+
properties: {
|
|
37
|
+
query: {
|
|
38
|
+
type: string;
|
|
39
|
+
description: string;
|
|
40
|
+
};
|
|
41
|
+
category: {
|
|
42
|
+
type: string;
|
|
43
|
+
description: string;
|
|
44
|
+
enum: string[];
|
|
45
|
+
};
|
|
46
|
+
trust_tier: {
|
|
47
|
+
type: string;
|
|
48
|
+
description: string;
|
|
49
|
+
enum: string[];
|
|
50
|
+
};
|
|
51
|
+
min_score: {
|
|
52
|
+
type: string;
|
|
53
|
+
description: string;
|
|
54
|
+
minimum: number;
|
|
55
|
+
maximum: number;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
required: string[];
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Input parameters for the search operation
|
|
63
|
+
* @interface SearchInput
|
|
64
|
+
*/
|
|
65
|
+
export interface SearchInput {
|
|
66
|
+
/** Search query string (minimum 2 characters) */
|
|
67
|
+
query: string;
|
|
68
|
+
/** Filter by skill category */
|
|
69
|
+
category?: string;
|
|
70
|
+
/** Filter by trust tier level */
|
|
71
|
+
trust_tier?: string;
|
|
72
|
+
/** Minimum quality score (0-100) */
|
|
73
|
+
min_score?: number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Execute a search for Claude Code skills with optional filters.
|
|
77
|
+
*
|
|
78
|
+
* Uses SearchService with FTS5/BM25 ranking for relevance-based results.
|
|
79
|
+
* Results are sorted by BM25 rank and limited to specified count.
|
|
80
|
+
*
|
|
81
|
+
* @param input - Search parameters including query and optional filters
|
|
82
|
+
* @param context - Tool context with database and services
|
|
83
|
+
* @returns Promise resolving to search response with results and timing
|
|
84
|
+
* @throws {SkillsmithError} When query is empty or less than 2 characters
|
|
85
|
+
* @throws {SkillsmithError} When min_score is outside 0-100 range
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Search for commit-related skills
|
|
89
|
+
* const response = await executeSearch({ query: 'commit' }, context);
|
|
90
|
+
* console.log(`Found ${response.total} skills in ${response.timing.totalMs}ms`);
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Search with multiple filters
|
|
94
|
+
* const response = await executeSearch({
|
|
95
|
+
* query: 'react',
|
|
96
|
+
* category: 'testing',
|
|
97
|
+
* min_score: 85
|
|
98
|
+
* }, context);
|
|
99
|
+
*/
|
|
100
|
+
export declare function executeSearch(input: SearchInput, context: ToolContext): Promise<SearchResponse>;
|
|
101
|
+
/**
|
|
102
|
+
* Format search results for terminal/CLI display.
|
|
103
|
+
*
|
|
104
|
+
* Produces a human-readable string with skill listings including
|
|
105
|
+
* trust badges, scores, and timing information.
|
|
106
|
+
*
|
|
107
|
+
* @param response - Search response from executeSearch
|
|
108
|
+
* @returns Formatted string suitable for terminal output
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* const response = await executeSearch({ query: 'test' });
|
|
112
|
+
* console.log(formatSearchResults(response));
|
|
113
|
+
* // Output:
|
|
114
|
+
* // === Search Results for "test" ===
|
|
115
|
+
* // Found 3 skill(s):
|
|
116
|
+
* // 1. jest-helper [COMMUNITY]
|
|
117
|
+
* // Author: community | Score: 87/100
|
|
118
|
+
* // Generate Jest test cases...
|
|
119
|
+
*/
|
|
120
|
+
export declare function formatSearchResults(response: SearchResponse): string;
|
|
121
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/tools/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAGL,KAAK,iBAAiB,IAAI,cAAc,EAMzC,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAqChD;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwC5B,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CA2EzB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAgCpE"}
|