@skillsmith/mcp-server 0.4.2 ā 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/__tests__/LocalIndexer.test.js +158 -0
- package/dist/src/__tests__/LocalIndexer.test.js.map +1 -1
- package/dist/src/__tests__/compare.test.d.ts +8 -0
- package/dist/src/__tests__/compare.test.d.ts.map +1 -0
- package/dist/src/__tests__/compare.test.js +162 -0
- package/dist/src/__tests__/compare.test.js.map +1 -0
- package/dist/src/__tests__/context.async.test.d.ts +8 -0
- package/dist/src/__tests__/context.async.test.d.ts.map +1 -0
- package/dist/src/__tests__/context.async.test.js +223 -0
- package/dist/src/__tests__/context.async.test.js.map +1 -0
- package/dist/src/__tests__/middleware/errorFormatter.builders.test.d.ts +10 -0
- package/dist/src/__tests__/middleware/errorFormatter.builders.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/errorFormatter.builders.test.js +93 -0
- package/dist/src/__tests__/middleware/errorFormatter.builders.test.js.map +1 -0
- package/dist/src/__tests__/middleware/license-renewal.test.d.ts +10 -0
- package/dist/src/__tests__/middleware/license-renewal.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/license-renewal.test.js +152 -0
- package/dist/src/__tests__/middleware/license-renewal.test.js.map +1 -0
- package/dist/src/__tests__/middleware/quota-helpers.test.d.ts +9 -0
- package/dist/src/__tests__/middleware/quota-helpers.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/quota-helpers.test.js +105 -0
- package/dist/src/__tests__/middleware/quota-helpers.test.js.map +1 -0
- package/dist/src/__tests__/middleware/quota.test.d.ts +12 -0
- package/dist/src/__tests__/middleware/quota.test.d.ts.map +1 -0
- package/dist/src/__tests__/middleware/quota.test.js +189 -0
- package/dist/src/__tests__/middleware/quota.test.js.map +1 -0
- package/dist/src/__tests__/recommend-online-path.test.d.ts +10 -0
- package/dist/src/__tests__/recommend-online-path.test.d.ts.map +1 -0
- package/dist/src/__tests__/recommend-online-path.test.js +225 -0
- package/dist/src/__tests__/recommend-online-path.test.js.map +1 -0
- package/dist/src/__tests__/recommend.test.d.ts +2 -0
- package/dist/src/__tests__/recommend.test.d.ts.map +1 -1
- package/dist/src/__tests__/recommend.test.js +14 -2
- package/dist/src/__tests__/recommend.test.js.map +1 -1
- package/dist/src/__tests__/search-online-path.test.d.ts +10 -0
- package/dist/src/__tests__/search-online-path.test.d.ts.map +1 -0
- package/dist/src/__tests__/search-online-path.test.js +140 -0
- package/dist/src/__tests__/search-online-path.test.js.map +1 -0
- package/dist/src/__tests__/search.test.js +153 -5
- package/dist/src/__tests__/search.test.js.map +1 -1
- package/dist/src/context/project-detector.d.ts.map +1 -1
- package/dist/src/context/project-detector.js +1 -0
- package/dist/src/context/project-detector.js.map +1 -1
- package/dist/src/context.async.d.ts +48 -0
- package/dist/src/context.async.d.ts.map +1 -0
- package/dist/src/context.async.js +215 -0
- package/dist/src/context.async.js.map +1 -0
- package/dist/src/context.d.ts +5 -145
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.helpers.d.ts +25 -0
- package/dist/src/context.helpers.d.ts.map +1 -0
- package/dist/src/context.helpers.js +49 -0
- package/dist/src/context.helpers.js.map +1 -0
- package/dist/src/context.js +11 -228
- package/dist/src/context.js.map +1 -1
- package/dist/src/context.types.d.ts +110 -0
- package/dist/src/context.types.d.ts.map +1 -0
- package/dist/src/context.types.js +10 -0
- package/dist/src/context.types.js.map +1 -0
- package/dist/src/health/readinessCheck.d.ts +1 -1
- package/dist/src/health/readinessCheck.d.ts.map +1 -1
- package/dist/src/index.js +21 -152
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexer/FrontmatterParser.d.ts +6 -0
- package/dist/src/indexer/FrontmatterParser.d.ts.map +1 -1
- package/dist/src/indexer/FrontmatterParser.js +15 -0
- package/dist/src/indexer/FrontmatterParser.js.map +1 -1
- package/dist/src/indexer/LocalIndexer.d.ts +4 -0
- package/dist/src/indexer/LocalIndexer.d.ts.map +1 -1
- package/dist/src/indexer/LocalIndexer.js +3 -0
- package/dist/src/indexer/LocalIndexer.js.map +1 -1
- package/dist/src/middleware/degradation.d.ts.map +1 -1
- package/dist/src/middleware/degradation.js +8 -0
- package/dist/src/middleware/degradation.js.map +1 -1
- package/dist/src/middleware/errorFormatter.builders.d.ts +49 -0
- package/dist/src/middleware/errorFormatter.builders.d.ts.map +1 -0
- package/dist/src/middleware/errorFormatter.builders.js +237 -0
- package/dist/src/middleware/errorFormatter.builders.js.map +1 -0
- package/dist/src/middleware/errorFormatter.d.ts +5 -100
- package/dist/src/middleware/errorFormatter.d.ts.map +1 -1
- package/dist/src/middleware/errorFormatter.js +16 -238
- package/dist/src/middleware/errorFormatter.js.map +1 -1
- package/dist/src/middleware/errorFormatter.types.d.ts +81 -0
- package/dist/src/middleware/errorFormatter.types.d.ts.map +1 -0
- package/dist/src/middleware/errorFormatter.types.js +34 -0
- package/dist/src/middleware/errorFormatter.types.js.map +1 -0
- package/dist/src/middleware/toolFeatureMapping.d.ts +1 -1
- package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -1
- package/dist/src/middleware/toolFeatureMapping.js +8 -0
- package/dist/src/middleware/toolFeatureMapping.js.map +1 -1
- package/dist/src/tool-dispatch.d.ts +27 -0
- package/dist/src/tool-dispatch.d.ts.map +1 -0
- package/dist/src/tool-dispatch.js +127 -0
- package/dist/src/tool-dispatch.js.map +1 -0
- package/dist/src/tools/LocalSkillSearch.d.ts.map +1 -1
- package/dist/src/tools/LocalSkillSearch.js +4 -0
- package/dist/src/tools/LocalSkillSearch.js.map +1 -1
- package/dist/src/tools/get-skill.d.ts.map +1 -1
- package/dist/src/tools/get-skill.js +14 -0
- package/dist/src/tools/get-skill.js.map +1 -1
- package/dist/src/tools/index.d.ts +6 -0
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +6 -0
- package/dist/src/tools/index.js.map +1 -1
- package/dist/src/tools/install.d.ts +3 -35
- package/dist/src/tools/install.d.ts.map +1 -1
- package/dist/src/tools/install.js +22 -74
- package/dist/src/tools/install.js.map +1 -1
- package/dist/src/tools/install.optimize.d.ts +46 -0
- package/dist/src/tools/install.optimize.d.ts.map +1 -0
- package/dist/src/tools/install.optimize.js +67 -0
- package/dist/src/tools/install.optimize.js.map +1 -0
- package/dist/src/tools/install.tool.d.ts +44 -0
- package/dist/src/tools/install.tool.d.ts.map +1 -0
- package/dist/src/tools/install.tool.js +44 -0
- package/dist/src/tools/install.tool.js.map +1 -0
- package/dist/src/tools/install.types.d.ts +7 -1
- package/dist/src/tools/install.types.d.ts.map +1 -1
- package/dist/src/tools/recommend.d.ts +2 -4
- package/dist/src/tools/recommend.d.ts.map +1 -1
- package/dist/src/tools/recommend.format.d.ts +28 -0
- package/dist/src/tools/recommend.format.d.ts.map +1 -0
- package/dist/src/tools/recommend.format.js +111 -0
- package/dist/src/tools/recommend.format.js.map +1 -0
- package/dist/src/tools/recommend.js +6 -97
- package/dist/src/tools/recommend.js.map +1 -1
- package/dist/src/tools/recommend.types.d.ts +1 -1
- package/dist/src/tools/search.d.ts +24 -21
- package/dist/src/tools/search.d.ts.map +1 -1
- package/dist/src/tools/search.formatter.d.ts +30 -0
- package/dist/src/tools/search.formatter.d.ts.map +1 -0
- package/dist/src/tools/search.formatter.js +64 -0
- package/dist/src/tools/search.formatter.js.map +1 -0
- package/dist/src/tools/search.js +55 -54
- package/dist/src/tools/search.js.map +1 -1
- package/dist/src/tools/skill-audit.d.ts +98 -0
- package/dist/src/tools/skill-audit.d.ts.map +1 -0
- package/dist/src/tools/skill-audit.js +105 -0
- package/dist/src/tools/skill-audit.js.map +1 -0
- package/dist/src/tools/skill-audit.test.d.ts +6 -0
- package/dist/src/tools/skill-audit.test.d.ts.map +1 -0
- package/dist/src/tools/skill-audit.test.js +121 -0
- package/dist/src/tools/skill-audit.test.js.map +1 -0
- package/dist/src/tools/skill-diff.d.ts +107 -0
- package/dist/src/tools/skill-diff.d.ts.map +1 -0
- package/dist/src/tools/skill-diff.js +268 -0
- package/dist/src/tools/skill-diff.js.map +1 -0
- package/dist/src/tools/skill-diff.test.d.ts +6 -0
- package/dist/src/tools/skill-diff.test.d.ts.map +1 -0
- package/dist/src/tools/skill-diff.test.js +260 -0
- package/dist/src/tools/skill-diff.test.js.map +1 -0
- package/dist/src/tools/skill-updates.d.ts +1 -1
- package/dist/src/tools/skill-updates.d.ts.map +1 -1
- package/dist/src/tools/suggest.d.ts +4 -4
- package/dist/src/tools/uninstall.d.ts +1 -1
- package/dist/src/tools/validate.helpers.d.ts.map +1 -1
- package/dist/src/tools/validate.helpers.js +31 -0
- package/dist/src/tools/validate.helpers.js.map +1 -1
- package/dist/src/utils/validation.d.ts +13 -0
- package/dist/src/utils/validation.d.ts.map +1 -1
- package/dist/src/utils/validation.js +27 -0
- package/dist/src/utils/validation.js.map +1 -1
- package/dist/tests/health.test.js +4 -4
- package/dist/tests/health.test.js.map +1 -1
- package/dist/tests/integration/recommend.integration.test.js +2 -0
- package/dist/tests/integration/recommend.integration.test.js.map +1 -1
- package/dist/tests/integration/setup.d.ts +3 -1
- package/dist/tests/integration/setup.d.ts.map +1 -1
- package/dist/tests/integration/setup.js +4 -1
- package/dist/tests/integration/setup.js.map +1 -1
- package/dist/tests/recommend.test.js +2 -0
- package/dist/tests/recommend.test.js.map +1 -1
- package/dist/tests/unit/validate-helpers.test.js +54 -0
- package/dist/tests/unit/validate-helpers.test.js.map +1 -1
- package/package.json +2 -2
- package/server.json +2 -2
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Error Response Builder Functions
|
|
3
|
+
* @module @skillsmith/mcp-server/middleware/errorFormatter.builders
|
|
4
|
+
* @see SMI-1061: MCP Error Formatter for License Errors
|
|
5
|
+
* @see SMI-2741: Split from errorFormatter.ts to meet 500-line standard
|
|
6
|
+
*
|
|
7
|
+
* Pre-built MCP error response factories for common license error scenarios:
|
|
8
|
+
* - Upgrade required (feature tier mismatch)
|
|
9
|
+
* - License expired (renewal needed)
|
|
10
|
+
* - Quota exceeded (usage limit hit)
|
|
11
|
+
* - API authentication errors (401 handling)
|
|
12
|
+
*/
|
|
13
|
+
import { DEFAULT_UPGRADE_URL_CONFIG } from './errorFormatter.types.js';
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Upgrade URL Generation
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Generate a customized upgrade URL with tracking parameters
|
|
19
|
+
*/
|
|
20
|
+
export function generateUpgradeUrl(error, config = {}) {
|
|
21
|
+
const fullConfig = { ...DEFAULT_UPGRADE_URL_CONFIG, ...config };
|
|
22
|
+
const params = new URLSearchParams();
|
|
23
|
+
if (fullConfig.includeFeature && error.feature) {
|
|
24
|
+
params.set('feature', error.feature);
|
|
25
|
+
}
|
|
26
|
+
if (fullConfig.includeTiers) {
|
|
27
|
+
if (error.currentTier) {
|
|
28
|
+
params.set('from', error.currentTier);
|
|
29
|
+
}
|
|
30
|
+
if (error.requiredTier) {
|
|
31
|
+
params.set('to', error.requiredTier);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (fullConfig.includeSource) {
|
|
35
|
+
params.set('source', 'mcp-error');
|
|
36
|
+
if (error.code) {
|
|
37
|
+
params.set('error_code', error.code);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const queryString = params.toString();
|
|
41
|
+
return queryString ? `${fullConfig.baseUrl}?${queryString}` : fullConfig.baseUrl || '';
|
|
42
|
+
}
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Response Builders
|
|
45
|
+
// ============================================================================
|
|
46
|
+
/**
|
|
47
|
+
* Build an upgrade required response
|
|
48
|
+
*
|
|
49
|
+
* Use this when a feature requires an upgrade but isn't a full error.
|
|
50
|
+
*/
|
|
51
|
+
export function buildUpgradeRequiredResponse(feature, currentTier, requiredTier) {
|
|
52
|
+
const upgradeUrl = `https://skillsmith.app/upgrade?feature=${feature}&from=${currentTier}&to=${requiredTier}`;
|
|
53
|
+
return {
|
|
54
|
+
content: [
|
|
55
|
+
{
|
|
56
|
+
type: 'text',
|
|
57
|
+
text: JSON.stringify({
|
|
58
|
+
error: {
|
|
59
|
+
code: 'E004',
|
|
60
|
+
message: `${feature} requires ${requiredTier} tier`,
|
|
61
|
+
details: {
|
|
62
|
+
feature,
|
|
63
|
+
currentTier,
|
|
64
|
+
requiredTier,
|
|
65
|
+
upgradeUrl,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
}, null, 2),
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
isError: true,
|
|
72
|
+
_meta: {
|
|
73
|
+
upgradeUrl,
|
|
74
|
+
errorCode: 'E004',
|
|
75
|
+
recoverable: false,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Build a license expired response with renewal URL
|
|
81
|
+
*/
|
|
82
|
+
export function buildLicenseExpiredResponse(expiredAt) {
|
|
83
|
+
const renewUrl = 'https://skillsmith.app/renew';
|
|
84
|
+
return {
|
|
85
|
+
content: [
|
|
86
|
+
{
|
|
87
|
+
type: 'text',
|
|
88
|
+
text: JSON.stringify({
|
|
89
|
+
error: {
|
|
90
|
+
code: 'E001',
|
|
91
|
+
message: 'Your license has expired',
|
|
92
|
+
details: {
|
|
93
|
+
expiredAt: expiredAt?.toISOString(),
|
|
94
|
+
renewUrl,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
}, null, 2),
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
isError: true,
|
|
101
|
+
_meta: {
|
|
102
|
+
upgradeUrl: renewUrl,
|
|
103
|
+
errorCode: 'E001',
|
|
104
|
+
recoverable: false,
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Build a quota exceeded response
|
|
110
|
+
*/
|
|
111
|
+
export function buildQuotaExceededResponse(quotaType, current, max) {
|
|
112
|
+
const upgradeUrl = `https://skillsmith.app/upgrade?quota=${quotaType}`;
|
|
113
|
+
return {
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: 'text',
|
|
117
|
+
text: JSON.stringify({
|
|
118
|
+
error: {
|
|
119
|
+
code: 'E005',
|
|
120
|
+
message: `${quotaType} quota exceeded`,
|
|
121
|
+
details: {
|
|
122
|
+
quotaType,
|
|
123
|
+
current,
|
|
124
|
+
max,
|
|
125
|
+
upgradeUrl,
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
}, null, 2),
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
isError: true,
|
|
132
|
+
_meta: {
|
|
133
|
+
upgradeUrl,
|
|
134
|
+
errorCode: 'E005',
|
|
135
|
+
recoverable: false,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// API Authentication Error Formatting (SMI-XXXX)
|
|
141
|
+
// ============================================================================
|
|
142
|
+
/**
|
|
143
|
+
* Format a 401 authentication error for MCP display
|
|
144
|
+
* Provides user-friendly instructions for getting an API key
|
|
145
|
+
*
|
|
146
|
+
* @param details - Error details from the API response
|
|
147
|
+
* @returns MCP-formatted error response with signup instructions
|
|
148
|
+
*/
|
|
149
|
+
export function formatAuthenticationError(details = {}) {
|
|
150
|
+
const signupUrl = details.signupUrl || 'https://skillsmith.app/signup';
|
|
151
|
+
const docsUrl = details.docsUrl || 'https://skillsmith.app/docs/getting-started#api-key';
|
|
152
|
+
const trialInfo = details.trialUsed !== undefined && details.trialLimit !== undefined
|
|
153
|
+
? `\n\nš **Trial Usage**: ${details.trialUsed}/${details.trialLimit} free requests used`
|
|
154
|
+
: '';
|
|
155
|
+
const message = `š **Authentication Required**
|
|
156
|
+
|
|
157
|
+
${details.reason || 'API key required for this request.'}
|
|
158
|
+
|
|
159
|
+
**Get Started (Free - 1,000 requests/month):**
|
|
160
|
+
1. Create account: ${signupUrl}
|
|
161
|
+
2. Your API key will be generated automatically
|
|
162
|
+
3. Add to your Claude settings:
|
|
163
|
+
|
|
164
|
+
\`\`\`json
|
|
165
|
+
{
|
|
166
|
+
"mcpServers": {
|
|
167
|
+
"skillsmith": {
|
|
168
|
+
"command": "npx",
|
|
169
|
+
"args": ["-y", "@skillsmith/mcp-server"],
|
|
170
|
+
"env": {
|
|
171
|
+
"SKILLSMITH_API_KEY": "your_key_here"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
\`\`\`${trialInfo}
|
|
177
|
+
|
|
178
|
+
[Documentation](${docsUrl})
|
|
179
|
+
`;
|
|
180
|
+
return {
|
|
181
|
+
content: [
|
|
182
|
+
{
|
|
183
|
+
type: 'text',
|
|
184
|
+
text: message,
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
isError: true,
|
|
188
|
+
_meta: {
|
|
189
|
+
errorCode: 'AUTHENTICATION_REQUIRED',
|
|
190
|
+
recoverable: true,
|
|
191
|
+
upgradeUrl: signupUrl,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Check if an API error is an authentication error (401)
|
|
197
|
+
*/
|
|
198
|
+
export function isAuthenticationError(error) {
|
|
199
|
+
if (!error || typeof error !== 'object') {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const e = error;
|
|
203
|
+
// Check for status code
|
|
204
|
+
if (e.statusCode === 401 || e.status === 401) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
// Check for error message patterns
|
|
208
|
+
if (typeof e.message === 'string') {
|
|
209
|
+
const msg = e.message.toLowerCase();
|
|
210
|
+
if (msg.includes('authentication required') || msg.includes('free trial exhausted')) {
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Check for error field
|
|
215
|
+
if (typeof e.error === 'string') {
|
|
216
|
+
const err = e.error.toLowerCase();
|
|
217
|
+
if (err.includes('authentication required')) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Extract authentication error details from an API error response
|
|
225
|
+
*/
|
|
226
|
+
export function extractAuthErrorDetails(error) {
|
|
227
|
+
if (!error || typeof error !== 'object') {
|
|
228
|
+
return {};
|
|
229
|
+
}
|
|
230
|
+
const e = error;
|
|
231
|
+
// Check for details object
|
|
232
|
+
if (e.details && typeof e.details === 'object') {
|
|
233
|
+
return e.details;
|
|
234
|
+
}
|
|
235
|
+
return {};
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=errorFormatter.builders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorFormatter.builders.js","sourceRoot":"","sources":["../../../src/middleware/errorFormatter.builders.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,55 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SMI-1061: MCP Error Formatter for License Errors
|
|
3
|
+
* @see SMI-2741: Types split to errorFormatter.types.ts, builders to errorFormatter.builders.ts
|
|
3
4
|
*
|
|
4
5
|
* Formats license errors into MCP protocol-compliant error responses
|
|
5
6
|
* with actionable information for clients.
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
type: 'text';
|
|
12
|
-
text: string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* MCP-formatted error response
|
|
16
|
-
*/
|
|
17
|
-
export interface MCPErrorResponse {
|
|
18
|
-
content: MCPErrorContent[];
|
|
19
|
-
isError: true;
|
|
20
|
-
_meta?: {
|
|
21
|
-
upgradeUrl?: string;
|
|
22
|
-
errorCode?: string;
|
|
23
|
-
recoverable?: boolean;
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* License error details structure (mirrors the enterprise package)
|
|
28
|
-
*/
|
|
29
|
-
export interface LicenseErrorDetails {
|
|
30
|
-
code: string;
|
|
31
|
-
message: string;
|
|
32
|
-
feature?: string;
|
|
33
|
-
currentTier?: string;
|
|
34
|
-
requiredTier?: string;
|
|
35
|
-
upgradeUrl?: string;
|
|
36
|
-
context?: Record<string, unknown>;
|
|
37
|
-
timestamp?: string;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Interface for license errors (duck-typed for optional enterprise package)
|
|
41
|
-
*/
|
|
42
|
-
export interface LicenseErrorLike {
|
|
43
|
-
code?: string;
|
|
44
|
-
message: string;
|
|
45
|
-
feature?: string;
|
|
46
|
-
currentTier?: string;
|
|
47
|
-
requiredTier?: string;
|
|
48
|
-
upgradeUrl?: string;
|
|
49
|
-
context?: Record<string, unknown>;
|
|
50
|
-
timestamp?: Date;
|
|
51
|
-
toJSON?: () => Record<string, unknown>;
|
|
52
|
-
}
|
|
8
|
+
export type { MCPErrorContent, MCPErrorResponse, LicenseErrorDetails, LicenseErrorLike, UpgradeUrlConfig, ApiAuthErrorDetails, } from './errorFormatter.types.js';
|
|
9
|
+
export { ERROR_MESSAGES, DEFAULT_UPGRADE_URL_CONFIG } from './errorFormatter.types.js';
|
|
10
|
+
export { generateUpgradeUrl, buildUpgradeRequiredResponse, buildLicenseExpiredResponse, buildQuotaExceededResponse, formatAuthenticationError, isAuthenticationError, extractAuthErrorDetails, } from './errorFormatter.builders.js';
|
|
11
|
+
import type { MCPErrorResponse, LicenseErrorLike } from './errorFormatter.types.js';
|
|
53
12
|
/**
|
|
54
13
|
* Format a license error into an MCP-compliant error response
|
|
55
14
|
*
|
|
@@ -81,33 +40,6 @@ export declare function formatGenericError(error: Error, code?: string): MCPErro
|
|
|
81
40
|
* Get a user-friendly message for an error code
|
|
82
41
|
*/
|
|
83
42
|
export declare function getUserFriendlyMessage(code: string): string;
|
|
84
|
-
/**
|
|
85
|
-
* Configuration for upgrade URLs
|
|
86
|
-
*/
|
|
87
|
-
export interface UpgradeUrlConfig {
|
|
88
|
-
baseUrl?: string;
|
|
89
|
-
includeFeature?: boolean;
|
|
90
|
-
includeTiers?: boolean;
|
|
91
|
-
includeSource?: boolean;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Generate a customized upgrade URL with tracking parameters
|
|
95
|
-
*/
|
|
96
|
-
export declare function generateUpgradeUrl(error: LicenseErrorLike, config?: Partial<UpgradeUrlConfig>): string;
|
|
97
|
-
/**
|
|
98
|
-
* Build an upgrade required response
|
|
99
|
-
*
|
|
100
|
-
* Use this when a feature requires an upgrade but isn't a full error.
|
|
101
|
-
*/
|
|
102
|
-
export declare function buildUpgradeRequiredResponse(feature: string, currentTier: string, requiredTier: string): MCPErrorResponse;
|
|
103
|
-
/**
|
|
104
|
-
* Build a license expired response with renewal URL
|
|
105
|
-
*/
|
|
106
|
-
export declare function buildLicenseExpiredResponse(expiredAt?: Date): MCPErrorResponse;
|
|
107
|
-
/**
|
|
108
|
-
* Build a quota exceeded response
|
|
109
|
-
*/
|
|
110
|
-
export declare function buildQuotaExceededResponse(quotaType: string, current: number, max: number): MCPErrorResponse;
|
|
111
43
|
/**
|
|
112
44
|
* Check if an object looks like a license error
|
|
113
45
|
*/
|
|
@@ -116,31 +48,4 @@ export declare function isLicenseErrorLike(error: unknown): error is LicenseErro
|
|
|
116
48
|
* Safely convert any error to MCP format
|
|
117
49
|
*/
|
|
118
50
|
export declare function safeFormatError(error: unknown): MCPErrorResponse;
|
|
119
|
-
/**
|
|
120
|
-
* Details from a 401 API authentication error
|
|
121
|
-
*/
|
|
122
|
-
export interface ApiAuthErrorDetails {
|
|
123
|
-
reason?: string;
|
|
124
|
-
signupUrl?: string;
|
|
125
|
-
docsUrl?: string;
|
|
126
|
-
hint?: string;
|
|
127
|
-
trialUsed?: number;
|
|
128
|
-
trialLimit?: number;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Format a 401 authentication error for MCP display
|
|
132
|
-
* Provides user-friendly instructions for getting an API key
|
|
133
|
-
*
|
|
134
|
-
* @param details - Error details from the API response
|
|
135
|
-
* @returns MCP-formatted error response with signup instructions
|
|
136
|
-
*/
|
|
137
|
-
export declare function formatAuthenticationError(details?: ApiAuthErrorDetails): MCPErrorResponse;
|
|
138
|
-
/**
|
|
139
|
-
* Check if an API error is an authentication error (401)
|
|
140
|
-
*/
|
|
141
|
-
export declare function isAuthenticationError(error: unknown): boolean;
|
|
142
|
-
/**
|
|
143
|
-
* Extract authentication error details from an API error response
|
|
144
|
-
*/
|
|
145
|
-
export declare function extractAuthErrorDetails(error: unknown): ApiAuthErrorDetails;
|
|
146
51
|
//# sourceMappingURL=errorFormatter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorFormatter.d.ts","sourceRoot":"","sources":["../../../src/middleware/errorFormatter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"errorFormatter.d.ts","sourceRoot":"","sources":["../../../src/middleware/errorFormatter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AAGtF,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAEjB,MAAM,2BAA2B,CAAA;AAMlC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,CAsD5E;AAYD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,SAAmB,GAAG,gBAAgB,CAmB1F;AAMD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAe3D;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAiB5E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAUhE"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SMI-1061: MCP Error Formatter for License Errors
|
|
3
|
+
* @see SMI-2741: Types split to errorFormatter.types.ts, builders to errorFormatter.builders.ts
|
|
3
4
|
*
|
|
4
5
|
* Formats license errors into MCP protocol-compliant error responses
|
|
5
6
|
* with actionable information for clients.
|
|
6
7
|
*/
|
|
8
|
+
export { ERROR_MESSAGES, DEFAULT_UPGRADE_URL_CONFIG } from './errorFormatter.types.js';
|
|
9
|
+
// Re-export builders from companion file
|
|
10
|
+
export { generateUpgradeUrl, buildUpgradeRequiredResponse, buildLicenseExpiredResponse, buildQuotaExceededResponse, formatAuthenticationError, isAuthenticationError, extractAuthErrorDetails, } from './errorFormatter.builders.js';
|
|
7
11
|
// ============================================================================
|
|
8
12
|
// Error Formatting
|
|
9
13
|
// ============================================================================
|
|
@@ -111,154 +115,23 @@ export function formatGenericError(error, code = 'INTERNAL_ERROR') {
|
|
|
111
115
|
// ============================================================================
|
|
112
116
|
// Error Code Mapping
|
|
113
117
|
// ============================================================================
|
|
114
|
-
/**
|
|
115
|
-
* Map internal license error codes to user-friendly messages
|
|
116
|
-
*/
|
|
117
|
-
const ERROR_MESSAGES = {
|
|
118
|
-
E001: 'Your license has expired. Please renew to continue using premium features.',
|
|
119
|
-
E002: 'Your license key is invalid. Please verify the key format or contact support.',
|
|
120
|
-
E003: 'No license key found. Set SKILLSMITH_LICENSE_KEY environment variable.',
|
|
121
|
-
E004: 'This feature is not available in your current license tier.',
|
|
122
|
-
E005: 'You have exceeded your license quota. Please upgrade or reduce usage.',
|
|
123
|
-
LICENSE_EXPIRED: 'Your license has expired. Please renew to continue using premium features.',
|
|
124
|
-
LICENSE_INVALID: 'Your license key is invalid. Please verify the key format or contact support.',
|
|
125
|
-
LICENSE_NOT_FOUND: 'No license key found. Set SKILLSMITH_LICENSE_KEY environment variable.',
|
|
126
|
-
FEATURE_NOT_AVAILABLE: 'This feature is not available in your current license tier.',
|
|
127
|
-
QUOTA_EXCEEDED: 'You have exceeded your license quota. Please upgrade or reduce usage.',
|
|
128
|
-
};
|
|
129
118
|
/**
|
|
130
119
|
* Get a user-friendly message for an error code
|
|
131
120
|
*/
|
|
132
121
|
export function getUserFriendlyMessage(code) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
export function generateUpgradeUrl(error, config = {}) {
|
|
145
|
-
const fullConfig = { ...DEFAULT_UPGRADE_URL_CONFIG, ...config };
|
|
146
|
-
const params = new URLSearchParams();
|
|
147
|
-
if (fullConfig.includeFeature && error.feature) {
|
|
148
|
-
params.set('feature', error.feature);
|
|
149
|
-
}
|
|
150
|
-
if (fullConfig.includeTiers) {
|
|
151
|
-
if (error.currentTier) {
|
|
152
|
-
params.set('from', error.currentTier);
|
|
153
|
-
}
|
|
154
|
-
if (error.requiredTier) {
|
|
155
|
-
params.set('to', error.requiredTier);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
if (fullConfig.includeSource) {
|
|
159
|
-
params.set('source', 'mcp-error');
|
|
160
|
-
if (error.code) {
|
|
161
|
-
params.set('error_code', error.code);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
const queryString = params.toString();
|
|
165
|
-
return queryString ? `${fullConfig.baseUrl}?${queryString}` : fullConfig.baseUrl || '';
|
|
166
|
-
}
|
|
167
|
-
// ============================================================================
|
|
168
|
-
// Response Builders
|
|
169
|
-
// ============================================================================
|
|
170
|
-
/**
|
|
171
|
-
* Build an upgrade required response
|
|
172
|
-
*
|
|
173
|
-
* Use this when a feature requires an upgrade but isn't a full error.
|
|
174
|
-
*/
|
|
175
|
-
export function buildUpgradeRequiredResponse(feature, currentTier, requiredTier) {
|
|
176
|
-
const upgradeUrl = `https://skillsmith.app/upgrade?feature=${feature}&from=${currentTier}&to=${requiredTier}`;
|
|
177
|
-
return {
|
|
178
|
-
content: [
|
|
179
|
-
{
|
|
180
|
-
type: 'text',
|
|
181
|
-
text: JSON.stringify({
|
|
182
|
-
error: {
|
|
183
|
-
code: 'E004',
|
|
184
|
-
message: `${feature} requires ${requiredTier} tier`,
|
|
185
|
-
details: {
|
|
186
|
-
feature,
|
|
187
|
-
currentTier,
|
|
188
|
-
requiredTier,
|
|
189
|
-
upgradeUrl,
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
}, null, 2),
|
|
193
|
-
},
|
|
194
|
-
],
|
|
195
|
-
isError: true,
|
|
196
|
-
_meta: {
|
|
197
|
-
upgradeUrl,
|
|
198
|
-
errorCode: 'E004',
|
|
199
|
-
recoverable: false,
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Build a license expired response with renewal URL
|
|
205
|
-
*/
|
|
206
|
-
export function buildLicenseExpiredResponse(expiredAt) {
|
|
207
|
-
const renewUrl = 'https://skillsmith.app/renew';
|
|
208
|
-
return {
|
|
209
|
-
content: [
|
|
210
|
-
{
|
|
211
|
-
type: 'text',
|
|
212
|
-
text: JSON.stringify({
|
|
213
|
-
error: {
|
|
214
|
-
code: 'E001',
|
|
215
|
-
message: 'Your license has expired',
|
|
216
|
-
details: {
|
|
217
|
-
expiredAt: expiredAt?.toISOString(),
|
|
218
|
-
renewUrl,
|
|
219
|
-
},
|
|
220
|
-
},
|
|
221
|
-
}, null, 2),
|
|
222
|
-
},
|
|
223
|
-
],
|
|
224
|
-
isError: true,
|
|
225
|
-
_meta: {
|
|
226
|
-
upgradeUrl: renewUrl,
|
|
227
|
-
errorCode: 'E001',
|
|
228
|
-
recoverable: false,
|
|
229
|
-
},
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Build a quota exceeded response
|
|
234
|
-
*/
|
|
235
|
-
export function buildQuotaExceededResponse(quotaType, current, max) {
|
|
236
|
-
const upgradeUrl = `https://skillsmith.app/upgrade?quota=${quotaType}`;
|
|
237
|
-
return {
|
|
238
|
-
content: [
|
|
239
|
-
{
|
|
240
|
-
type: 'text',
|
|
241
|
-
text: JSON.stringify({
|
|
242
|
-
error: {
|
|
243
|
-
code: 'E005',
|
|
244
|
-
message: `${quotaType} quota exceeded`,
|
|
245
|
-
details: {
|
|
246
|
-
quotaType,
|
|
247
|
-
current,
|
|
248
|
-
max,
|
|
249
|
-
upgradeUrl,
|
|
250
|
-
},
|
|
251
|
-
},
|
|
252
|
-
}, null, 2),
|
|
253
|
-
},
|
|
254
|
-
],
|
|
255
|
-
isError: true,
|
|
256
|
-
_meta: {
|
|
257
|
-
upgradeUrl,
|
|
258
|
-
errorCode: 'E005',
|
|
259
|
-
recoverable: false,
|
|
260
|
-
},
|
|
122
|
+
const ERROR_MESSAGES = {
|
|
123
|
+
E001: 'Your license has expired. Please renew to continue using premium features.',
|
|
124
|
+
E002: 'Your license key is invalid. Please verify the key format or contact support.',
|
|
125
|
+
E003: 'No license key found. Set SKILLSMITH_LICENSE_KEY environment variable.',
|
|
126
|
+
E004: 'This feature is not available in your current license tier.',
|
|
127
|
+
E005: 'You have exceeded your license quota. Please upgrade or reduce usage.',
|
|
128
|
+
LICENSE_EXPIRED: 'Your license has expired. Please renew to continue using premium features.',
|
|
129
|
+
LICENSE_INVALID: 'Your license key is invalid. Please verify the key format or contact support.',
|
|
130
|
+
LICENSE_NOT_FOUND: 'No license key found. Set SKILLSMITH_LICENSE_KEY environment variable.',
|
|
131
|
+
FEATURE_NOT_AVAILABLE: 'This feature is not available in your current license tier.',
|
|
132
|
+
QUOTA_EXCEEDED: 'You have exceeded your license quota. Please upgrade or reduce usage.',
|
|
261
133
|
};
|
|
134
|
+
return ERROR_MESSAGES[code] || 'An error occurred with your license. Please contact support.';
|
|
262
135
|
}
|
|
263
136
|
// ============================================================================
|
|
264
137
|
// Validation Helpers
|
|
@@ -291,99 +164,4 @@ export function safeFormatError(error) {
|
|
|
291
164
|
}
|
|
292
165
|
return formatGenericError(new Error(String(error)));
|
|
293
166
|
}
|
|
294
|
-
/**
|
|
295
|
-
* Format a 401 authentication error for MCP display
|
|
296
|
-
* Provides user-friendly instructions for getting an API key
|
|
297
|
-
*
|
|
298
|
-
* @param details - Error details from the API response
|
|
299
|
-
* @returns MCP-formatted error response with signup instructions
|
|
300
|
-
*/
|
|
301
|
-
export function formatAuthenticationError(details = {}) {
|
|
302
|
-
const signupUrl = details.signupUrl || 'https://skillsmith.app/signup';
|
|
303
|
-
const docsUrl = details.docsUrl || 'https://skillsmith.app/docs/getting-started#api-key';
|
|
304
|
-
const trialInfo = details.trialUsed !== undefined && details.trialLimit !== undefined
|
|
305
|
-
? `\n\nš **Trial Usage**: ${details.trialUsed}/${details.trialLimit} free requests used`
|
|
306
|
-
: '';
|
|
307
|
-
const message = `š **Authentication Required**
|
|
308
|
-
|
|
309
|
-
${details.reason || 'API key required for this request.'}
|
|
310
|
-
|
|
311
|
-
**Get Started (Free - 1,000 requests/month):**
|
|
312
|
-
1. Create account: ${signupUrl}
|
|
313
|
-
2. Your API key will be generated automatically
|
|
314
|
-
3. Add to your Claude settings:
|
|
315
|
-
|
|
316
|
-
\`\`\`json
|
|
317
|
-
{
|
|
318
|
-
"mcpServers": {
|
|
319
|
-
"skillsmith": {
|
|
320
|
-
"command": "npx",
|
|
321
|
-
"args": ["-y", "@skillsmith/mcp-server"],
|
|
322
|
-
"env": {
|
|
323
|
-
"SKILLSMITH_API_KEY": "your_key_here"
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
\`\`\`${trialInfo}
|
|
329
|
-
|
|
330
|
-
[Documentation](${docsUrl})
|
|
331
|
-
`;
|
|
332
|
-
return {
|
|
333
|
-
content: [
|
|
334
|
-
{
|
|
335
|
-
type: 'text',
|
|
336
|
-
text: message,
|
|
337
|
-
},
|
|
338
|
-
],
|
|
339
|
-
isError: true,
|
|
340
|
-
_meta: {
|
|
341
|
-
errorCode: 'AUTHENTICATION_REQUIRED',
|
|
342
|
-
recoverable: true,
|
|
343
|
-
upgradeUrl: signupUrl,
|
|
344
|
-
},
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Check if an API error is an authentication error (401)
|
|
349
|
-
*/
|
|
350
|
-
export function isAuthenticationError(error) {
|
|
351
|
-
if (!error || typeof error !== 'object') {
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
const e = error;
|
|
355
|
-
// Check for status code
|
|
356
|
-
if (e.statusCode === 401 || e.status === 401) {
|
|
357
|
-
return true;
|
|
358
|
-
}
|
|
359
|
-
// Check for error message patterns
|
|
360
|
-
if (typeof e.message === 'string') {
|
|
361
|
-
const msg = e.message.toLowerCase();
|
|
362
|
-
if (msg.includes('authentication required') || msg.includes('free trial exhausted')) {
|
|
363
|
-
return true;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
// Check for error field
|
|
367
|
-
if (typeof e.error === 'string') {
|
|
368
|
-
const err = e.error.toLowerCase();
|
|
369
|
-
if (err.includes('authentication required')) {
|
|
370
|
-
return true;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
return false;
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Extract authentication error details from an API error response
|
|
377
|
-
*/
|
|
378
|
-
export function extractAuthErrorDetails(error) {
|
|
379
|
-
if (!error || typeof error !== 'object') {
|
|
380
|
-
return {};
|
|
381
|
-
}
|
|
382
|
-
const e = error;
|
|
383
|
-
// Check for details object
|
|
384
|
-
if (e.details && typeof e.details === 'object') {
|
|
385
|
-
return e.details;
|
|
386
|
-
}
|
|
387
|
-
return {};
|
|
388
|
-
}
|
|
389
167
|
//# sourceMappingURL=errorFormatter.js.map
|