@vibescope/mcp-server 0.0.1 → 0.2.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/README.md +113 -98
- package/dist/api-client.d.ts +1169 -0
- package/dist/api-client.js +713 -0
- package/dist/cli.d.ts +1 -6
- package/dist/cli.js +39 -240
- package/dist/config/tool-categories.d.ts +31 -0
- package/dist/config/tool-categories.js +253 -0
- package/dist/handlers/blockers.js +57 -58
- package/dist/handlers/bodies-of-work.d.ts +2 -0
- package/dist/handlers/bodies-of-work.js +108 -477
- package/dist/handlers/cost.d.ts +1 -0
- package/dist/handlers/cost.js +35 -113
- package/dist/handlers/decisions.d.ts +2 -0
- package/dist/handlers/decisions.js +28 -27
- package/dist/handlers/deployment.js +113 -828
- package/dist/handlers/discovery.d.ts +3 -0
- package/dist/handlers/discovery.js +26 -627
- package/dist/handlers/fallback.d.ts +2 -0
- package/dist/handlers/fallback.js +56 -142
- package/dist/handlers/findings.d.ts +8 -1
- package/dist/handlers/findings.js +65 -68
- package/dist/handlers/git-issues.d.ts +9 -13
- package/dist/handlers/git-issues.js +80 -225
- package/dist/handlers/ideas.d.ts +3 -0
- package/dist/handlers/ideas.js +53 -134
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +6 -0
- package/dist/handlers/milestones.d.ts +2 -0
- package/dist/handlers/milestones.js +51 -98
- package/dist/handlers/organizations.js +79 -275
- package/dist/handlers/progress.d.ts +2 -0
- package/dist/handlers/progress.js +25 -123
- package/dist/handlers/project.js +42 -221
- package/dist/handlers/requests.d.ts +2 -0
- package/dist/handlers/requests.js +23 -83
- package/dist/handlers/session.js +119 -590
- package/dist/handlers/sprints.d.ts +32 -0
- package/dist/handlers/sprints.js +275 -0
- package/dist/handlers/tasks.d.ts +7 -10
- package/dist/handlers/tasks.js +245 -894
- package/dist/handlers/tool-docs.d.ts +9 -0
- package/dist/handlers/tool-docs.js +904 -0
- package/dist/handlers/types.d.ts +11 -3
- package/dist/handlers/validation.d.ts +1 -1
- package/dist/handlers/validation.js +38 -153
- package/dist/index.js +493 -162
- package/dist/knowledge.js +106 -9
- package/dist/tools.js +34 -4
- package/dist/validators.d.ts +21 -0
- package/dist/validators.js +91 -0
- package/package.json +2 -3
- package/src/api-client.ts +1822 -0
- package/src/cli.test.ts +128 -302
- package/src/cli.ts +41 -285
- package/src/handlers/__test-setup__.ts +215 -0
- package/src/handlers/__test-utils__.ts +4 -134
- package/src/handlers/blockers.test.ts +114 -124
- package/src/handlers/blockers.ts +68 -70
- package/src/handlers/bodies-of-work.test.ts +236 -831
- package/src/handlers/bodies-of-work.ts +210 -525
- package/src/handlers/cost.test.ts +149 -113
- package/src/handlers/cost.ts +44 -132
- package/src/handlers/decisions.test.ts +111 -209
- package/src/handlers/decisions.ts +35 -27
- package/src/handlers/deployment.test.ts +193 -239
- package/src/handlers/deployment.ts +143 -896
- package/src/handlers/discovery.test.ts +20 -67
- package/src/handlers/discovery.ts +29 -714
- package/src/handlers/fallback.test.ts +206 -361
- package/src/handlers/fallback.ts +81 -156
- package/src/handlers/findings.test.ts +229 -320
- package/src/handlers/findings.ts +76 -64
- package/src/handlers/git-issues.test.ts +623 -0
- package/src/handlers/git-issues.ts +174 -0
- package/src/handlers/ideas.test.ts +229 -343
- package/src/handlers/ideas.ts +69 -143
- package/src/handlers/index.ts +6 -0
- package/src/handlers/milestones.test.ts +167 -281
- package/src/handlers/milestones.ts +54 -93
- package/src/handlers/organizations.test.ts +275 -467
- package/src/handlers/organizations.ts +84 -294
- package/src/handlers/progress.test.ts +112 -218
- package/src/handlers/progress.ts +29 -142
- package/src/handlers/project.test.ts +203 -226
- package/src/handlers/project.ts +48 -238
- package/src/handlers/requests.test.ts +74 -342
- package/src/handlers/requests.ts +25 -83
- package/src/handlers/session.test.ts +276 -206
- package/src/handlers/session.ts +136 -662
- package/src/handlers/sprints.test.ts +711 -0
- package/src/handlers/sprints.ts +510 -0
- package/src/handlers/tasks.test.ts +669 -353
- package/src/handlers/tasks.ts +263 -1015
- package/src/handlers/tool-docs.ts +1024 -0
- package/src/handlers/types.ts +12 -4
- package/src/handlers/validation.test.ts +237 -568
- package/src/handlers/validation.ts +43 -167
- package/src/index.ts +493 -186
- package/src/tools.ts +2532 -0
- package/src/validators.test.ts +223 -223
- package/src/validators.ts +127 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +14 -13
- package/dist/cli.test.d.ts +0 -1
- package/dist/cli.test.js +0 -367
- package/dist/handlers/__test-utils__.d.ts +0 -72
- package/dist/handlers/__test-utils__.js +0 -176
- package/dist/handlers/checkouts.d.ts +0 -37
- package/dist/handlers/checkouts.js +0 -377
- package/dist/handlers/knowledge-query.d.ts +0 -22
- package/dist/handlers/knowledge-query.js +0 -253
- package/dist/handlers/knowledge.d.ts +0 -12
- package/dist/handlers/knowledge.js +0 -108
- package/dist/handlers/roles.d.ts +0 -30
- package/dist/handlers/roles.js +0 -281
- package/dist/handlers/tasks.test.d.ts +0 -1
- package/dist/handlers/tasks.test.js +0 -431
- package/dist/utils.test.d.ts +0 -1
- package/dist/utils.test.js +0 -532
- package/dist/validators.test.d.ts +0 -1
- package/dist/validators.test.js +0 -176
- package/src/knowledge.ts +0 -132
- package/src/tmpclaude-0078-cwd +0 -1
- package/src/tmpclaude-0ee1-cwd +0 -1
- package/src/tmpclaude-2dd5-cwd +0 -1
- package/src/tmpclaude-344c-cwd +0 -1
- package/src/tmpclaude-3860-cwd +0 -1
- package/src/tmpclaude-4b63-cwd +0 -1
- package/src/tmpclaude-5c73-cwd +0 -1
- package/src/tmpclaude-5ee3-cwd +0 -1
- package/src/tmpclaude-6795-cwd +0 -1
- package/src/tmpclaude-709e-cwd +0 -1
- package/src/tmpclaude-9839-cwd +0 -1
- package/src/tmpclaude-d829-cwd +0 -1
- package/src/tmpclaude-e072-cwd +0 -1
- package/src/tmpclaude-f6ee-cwd +0 -1
- package/tmpclaude-0439-cwd +0 -1
- package/tmpclaude-132f-cwd +0 -1
- package/tmpclaude-15bb-cwd +0 -1
- package/tmpclaude-165a-cwd +0 -1
- package/tmpclaude-1ba9-cwd +0 -1
- package/tmpclaude-21a3-cwd +0 -1
- package/tmpclaude-2a38-cwd +0 -1
- package/tmpclaude-2adf-cwd +0 -1
- package/tmpclaude-2f56-cwd +0 -1
- package/tmpclaude-3626-cwd +0 -1
- package/tmpclaude-3727-cwd +0 -1
- package/tmpclaude-40bc-cwd +0 -1
- package/tmpclaude-436f-cwd +0 -1
- package/tmpclaude-4783-cwd +0 -1
- package/tmpclaude-4b6d-cwd +0 -1
- package/tmpclaude-4ba4-cwd +0 -1
- package/tmpclaude-51e6-cwd +0 -1
- package/tmpclaude-5ecf-cwd +0 -1
- package/tmpclaude-6f97-cwd +0 -1
- package/tmpclaude-7fb2-cwd +0 -1
- package/tmpclaude-825c-cwd +0 -1
- package/tmpclaude-8baf-cwd +0 -1
- package/tmpclaude-8d9f-cwd +0 -1
- package/tmpclaude-975c-cwd +0 -1
- package/tmpclaude-9983-cwd +0 -1
- package/tmpclaude-a045-cwd +0 -1
- package/tmpclaude-ac4a-cwd +0 -1
- package/tmpclaude-b593-cwd +0 -1
- package/tmpclaude-b891-cwd +0 -1
- package/tmpclaude-c032-cwd +0 -1
- package/tmpclaude-cf43-cwd +0 -1
- package/tmpclaude-d040-cwd +0 -1
- package/tmpclaude-dcdd-cwd +0 -1
- package/tmpclaude-dcee-cwd +0 -1
- package/tmpclaude-e16b-cwd +0 -1
- package/tmpclaude-ecd2-cwd +0 -1
- package/tmpclaude-f48d-cwd +0 -1
package/src/index.ts
CHANGED
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
ListToolsRequestSchema,
|
|
8
8
|
type Tool,
|
|
9
9
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
10
|
-
import { createClient } from '@supabase/supabase-js';
|
|
11
10
|
import { randomUUID } from 'crypto';
|
|
11
|
+
import { initApiClient, getApiClient } from './api-client.js';
|
|
12
12
|
import {
|
|
13
13
|
ValidationError,
|
|
14
14
|
validateRequired,
|
|
@@ -34,7 +34,6 @@ import {
|
|
|
34
34
|
extractProjectNameFromGitUrl,
|
|
35
35
|
isValidStatusTransition,
|
|
36
36
|
} from './utils.js';
|
|
37
|
-
import { hashApiKey } from './cli.js';
|
|
38
37
|
import { buildHandlerRegistry, type HandlerContext } from './handlers/index.js';
|
|
39
38
|
|
|
40
39
|
// ============================================================================
|
|
@@ -50,6 +49,9 @@ let currentSessionId: string | null = null;
|
|
|
50
49
|
// Assigned persona for this agent instance
|
|
51
50
|
let currentPersona: string | null = null;
|
|
52
51
|
|
|
52
|
+
// Current role for this agent instance
|
|
53
|
+
let currentRole: 'developer' | 'validator' | 'deployer' | 'reviewer' | 'maintainer' | null = null;
|
|
54
|
+
|
|
53
55
|
// Token usage tracking for this session
|
|
54
56
|
interface ModelTokens {
|
|
55
57
|
input: number;
|
|
@@ -589,188 +591,35 @@ interface UserUpdates {
|
|
|
589
591
|
// Configuration
|
|
590
592
|
// ============================================================================
|
|
591
593
|
|
|
592
|
-
// Default Supabase URL for Vibescope production instance
|
|
593
|
-
const DEFAULT_SUPABASE_URL = 'https://uuneucmuubpgswvfijwd.supabase.co';
|
|
594
|
-
|
|
595
|
-
const SUPABASE_URL = process.env.SUPABASE_URL || process.env.PUBLIC_SUPABASE_URL || DEFAULT_SUPABASE_URL;
|
|
596
|
-
const SUPABASE_SERVICE_KEY = process.env.SUPABASE_SERVICE_KEY;
|
|
597
594
|
const API_KEY = process.env.VIBESCOPE_API_KEY;
|
|
598
595
|
|
|
599
|
-
if (!SUPABASE_SERVICE_KEY) {
|
|
600
|
-
console.error('Missing required environment variable: SUPABASE_SERVICE_KEY');
|
|
601
|
-
process.exit(1);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
596
|
if (!API_KEY) {
|
|
605
597
|
console.error('Missing required environment variable: VIBESCOPE_API_KEY');
|
|
606
598
|
process.exit(1);
|
|
607
599
|
}
|
|
608
600
|
|
|
609
|
-
//
|
|
610
|
-
|
|
611
|
-
// ============================================================================
|
|
612
|
-
|
|
613
|
-
// Using untyped client for MCP server - data validation happens at runtime
|
|
614
|
-
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY);
|
|
601
|
+
// Initialize the API client
|
|
602
|
+
initApiClient({ apiKey: API_KEY });
|
|
615
603
|
|
|
616
604
|
// ============================================================================
|
|
617
605
|
// Authentication
|
|
618
606
|
// ============================================================================
|
|
619
607
|
|
|
620
|
-
async function validateApiKey(
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
const { data, error } = await supabase
|
|
624
|
-
.from('api_keys')
|
|
625
|
-
.select('id, user_id, organization_id, scope, is_valid')
|
|
626
|
-
.eq('key_hash', keyHash)
|
|
627
|
-
.single();
|
|
628
|
-
|
|
629
|
-
if (error || !data) {
|
|
630
|
-
return null;
|
|
631
|
-
}
|
|
608
|
+
async function validateApiKey(): Promise<AuthContext | null> {
|
|
609
|
+
const apiClient = getApiClient();
|
|
610
|
+
const response = await apiClient.validateAuth();
|
|
632
611
|
|
|
633
|
-
|
|
634
|
-
if (data.is_valid === false) {
|
|
612
|
+
if (!response.ok || !response.data?.valid) {
|
|
635
613
|
return null;
|
|
636
614
|
}
|
|
637
615
|
|
|
638
|
-
// For org-scoped keys, verify user is still a member
|
|
639
|
-
if (data.scope === 'organization' && data.organization_id) {
|
|
640
|
-
const { data: member } = await supabase
|
|
641
|
-
.from('organization_members')
|
|
642
|
-
.select('role')
|
|
643
|
-
.eq('organization_id', data.organization_id)
|
|
644
|
-
.eq('user_id', data.user_id)
|
|
645
|
-
.single();
|
|
646
|
-
|
|
647
|
-
if (!member) {
|
|
648
|
-
// User is no longer a member, invalidate the key
|
|
649
|
-
await supabase
|
|
650
|
-
.from('api_keys')
|
|
651
|
-
.update({ is_valid: false })
|
|
652
|
-
.eq('id', data.id);
|
|
653
|
-
return null;
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// Update last_used_at
|
|
658
|
-
await supabase
|
|
659
|
-
.from('api_keys')
|
|
660
|
-
.update({ last_used_at: new Date().toISOString() })
|
|
661
|
-
.eq('id', data.id);
|
|
662
|
-
|
|
663
616
|
return {
|
|
664
|
-
userId: data.user_id,
|
|
665
|
-
apiKeyId: data.
|
|
666
|
-
|
|
667
|
-
scope: data.scope || 'personal',
|
|
617
|
+
userId: response.data.user_id,
|
|
618
|
+
apiKeyId: response.data.api_key_id,
|
|
619
|
+
scope: 'personal', // API handles authorization, scope not needed locally
|
|
668
620
|
};
|
|
669
621
|
}
|
|
670
622
|
|
|
671
|
-
// ============================================================================
|
|
672
|
-
// Session Status Checking (Multi-Agent Coordination)
|
|
673
|
-
// ============================================================================
|
|
674
|
-
|
|
675
|
-
/**
|
|
676
|
-
* Check if an agent session is active or stale.
|
|
677
|
-
* A session is considered stale if:
|
|
678
|
-
* - It doesn't exist (orphaned reference)
|
|
679
|
-
* - Its status is 'disconnected'
|
|
680
|
-
* - Its last_synced_at is older than 5 minutes
|
|
681
|
-
*/
|
|
682
|
-
async function checkSessionStatus(
|
|
683
|
-
sessionId: string
|
|
684
|
-
): Promise<{ exists: boolean; isActive: boolean; agentName?: string }> {
|
|
685
|
-
const { data: session } = await supabase
|
|
686
|
-
.from('agent_sessions')
|
|
687
|
-
.select('id, status, last_synced_at, agent_name, instance_id')
|
|
688
|
-
.eq('id', sessionId)
|
|
689
|
-
.single();
|
|
690
|
-
|
|
691
|
-
if (!session) {
|
|
692
|
-
return { exists: false, isActive: false };
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
const lastSync = new Date(session.last_synced_at).getTime();
|
|
696
|
-
const fiveMinutesAgo = Date.now() - 5 * 60 * 1000;
|
|
697
|
-
const isActive = session.status !== 'disconnected' && lastSync > fiveMinutesAgo;
|
|
698
|
-
|
|
699
|
-
return {
|
|
700
|
-
exists: true,
|
|
701
|
-
isActive,
|
|
702
|
-
agentName: session.agent_name || `Agent ${session.instance_id?.slice(0, 8) || sessionId.slice(0, 8)}`,
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
// ============================================================================
|
|
707
|
-
// User Updates Tracking
|
|
708
|
-
// ============================================================================
|
|
709
|
-
|
|
710
|
-
async function getUserUpdates(
|
|
711
|
-
auth: AuthContext,
|
|
712
|
-
projectId: string
|
|
713
|
-
): Promise<UserUpdates | undefined> {
|
|
714
|
-
// Get session's last_synced_at - prefer currentSessionId for accuracy
|
|
715
|
-
let lastSyncedAt: string;
|
|
716
|
-
|
|
717
|
-
if (currentSessionId) {
|
|
718
|
-
const { data: session } = await supabase
|
|
719
|
-
.from('agent_sessions')
|
|
720
|
-
.select('last_synced_at')
|
|
721
|
-
.eq('id', currentSessionId)
|
|
722
|
-
.single();
|
|
723
|
-
lastSyncedAt = session?.last_synced_at || new Date(0).toISOString();
|
|
724
|
-
} else {
|
|
725
|
-
const { data: session } = await supabase
|
|
726
|
-
.from('agent_sessions')
|
|
727
|
-
.select('last_synced_at')
|
|
728
|
-
.eq('api_key_id', auth.apiKeyId)
|
|
729
|
-
.eq('project_id', projectId)
|
|
730
|
-
.single();
|
|
731
|
-
lastSyncedAt = session?.last_synced_at || new Date(0).toISOString();
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
// Fetch user-created items since last sync (limit to 5 each for context efficiency)
|
|
735
|
-
const [tasksResult, blockersResult, ideasResult] = await Promise.all([
|
|
736
|
-
supabase
|
|
737
|
-
.from('tasks')
|
|
738
|
-
.select('id, title, created_at')
|
|
739
|
-
.eq('project_id', projectId)
|
|
740
|
-
.eq('created_by', 'user')
|
|
741
|
-
.gt('created_at', lastSyncedAt)
|
|
742
|
-
.order('created_at', { ascending: false })
|
|
743
|
-
.limit(5),
|
|
744
|
-
supabase
|
|
745
|
-
.from('blockers')
|
|
746
|
-
.select('id, description, created_at')
|
|
747
|
-
.eq('project_id', projectId)
|
|
748
|
-
.eq('created_by', 'user')
|
|
749
|
-
.gt('created_at', lastSyncedAt)
|
|
750
|
-
.order('created_at', { ascending: false })
|
|
751
|
-
.limit(5),
|
|
752
|
-
supabase
|
|
753
|
-
.from('ideas')
|
|
754
|
-
.select('id, title, created_at')
|
|
755
|
-
.eq('project_id', projectId)
|
|
756
|
-
.eq('created_by', 'user')
|
|
757
|
-
.gt('created_at', lastSyncedAt)
|
|
758
|
-
.order('created_at', { ascending: false })
|
|
759
|
-
.limit(5),
|
|
760
|
-
]);
|
|
761
|
-
|
|
762
|
-
const tasks = tasksResult.data || [];
|
|
763
|
-
const blockers = blockersResult.data || [];
|
|
764
|
-
const ideas = ideasResult.data || [];
|
|
765
|
-
|
|
766
|
-
// Return undefined if no new updates (saves context window space)
|
|
767
|
-
if (tasks.length === 0 && blockers.length === 0 && ideas.length === 0) {
|
|
768
|
-
return undefined;
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
return { tasks, blockers, ideas };
|
|
772
|
-
}
|
|
773
|
-
|
|
774
623
|
// ============================================================================
|
|
775
624
|
// Tool Definitions
|
|
776
625
|
// ============================================================================
|
|
@@ -812,7 +661,7 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
812
661
|
properties: {
|
|
813
662
|
topic: {
|
|
814
663
|
type: 'string',
|
|
815
|
-
enum: ['getting_started', 'tasks', 'validation', 'deployment', 'git', 'blockers', 'milestones', 'fallback', 'session', 'tokens', 'topics'],
|
|
664
|
+
enum: ['getting_started', 'tasks', 'validation', 'deployment', 'git', 'blockers', 'milestones', 'fallback', 'session', 'tokens', 'sprints', 'topics'],
|
|
816
665
|
description: 'Help topic. Use "topics" to list all available.',
|
|
817
666
|
},
|
|
818
667
|
},
|
|
@@ -1138,6 +987,14 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1138
987
|
type: 'number',
|
|
1139
988
|
description: 'Max number of tasks to return (default 50)',
|
|
1140
989
|
},
|
|
990
|
+
offset: {
|
|
991
|
+
type: 'number',
|
|
992
|
+
description: 'Number of tasks to skip for pagination (default 0)',
|
|
993
|
+
},
|
|
994
|
+
search_query: {
|
|
995
|
+
type: 'string',
|
|
996
|
+
description: 'Search tasks by title',
|
|
997
|
+
},
|
|
1141
998
|
include_subtasks: {
|
|
1142
999
|
type: 'boolean',
|
|
1143
1000
|
description: 'Include subtasks in results (default false). Use get_subtasks for subtasks of a specific task.',
|
|
@@ -1193,6 +1050,11 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1193
1050
|
type: 'boolean',
|
|
1194
1051
|
description: 'When true, this task blocks all other work until complete (used for deployment finalization)',
|
|
1195
1052
|
},
|
|
1053
|
+
task_type: {
|
|
1054
|
+
type: 'string',
|
|
1055
|
+
enum: ['frontend', 'backend', 'database', 'feature', 'bugfix', 'design', 'mcp', 'testing', 'docs', 'infra', 'other'],
|
|
1056
|
+
description: 'Task category (frontend, backend, database, feature, bugfix, design, mcp, testing, docs, infra, other)',
|
|
1057
|
+
},
|
|
1196
1058
|
},
|
|
1197
1059
|
required: ['project_id', 'title'],
|
|
1198
1060
|
},
|
|
@@ -1237,6 +1099,11 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1237
1099
|
type: 'string',
|
|
1238
1100
|
description: 'Git branch associated with this task',
|
|
1239
1101
|
},
|
|
1102
|
+
task_type: {
|
|
1103
|
+
type: 'string',
|
|
1104
|
+
enum: ['frontend', 'backend', 'database', 'feature', 'bugfix', 'design', 'mcp', 'testing', 'docs', 'infra', 'other'],
|
|
1105
|
+
description: 'Task category (frontend, backend, database, feature, bugfix, design, mcp, testing, docs, infra, other)',
|
|
1106
|
+
},
|
|
1240
1107
|
},
|
|
1241
1108
|
required: ['task_id'],
|
|
1242
1109
|
},
|
|
@@ -1336,6 +1203,18 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1336
1203
|
enum: ['open', 'resolved'],
|
|
1337
1204
|
description: 'Filter by status (default: open)',
|
|
1338
1205
|
},
|
|
1206
|
+
limit: {
|
|
1207
|
+
type: 'number',
|
|
1208
|
+
description: 'Max number of blockers to return (default 50, max 200)',
|
|
1209
|
+
},
|
|
1210
|
+
offset: {
|
|
1211
|
+
type: 'number',
|
|
1212
|
+
description: 'Number of blockers to skip for pagination (default 0)',
|
|
1213
|
+
},
|
|
1214
|
+
search_query: {
|
|
1215
|
+
type: 'string',
|
|
1216
|
+
description: 'Search blockers by description',
|
|
1217
|
+
},
|
|
1339
1218
|
},
|
|
1340
1219
|
required: ['project_id'],
|
|
1341
1220
|
},
|
|
@@ -1381,6 +1260,18 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1381
1260
|
type: 'string',
|
|
1382
1261
|
description: 'Project UUID',
|
|
1383
1262
|
},
|
|
1263
|
+
limit: {
|
|
1264
|
+
type: 'number',
|
|
1265
|
+
description: 'Max number of decisions to return (default 50, max 200)',
|
|
1266
|
+
},
|
|
1267
|
+
offset: {
|
|
1268
|
+
type: 'number',
|
|
1269
|
+
description: 'Number of decisions to skip for pagination (default 0)',
|
|
1270
|
+
},
|
|
1271
|
+
search_query: {
|
|
1272
|
+
type: 'string',
|
|
1273
|
+
description: 'Search decisions by title or description',
|
|
1274
|
+
},
|
|
1384
1275
|
},
|
|
1385
1276
|
required: ['project_id'],
|
|
1386
1277
|
},
|
|
@@ -1458,6 +1349,18 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1458
1349
|
enum: ['raw', 'exploring', 'planned', 'in_development', 'shipped'],
|
|
1459
1350
|
description: 'Filter by status (optional)',
|
|
1460
1351
|
},
|
|
1352
|
+
limit: {
|
|
1353
|
+
type: 'number',
|
|
1354
|
+
description: 'Max number of ideas to return (default 50, max 100)',
|
|
1355
|
+
},
|
|
1356
|
+
offset: {
|
|
1357
|
+
type: 'number',
|
|
1358
|
+
description: 'Number of ideas to skip for pagination (default 0)',
|
|
1359
|
+
},
|
|
1360
|
+
search_query: {
|
|
1361
|
+
type: 'string',
|
|
1362
|
+
description: 'Search ideas by title or description',
|
|
1363
|
+
},
|
|
1461
1364
|
},
|
|
1462
1365
|
required: ['project_id'],
|
|
1463
1366
|
},
|
|
@@ -1588,7 +1491,9 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1588
1491
|
category: { type: 'string', enum: ['performance', 'security', 'code_quality', 'accessibility', 'documentation', 'architecture', 'testing', 'other'], description: 'Filter by category (optional)' },
|
|
1589
1492
|
severity: { type: 'string', enum: ['info', 'low', 'medium', 'high', 'critical'], description: 'Filter by severity (optional)' },
|
|
1590
1493
|
status: { type: 'string', enum: ['open', 'addressed', 'dismissed', 'wontfix'], description: 'Filter by status (default: all)' },
|
|
1591
|
-
limit: { type: 'number', description: 'Max number of findings to return (default 50)' },
|
|
1494
|
+
limit: { type: 'number', description: 'Max number of findings to return (default 50, max 200)' },
|
|
1495
|
+
offset: { type: 'number', description: 'Number of findings to skip for pagination (default 0)' },
|
|
1496
|
+
search_query: { type: 'string', description: 'Search findings by title or description' },
|
|
1592
1497
|
},
|
|
1593
1498
|
required: ['project_id'],
|
|
1594
1499
|
},
|
|
@@ -1634,6 +1539,119 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
|
|
|
1634
1539
|
required: ['blocker_id'],
|
|
1635
1540
|
},
|
|
1636
1541
|
},
|
|
1542
|
+
// Git Issues tools
|
|
1543
|
+
{
|
|
1544
|
+
name: 'add_git_issue',
|
|
1545
|
+
description: `Record a git-related issue (merge conflict, push failure, etc.). Auto-created by claim_validation when conflicts detected.`,
|
|
1546
|
+
inputSchema: {
|
|
1547
|
+
type: 'object',
|
|
1548
|
+
properties: {
|
|
1549
|
+
project_id: {
|
|
1550
|
+
type: 'string',
|
|
1551
|
+
description: 'Project UUID',
|
|
1552
|
+
},
|
|
1553
|
+
issue_type: {
|
|
1554
|
+
type: 'string',
|
|
1555
|
+
enum: ['merge_conflict', 'push_failed', 'rebase_needed', 'branch_diverged', 'pr_not_mergeable'],
|
|
1556
|
+
description: 'Type of git issue',
|
|
1557
|
+
},
|
|
1558
|
+
branch: {
|
|
1559
|
+
type: 'string',
|
|
1560
|
+
description: 'Branch where the issue occurred',
|
|
1561
|
+
},
|
|
1562
|
+
target_branch: {
|
|
1563
|
+
type: 'string',
|
|
1564
|
+
description: 'Target branch for merge/rebase (optional)',
|
|
1565
|
+
},
|
|
1566
|
+
pr_url: {
|
|
1567
|
+
type: 'string',
|
|
1568
|
+
description: 'Pull request URL if applicable (optional)',
|
|
1569
|
+
},
|
|
1570
|
+
conflicting_files: {
|
|
1571
|
+
type: 'array',
|
|
1572
|
+
items: { type: 'string' },
|
|
1573
|
+
description: 'List of files with conflicts (optional)',
|
|
1574
|
+
},
|
|
1575
|
+
error_message: {
|
|
1576
|
+
type: 'string',
|
|
1577
|
+
description: 'Error message from git operation (optional)',
|
|
1578
|
+
},
|
|
1579
|
+
task_id: {
|
|
1580
|
+
type: 'string',
|
|
1581
|
+
description: 'Related task UUID (optional)',
|
|
1582
|
+
},
|
|
1583
|
+
},
|
|
1584
|
+
required: ['project_id', 'issue_type', 'branch'],
|
|
1585
|
+
},
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
name: 'resolve_git_issue',
|
|
1589
|
+
description: `Mark a git issue as resolved.`,
|
|
1590
|
+
inputSchema: {
|
|
1591
|
+
type: 'object',
|
|
1592
|
+
properties: {
|
|
1593
|
+
git_issue_id: {
|
|
1594
|
+
type: 'string',
|
|
1595
|
+
description: 'Git issue UUID',
|
|
1596
|
+
},
|
|
1597
|
+
resolution_note: {
|
|
1598
|
+
type: 'string',
|
|
1599
|
+
description: 'How the issue was resolved (optional)',
|
|
1600
|
+
},
|
|
1601
|
+
auto_resolved: {
|
|
1602
|
+
type: 'boolean',
|
|
1603
|
+
description: 'Whether this was auto-resolved (e.g., PR became mergeable)',
|
|
1604
|
+
},
|
|
1605
|
+
},
|
|
1606
|
+
required: ['git_issue_id'],
|
|
1607
|
+
},
|
|
1608
|
+
},
|
|
1609
|
+
{
|
|
1610
|
+
name: 'get_git_issues',
|
|
1611
|
+
description: `Get git issues for a project, optionally filtered by status, type, or branch.`,
|
|
1612
|
+
inputSchema: {
|
|
1613
|
+
type: 'object',
|
|
1614
|
+
properties: {
|
|
1615
|
+
project_id: {
|
|
1616
|
+
type: 'string',
|
|
1617
|
+
description: 'Project UUID',
|
|
1618
|
+
},
|
|
1619
|
+
status: {
|
|
1620
|
+
type: 'string',
|
|
1621
|
+
enum: ['open', 'resolved'],
|
|
1622
|
+
description: 'Filter by status (default: open)',
|
|
1623
|
+
},
|
|
1624
|
+
issue_type: {
|
|
1625
|
+
type: 'string',
|
|
1626
|
+
enum: ['merge_conflict', 'push_failed', 'rebase_needed', 'branch_diverged', 'pr_not_mergeable'],
|
|
1627
|
+
description: 'Filter by issue type (optional)',
|
|
1628
|
+
},
|
|
1629
|
+
branch: {
|
|
1630
|
+
type: 'string',
|
|
1631
|
+
description: 'Filter by branch (optional)',
|
|
1632
|
+
},
|
|
1633
|
+
limit: {
|
|
1634
|
+
type: 'number',
|
|
1635
|
+
description: 'Max issues to return (default: 50)',
|
|
1636
|
+
},
|
|
1637
|
+
},
|
|
1638
|
+
required: ['project_id'],
|
|
1639
|
+
},
|
|
1640
|
+
},
|
|
1641
|
+
{
|
|
1642
|
+
name: 'delete_git_issue',
|
|
1643
|
+
description: `Delete a git issue.`,
|
|
1644
|
+
inputSchema: {
|
|
1645
|
+
type: 'object',
|
|
1646
|
+
properties: {
|
|
1647
|
+
git_issue_id: {
|
|
1648
|
+
type: 'string',
|
|
1649
|
+
description: 'Git issue UUID',
|
|
1650
|
+
},
|
|
1651
|
+
},
|
|
1652
|
+
required: ['git_issue_id'],
|
|
1653
|
+
},
|
|
1654
|
+
},
|
|
1637
1655
|
{
|
|
1638
1656
|
name: 'delete_decision',
|
|
1639
1657
|
description: `Delete a decision.`,
|
|
@@ -1799,6 +1817,10 @@ Returns subtasks with aggregate completion stats.`,
|
|
|
1799
1817
|
type: 'string',
|
|
1800
1818
|
description: 'Session ID from start_work_session (optional, uses current session if not provided)',
|
|
1801
1819
|
},
|
|
1820
|
+
current_worktree_path: {
|
|
1821
|
+
type: ['string', 'null'],
|
|
1822
|
+
description: 'Report your current git worktree path (e.g., "../project-task-abc123"). Set to null to clear.',
|
|
1823
|
+
},
|
|
1802
1824
|
},
|
|
1803
1825
|
},
|
|
1804
1826
|
},
|
|
@@ -1848,7 +1870,7 @@ Returns subtasks with aggregate completion stats.`,
|
|
|
1848
1870
|
},
|
|
1849
1871
|
{
|
|
1850
1872
|
name: 'validate_task',
|
|
1851
|
-
description: 'Validate a completed task. Include test results in validation_notes.',
|
|
1873
|
+
description: 'Validate a completed task. Include test results in validation_notes. For github-flow/git-flow projects, a PR must exist before approval (add via add_task_reference).',
|
|
1852
1874
|
inputSchema: {
|
|
1853
1875
|
type: 'object',
|
|
1854
1876
|
properties: {
|
|
@@ -1864,6 +1886,10 @@ Returns subtasks with aggregate completion stats.`,
|
|
|
1864
1886
|
type: 'boolean',
|
|
1865
1887
|
description: 'Whether the task passes validation (true = approved, false = needs more work)',
|
|
1866
1888
|
},
|
|
1889
|
+
skip_pr_check: {
|
|
1890
|
+
type: 'boolean',
|
|
1891
|
+
description: 'Skip PR existence check (use only for tasks that legitimately do not need a PR)',
|
|
1892
|
+
},
|
|
1867
1893
|
},
|
|
1868
1894
|
required: ['task_id', 'approved'],
|
|
1869
1895
|
},
|
|
@@ -2571,7 +2597,8 @@ Bodies of work allow organizing related tasks with optional auto-deployment on c
|
|
|
2571
2597
|
},
|
|
2572
2598
|
{
|
|
2573
2599
|
name: 'get_body_of_work',
|
|
2574
|
-
description: `Get a body of work with all its tasks organized by phase
|
|
2600
|
+
description: `Get a body of work with all its tasks organized by phase.
|
|
2601
|
+
Use summary_only: true to get task counts and next task instead of full task arrays (saves tokens).`,
|
|
2575
2602
|
inputSchema: {
|
|
2576
2603
|
type: 'object',
|
|
2577
2604
|
properties: {
|
|
@@ -2579,6 +2606,10 @@ Bodies of work allow organizing related tasks with optional auto-deployment on c
|
|
|
2579
2606
|
type: 'string',
|
|
2580
2607
|
description: 'Body of work UUID',
|
|
2581
2608
|
},
|
|
2609
|
+
summary_only: {
|
|
2610
|
+
type: 'boolean',
|
|
2611
|
+
description: 'Return task counts and next task instead of full task arrays (default: false)',
|
|
2612
|
+
},
|
|
2582
2613
|
},
|
|
2583
2614
|
required: ['body_of_work_id'],
|
|
2584
2615
|
},
|
|
@@ -2598,6 +2629,18 @@ Bodies of work allow organizing related tasks with optional auto-deployment on c
|
|
|
2598
2629
|
enum: ['draft', 'active', 'completed', 'cancelled'],
|
|
2599
2630
|
description: 'Filter by status (optional)',
|
|
2600
2631
|
},
|
|
2632
|
+
limit: {
|
|
2633
|
+
type: 'number',
|
|
2634
|
+
description: 'Max number of bodies of work to return (default 50, max 100)',
|
|
2635
|
+
},
|
|
2636
|
+
offset: {
|
|
2637
|
+
type: 'number',
|
|
2638
|
+
description: 'Number of items to skip for pagination (default 0)',
|
|
2639
|
+
},
|
|
2640
|
+
search_query: {
|
|
2641
|
+
type: 'string',
|
|
2642
|
+
description: 'Search bodies of work by title or description',
|
|
2643
|
+
},
|
|
2601
2644
|
},
|
|
2602
2645
|
required: ['project_id'],
|
|
2603
2646
|
},
|
|
@@ -2748,6 +2791,278 @@ Only returns tasks where all dependencies are completed.`,
|
|
|
2748
2791
|
},
|
|
2749
2792
|
},
|
|
2750
2793
|
// ============================================================================
|
|
2794
|
+
// Sprint Tools
|
|
2795
|
+
// ============================================================================
|
|
2796
|
+
{
|
|
2797
|
+
name: 'create_sprint',
|
|
2798
|
+
description: `Create a new sprint. Sprints are time-bounded bodies of work with velocity tracking.
|
|
2799
|
+
Sprints start in 'planning' status where tasks can be added with story points.`,
|
|
2800
|
+
inputSchema: {
|
|
2801
|
+
type: 'object',
|
|
2802
|
+
properties: {
|
|
2803
|
+
project_id: {
|
|
2804
|
+
type: 'string',
|
|
2805
|
+
description: 'Project UUID',
|
|
2806
|
+
},
|
|
2807
|
+
title: {
|
|
2808
|
+
type: 'string',
|
|
2809
|
+
description: 'Sprint title (e.g., "Sprint 5" or "Q1 Release")',
|
|
2810
|
+
},
|
|
2811
|
+
goal: {
|
|
2812
|
+
type: 'string',
|
|
2813
|
+
description: 'Sprint goal statement',
|
|
2814
|
+
},
|
|
2815
|
+
start_date: {
|
|
2816
|
+
type: 'string',
|
|
2817
|
+
description: 'Start date (YYYY-MM-DD)',
|
|
2818
|
+
},
|
|
2819
|
+
end_date: {
|
|
2820
|
+
type: 'string',
|
|
2821
|
+
description: 'End date (YYYY-MM-DD)',
|
|
2822
|
+
},
|
|
2823
|
+
auto_deploy_on_completion: {
|
|
2824
|
+
type: 'boolean',
|
|
2825
|
+
description: 'Automatically request deployment when sprint completes (default: false)',
|
|
2826
|
+
},
|
|
2827
|
+
deploy_environment: {
|
|
2828
|
+
type: 'string',
|
|
2829
|
+
enum: ['development', 'staging', 'production'],
|
|
2830
|
+
description: 'Target environment for auto-deploy (default: production)',
|
|
2831
|
+
},
|
|
2832
|
+
deploy_version_bump: {
|
|
2833
|
+
type: 'string',
|
|
2834
|
+
enum: ['patch', 'minor', 'major'],
|
|
2835
|
+
description: 'Version bump for auto-deploy (default: minor)',
|
|
2836
|
+
},
|
|
2837
|
+
},
|
|
2838
|
+
required: ['project_id', 'title', 'start_date', 'end_date'],
|
|
2839
|
+
},
|
|
2840
|
+
},
|
|
2841
|
+
{
|
|
2842
|
+
name: 'update_sprint',
|
|
2843
|
+
description: `Update a sprint's details. Can update title, goal, dates, and deployment settings.`,
|
|
2844
|
+
inputSchema: {
|
|
2845
|
+
type: 'object',
|
|
2846
|
+
properties: {
|
|
2847
|
+
sprint_id: {
|
|
2848
|
+
type: 'string',
|
|
2849
|
+
description: 'Sprint UUID',
|
|
2850
|
+
},
|
|
2851
|
+
title: {
|
|
2852
|
+
type: 'string',
|
|
2853
|
+
description: 'New sprint title',
|
|
2854
|
+
},
|
|
2855
|
+
goal: {
|
|
2856
|
+
type: 'string',
|
|
2857
|
+
description: 'New sprint goal',
|
|
2858
|
+
},
|
|
2859
|
+
start_date: {
|
|
2860
|
+
type: 'string',
|
|
2861
|
+
description: 'New start date (YYYY-MM-DD)',
|
|
2862
|
+
},
|
|
2863
|
+
end_date: {
|
|
2864
|
+
type: 'string',
|
|
2865
|
+
description: 'New end date (YYYY-MM-DD)',
|
|
2866
|
+
},
|
|
2867
|
+
auto_deploy_on_completion: {
|
|
2868
|
+
type: 'boolean',
|
|
2869
|
+
description: 'Auto-deploy setting',
|
|
2870
|
+
},
|
|
2871
|
+
deploy_environment: {
|
|
2872
|
+
type: 'string',
|
|
2873
|
+
enum: ['development', 'staging', 'production'],
|
|
2874
|
+
description: 'Target environment',
|
|
2875
|
+
},
|
|
2876
|
+
deploy_version_bump: {
|
|
2877
|
+
type: 'string',
|
|
2878
|
+
enum: ['patch', 'minor', 'major'],
|
|
2879
|
+
description: 'Version bump type',
|
|
2880
|
+
},
|
|
2881
|
+
},
|
|
2882
|
+
required: ['sprint_id'],
|
|
2883
|
+
},
|
|
2884
|
+
},
|
|
2885
|
+
{
|
|
2886
|
+
name: 'get_sprint',
|
|
2887
|
+
description: `Get a sprint with all its tasks organized by phase (pre/core/post).
|
|
2888
|
+
Includes progress percentage, velocity points, and committed points.
|
|
2889
|
+
Use summary_only: true to get task counts and next task instead of full task arrays (saves tokens).`,
|
|
2890
|
+
inputSchema: {
|
|
2891
|
+
type: 'object',
|
|
2892
|
+
properties: {
|
|
2893
|
+
sprint_id: {
|
|
2894
|
+
type: 'string',
|
|
2895
|
+
description: 'Sprint UUID',
|
|
2896
|
+
},
|
|
2897
|
+
summary_only: {
|
|
2898
|
+
type: 'boolean',
|
|
2899
|
+
description: 'Return task counts and next task instead of full task arrays (default: false)',
|
|
2900
|
+
},
|
|
2901
|
+
},
|
|
2902
|
+
required: ['sprint_id'],
|
|
2903
|
+
},
|
|
2904
|
+
},
|
|
2905
|
+
{
|
|
2906
|
+
name: 'get_sprints',
|
|
2907
|
+
description: `List sprints for a project with velocity metrics.
|
|
2908
|
+
Returns sprints sorted by sprint_number descending (most recent first).`,
|
|
2909
|
+
inputSchema: {
|
|
2910
|
+
type: 'object',
|
|
2911
|
+
properties: {
|
|
2912
|
+
project_id: {
|
|
2913
|
+
type: 'string',
|
|
2914
|
+
description: 'Project UUID',
|
|
2915
|
+
},
|
|
2916
|
+
status: {
|
|
2917
|
+
type: 'string',
|
|
2918
|
+
enum: ['planning', 'active', 'in_review', 'retrospective', 'completed', 'cancelled'],
|
|
2919
|
+
description: 'Filter by sprint status (optional)',
|
|
2920
|
+
},
|
|
2921
|
+
limit: {
|
|
2922
|
+
type: 'number',
|
|
2923
|
+
description: 'Max sprints to return (default: 20, max: 100)',
|
|
2924
|
+
},
|
|
2925
|
+
},
|
|
2926
|
+
required: ['project_id'],
|
|
2927
|
+
},
|
|
2928
|
+
},
|
|
2929
|
+
{
|
|
2930
|
+
name: 'delete_sprint',
|
|
2931
|
+
description: `Delete a sprint. Tasks are preserved but no longer grouped.`,
|
|
2932
|
+
inputSchema: {
|
|
2933
|
+
type: 'object',
|
|
2934
|
+
properties: {
|
|
2935
|
+
sprint_id: {
|
|
2936
|
+
type: 'string',
|
|
2937
|
+
description: 'Sprint UUID',
|
|
2938
|
+
},
|
|
2939
|
+
},
|
|
2940
|
+
required: ['sprint_id'],
|
|
2941
|
+
},
|
|
2942
|
+
},
|
|
2943
|
+
{
|
|
2944
|
+
name: 'start_sprint',
|
|
2945
|
+
description: `Start a sprint. Transitions from 'planning' to 'active' status.
|
|
2946
|
+
Locks the committed_points at the current total story points.`,
|
|
2947
|
+
inputSchema: {
|
|
2948
|
+
type: 'object',
|
|
2949
|
+
properties: {
|
|
2950
|
+
sprint_id: {
|
|
2951
|
+
type: 'string',
|
|
2952
|
+
description: 'Sprint UUID',
|
|
2953
|
+
},
|
|
2954
|
+
},
|
|
2955
|
+
required: ['sprint_id'],
|
|
2956
|
+
},
|
|
2957
|
+
},
|
|
2958
|
+
{
|
|
2959
|
+
name: 'complete_sprint',
|
|
2960
|
+
description: `Complete a sprint. Handles retrospective phase and auto-deployment if configured.
|
|
2961
|
+
Status flow: active → in_review → retrospective → completed`,
|
|
2962
|
+
inputSchema: {
|
|
2963
|
+
type: 'object',
|
|
2964
|
+
properties: {
|
|
2965
|
+
sprint_id: {
|
|
2966
|
+
type: 'string',
|
|
2967
|
+
description: 'Sprint UUID',
|
|
2968
|
+
},
|
|
2969
|
+
retrospective_notes: {
|
|
2970
|
+
type: 'string',
|
|
2971
|
+
description: 'Sprint retrospective notes',
|
|
2972
|
+
},
|
|
2973
|
+
skip_retrospective: {
|
|
2974
|
+
type: 'boolean',
|
|
2975
|
+
description: 'Skip retrospective phase and go directly to completed (default: false)',
|
|
2976
|
+
},
|
|
2977
|
+
},
|
|
2978
|
+
required: ['sprint_id'],
|
|
2979
|
+
},
|
|
2980
|
+
},
|
|
2981
|
+
{
|
|
2982
|
+
name: 'add_task_to_sprint',
|
|
2983
|
+
description: `Add a task to a sprint with optional story points.
|
|
2984
|
+
Tasks can be added during 'planning' status. Story points contribute to committed_points.`,
|
|
2985
|
+
inputSchema: {
|
|
2986
|
+
type: 'object',
|
|
2987
|
+
properties: {
|
|
2988
|
+
sprint_id: {
|
|
2989
|
+
type: 'string',
|
|
2990
|
+
description: 'Sprint UUID',
|
|
2991
|
+
},
|
|
2992
|
+
task_id: {
|
|
2993
|
+
type: 'string',
|
|
2994
|
+
description: 'Task UUID to add',
|
|
2995
|
+
},
|
|
2996
|
+
story_points: {
|
|
2997
|
+
type: 'number',
|
|
2998
|
+
description: 'Story point estimate (optional, must be non-negative integer)',
|
|
2999
|
+
},
|
|
3000
|
+
phase: {
|
|
3001
|
+
type: 'string',
|
|
3002
|
+
enum: ['pre', 'core', 'post'],
|
|
3003
|
+
description: 'Task phase (default: core)',
|
|
3004
|
+
},
|
|
3005
|
+
},
|
|
3006
|
+
required: ['sprint_id', 'task_id'],
|
|
3007
|
+
},
|
|
3008
|
+
},
|
|
3009
|
+
{
|
|
3010
|
+
name: 'remove_task_from_sprint',
|
|
3011
|
+
description: `Remove a task from a sprint. Task is preserved but returns to backlog.`,
|
|
3012
|
+
inputSchema: {
|
|
3013
|
+
type: 'object',
|
|
3014
|
+
properties: {
|
|
3015
|
+
sprint_id: {
|
|
3016
|
+
type: 'string',
|
|
3017
|
+
description: 'Sprint UUID',
|
|
3018
|
+
},
|
|
3019
|
+
task_id: {
|
|
3020
|
+
type: 'string',
|
|
3021
|
+
description: 'Task UUID to remove',
|
|
3022
|
+
},
|
|
3023
|
+
},
|
|
3024
|
+
required: ['sprint_id', 'task_id'],
|
|
3025
|
+
},
|
|
3026
|
+
},
|
|
3027
|
+
{
|
|
3028
|
+
name: 'get_sprint_backlog',
|
|
3029
|
+
description: `Get tasks from backlog/pending that can be added to a sprint.
|
|
3030
|
+
Returns tasks not already assigned to any body of work or sprint.`,
|
|
3031
|
+
inputSchema: {
|
|
3032
|
+
type: 'object',
|
|
3033
|
+
properties: {
|
|
3034
|
+
project_id: {
|
|
3035
|
+
type: 'string',
|
|
3036
|
+
description: 'Project UUID',
|
|
3037
|
+
},
|
|
3038
|
+
sprint_id: {
|
|
3039
|
+
type: 'string',
|
|
3040
|
+
description: 'Sprint UUID to exclude already-added tasks (optional)',
|
|
3041
|
+
},
|
|
3042
|
+
},
|
|
3043
|
+
required: ['project_id'],
|
|
3044
|
+
},
|
|
3045
|
+
},
|
|
3046
|
+
{
|
|
3047
|
+
name: 'get_sprint_velocity',
|
|
3048
|
+
description: `Get velocity metrics for completed sprints.
|
|
3049
|
+
Returns committed vs completed points and average velocity.`,
|
|
3050
|
+
inputSchema: {
|
|
3051
|
+
type: 'object',
|
|
3052
|
+
properties: {
|
|
3053
|
+
project_id: {
|
|
3054
|
+
type: 'string',
|
|
3055
|
+
description: 'Project UUID',
|
|
3056
|
+
},
|
|
3057
|
+
limit: {
|
|
3058
|
+
type: 'number',
|
|
3059
|
+
description: 'Number of sprints to analyze (default: 10, max: 50)',
|
|
3060
|
+
},
|
|
3061
|
+
},
|
|
3062
|
+
required: ['project_id'],
|
|
3063
|
+
},
|
|
3064
|
+
},
|
|
3065
|
+
// ============================================================================
|
|
2751
3066
|
// Organization Tools
|
|
2752
3067
|
// ============================================================================
|
|
2753
3068
|
{
|
|
@@ -3001,24 +3316,15 @@ async function handleTool(
|
|
|
3001
3316
|
name: string,
|
|
3002
3317
|
args: Record<string, unknown>
|
|
3003
3318
|
): Promise<{ result: unknown; user_updates?: UserUpdates; reminder?: string }> {
|
|
3004
|
-
// Update session on every tool call:
|
|
3319
|
+
// Update session on every tool call via API:
|
|
3005
3320
|
// - last_synced_at: keeps session alive and visible as "active" on dashboard
|
|
3006
|
-
// -
|
|
3007
|
-
// - last_tool_at: timestamp of last tool call
|
|
3321
|
+
// - token tracking: synced periodically for cost monitoring
|
|
3008
3322
|
// Skip for start_work_session since it handles its own session setup
|
|
3009
3323
|
if (currentSessionId && name !== 'start_work_session') {
|
|
3010
|
-
const
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
}).then(({ error }) => {
|
|
3015
|
-
// Fallback to direct update if RPC doesn't exist (pre-migration)
|
|
3016
|
-
if (error) {
|
|
3017
|
-
return supabase
|
|
3018
|
-
.from('agent_sessions')
|
|
3019
|
-
.update({ last_synced_at: now })
|
|
3020
|
-
.eq('id', currentSessionId);
|
|
3021
|
-
}
|
|
3324
|
+
const apiClient = getApiClient();
|
|
3325
|
+
// Fire and forget - don't block tool execution on session sync
|
|
3326
|
+
apiClient.syncSession(currentSessionId).catch(() => {
|
|
3327
|
+
// Silently ignore sync errors - session tracking is non-critical
|
|
3022
3328
|
});
|
|
3023
3329
|
}
|
|
3024
3330
|
|
|
@@ -3027,17 +3333,18 @@ async function handleTool(
|
|
|
3027
3333
|
if (handler) {
|
|
3028
3334
|
// Build handler context
|
|
3029
3335
|
const ctx: HandlerContext = {
|
|
3030
|
-
supabase,
|
|
3031
3336
|
auth,
|
|
3032
3337
|
session: {
|
|
3033
3338
|
instanceId: INSTANCE_ID,
|
|
3034
3339
|
currentSessionId,
|
|
3035
3340
|
currentPersona,
|
|
3341
|
+
currentRole,
|
|
3036
3342
|
tokenUsage: sessionTokenUsage,
|
|
3037
3343
|
},
|
|
3038
3344
|
updateSession: (updates) => {
|
|
3039
3345
|
if (updates.currentSessionId !== undefined) currentSessionId = updates.currentSessionId;
|
|
3040
3346
|
if (updates.currentPersona !== undefined) currentPersona = updates.currentPersona;
|
|
3347
|
+
if (updates.currentRole !== undefined) currentRole = updates.currentRole;
|
|
3041
3348
|
if (updates.tokenUsage !== undefined) sessionTokenUsage = updates.tokenUsage;
|
|
3042
3349
|
},
|
|
3043
3350
|
};
|
|
@@ -3054,8 +3361,8 @@ async function handleTool(
|
|
|
3054
3361
|
// ============================================================================
|
|
3055
3362
|
|
|
3056
3363
|
async function main() {
|
|
3057
|
-
// Validate API key on startup
|
|
3058
|
-
const auth = await validateApiKey(
|
|
3364
|
+
// Validate API key on startup via API
|
|
3365
|
+
const auth = await validateApiKey();
|
|
3059
3366
|
if (!auth) {
|
|
3060
3367
|
console.error('Invalid API key');
|
|
3061
3368
|
process.exit(1);
|