@segosolutions/mcp-server 1.0.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/index.js ADDED
@@ -0,0 +1,478 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sego PM MCP Server
4
+ *
5
+ * Model Context Protocol server for AI-assisted project management.
6
+ * Communicates with the Sego PM web application via HTTP API.
7
+ */
8
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
11
+ import { initializeApiClient, } from './api/client.js';
12
+ import { resolveClaudeFile } from './lib/claude-file-resolver.js';
13
+ import dotenv from 'dotenv';
14
+ import { fileURLToPath } from 'url';
15
+ import { dirname, join } from 'path';
16
+ // Get the directory of this file
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = dirname(__filename);
19
+ // Load environment variables
20
+ // Try multiple locations in order of precedence:
21
+ // 1. Current working directory (user's project)
22
+ // 2. Package root (for standalone package installation)
23
+ dotenv.config(); // CWD first
24
+ dotenv.config({ path: join(__dirname, '../../.env') }); // Package root fallback
25
+ // Get configuration from environment
26
+ const API_KEY = process.env.SEGO_API_KEY;
27
+ const API_URL = process.env.SEGO_API_URL || 'http://localhost:3000';
28
+ if (!API_KEY) {
29
+ console.error('Error: SEGO_API_KEY environment variable is required');
30
+ process.exit(1);
31
+ }
32
+ // API client and authenticated user
33
+ let apiClient;
34
+ let authenticatedUser;
35
+ /**
36
+ * Initialize the MCP server by validating credentials with the API
37
+ */
38
+ async function initialize() {
39
+ try {
40
+ // API_KEY is guaranteed to be defined here due to the check above
41
+ apiClient = initializeApiClient(API_URL, API_KEY);
42
+ const authResult = await apiClient.validateAuth();
43
+ authenticatedUser = authResult.user;
44
+ // Log environment configuration on startup
45
+ const isProduction = API_URL.includes('sego.pm') || API_URL.includes('vercel');
46
+ const environment = isProduction ? 'PRODUCTION' : 'DEVELOPMENT';
47
+ console.error('');
48
+ console.error('='.repeat(60));
49
+ console.error('Sego PM MCP Server - Environment Configuration');
50
+ console.error('='.repeat(60));
51
+ console.error(`Environment: ${environment}`);
52
+ console.error(`API URL: ${API_URL}`);
53
+ console.error(`Authenticated: ${authenticatedUser.name} (${authenticatedUser.email})`);
54
+ console.error(`Projects: ${authResult.projects.length} accessible`);
55
+ console.error('='.repeat(60));
56
+ console.error('');
57
+ }
58
+ catch (error) {
59
+ console.error('Failed to authenticate with API:', error);
60
+ process.exit(1);
61
+ }
62
+ }
63
+ // Create MCP server
64
+ const server = new Server({
65
+ name: 'sego-pm',
66
+ version: '0.2.0', // Version bump for API-based implementation
67
+ }, {
68
+ capabilities: {
69
+ tools: {},
70
+ resources: {},
71
+ },
72
+ });
73
+ // List available tools
74
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
75
+ return {
76
+ tools: [
77
+ {
78
+ name: 'get_my_tasks',
79
+ description: 'Get tasks assigned to you, optionally filtered by project or status. Returns a list of tasks with full details including acceptance criteria and technical notes.',
80
+ inputSchema: {
81
+ type: 'object',
82
+ properties: {
83
+ projectId: {
84
+ type: 'string',
85
+ description: 'Optional: Filter by project ID',
86
+ },
87
+ status: {
88
+ type: 'string',
89
+ enum: [
90
+ 'AI_REVIEW',
91
+ 'DRAFT',
92
+ 'BACKLOG',
93
+ 'IN_PROGRESS',
94
+ 'IN_REVIEW',
95
+ 'BLOCKED',
96
+ 'COMPLETED',
97
+ 'CANCELLED',
98
+ ],
99
+ description: 'Optional: Filter by task status',
100
+ },
101
+ },
102
+ },
103
+ },
104
+ {
105
+ name: 'search_tasks',
106
+ description: 'Search tasks by keyword in title, description, or technical notes. Returns tasks you have access to (assigned to you or created by you).',
107
+ inputSchema: {
108
+ type: 'object',
109
+ properties: {
110
+ query: {
111
+ type: 'string',
112
+ description: 'Search query (searches title, description, technical notes)',
113
+ },
114
+ projectId: {
115
+ type: 'string',
116
+ description: 'Optional: Limit search to specific project',
117
+ },
118
+ },
119
+ required: ['query'],
120
+ },
121
+ },
122
+ {
123
+ name: 'update_task_status',
124
+ description: 'Update the status of a task. Validates status transitions to ensure workflow integrity. Optionally add a comment explaining the status change.',
125
+ inputSchema: {
126
+ type: 'object',
127
+ properties: {
128
+ taskId: {
129
+ type: 'string',
130
+ description: 'Task ID',
131
+ },
132
+ status: {
133
+ type: 'string',
134
+ enum: [
135
+ 'AI_REVIEW',
136
+ 'DRAFT',
137
+ 'BACKLOG',
138
+ 'IN_PROGRESS',
139
+ 'IN_REVIEW',
140
+ 'BLOCKED',
141
+ 'COMPLETED',
142
+ 'CANCELLED',
143
+ ],
144
+ description: 'New status for the task',
145
+ },
146
+ comment: {
147
+ type: 'string',
148
+ description: 'Optional: Comment explaining the status change',
149
+ },
150
+ },
151
+ required: ['taskId', 'status'],
152
+ },
153
+ },
154
+ {
155
+ name: 'add_task_comment',
156
+ description: 'Add a comment to a task. Useful for progress updates, questions, or completion notes. Supports markdown formatting.',
157
+ inputSchema: {
158
+ type: 'object',
159
+ properties: {
160
+ taskId: {
161
+ type: 'string',
162
+ description: 'Task ID',
163
+ },
164
+ content: {
165
+ type: 'string',
166
+ description: 'Comment content (supports markdown)',
167
+ },
168
+ },
169
+ required: ['taskId', 'content'],
170
+ },
171
+ },
172
+ {
173
+ name: 'assign_task',
174
+ description: 'Assign a task to a user. If no assignToUserId is provided, assigns the task to yourself.',
175
+ inputSchema: {
176
+ type: 'object',
177
+ properties: {
178
+ taskId: {
179
+ type: 'string',
180
+ description: 'Task ID',
181
+ },
182
+ assignToUserId: {
183
+ type: 'string',
184
+ description: 'Optional: User ID to assign the task to. If not provided, assigns to yourself.',
185
+ },
186
+ },
187
+ required: ['taskId'],
188
+ },
189
+ },
190
+ {
191
+ name: 'get_client_request',
192
+ description: 'Get a client request with all associated tasks and full context. Includes task details, comments, project information, and progress summary.',
193
+ inputSchema: {
194
+ type: 'object',
195
+ properties: {
196
+ requestId: {
197
+ type: 'string',
198
+ description: 'Client request ID',
199
+ },
200
+ },
201
+ required: ['requestId'],
202
+ },
203
+ },
204
+ {
205
+ name: 'search_client_requests',
206
+ description: 'Search client requests by project, status, or keyword. Returns requests with task summaries and counts.',
207
+ inputSchema: {
208
+ type: 'object',
209
+ properties: {
210
+ projectId: {
211
+ type: 'string',
212
+ description: 'Optional: Filter by project ID',
213
+ },
214
+ status: {
215
+ type: 'string',
216
+ enum: ['PENDING_AI', 'PENDING_REVIEW', 'APPROVED', 'REJECTED'],
217
+ description: 'Optional: Filter by request status',
218
+ },
219
+ query: {
220
+ type: 'string',
221
+ description: 'Optional: Search keyword in description, raw content, or AI analysis',
222
+ },
223
+ },
224
+ },
225
+ },
226
+ {
227
+ name: 'create_project_from_codebase',
228
+ description: 'Create a Sego PM project from a local codebase with CLAUDE.md file. ' +
229
+ 'Automatically extracts project name, description, and tech stack from CLAUDE.md, ' +
230
+ 'stores the full content as project knowledge base, and sets you as project owner. ' +
231
+ 'Will auto-detect CLAUDE.md in current directory or .claude/ subdirectory, or you can provide explicit path.',
232
+ inputSchema: {
233
+ type: 'object',
234
+ properties: {
235
+ claudePath: {
236
+ type: 'string',
237
+ description: 'Optional explicit path to CLAUDE.md file. If not provided, will auto-detect.',
238
+ },
239
+ baseDir: {
240
+ type: 'string',
241
+ description: 'Optional base directory for file resolution. Defaults to current working directory.',
242
+ },
243
+ projectNameOverride: {
244
+ type: 'string',
245
+ description: 'Optional override for project name if auto-extraction fails or you want different name.',
246
+ },
247
+ monthlyHours: {
248
+ type: 'number',
249
+ description: 'Monthly hour allocation (default: 40)',
250
+ default: 40,
251
+ },
252
+ hourlyRate: {
253
+ type: 'number',
254
+ description: 'Hourly rate (default: 0, can be set later)',
255
+ default: 0,
256
+ },
257
+ },
258
+ },
259
+ },
260
+ ],
261
+ };
262
+ });
263
+ // Handle tool calls
264
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
265
+ try {
266
+ const { name, arguments: args } = request.params;
267
+ switch (name) {
268
+ case 'get_my_tasks': {
269
+ const tasks = await apiClient.getTasks({
270
+ projectId: args?.projectId,
271
+ status: args?.status,
272
+ });
273
+ return {
274
+ content: [
275
+ {
276
+ type: 'text',
277
+ text: JSON.stringify(tasks, null, 2),
278
+ },
279
+ ],
280
+ };
281
+ }
282
+ case 'search_tasks': {
283
+ if (!args?.query) {
284
+ throw new Error('query parameter is required');
285
+ }
286
+ const result = await apiClient.searchTasks(args.query, args?.projectId);
287
+ return {
288
+ content: [
289
+ {
290
+ type: 'text',
291
+ text: JSON.stringify(result.tasks, null, 2),
292
+ },
293
+ ],
294
+ };
295
+ }
296
+ case 'update_task_status': {
297
+ if (!args?.taskId || !args?.status) {
298
+ throw new Error('taskId and status parameters are required');
299
+ }
300
+ const result = await apiClient.updateTask(args.taskId, {
301
+ status: args.status,
302
+ comment: args?.comment,
303
+ });
304
+ return {
305
+ content: [
306
+ {
307
+ type: 'text',
308
+ text: JSON.stringify(result.task, null, 2),
309
+ },
310
+ ],
311
+ };
312
+ }
313
+ case 'add_task_comment': {
314
+ if (!args?.taskId || !args?.content) {
315
+ throw new Error('taskId and content parameters are required');
316
+ }
317
+ const result = await apiClient.addTaskComment(args.taskId, args.content);
318
+ return {
319
+ content: [
320
+ {
321
+ type: 'text',
322
+ text: JSON.stringify(result.comment, null, 2),
323
+ },
324
+ ],
325
+ };
326
+ }
327
+ case 'assign_task': {
328
+ if (!args?.taskId) {
329
+ throw new Error('taskId parameter is required');
330
+ }
331
+ // Use 'me' to assign to self if no user specified
332
+ const assignToUserId = args?.assignToUserId;
333
+ const result = await apiClient.updateTask(args.taskId, {
334
+ assignedToId: assignToUserId || 'me',
335
+ });
336
+ return {
337
+ content: [
338
+ {
339
+ type: 'text',
340
+ text: JSON.stringify(result.task, null, 2),
341
+ },
342
+ ],
343
+ };
344
+ }
345
+ case 'create_project_from_codebase': {
346
+ // Read the local CLAUDE.md file
347
+ const resolvedFile = await resolveClaudeFile({
348
+ explicitPath: args?.claudePath,
349
+ baseDir: args?.baseDir,
350
+ });
351
+ // Send content to API
352
+ const result = await apiClient.createProjectFromCodebase({
353
+ content: resolvedFile.content,
354
+ projectName: args?.projectNameOverride,
355
+ monthlyHours: args?.monthlyHours || 40,
356
+ hourlyRate: args?.hourlyRate || 0,
357
+ claudeFilePath: resolvedFile.path,
358
+ });
359
+ return {
360
+ content: [
361
+ {
362
+ type: 'text',
363
+ text: JSON.stringify(result, null, 2),
364
+ },
365
+ ],
366
+ };
367
+ }
368
+ case 'get_client_request': {
369
+ if (!args?.requestId) {
370
+ throw new Error('requestId parameter is required');
371
+ }
372
+ const result = await apiClient.getClientRequest(args.requestId);
373
+ return {
374
+ content: [
375
+ {
376
+ type: 'text',
377
+ text: JSON.stringify(result, null, 2),
378
+ },
379
+ ],
380
+ };
381
+ }
382
+ case 'search_client_requests': {
383
+ const result = await apiClient.searchClientRequests({
384
+ projectId: args?.projectId,
385
+ status: args?.status,
386
+ query: args?.query,
387
+ });
388
+ return {
389
+ content: [
390
+ {
391
+ type: 'text',
392
+ text: JSON.stringify(result.requests, null, 2),
393
+ },
394
+ ],
395
+ };
396
+ }
397
+ default:
398
+ throw new Error(`Unknown tool: ${name}`);
399
+ }
400
+ }
401
+ catch (error) {
402
+ return {
403
+ content: [
404
+ {
405
+ type: 'text',
406
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
407
+ },
408
+ ],
409
+ isError: true,
410
+ };
411
+ }
412
+ });
413
+ // List available resources
414
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
415
+ return {
416
+ resources: [
417
+ {
418
+ uri: 'sego://tasks/{taskId}',
419
+ name: 'Task Detail',
420
+ description: 'Get detailed information about a specific task including comments and full context',
421
+ mimeType: 'application/json',
422
+ },
423
+ {
424
+ uri: 'sego://client-requests/{requestId}',
425
+ name: 'Client Request Detail',
426
+ description: 'Get detailed information about a client request including all associated tasks, comments, and project context',
427
+ mimeType: 'application/json',
428
+ },
429
+ ],
430
+ };
431
+ });
432
+ // Handle resource reads
433
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
434
+ const uri = request.params.uri;
435
+ // Parse task detail URI: sego://tasks/{taskId}
436
+ const taskMatch = uri.match(/^sego:\/\/tasks\/(.+)$/);
437
+ if (taskMatch) {
438
+ const taskId = taskMatch[1];
439
+ const task = await apiClient.getTask(taskId);
440
+ return {
441
+ contents: [
442
+ {
443
+ uri,
444
+ mimeType: 'application/json',
445
+ text: JSON.stringify(task, null, 2),
446
+ },
447
+ ],
448
+ };
449
+ }
450
+ // Parse client request detail URI: sego://client-requests/{requestId}
451
+ const clientRequestMatch = uri.match(/^sego:\/\/client-requests\/(.+)$/);
452
+ if (clientRequestMatch) {
453
+ const requestId = clientRequestMatch[1];
454
+ const clientRequest = await apiClient.getClientRequest(requestId);
455
+ return {
456
+ contents: [
457
+ {
458
+ uri,
459
+ mimeType: 'application/json',
460
+ text: JSON.stringify(clientRequest, null, 2),
461
+ },
462
+ ],
463
+ };
464
+ }
465
+ throw new Error(`Unknown resource URI: ${uri}`);
466
+ });
467
+ // Start server
468
+ async function main() {
469
+ await initialize();
470
+ const transport = new StdioServerTransport();
471
+ await server.connect(transport);
472
+ console.error('Sego PM MCP Server running on stdio');
473
+ }
474
+ main().catch((error) => {
475
+ console.error('Server error:', error);
476
+ process.exit(1);
477
+ });
478
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * CLAUDE.md File Resolver Service
3
+ *
4
+ * Handles secure file path resolution and CLAUDE.md file discovery
5
+ * with path traversal prevention and validation.
6
+ */
7
+ export interface FileResolverOptions {
8
+ explicitPath?: string;
9
+ baseDir?: string;
10
+ searchDirs?: string[];
11
+ }
12
+ export interface ResolvedFile {
13
+ path: string;
14
+ content: string;
15
+ foundMethod: 'explicit' | 'auto-detect';
16
+ sizeBytes: number;
17
+ }
18
+ /**
19
+ * Resolve and read CLAUDE.md file
20
+ *
21
+ * @param options - Resolution options
22
+ * @returns Resolved file with content and metadata
23
+ * @throws Error if file not found or validation fails
24
+ *
25
+ * @example
26
+ * // Auto-detect
27
+ * const file = await resolveClaudeFile()
28
+ *
29
+ * @example
30
+ * // Explicit path
31
+ * const file = await resolveClaudeFile({ explicitPath: 'docs/CLAUDE.md' })
32
+ */
33
+ export declare function resolveClaudeFile(options?: FileResolverOptions): Promise<ResolvedFile>;
34
+ /**
35
+ * Resolve explicit path with security checks
36
+ *
37
+ * Prevents path traversal attacks by ensuring the resolved path
38
+ * stays within the allowed baseDir.
39
+ *
40
+ * @param explicitPath - User-provided file path
41
+ * @param baseDir - Base directory to restrict access to
42
+ * @returns Absolute path to file
43
+ * @throws Error if path is invalid or escapes baseDir
44
+ */
45
+ export declare function resolveExplicitPath(explicitPath: string, baseDir: string): Promise<string>;
46
+ /**
47
+ * Auto-detect CLAUDE.md in common locations
48
+ *
49
+ * Searches for CLAUDE.md in standard locations:
50
+ * 1. ./CLAUDE.md
51
+ * 2. ./.claude/CLAUDE.md
52
+ * 3. ./claude.md (lowercase variant)
53
+ * 4. ./.claude/claude.md
54
+ *
55
+ * @param baseDir - Base directory to search from
56
+ * @param additionalDirs - Additional directories to search
57
+ * @returns Absolute path to CLAUDE.md or null if not found
58
+ */
59
+ export declare function autoDetectClaudeFile(baseDir: string, additionalDirs?: string[]): Promise<string | null>;
60
+ /**
61
+ * Get relative path for display purposes
62
+ *
63
+ * @param absolutePath - Absolute path to file
64
+ * @param baseDir - Base directory (defaults to CWD)
65
+ * @returns Relative path from baseDir
66
+ */
67
+ export declare function getDisplayPath(absolutePath: string, baseDir?: string): string;
68
+ export declare class SecurityError extends Error {
69
+ constructor(message: string);
70
+ }
71
+ export declare class ClaudeFileNotFoundError extends Error {
72
+ constructor(searchedPaths: string[]);
73
+ }
74
+ //# sourceMappingURL=claude-file-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-file-resolver.d.ts","sourceRoot":"","sources":["../../src/lib/claude-file-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,UAAU,GAAG,aAAa,CAAA;IACvC,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,YAAY,CAAC,CAkCvB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAqCjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,MAAM,EAAO,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA0BxB;AAmBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAI7E;AAID,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,aAAa,EAAE,MAAM,EAAE;CAWpC"}