@elliotding/ai-agent-mcp 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/api/cached-client.d.ts +48 -0
- package/dist/api/cached-client.d.ts.map +1 -0
- package/dist/api/cached-client.js +126 -0
- package/dist/api/cached-client.js.map +1 -0
- package/dist/api/client.d.ts +213 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +326 -0
- package/dist/api/client.js.map +1 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +26 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +36 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +194 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/permissions.d.ts +60 -0
- package/dist/auth/permissions.d.ts.map +1 -0
- package/dist/auth/permissions.js +256 -0
- package/dist/auth/permissions.js.map +1 -0
- package/dist/auth/token-validator.d.ts +52 -0
- package/dist/auth/token-validator.d.ts.map +1 -0
- package/dist/auth/token-validator.js +217 -0
- package/dist/auth/token-validator.js.map +1 -0
- package/dist/cache/cache-manager.d.ts +49 -0
- package/dist/cache/cache-manager.d.ts.map +1 -0
- package/dist/cache/cache-manager.js +191 -0
- package/dist/cache/cache-manager.js.map +1 -0
- package/dist/cache/index.d.ts +6 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +12 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/redis-client.d.ts +45 -0
- package/dist/cache/redis-client.d.ts.map +1 -0
- package/dist/cache/redis-client.js +210 -0
- package/dist/cache/redis-client.js.map +1 -0
- package/dist/config/constants.d.ts +28 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +31 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/config/index.d.ts +54 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +168 -0
- package/dist/config/index.js.map +1 -0
- package/dist/filesystem/manager.d.ts +45 -0
- package/dist/filesystem/manager.d.ts.map +1 -0
- package/dist/filesystem/manager.js +246 -0
- package/dist/filesystem/manager.js.map +1 -0
- package/dist/git/multi-source-manager.d.ts +62 -0
- package/dist/git/multi-source-manager.d.ts.map +1 -0
- package/dist/git/multi-source-manager.js +293 -0
- package/dist/git/multi-source-manager.js.map +1 -0
- package/dist/git/operations.d.ts +27 -0
- package/dist/git/operations.d.ts.map +1 -0
- package/dist/git/operations.js +83 -0
- package/dist/git/operations.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/monitoring/health.d.ts +35 -0
- package/dist/monitoring/health.d.ts.map +1 -0
- package/dist/monitoring/health.js +105 -0
- package/dist/monitoring/health.js.map +1 -0
- package/dist/resources/index.d.ts +6 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +10 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/loader.d.ts +87 -0
- package/dist/resources/loader.d.ts.map +1 -0
- package/dist/resources/loader.js +452 -0
- package/dist/resources/loader.js.map +1 -0
- package/dist/server/http.d.ts +57 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +336 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +157 -0
- package/dist/server.js.map +1 -0
- package/dist/session/manager.d.ts +91 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +251 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +27 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/manage-subscription.d.ts +43 -0
- package/dist/tools/manage-subscription.d.ts.map +1 -0
- package/dist/tools/manage-subscription.js +268 -0
- package/dist/tools/manage-subscription.js.map +1 -0
- package/dist/tools/registry.d.ts +40 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +85 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/search-resources.d.ts +31 -0
- package/dist/tools/search-resources.d.ts.map +1 -0
- package/dist/tools/search-resources.js +154 -0
- package/dist/tools/search-resources.js.map +1 -0
- package/dist/tools/sync-resources.d.ts +41 -0
- package/dist/tools/sync-resources.d.ts.map +1 -0
- package/dist/tools/sync-resources.js +606 -0
- package/dist/tools/sync-resources.js.map +1 -0
- package/dist/tools/uninstall-resource.d.ts +30 -0
- package/dist/tools/uninstall-resource.d.ts.map +1 -0
- package/dist/tools/uninstall-resource.js +259 -0
- package/dist/tools/uninstall-resource.js.map +1 -0
- package/dist/tools/upload-resource.d.ts +77 -0
- package/dist/tools/upload-resource.d.ts.map +1 -0
- package/dist/tools/upload-resource.js +252 -0
- package/dist/tools/upload-resource.js.map +1 -0
- package/dist/transport/sse.d.ts +29 -0
- package/dist/transport/sse.d.ts.map +1 -0
- package/dist/transport/sse.js +271 -0
- package/dist/transport/sse.js.map +1 -0
- package/dist/types/errors.d.ts +60 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +112 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mcp.d.ts +50 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +6 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/resources.d.ts +109 -0
- package/dist/types/resources.d.ts.map +1 -0
- package/dist/types/resources.js +7 -0
- package/dist/types/resources.js.map +1 -0
- package/dist/types/tools.d.ts +147 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +6 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/utils/cursor-paths.d.ts +49 -0
- package/dist/utils/cursor-paths.d.ts.map +1 -0
- package/dist/utils/cursor-paths.js +116 -0
- package/dist/utils/cursor-paths.js.map +1 -0
- package/dist/utils/log-cleaner.d.ts +18 -0
- package/dist/utils/log-cleaner.d.ts.map +1 -0
- package/dist/utils/log-cleaner.js +112 -0
- package/dist/utils/log-cleaner.js.map +1 -0
- package/dist/utils/logger.d.ts +59 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +292 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/validation.d.ts +58 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +214 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +58 -0
- package/src/api/cached-client.ts +144 -0
- package/src/api/client.ts +578 -0
- package/src/auth/index.ts +11 -0
- package/src/auth/middleware.ts +244 -0
- package/src/auth/permissions.ts +317 -0
- package/src/auth/token-validator.ts +294 -0
- package/src/cache/cache-manager.ts +243 -0
- package/src/cache/index.ts +6 -0
- package/src/cache/redis-client.ts +249 -0
- package/src/config/constants.ts +33 -0
- package/src/config/index.ts +228 -0
- package/src/filesystem/manager.ts +235 -0
- package/src/git/multi-source-manager.ts +333 -0
- package/src/git/operations.ts +93 -0
- package/src/index.ts +139 -0
- package/src/monitoring/health.ts +132 -0
- package/src/resources/index.ts +13 -0
- package/src/resources/loader.ts +530 -0
- package/src/server/http.ts +427 -0
- package/src/server.ts +191 -0
- package/src/session/manager.ts +296 -0
- package/src/tools/index.ts +11 -0
- package/src/tools/manage-subscription.ts +332 -0
- package/src/tools/registry.ts +97 -0
- package/src/tools/search-resources.ts +177 -0
- package/src/tools/sync-resources.ts +662 -0
- package/src/tools/uninstall-resource.ts +248 -0
- package/src/tools/upload-resource.ts +258 -0
- package/src/transport/sse.ts +308 -0
- package/src/types/errors.ts +146 -0
- package/src/types/index.ts +7 -0
- package/src/types/mcp.ts +61 -0
- package/src/types/resources.ts +141 -0
- package/src/types/tools.ts +175 -0
- package/src/utils/cursor-paths.ts +83 -0
- package/src/utils/log-cleaner.ts +92 -0
- package/src/utils/logger.ts +333 -0
- package/src/utils/validation.ts +262 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE Transport Implementation
|
|
3
|
+
* MCP protocol over Server-Sent Events
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { logger, logToolStep } from '../utils/logger';
|
|
7
|
+
import { sessionManager } from '../session/manager';
|
|
8
|
+
import { toolRegistry } from '../tools/registry';
|
|
9
|
+
import { checkToolCallPermission } from '../auth/middleware';
|
|
10
|
+
|
|
11
|
+
export interface SSEMessage {
|
|
12
|
+
jsonrpc: '2.0';
|
|
13
|
+
id?: string | number;
|
|
14
|
+
method?: string;
|
|
15
|
+
params?: unknown;
|
|
16
|
+
result?: unknown;
|
|
17
|
+
error?: {
|
|
18
|
+
code: number;
|
|
19
|
+
message: string;
|
|
20
|
+
data?: unknown;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class SSETransport {
|
|
25
|
+
constructor() {
|
|
26
|
+
logger.info('SSE transport initialized');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Handle incoming message from client
|
|
31
|
+
*/
|
|
32
|
+
async handleMessage(sessionId: string, message: SSEMessage): Promise<void> {
|
|
33
|
+
const messageStartTime = Date.now();
|
|
34
|
+
|
|
35
|
+
logger.info({
|
|
36
|
+
type: 'sse_message_received',
|
|
37
|
+
sessionId,
|
|
38
|
+
method: message.method,
|
|
39
|
+
messageId: message.id,
|
|
40
|
+
hasParams: !!message.params,
|
|
41
|
+
timestamp: new Date().toISOString()
|
|
42
|
+
}, `SSE message received: ${message.method}`);
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
// Validate session
|
|
46
|
+
logToolStep('sse', 'Validating session', { sessionId });
|
|
47
|
+
|
|
48
|
+
const session = sessionManager.getSession(sessionId);
|
|
49
|
+
if (!session) {
|
|
50
|
+
logger.error({
|
|
51
|
+
type: 'sse_error',
|
|
52
|
+
sessionId,
|
|
53
|
+
method: message.method,
|
|
54
|
+
error: 'session_not_found',
|
|
55
|
+
timestamp: new Date().toISOString()
|
|
56
|
+
}, 'Session not found or expired');
|
|
57
|
+
throw new Error('Session not found or expired');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
logger.debug({
|
|
61
|
+
type: 'sse_session_validated',
|
|
62
|
+
sessionId,
|
|
63
|
+
userId: session.userId,
|
|
64
|
+
email: session.email,
|
|
65
|
+
groups: session.groups,
|
|
66
|
+
timestamp: new Date().toISOString()
|
|
67
|
+
}, 'Session validated');
|
|
68
|
+
|
|
69
|
+
// Update session activity
|
|
70
|
+
sessionManager.updateActivity(sessionId);
|
|
71
|
+
logToolStep('sse', 'Session activity updated', { sessionId });
|
|
72
|
+
|
|
73
|
+
// Handle MCP message
|
|
74
|
+
if (message.method === 'tools/list') {
|
|
75
|
+
logToolStep('sse', 'Handling tools/list request', { sessionId });
|
|
76
|
+
|
|
77
|
+
const tools = toolRegistry.getMCPToolDefinitions();
|
|
78
|
+
|
|
79
|
+
logger.info({
|
|
80
|
+
type: 'sse_tools_list',
|
|
81
|
+
sessionId,
|
|
82
|
+
toolCount: tools.length,
|
|
83
|
+
toolNames: tools.map(t => t.name),
|
|
84
|
+
timestamp: new Date().toISOString()
|
|
85
|
+
}, `Returning ${tools.length} tool definitions`);
|
|
86
|
+
|
|
87
|
+
const response: SSEMessage = {
|
|
88
|
+
jsonrpc: '2.0',
|
|
89
|
+
id: message.id,
|
|
90
|
+
result: { tools },
|
|
91
|
+
};
|
|
92
|
+
this.sendMessage(sessionId, response);
|
|
93
|
+
} else if (message.method === 'tools/call') {
|
|
94
|
+
const params = message.params as { name: string; arguments?: Record<string, unknown> };
|
|
95
|
+
const toolName = params.name;
|
|
96
|
+
const args = params.arguments || {};
|
|
97
|
+
|
|
98
|
+
logger.info({
|
|
99
|
+
type: 'sse_tool_call',
|
|
100
|
+
sessionId,
|
|
101
|
+
toolName,
|
|
102
|
+
userId: session.userId,
|
|
103
|
+
email: session.email,
|
|
104
|
+
argsPreview: JSON.stringify(args).substring(0, 200),
|
|
105
|
+
timestamp: new Date().toISOString()
|
|
106
|
+
}, `Executing tool: ${toolName}`);
|
|
107
|
+
|
|
108
|
+
logToolStep(toolName, 'Tool call initiated via SSE', {
|
|
109
|
+
sessionId,
|
|
110
|
+
userId: session.userId,
|
|
111
|
+
email: session.email
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
// Check permissions if user is authenticated
|
|
116
|
+
if (session.userId && session.groups && session.groups.length > 0) {
|
|
117
|
+
logToolStep(toolName, 'Checking tool permissions', {
|
|
118
|
+
userId: session.userId,
|
|
119
|
+
email: session.email,
|
|
120
|
+
groups: session.groups
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const permissionStartTime = Date.now();
|
|
124
|
+
const permissionCheck = checkToolCallPermission(toolName, {
|
|
125
|
+
userId: session.userId,
|
|
126
|
+
email: session.email,
|
|
127
|
+
groups: session.groups,
|
|
128
|
+
});
|
|
129
|
+
const permissionDuration = Date.now() - permissionStartTime;
|
|
130
|
+
|
|
131
|
+
if (!permissionCheck.allowed) {
|
|
132
|
+
logger.warn(
|
|
133
|
+
{
|
|
134
|
+
type: 'sse_permission_denied',
|
|
135
|
+
sessionId,
|
|
136
|
+
userId: session.userId,
|
|
137
|
+
email: session.email,
|
|
138
|
+
groups: session.groups,
|
|
139
|
+
toolName,
|
|
140
|
+
reason: permissionCheck.reason,
|
|
141
|
+
duration: permissionDuration,
|
|
142
|
+
timestamp: new Date().toISOString()
|
|
143
|
+
},
|
|
144
|
+
`Tool call permission denied for ${toolName}`
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const errorResponse: SSEMessage = {
|
|
148
|
+
jsonrpc: '2.0',
|
|
149
|
+
id: message.id,
|
|
150
|
+
error: {
|
|
151
|
+
code: -32600, // Invalid Request
|
|
152
|
+
message: permissionCheck.reason || 'Permission denied',
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
this.sendMessage(sessionId, errorResponse);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
logger.debug({
|
|
160
|
+
type: 'sse_permission_granted',
|
|
161
|
+
sessionId,
|
|
162
|
+
userId: session.userId,
|
|
163
|
+
toolName,
|
|
164
|
+
duration: permissionDuration,
|
|
165
|
+
timestamp: new Date().toISOString()
|
|
166
|
+
}, `Permission granted for ${toolName}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
logToolStep(toolName, 'Executing tool handler', { args });
|
|
170
|
+
const toolStartTime = Date.now();
|
|
171
|
+
|
|
172
|
+
const result = await toolRegistry.callTool(toolName, args);
|
|
173
|
+
|
|
174
|
+
const toolDuration = Date.now() - toolStartTime;
|
|
175
|
+
|
|
176
|
+
// Log complete result
|
|
177
|
+
logger.info({
|
|
178
|
+
type: 'sse_tool_success',
|
|
179
|
+
sessionId,
|
|
180
|
+
toolName,
|
|
181
|
+
userId: session.userId,
|
|
182
|
+
resultType: typeof result,
|
|
183
|
+
resultPreview: JSON.stringify(result).substring(0, 500),
|
|
184
|
+
duration: toolDuration,
|
|
185
|
+
timestamp: new Date().toISOString()
|
|
186
|
+
}, `Tool ${toolName} executed successfully`);
|
|
187
|
+
|
|
188
|
+
logToolStep(toolName, 'Tool execution completed', {
|
|
189
|
+
duration: toolDuration,
|
|
190
|
+
resultSize: JSON.stringify(result).length
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const response: SSEMessage = {
|
|
194
|
+
jsonrpc: '2.0',
|
|
195
|
+
id: message.id,
|
|
196
|
+
result,
|
|
197
|
+
};
|
|
198
|
+
this.sendMessage(sessionId, response);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
const toolDuration = Date.now() - messageStartTime;
|
|
201
|
+
|
|
202
|
+
logger.error({
|
|
203
|
+
type: 'sse_tool_error',
|
|
204
|
+
sessionId,
|
|
205
|
+
toolName,
|
|
206
|
+
userId: session.userId,
|
|
207
|
+
error: error instanceof Error ? {
|
|
208
|
+
message: error.message,
|
|
209
|
+
stack: error.stack,
|
|
210
|
+
name: error.name
|
|
211
|
+
} : String(error),
|
|
212
|
+
duration: toolDuration,
|
|
213
|
+
timestamp: new Date().toISOString()
|
|
214
|
+
}, `Tool ${toolName} execution failed`);
|
|
215
|
+
|
|
216
|
+
const errorResponse: SSEMessage = {
|
|
217
|
+
jsonrpc: '2.0',
|
|
218
|
+
id: message.id,
|
|
219
|
+
error: {
|
|
220
|
+
code: -32603,
|
|
221
|
+
message: error instanceof Error ? error.message : 'Tool execution failed',
|
|
222
|
+
data: error,
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
this.sendMessage(sessionId, errorResponse);
|
|
226
|
+
}
|
|
227
|
+
} else if (message.method === 'initialize') {
|
|
228
|
+
logger.info({
|
|
229
|
+
type: 'sse_initialize',
|
|
230
|
+
sessionId,
|
|
231
|
+
timestamp: new Date().toISOString()
|
|
232
|
+
}, 'Client initialization request');
|
|
233
|
+
|
|
234
|
+
const response: SSEMessage = {
|
|
235
|
+
jsonrpc: '2.0',
|
|
236
|
+
id: message.id,
|
|
237
|
+
result: {
|
|
238
|
+
protocolVersion: '2024-11-05',
|
|
239
|
+
capabilities: {
|
|
240
|
+
tools: {},
|
|
241
|
+
},
|
|
242
|
+
serverInfo: {
|
|
243
|
+
name: 'csp-ai-agent-mcp',
|
|
244
|
+
version: '0.2.0',
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
this.sendMessage(sessionId, response);
|
|
249
|
+
} else if (message.method === 'ping') {
|
|
250
|
+
// Keepalive ping
|
|
251
|
+
logger.debug({
|
|
252
|
+
type: 'sse_ping',
|
|
253
|
+
sessionId,
|
|
254
|
+
timestamp: new Date().toISOString()
|
|
255
|
+
}, 'Keepalive ping received');
|
|
256
|
+
|
|
257
|
+
const response: SSEMessage = {
|
|
258
|
+
jsonrpc: '2.0',
|
|
259
|
+
id: message.id,
|
|
260
|
+
result: { type: 'pong' },
|
|
261
|
+
};
|
|
262
|
+
this.sendMessage(sessionId, response);
|
|
263
|
+
} else {
|
|
264
|
+
// Unknown method
|
|
265
|
+
logger.warn({
|
|
266
|
+
type: 'sse_unknown_method',
|
|
267
|
+
sessionId,
|
|
268
|
+
method: message.method,
|
|
269
|
+
timestamp: new Date().toISOString()
|
|
270
|
+
}, `Unknown method: ${message.method}`);
|
|
271
|
+
|
|
272
|
+
const errorResponse: SSEMessage = {
|
|
273
|
+
jsonrpc: '2.0',
|
|
274
|
+
id: message.id,
|
|
275
|
+
error: {
|
|
276
|
+
code: -32601,
|
|
277
|
+
message: `Method not found: ${message.method}`,
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
this.sendMessage(sessionId, errorResponse);
|
|
281
|
+
}
|
|
282
|
+
} catch (error) {
|
|
283
|
+
logger.error({ error, sessionId }, 'Error handling message');
|
|
284
|
+
const errorResponse: SSEMessage = {
|
|
285
|
+
jsonrpc: '2.0',
|
|
286
|
+
id: message.id,
|
|
287
|
+
error: {
|
|
288
|
+
code: -32603,
|
|
289
|
+
message: error instanceof Error ? error.message : 'Internal error',
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
this.sendMessage(sessionId, errorResponse);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Send message to client via SSE
|
|
298
|
+
*/
|
|
299
|
+
private sendMessage(sessionId: string, message: SSEMessage): void {
|
|
300
|
+
const sent = sessionManager.sendMessage(sessionId, message);
|
|
301
|
+
if (!sent) {
|
|
302
|
+
logger.warn({ sessionId, messageId: message.id }, 'Failed to send message to client');
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Singleton instance
|
|
308
|
+
export const sseTransport = new SSETransport();
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Error Types
|
|
3
|
+
* Typed errors for different failure scenarios
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Base Error for MCP Server operations
|
|
8
|
+
*/
|
|
9
|
+
export class MCPServerError extends Error {
|
|
10
|
+
constructor(
|
|
11
|
+
message: string,
|
|
12
|
+
public readonly code: string,
|
|
13
|
+
public readonly details?: unknown
|
|
14
|
+
) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = this.constructor.name;
|
|
17
|
+
Error.captureStackTrace(this, this.constructor);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Git Operation Error
|
|
23
|
+
*/
|
|
24
|
+
export class GitError extends MCPServerError {
|
|
25
|
+
constructor(
|
|
26
|
+
message: string,
|
|
27
|
+
public readonly operation: string,
|
|
28
|
+
public readonly repositoryUrl?: string,
|
|
29
|
+
details?: unknown
|
|
30
|
+
) {
|
|
31
|
+
super(message, 'GIT_ERROR', details);
|
|
32
|
+
|
|
33
|
+
// Redact credentials from repository URL
|
|
34
|
+
if (this.repositoryUrl) {
|
|
35
|
+
this.repositoryUrl = this.redactCredentials(this.repositoryUrl);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private redactCredentials(url: string): string {
|
|
40
|
+
return url.replace(/:\/\/([^:]+):([^@]+)@/, '://***:***@');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* API Request Error
|
|
46
|
+
*/
|
|
47
|
+
export class APIError extends MCPServerError {
|
|
48
|
+
constructor(
|
|
49
|
+
message: string,
|
|
50
|
+
public readonly statusCode?: number,
|
|
51
|
+
public readonly method?: string,
|
|
52
|
+
public readonly url?: string,
|
|
53
|
+
public readonly retryCount?: number,
|
|
54
|
+
details?: unknown
|
|
55
|
+
) {
|
|
56
|
+
super(message, 'API_ERROR', details);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resource Validation Error
|
|
62
|
+
*/
|
|
63
|
+
export class ValidationError extends MCPServerError {
|
|
64
|
+
constructor(
|
|
65
|
+
message: string,
|
|
66
|
+
public readonly filePath?: string,
|
|
67
|
+
public readonly expectedFormat?: string,
|
|
68
|
+
public readonly validationReason?: string,
|
|
69
|
+
details?: unknown
|
|
70
|
+
) {
|
|
71
|
+
super(message, 'VALIDATION_ERROR', details);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Filesystem Operation Error
|
|
77
|
+
*/
|
|
78
|
+
export class FileSystemError extends MCPServerError {
|
|
79
|
+
constructor(
|
|
80
|
+
message: string,
|
|
81
|
+
public readonly operation: string,
|
|
82
|
+
public readonly path?: string,
|
|
83
|
+
public readonly systemErrorCode?: string,
|
|
84
|
+
public readonly suggestedResolution?: string,
|
|
85
|
+
details?: unknown
|
|
86
|
+
) {
|
|
87
|
+
super(message, 'FILESYSTEM_ERROR', details);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Error Factory Functions
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
export function createGitError(
|
|
96
|
+
operation: string,
|
|
97
|
+
error: Error,
|
|
98
|
+
repositoryUrl?: string
|
|
99
|
+
): GitError {
|
|
100
|
+
return new GitError(
|
|
101
|
+
`Git ${operation} failed: ${error.message}`,
|
|
102
|
+
operation,
|
|
103
|
+
repositoryUrl,
|
|
104
|
+
{ originalError: error }
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function createAPIError(
|
|
109
|
+
method: string,
|
|
110
|
+
url: string,
|
|
111
|
+
error: Error,
|
|
112
|
+
statusCode?: number,
|
|
113
|
+
retryCount?: number
|
|
114
|
+
): APIError {
|
|
115
|
+
const message = `API ${method} ${url} failed: ${error.message}`;
|
|
116
|
+
return new APIError(message, statusCode, method, url, retryCount, { originalError: error });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function createValidationError(
|
|
120
|
+
filePath: string,
|
|
121
|
+
expectedFormat: string,
|
|
122
|
+
reason: string
|
|
123
|
+
): ValidationError {
|
|
124
|
+
return new ValidationError(
|
|
125
|
+
`Resource validation failed: ${reason}`,
|
|
126
|
+
filePath,
|
|
127
|
+
expectedFormat,
|
|
128
|
+
reason
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function createFileSystemError(
|
|
133
|
+
operation: string,
|
|
134
|
+
path: string,
|
|
135
|
+
error: Error & { code?: string },
|
|
136
|
+
suggestedResolution?: string
|
|
137
|
+
): FileSystemError {
|
|
138
|
+
return new FileSystemError(
|
|
139
|
+
`Filesystem ${operation} failed: ${error.message}`,
|
|
140
|
+
operation,
|
|
141
|
+
path,
|
|
142
|
+
error.code,
|
|
143
|
+
suggestedResolution,
|
|
144
|
+
{ originalError: error }
|
|
145
|
+
);
|
|
146
|
+
}
|
package/src/types/mcp.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Protocol Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// MCP Tool Schema
|
|
6
|
+
export interface MCPToolSchema {
|
|
7
|
+
type: 'object';
|
|
8
|
+
properties: Record<string, {
|
|
9
|
+
type: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
enum?: string[];
|
|
12
|
+
default?: unknown;
|
|
13
|
+
}>;
|
|
14
|
+
required?: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// MCP Tool Definition
|
|
18
|
+
export interface MCPToolDefinition {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
inputSchema: MCPToolSchema;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// MCP Initialize Request
|
|
25
|
+
export interface MCPInitializeRequest {
|
|
26
|
+
protocolVersion: string;
|
|
27
|
+
capabilities: {
|
|
28
|
+
tools?: Record<string, never>;
|
|
29
|
+
};
|
|
30
|
+
clientInfo: {
|
|
31
|
+
name: string;
|
|
32
|
+
version: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// MCP Initialize Response
|
|
37
|
+
export interface MCPInitializeResponse {
|
|
38
|
+
protocolVersion: string;
|
|
39
|
+
capabilities: {
|
|
40
|
+
tools?: Record<string, never>;
|
|
41
|
+
};
|
|
42
|
+
serverInfo: {
|
|
43
|
+
name: string;
|
|
44
|
+
version: string;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// MCP Tool Call Request
|
|
49
|
+
export interface MCPToolCallRequest {
|
|
50
|
+
name: string;
|
|
51
|
+
arguments?: Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// MCP Tool Call Response
|
|
55
|
+
export interface MCPToolCallResponse {
|
|
56
|
+
content: Array<{
|
|
57
|
+
type: 'text';
|
|
58
|
+
text: string;
|
|
59
|
+
}>;
|
|
60
|
+
isError?: boolean;
|
|
61
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Resources Type Definitions
|
|
3
|
+
* Defines types for multi-source AI resource management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resource type enumeration
|
|
8
|
+
*/
|
|
9
|
+
export type ResourceType = 'commands' | 'skills' | 'mcp' | 'rules';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Resource source configuration
|
|
13
|
+
*/
|
|
14
|
+
export interface ResourceSource {
|
|
15
|
+
/** Source name (identifier) */
|
|
16
|
+
name: string;
|
|
17
|
+
|
|
18
|
+
/** Relative path to AI-Resources root */
|
|
19
|
+
path: string;
|
|
20
|
+
|
|
21
|
+
/** Whether this source is enabled */
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
|
|
24
|
+
/** Priority (higher number = higher priority) */
|
|
25
|
+
priority: number;
|
|
26
|
+
|
|
27
|
+
/** Mapping of resource types to subdirectories */
|
|
28
|
+
resources: Partial<Record<ResourceType, string>>;
|
|
29
|
+
|
|
30
|
+
/** Optional description */
|
|
31
|
+
description?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* AI Resources configuration
|
|
36
|
+
*/
|
|
37
|
+
export interface AIResourcesConfig {
|
|
38
|
+
/** Configuration version */
|
|
39
|
+
version: string;
|
|
40
|
+
|
|
41
|
+
/** Optional description */
|
|
42
|
+
description?: string;
|
|
43
|
+
|
|
44
|
+
/** Default resource source (always loaded) */
|
|
45
|
+
default_source: ResourceSource;
|
|
46
|
+
|
|
47
|
+
/** Extended resource sources */
|
|
48
|
+
extended_sources: ResourceSource[];
|
|
49
|
+
|
|
50
|
+
/** Supported resource types */
|
|
51
|
+
resource_types: ResourceType[];
|
|
52
|
+
|
|
53
|
+
/** Loading order strategy */
|
|
54
|
+
loading_order: 'priority_desc' | 'priority_asc' | 'name_asc';
|
|
55
|
+
|
|
56
|
+
/** Conflict resolution strategy */
|
|
57
|
+
conflict_resolution: 'highest_priority_wins' | 'merge' | 'error';
|
|
58
|
+
|
|
59
|
+
/** Cache configuration */
|
|
60
|
+
cache?: {
|
|
61
|
+
enabled: boolean;
|
|
62
|
+
ttl: number; // seconds
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Resource metadata
|
|
68
|
+
*/
|
|
69
|
+
export interface ResourceMetadata {
|
|
70
|
+
/** Resource ID */
|
|
71
|
+
id: string;
|
|
72
|
+
|
|
73
|
+
/** Resource name */
|
|
74
|
+
name: string;
|
|
75
|
+
|
|
76
|
+
/** Resource type */
|
|
77
|
+
type: ResourceType;
|
|
78
|
+
|
|
79
|
+
/** Source name */
|
|
80
|
+
source: string;
|
|
81
|
+
|
|
82
|
+
/** Source priority */
|
|
83
|
+
priority: number;
|
|
84
|
+
|
|
85
|
+
/** Full file path */
|
|
86
|
+
path: string;
|
|
87
|
+
|
|
88
|
+
/** Version (if available) */
|
|
89
|
+
version?: string;
|
|
90
|
+
|
|
91
|
+
/** Description (if available) */
|
|
92
|
+
description?: string;
|
|
93
|
+
|
|
94
|
+
/** Tags (if available) */
|
|
95
|
+
tags?: string[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Resource conflict information
|
|
100
|
+
*/
|
|
101
|
+
export interface ResourceConflict {
|
|
102
|
+
/** Resource name */
|
|
103
|
+
name: string;
|
|
104
|
+
|
|
105
|
+
/** Resource type */
|
|
106
|
+
type: ResourceType;
|
|
107
|
+
|
|
108
|
+
/** Conflicting resources */
|
|
109
|
+
conflicts: Array<{
|
|
110
|
+
source: string;
|
|
111
|
+
priority: number;
|
|
112
|
+
path: string;
|
|
113
|
+
}>;
|
|
114
|
+
|
|
115
|
+
/** Selected resource (after conflict resolution) */
|
|
116
|
+
selected: {
|
|
117
|
+
source: string;
|
|
118
|
+
priority: number;
|
|
119
|
+
path: string;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Resource loader statistics
|
|
125
|
+
*/
|
|
126
|
+
export interface LoaderStats {
|
|
127
|
+
/** Total sources loaded */
|
|
128
|
+
sourcesLoaded: number;
|
|
129
|
+
|
|
130
|
+
/** Total resources indexed */
|
|
131
|
+
resourcesIndexed: number;
|
|
132
|
+
|
|
133
|
+
/** Resources by type */
|
|
134
|
+
byType: Record<ResourceType, number>;
|
|
135
|
+
|
|
136
|
+
/** Conflicts detected */
|
|
137
|
+
conflictsDetected: number;
|
|
138
|
+
|
|
139
|
+
/** Load duration (ms) */
|
|
140
|
+
loadDuration: number;
|
|
141
|
+
}
|