infra-kit 0.1.38 → 0.1.41

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.
Files changed (37) hide show
  1. package/dist/cli.js +18 -18
  2. package/dist/cli.js.map +4 -4
  3. package/dist/mcp.js +18 -1
  4. package/dist/mcp.js.map +4 -4
  5. package/package.json +3 -2
  6. package/src/commands/gh-merge-dev/gh-merge-dev.ts +59 -22
  7. package/src/commands/gh-merge-dev/index.ts +1 -1
  8. package/src/commands/gh-release-create/gh-release-create.ts +58 -20
  9. package/src/commands/gh-release-create/index.ts +1 -1
  10. package/src/commands/gh-release-deliver/gh-release-deliver.ts +47 -11
  11. package/src/commands/gh-release-deliver/index.ts +1 -1
  12. package/src/commands/gh-release-deploy/gh-release-deploy.ts +47 -7
  13. package/src/commands/gh-release-deploy/index.ts +1 -1
  14. package/src/commands/gh-release-list/gh-release-list.ts +37 -5
  15. package/src/commands/gh-release-list/index.ts +1 -1
  16. package/src/commands/worktrees-add/index.ts +1 -1
  17. package/src/commands/worktrees-add/worktrees-add.ts +45 -19
  18. package/src/commands/worktrees-list/index.ts +1 -1
  19. package/src/commands/worktrees-list/worktrees-list.ts +69 -33
  20. package/src/commands/worktrees-remove/index.ts +1 -1
  21. package/src/commands/worktrees-remove/worktrees-remove.ts +44 -18
  22. package/src/commands/worktrees-sync/index.ts +1 -1
  23. package/src/commands/worktrees-sync/worktrees-sync.ts +42 -19
  24. package/src/entry/cli.ts +8 -9
  25. package/src/entry/mcp.ts +4 -4
  26. package/src/lib/error-handlers/index.ts +8 -2
  27. package/src/lib/logger/index.ts +23 -2
  28. package/src/mcp/prompts/index.ts +1 -1
  29. package/src/mcp/resources/index.ts +1 -1
  30. package/src/mcp/server.ts +2 -2
  31. package/src/mcp/tools/index.ts +39 -1
  32. package/src/shared/gh-cli-auth/gh-cli-auth.ts +6 -4
  33. package/src/shared/gh-release-prs/gh-release-prs.ts +4 -2
  34. package/src/shared/logger/index.ts +4 -0
  35. package/src/shared/tool-handler/index.ts +1 -0
  36. package/src/shared/tool-handler/tool-handler.ts +29 -0
  37. package/src/types.ts +11 -0
@@ -1,21 +1,22 @@
1
- /* eslint-disable no-console */
2
1
  import confirm from '@inquirer/confirm'
3
2
  import select from '@inquirer/select'
4
3
  import process from 'node:process'
4
+ import { z } from 'zod'
5
5
  import { $ } from 'zx'
6
6
 
7
7
  import { getReleasePRs } from 'src/shared/gh-release-prs'
8
+ import { logger } from 'src/shared/logger'
9
+ import type { RequiredConfirmedOptionArg, ToolsExecutionResult } from 'src/types'
8
10
 
9
- interface GhReleaseDeliverArgs {
11
+ interface GhReleaseDeliverArgs extends RequiredConfirmedOptionArg {
10
12
  version: string
11
- yes: boolean
12
13
  }
13
14
 
14
15
  /**
15
16
  * Deliver a release branch to production
16
17
  */
17
- export const ghReleaseDeliver = async (args: GhReleaseDeliverArgs): Promise<void> => {
18
- const { version, yes } = args
18
+ export const ghReleaseDeliver = async (args: GhReleaseDeliverArgs): Promise<ToolsExecutionResult> => {
19
+ const { version, confirmedCommand } = args
19
20
 
20
21
  const releasePRsList = await getReleasePRs()
21
22
 
@@ -35,18 +36,18 @@ export const ghReleaseDeliver = async (args: GhReleaseDeliverArgs): Promise<void
35
36
 
36
37
  // Check if release branch exists in the list
37
38
  if (!releasePRsList.includes(selectedReleaseBranch)) {
38
- console.error(`❌ Release branch ${selectedReleaseBranch} not found in open PRs. Exiting...`)
39
+ logger.error(`❌ Release branch ${selectedReleaseBranch} not found in open PRs. Exiting...`)
39
40
  process.exit(1)
40
41
  }
41
42
 
42
- const answer = yes
43
+ const answer = confirmedCommand
43
44
  ? true
44
45
  : await confirm({
45
46
  message: `Are you sure you want to deliver version ${selectedReleaseBranch} to production?`,
46
47
  })
47
48
 
48
49
  if (!answer) {
49
- console.log('Operation cancelled. Exiting...')
50
+ logger.info('Operation cancelled. Exiting...')
50
51
  process.exit(0)
51
52
  }
52
53
 
@@ -62,10 +63,45 @@ export const ghReleaseDeliver = async (args: GhReleaseDeliverArgs): Promise<void
62
63
  // Merge main into dev
63
64
  await $`git switch main && git pull && git switch dev && git pull && git merge main --no-edit && git push`
64
65
 
65
- console.log('\n')
66
- console.log(`✔️ Successfully delivered ${selectedReleaseBranch} to production!`)
66
+ logger.info('\n')
67
+ logger.info(`✔️ Successfully delivered ${selectedReleaseBranch} to production!`)
68
+
69
+ const structuredContent = {
70
+ releaseBranch: selectedReleaseBranch,
71
+ version: selectedReleaseBranch.replace('release/v', ''),
72
+ success: true,
73
+ }
74
+
75
+ return {
76
+ content: [
77
+ {
78
+ type: 'text',
79
+ text: JSON.stringify(structuredContent, null, 2),
80
+ },
81
+ ],
82
+ structuredContent,
83
+ }
67
84
  } catch (error: unknown) {
68
- console.error('❌ Error merging release branch into dev:', error instanceof Error ? error.message : 'Unknown error')
85
+ logger.error({ error }, '❌ Error merging release branch into dev')
69
86
  process.exit(1)
70
87
  }
71
88
  }
89
+
90
+ // MCP Tool Registration
91
+ const ghReleaseDeliverSchema = z.object({
92
+ version: z.string().describe('Version to deliver to production (e.g., "1.2.5")'),
93
+ })
94
+
95
+ const ghReleaseDeliverOutputSchema = z.object({
96
+ releaseBranch: z.string().describe('The release branch that was delivered'),
97
+ version: z.string().describe('The version that was delivered'),
98
+ success: z.boolean().describe('Whether the delivery was successful'),
99
+ })
100
+
101
+ export const ghReleaseDeliverMcpTool = {
102
+ name: 'gh-release-deliver',
103
+ description: 'Deliver a release branch to production',
104
+ inputSchema: ghReleaseDeliverSchema,
105
+ outputSchema: ghReleaseDeliverOutputSchema,
106
+ handler: ghReleaseDeliver,
107
+ }
@@ -1 +1 @@
1
- export { ghReleaseDeliver } from './gh-release-deliver'
1
+ export { ghReleaseDeliver, ghReleaseDeliverMcpTool } from './gh-release-deliver'
@@ -1,10 +1,12 @@
1
- /* eslint-disable no-console */
2
1
  import select from '@inquirer/select'
3
2
  import process from 'node:process'
3
+ import { z } from 'zod'
4
4
  import { $ } from 'zx'
5
5
 
6
6
  import { ENVs } from 'src/shared/constants'
7
7
  import { getReleasePRs } from 'src/shared/gh-release-prs'
8
+ import { logger } from 'src/shared/logger'
9
+ import type { ToolsExecutionResult } from 'src/types'
8
10
 
9
11
  interface GhReleaseDeployArgs {
10
12
  version: string
@@ -14,7 +16,7 @@ interface GhReleaseDeployArgs {
14
16
  /**
15
17
  * Deploy a release branch to an environment
16
18
  */
17
- export const ghReleaseDeploy = async (args: GhReleaseDeployArgs): Promise<void> => {
19
+ export const ghReleaseDeploy = async (args: GhReleaseDeployArgs): Promise<ToolsExecutionResult> => {
18
20
  const { version, env } = args
19
21
 
20
22
  // TODO: add validation for semver version for version variable
@@ -41,7 +43,7 @@ export const ghReleaseDeploy = async (args: GhReleaseDeployArgs): Promise<void>
41
43
 
42
44
  // Check if release branch exists in the list
43
45
  if (!releasePRsList.includes(selectedReleaseBranch)) {
44
- console.error(`❌ Release branch ${selectedReleaseBranch} not found in open PRs. Exiting...`)
46
+ logger.error(`❌ Release branch ${selectedReleaseBranch} not found in open PRs. Exiting...`)
45
47
  process.exit(1)
46
48
  }
47
49
 
@@ -60,19 +62,57 @@ export const ghReleaseDeploy = async (args: GhReleaseDeployArgs): Promise<void>
60
62
  }
61
63
 
62
64
  if (!ENVs.includes(selectedEnv)) {
63
- console.error(`❌ Invalid environment: ${selectedEnv}. Exiting...`)
65
+ logger.error(`❌ Invalid environment: ${selectedEnv}. Exiting...`)
64
66
  process.exit(1)
65
67
  }
66
68
 
67
69
  try {
68
70
  await $`gh workflow run deploy-all.yml --ref ${selectedReleaseBranch} -f environment=${selectedEnv}`
69
71
 
70
- console.log('\n')
71
- console.log(
72
+ logger.info('\n')
73
+ logger.info(
72
74
  `✅ Successfully launched deploy-all workflow_dispatch for release branch: ${selectedReleaseBranch} and environment: ${selectedEnv}`,
73
75
  )
76
+
77
+ const structuredContent = {
78
+ releaseBranch: selectedReleaseBranch,
79
+ version: selectedReleaseBranch.replace('release/v', ''),
80
+ environment: selectedEnv,
81
+ success: true,
82
+ }
83
+
84
+ return {
85
+ content: [
86
+ {
87
+ type: 'text',
88
+ text: JSON.stringify(structuredContent, null, 2),
89
+ },
90
+ ],
91
+ structuredContent,
92
+ }
74
93
  } catch (error: unknown) {
75
- console.error('❌ Error launching workflow:', error instanceof Error ? error.message : 'Unknown error')
94
+ logger.error({ error }, '❌ Error launching workflow')
76
95
  process.exit(1)
77
96
  }
78
97
  }
98
+
99
+ // MCP Tool Registration
100
+ const ghReleaseDeploySchema = z.object({
101
+ version: z.string().describe('Version to deploy (e.g., "1.2.5")'),
102
+ env: z.string().describe('Environment to deploy to (e.g., "dev", "renana", "oriana")'),
103
+ })
104
+
105
+ const ghReleaseDeployOutputSchema = z.object({
106
+ releaseBranch: z.string().describe('The release branch that was deployed'),
107
+ version: z.string().describe('The version that was deployed'),
108
+ environment: z.string().describe('The environment deployed to'),
109
+ success: z.boolean().describe('Whether the deployment was successful'),
110
+ })
111
+
112
+ export const ghReleaseDeployMcpTool = {
113
+ name: 'gh-release-deploy',
114
+ description: 'Deploy a release branch to a specified environment',
115
+ inputSchema: ghReleaseDeploySchema,
116
+ outputSchema: ghReleaseDeployOutputSchema,
117
+ handler: ghReleaseDeploy,
118
+ }
@@ -1 +1 @@
1
- export { ghReleaseDeploy } from './gh-release-deploy'
1
+ export { ghReleaseDeploy, ghReleaseDeployMcpTool } from './gh-release-deploy'
@@ -1,18 +1,50 @@
1
- /* eslint-disable no-console */
1
+ import { z } from 'zod'
2
+
2
3
  import { getReleasePRs } from 'src/shared/gh-release-prs'
4
+ import { logger } from 'src/shared/logger'
3
5
  import { sortVersions } from 'src/shared/version-utils'
6
+ import type { ToolsExecutionResult } from 'src/types'
4
7
 
5
8
  /**
6
9
  * List all open release branches
7
10
  */
8
- export const ghReleaseList = async () => {
11
+ export const ghReleaseList = async (): Promise<ToolsExecutionResult> => {
9
12
  const releasePRs = await getReleasePRs()
10
13
 
11
14
  const releasePRsList = releasePRs.map((pr) => pr.replace('release/', ''))
12
15
  const sortedReleases = sortVersions(releasePRsList)
13
16
 
14
- console.log('All release branches: \n')
15
- console.log(sortedReleases.join('\n'))
17
+ logger.info('All release branches: \n')
18
+ logger.info(sortedReleases.join('\n'))
19
+
20
+ const structuredContent = {
21
+ releases: sortedReleases,
22
+ count: sortedReleases.length,
23
+ }
24
+
25
+ return {
26
+ content: [
27
+ {
28
+ type: 'text',
29
+ text: JSON.stringify(structuredContent, null, 2),
30
+ },
31
+ ],
32
+ structuredContent,
33
+ }
34
+ }
35
+
36
+ // MCP Tool Registration
37
+ const ghReleaseListSchema = z.object({})
38
+
39
+ const ghReleaseListOutputSchema = z.object({
40
+ releases: z.array(z.string()).describe('List of all release branches'),
41
+ count: z.number().describe('Number of release branches'),
42
+ })
16
43
 
17
- return sortedReleases
44
+ export const ghReleaseListMcpTool = {
45
+ name: 'gh-release-list',
46
+ description: 'List all open release branches',
47
+ inputSchema: ghReleaseListSchema,
48
+ outputSchema: ghReleaseListOutputSchema,
49
+ handler: ghReleaseList,
18
50
  }
@@ -1 +1 @@
1
- export { ghReleaseList } from './gh-release-list'
1
+ export { ghReleaseList, ghReleaseListMcpTool } from './gh-release-list'
@@ -1 +1 @@
1
- export { worktreesAdd } from './worktrees-add'
1
+ export { worktreesAdd, worktreesAddMcpTool } from './worktrees-add'
@@ -1,33 +1,30 @@
1
- /* eslint-disable no-console */
2
1
  import checkbox from '@inquirer/checkbox'
3
2
  import confirm from '@inquirer/confirm'
4
3
  import process from 'node:process'
4
+ import { z } from 'zod'
5
5
  import { $ } from 'zx'
6
6
 
7
7
  import { WORKTREES_DIR_SUFFIX } from 'src/shared/constants'
8
8
  import { getReleasePRs } from 'src/shared/gh-release-prs'
9
9
  import { getCurrentWorktrees, getProjectRoot } from 'src/shared/git-utils'
10
+ import { logger } from 'src/shared/logger'
11
+ import type { RequiredConfirmedOptionArg, ToolsExecutionResult } from 'src/types'
10
12
 
11
13
  // Constants
12
14
  const FEATURE_DIR = 'feature'
13
15
  const RELEASE_DIR = 'release'
14
16
  const RELEASE_BRANCH_PREFIX = 'release/v'
15
17
 
16
- interface WorktreeManagementArgs {
17
- yes: boolean
18
+ interface WorktreeManagementArgs extends RequiredConfirmedOptionArg {
18
19
  all: boolean
19
20
  }
20
21
 
21
- interface WorktreeManagementResult {
22
- created: string[]
23
- }
24
-
25
22
  /**
26
23
  * Manage git worktrees for release branches
27
24
  * Creates worktrees for active release branches and removes unused ones
28
25
  */
29
- export const worktreesAdd = async (options: WorktreeManagementArgs): Promise<WorktreeManagementResult> => {
30
- const { yes, all } = options
26
+ export const worktreesAdd = async (options: WorktreeManagementArgs): Promise<ToolsExecutionResult> => {
27
+ const { confirmedCommand, all } = options
31
28
 
32
29
  try {
33
30
  const currentWorktrees = await getCurrentWorktrees('release')
@@ -55,14 +52,14 @@ export const worktreesAdd = async (options: WorktreeManagementArgs): Promise<Wor
55
52
  }
56
53
 
57
54
  // Ask for confirmation
58
- const answer = yes
55
+ const answer = confirmedCommand
59
56
  ? true
60
57
  : await confirm({
61
58
  message: 'Are you sure you want to proceed with these worktree changes?',
62
59
  })
63
60
 
64
61
  if (!answer) {
65
- console.log('Operation cancelled. Exiting...')
62
+ logger.info('Operation cancelled. Exiting...')
66
63
  process.exit(0)
67
64
  }
68
65
 
@@ -75,11 +72,22 @@ export const worktreesAdd = async (options: WorktreeManagementArgs): Promise<Wor
75
72
 
76
73
  logResults(createdWorktrees)
77
74
 
75
+ const structuredContent = {
76
+ createdWorktrees,
77
+ count: createdWorktrees.length,
78
+ }
79
+
78
80
  return {
79
- created: createdWorktrees,
81
+ content: [
82
+ {
83
+ type: 'text',
84
+ text: JSON.stringify(structuredContent, null, 2),
85
+ },
86
+ ],
87
+ structuredContent,
80
88
  }
81
89
  } catch (error) {
82
- console.error('❌ Error managing worktrees:', error)
90
+ logger.error({ error }, '❌ Error managing worktrees')
83
91
  throw error
84
92
  }
85
93
  }
@@ -123,7 +131,7 @@ const createWorktrees = async (branches: string[], worktreeDir: string): Promise
123
131
 
124
132
  created.push(branch)
125
133
  } catch (error) {
126
- console.error(`❌ Failed to create worktree for ${branch}:`, error)
134
+ logger.error({ error, branch }, `❌ Failed to create worktree for ${branch}`)
127
135
  }
128
136
  }
129
137
 
@@ -135,11 +143,29 @@ const createWorktrees = async (branches: string[], worktreeDir: string): Promise
135
143
  */
136
144
  const logResults = (created: string[]): void => {
137
145
  if (created.length > 0) {
138
- console.log('\n')
139
- console.log('✅ Created worktrees:')
140
- console.log(created.join('\n'))
141
- console.log()
146
+ logger.info('\n')
147
+ logger.info('✅ Created worktrees:')
148
+ logger.info(created.join('\n'))
149
+ logger.info('')
142
150
  } else {
143
- console.log('ℹ️ No new worktrees to create')
151
+ logger.info('ℹ️ No new worktrees to create')
144
152
  }
145
153
  }
154
+
155
+ // MCP Tool Registration
156
+ const worktreesAddSchema = z.object({
157
+ all: z.boolean().describe('Add worktrees for all release branches without prompting'),
158
+ })
159
+
160
+ const worktreesAddOutputSchema = z.object({
161
+ createdWorktrees: z.array(z.string()).describe('List of created worktree branches'),
162
+ count: z.number().describe('Number of worktrees created'),
163
+ })
164
+
165
+ export const worktreesAddMcpTool = {
166
+ name: 'worktrees-add',
167
+ description: 'Create worktrees for selected release branches',
168
+ inputSchema: worktreesAddSchema,
169
+ outputSchema: worktreesAddOutputSchema,
170
+ handler: worktreesAdd,
171
+ }
@@ -1 +1 @@
1
- export { worktreesList } from './worktrees-list'
1
+ export { worktreesList, worktreesListMcpTool } from './worktrees-list'
@@ -1,7 +1,9 @@
1
- /* eslint-disable no-console */
1
+ import { z } from 'zod'
2
2
  import { $ } from 'zx'
3
3
 
4
4
  import { getCurrentWorktrees, getProjectRoot } from 'src/shared/git-utils'
5
+ import { logger } from 'src/shared/logger'
6
+ import type { ToolsExecutionResult } from 'src/types'
5
7
 
6
8
  interface WorktreeInfo {
7
9
  branch: string
@@ -14,17 +16,10 @@ interface WorktreeInfo {
14
16
  aheadBehind: string
15
17
  }
16
18
 
17
- interface WorktreesListResult {
18
- worktrees: WorktreeInfo[]
19
- total: number
20
- releases: number
21
- features: number
22
- }
23
-
24
19
  /**
25
20
  * List all (features and releases) git worktrees with detailed information
26
21
  */
27
- export const worktreesList = async (): Promise<WorktreesListResult> => {
22
+ export const worktreesList = async (): Promise<ToolsExecutionResult> => {
28
23
  try {
29
24
  const [releaseWorktrees, featureWorktrees] = await Promise.all([
30
25
  getCurrentWorktrees('release'),
@@ -36,14 +31,24 @@ export const worktreesList = async (): Promise<WorktreesListResult> => {
36
31
 
37
32
  logResults(worktreesInfo)
38
33
 
39
- return {
34
+ const structuredContent = {
40
35
  worktrees: worktreesInfo,
41
- total: worktreesInfo.length,
42
- releases: releaseWorktrees.length,
43
- features: featureWorktrees.length,
36
+ totalCount: worktreesInfo.length,
37
+ releaseCount: releaseWorktrees.length,
38
+ featureCount: featureWorktrees.length,
39
+ }
40
+
41
+ return {
42
+ content: [
43
+ {
44
+ type: 'text',
45
+ text: JSON.stringify(structuredContent, null, 2),
46
+ },
47
+ ],
48
+ structuredContent,
44
49
  }
45
50
  } catch (error) {
46
- console.error('❌ Error listing worktrees:', error)
51
+ logger.error({ error }, '❌ Error listing worktrees')
47
52
  throw error
48
53
  }
49
54
  }
@@ -83,7 +88,7 @@ const processWorktrees = async (
83
88
  aheadBehind,
84
89
  })
85
90
  } catch (error) {
86
- console.warn(`⚠️ Could not process worktree ${branch}:`, error)
91
+ logger.warn({ error, branch }, `⚠️ Could not process worktree ${branch}`)
87
92
  }
88
93
  }
89
94
 
@@ -176,15 +181,15 @@ const getAheadBehind = async (worktreePath: string): Promise<string> => {
176
181
  */
177
182
  const logResults = (worktrees: WorktreeInfo[]): void => {
178
183
  if (worktrees.length === 0) {
179
- console.log('\n🌿 Git Worktrees')
180
- console.log('─'.repeat(80))
181
- console.log('ℹ️ No worktrees found')
182
- console.log('─'.repeat(80))
184
+ logger.info('\n🌿 Git Worktrees')
185
+ logger.info('─'.repeat(80))
186
+ logger.info('ℹ️ No worktrees found')
187
+ logger.info('─'.repeat(80))
183
188
  return
184
189
  }
185
190
 
186
- console.log('\n🌿 Git Worktrees')
187
- console.log('═'.repeat(100))
191
+ logger.info('\n🌿 Git Worktrees')
192
+ logger.info('═'.repeat(100))
188
193
 
189
194
  // Separate releases and features
190
195
  const releases = worktrees.filter((w) => w.type === 'release')
@@ -195,23 +200,23 @@ const logResults = (worktrees: WorktreeInfo[]): void => {
195
200
 
196
201
  // Display features second
197
202
  if (features.length > 0 && releases.length > 0) {
198
- console.log('')
203
+ logger.info('')
199
204
  }
200
205
 
201
206
  displayWorktreeSection('✨ Features', features)
202
207
 
203
208
  // Summary
204
209
  const current = worktrees.find((w) => w.isCurrent)
205
- console.log(`\n${'═'.repeat(100)}`)
206
- console.log(
210
+ logger.info(`\n${'═'.repeat(100)}`)
211
+ logger.info(
207
212
  `📊 Summary: ${worktrees.length} total worktrees (${releases.length} releases, ${features.length} features)`,
208
213
  )
209
214
 
210
215
  if (current) {
211
- console.log(`📍 Currently on: ${current.branch}`)
216
+ logger.info(`📍 Currently on: ${current.branch}`)
212
217
  }
213
218
 
214
- console.log('')
219
+ logger.info('')
215
220
  }
216
221
 
217
222
  /**
@@ -220,14 +225,14 @@ const logResults = (worktrees: WorktreeInfo[]): void => {
220
225
  const displayWorktreeSection = (sectionTitle: string, worktrees: WorktreeInfo[]): void => {
221
226
  if (worktrees.length === 0) return
222
227
 
223
- console.log(`\n${sectionTitle}`)
224
- console.log('─'.repeat(50))
228
+ logger.info(`\n${sectionTitle}`)
229
+ logger.info('─'.repeat(50))
225
230
 
226
231
  for (const [index, worktree] of worktrees.entries()) {
227
232
  displayWorktree(worktree)
228
233
 
229
234
  if (index < worktrees.length - 1) {
230
- console.log('')
235
+ logger.info('')
231
236
  }
232
237
  }
233
238
  }
@@ -245,18 +250,18 @@ const displayWorktree = (worktree: WorktreeInfo): void => {
245
250
  // Branch name with color coding
246
251
  const branchDisplay = `${typeIcon} ${worktree.branch}`
247
252
 
248
- console.log(`${currentIndicator} ${statusIndicator} ${branchDisplay}`)
253
+ logger.info(`${currentIndicator} ${statusIndicator} ${branchDisplay}`)
249
254
 
250
255
  // Commit and sync info
251
256
  const syncInfo = worktree.aheadBehind !== 'unknown' ? ` | ${worktree.aheadBehind}` : ''
252
- console.log(` 📝 ${worktree.commit}${syncInfo}`)
257
+ logger.info(` 📝 ${worktree.commit}${syncInfo}`)
253
258
 
254
259
  // Last commit message
255
- console.log(` 💬 ${worktree.lastCommitMessage}`)
260
+ logger.info(` 💬 ${worktree.lastCommitMessage}`)
256
261
 
257
262
  // Path (shortened for display)
258
263
  const shortPath = worktree.path.split('/').slice(-2).join('/')
259
- console.log(` 📁 ${shortPath}`)
264
+ logger.info(` 📁 ${shortPath}`)
260
265
  }
261
266
 
262
267
  /**
@@ -274,3 +279,34 @@ const getStatusIndicator = (status: string): string => {
274
279
  return '❓'
275
280
  }
276
281
  }
282
+
283
+ // MCP Tool Registration
284
+ const worktreesListSchema = z.object({})
285
+
286
+ const worktreesListOutputSchema = z.object({
287
+ worktrees: z
288
+ .array(
289
+ z.object({
290
+ branch: z.string(),
291
+ path: z.string(),
292
+ commit: z.string(),
293
+ isCurrent: z.boolean(),
294
+ type: z.enum(['release', 'feature']),
295
+ status: z.string(),
296
+ lastCommitMessage: z.string(),
297
+ aheadBehind: z.string(),
298
+ }),
299
+ )
300
+ .describe('List of all worktrees with details'),
301
+ totalCount: z.number().describe('Total number of worktrees'),
302
+ releaseCount: z.number().describe('Number of release worktrees'),
303
+ featureCount: z.number().describe('Number of feature worktrees'),
304
+ })
305
+
306
+ export const worktreesListMcpTool = {
307
+ name: 'worktrees-list',
308
+ description: 'List all git worktrees with detailed information',
309
+ inputSchema: worktreesListSchema,
310
+ outputSchema: worktreesListOutputSchema,
311
+ handler: worktreesList,
312
+ }
@@ -1 +1 @@
1
- export { worktreesRemove } from './worktrees-remove'
1
+ export { worktreesRemove, worktreesRemoveMcpTool } from './worktrees-remove'