@azerate/claudette-mcp 1.4.0 → 1.6.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 +34 -8
- package/dist/index.js +291 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,6 +63,9 @@ Add to `~/.claude.json`:
|
|
|
63
63
|
| Tool | Description |
|
|
64
64
|
|------|-------------|
|
|
65
65
|
| `get_changes` | Get pending git changes (modified, added, deleted files) |
|
|
66
|
+
| `get_branch_info` | Get current branch, behind/ahead status, sync state |
|
|
67
|
+
| `create_branch` | Create a new feature branch from main/master |
|
|
68
|
+
| `sync_branch` | Rebase or merge current branch with main |
|
|
66
69
|
| `get_checkpoints` | List saved checkpoints (git stash snapshots) |
|
|
67
70
|
| `create_checkpoint` | Create a checkpoint before risky changes |
|
|
68
71
|
| `restore_checkpoint` | Restore workspace to a previous checkpoint |
|
|
@@ -77,6 +80,9 @@ Add to `~/.claude.json`:
|
|
|
77
80
|
| `generate_commit_message` | Generate a commit message from changes |
|
|
78
81
|
| `approve_commit` | Stage and commit with the provided message |
|
|
79
82
|
| `approve_push` | Push committed changes to remote |
|
|
83
|
+
| `approve_write_tests` | Mark the write tests step as complete |
|
|
84
|
+
| `create_pr` | Create a pull request using gh CLI |
|
|
85
|
+
| `approve_code_review` | Mark the code review step as complete |
|
|
80
86
|
|
|
81
87
|
### Project Memory
|
|
82
88
|
|
|
@@ -111,26 +117,46 @@ Add to `~/.claude.json`:
|
|
|
111
117
|
|
|
112
118
|
## Workflow Pipeline
|
|
113
119
|
|
|
114
|
-
The workflow feature provides a guided development process:
|
|
120
|
+
The workflow feature provides a 10-step guided development process with best-practice Git support:
|
|
115
121
|
|
|
116
122
|
```
|
|
117
123
|
trigger_workflow()
|
|
118
124
|
|
|
|
119
125
|
v
|
|
120
|
-
[AUTOMATIC]
|
|
121
|
-
1.
|
|
122
|
-
2.
|
|
126
|
+
[AUTOMATIC CHECKS]
|
|
127
|
+
1. Type checking (tsc --noEmit)
|
|
128
|
+
2. Lint/Format (eslint --fix)
|
|
123
129
|
3. Run tests
|
|
124
|
-
4. Coverage analysis
|
|
130
|
+
4. Coverage analysis (files needing tests)
|
|
125
131
|
5. Benchmarks (optional)
|
|
126
132
|
|
|
|
127
133
|
v
|
|
128
134
|
[HUMAN GATES]
|
|
129
|
-
6.
|
|
130
|
-
7.
|
|
131
|
-
8.
|
|
135
|
+
6. Write Tests (if coverage found gaps)
|
|
136
|
+
7. Commit (approve_commit)
|
|
137
|
+
8. Push (approve_push)
|
|
138
|
+
9. Create PR (skipped if on main)
|
|
139
|
+
10. Code Review (approve_code_review)
|
|
132
140
|
```
|
|
133
141
|
|
|
142
|
+
### Branch Management
|
|
143
|
+
|
|
144
|
+
Best practice: Work on feature branches, not directly on main.
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
# Check current branch status
|
|
148
|
+
get_branch_info(workspace_path="/path/to/project")
|
|
149
|
+
|
|
150
|
+
# Create a feature branch
|
|
151
|
+
create_branch(workspace_path="/path/to/project", branch_name="feature/my-feature")
|
|
152
|
+
|
|
153
|
+
# Sync with latest main (rebase)
|
|
154
|
+
sync_branch(workspace_path="/path/to/project", method="rebase")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The workflow enforces feature branch usage by default (`requireFeatureBranch: true`).
|
|
158
|
+
Toggle this in the UI or set in `.claudette/workflow-config.json`.
|
|
159
|
+
|
|
134
160
|
## Example Usage
|
|
135
161
|
|
|
136
162
|
```
|
package/dist/index.js
CHANGED
|
@@ -521,6 +521,119 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
521
521
|
required: ["workspace_path"],
|
|
522
522
|
},
|
|
523
523
|
},
|
|
524
|
+
{
|
|
525
|
+
name: "approve_write_tests",
|
|
526
|
+
description: "Mark the write tests step as complete after tests have been written for uncovered files.",
|
|
527
|
+
inputSchema: {
|
|
528
|
+
type: "object",
|
|
529
|
+
properties: {
|
|
530
|
+
workspace_path: {
|
|
531
|
+
type: "string",
|
|
532
|
+
description: "Path to the workspace directory",
|
|
533
|
+
},
|
|
534
|
+
tests_written: {
|
|
535
|
+
type: "number",
|
|
536
|
+
description: "Number of test files written",
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
required: ["workspace_path", "tests_written"],
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
name: "approve_code_review",
|
|
544
|
+
description: "Mark the code review step as complete after the PR has been reviewed and approved.",
|
|
545
|
+
inputSchema: {
|
|
546
|
+
type: "object",
|
|
547
|
+
properties: {
|
|
548
|
+
workspace_path: {
|
|
549
|
+
type: "string",
|
|
550
|
+
description: "Path to the workspace directory",
|
|
551
|
+
},
|
|
552
|
+
reviewer: {
|
|
553
|
+
type: "string",
|
|
554
|
+
description: "Name of the reviewer (optional)",
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
required: ["workspace_path"],
|
|
558
|
+
},
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
name: "create_pr",
|
|
562
|
+
description: "Create a pull request for the current branch. Uses gh CLI to create the PR and updates workflow status.",
|
|
563
|
+
inputSchema: {
|
|
564
|
+
type: "object",
|
|
565
|
+
properties: {
|
|
566
|
+
workspace_path: {
|
|
567
|
+
type: "string",
|
|
568
|
+
description: "Path to the workspace directory",
|
|
569
|
+
},
|
|
570
|
+
title: {
|
|
571
|
+
type: "string",
|
|
572
|
+
description: "PR title",
|
|
573
|
+
},
|
|
574
|
+
body: {
|
|
575
|
+
type: "string",
|
|
576
|
+
description: "PR description/body",
|
|
577
|
+
},
|
|
578
|
+
},
|
|
579
|
+
required: ["workspace_path", "title"],
|
|
580
|
+
},
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
name: "get_branch_info",
|
|
584
|
+
description: "Get current git branch information including branch name, whether it's main/master, and behind/ahead counts relative to origin and main branch.",
|
|
585
|
+
inputSchema: {
|
|
586
|
+
type: "object",
|
|
587
|
+
properties: {
|
|
588
|
+
workspace_path: {
|
|
589
|
+
type: "string",
|
|
590
|
+
description: "Path to the workspace directory",
|
|
591
|
+
},
|
|
592
|
+
fetch: {
|
|
593
|
+
type: "boolean",
|
|
594
|
+
description: "Whether to fetch from remote first (slower but more accurate). Default: false",
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
required: ["workspace_path"],
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
name: "create_branch",
|
|
602
|
+
description: "Create a new feature branch from main/master. Best practice: always create feature branches for new work instead of committing directly to main.",
|
|
603
|
+
inputSchema: {
|
|
604
|
+
type: "object",
|
|
605
|
+
properties: {
|
|
606
|
+
workspace_path: {
|
|
607
|
+
type: "string",
|
|
608
|
+
description: "Path to the workspace directory",
|
|
609
|
+
},
|
|
610
|
+
branch_name: {
|
|
611
|
+
type: "string",
|
|
612
|
+
description: "Name for the new branch (e.g., 'feature/add-login', 'fix/button-alignment')",
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
required: ["workspace_path", "branch_name"],
|
|
616
|
+
},
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
name: "sync_branch",
|
|
620
|
+
description: "Sync current branch with main/master by rebasing or merging. Use when your branch is behind main to incorporate latest changes.",
|
|
621
|
+
inputSchema: {
|
|
622
|
+
type: "object",
|
|
623
|
+
properties: {
|
|
624
|
+
workspace_path: {
|
|
625
|
+
type: "string",
|
|
626
|
+
description: "Path to the workspace directory",
|
|
627
|
+
},
|
|
628
|
+
method: {
|
|
629
|
+
type: "string",
|
|
630
|
+
enum: ["rebase", "merge"],
|
|
631
|
+
description: "Sync method: 'rebase' (cleaner history, default) or 'merge' (preserves branch history)",
|
|
632
|
+
},
|
|
633
|
+
},
|
|
634
|
+
required: ["workspace_path"],
|
|
635
|
+
},
|
|
636
|
+
},
|
|
524
637
|
],
|
|
525
638
|
};
|
|
526
639
|
});
|
|
@@ -1341,6 +1454,184 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1341
1454
|
return { content: [{ type: "text", text: `Error pushing changes: ${err.message}` }] };
|
|
1342
1455
|
}
|
|
1343
1456
|
}
|
|
1457
|
+
case "approve_write_tests": {
|
|
1458
|
+
const workspacePath = args?.workspace_path;
|
|
1459
|
+
const testsWritten = args?.tests_written;
|
|
1460
|
+
if (!workspacePath) {
|
|
1461
|
+
return { content: [{ type: "text", text: "Error: workspace_path is required" }] };
|
|
1462
|
+
}
|
|
1463
|
+
if (testsWritten === undefined) {
|
|
1464
|
+
return { content: [{ type: "text", text: "Error: tests_written is required" }] };
|
|
1465
|
+
}
|
|
1466
|
+
try {
|
|
1467
|
+
const response = await fetch(`${CLAUDETTE_API}/api/workflow/write-tests`, {
|
|
1468
|
+
method: "POST",
|
|
1469
|
+
headers: { "Content-Type": "application/json" },
|
|
1470
|
+
body: JSON.stringify({ path: workspacePath, testsWritten }),
|
|
1471
|
+
});
|
|
1472
|
+
const result = await response.json();
|
|
1473
|
+
if (result.status === 'passed') {
|
|
1474
|
+
return { content: [{ type: "text", text: `✅ Write tests step complete!\n\nTests written: ${result.testsWritten}\n\nWorkflow advanced to commit stage.` }] };
|
|
1475
|
+
}
|
|
1476
|
+
else {
|
|
1477
|
+
return { content: [{ type: "text", text: `❌ Failed: ${result.error}` }] };
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
catch (err) {
|
|
1481
|
+
return { content: [{ type: "text", text: `Error: ${err.message}` }] };
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
case "approve_code_review": {
|
|
1485
|
+
const workspacePath = args?.workspace_path;
|
|
1486
|
+
const reviewer = args?.reviewer;
|
|
1487
|
+
if (!workspacePath) {
|
|
1488
|
+
return { content: [{ type: "text", text: "Error: workspace_path is required" }] };
|
|
1489
|
+
}
|
|
1490
|
+
try {
|
|
1491
|
+
const response = await fetch(`${CLAUDETTE_API}/api/workflow/code-review`, {
|
|
1492
|
+
method: "POST",
|
|
1493
|
+
headers: { "Content-Type": "application/json" },
|
|
1494
|
+
body: JSON.stringify({ path: workspacePath, reviewer }),
|
|
1495
|
+
});
|
|
1496
|
+
const result = await response.json();
|
|
1497
|
+
if (result.status === 'passed') {
|
|
1498
|
+
return { content: [{ type: "text", text: `✅ Code review approved!\n\n${result.reviewer ? `Reviewer: ${result.reviewer}\n` : ''}Workflow complete.` }] };
|
|
1499
|
+
}
|
|
1500
|
+
else {
|
|
1501
|
+
return { content: [{ type: "text", text: `❌ Failed: ${result.error}` }] };
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
catch (err) {
|
|
1505
|
+
return { content: [{ type: "text", text: `Error: ${err.message}` }] };
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
case "create_pr": {
|
|
1509
|
+
const workspacePath = args?.workspace_path;
|
|
1510
|
+
const title = args?.title;
|
|
1511
|
+
const body = args?.body ?? '';
|
|
1512
|
+
if (!workspacePath) {
|
|
1513
|
+
return { content: [{ type: "text", text: "Error: workspace_path is required" }] };
|
|
1514
|
+
}
|
|
1515
|
+
if (!title) {
|
|
1516
|
+
return { content: [{ type: "text", text: "Error: title is required" }] };
|
|
1517
|
+
}
|
|
1518
|
+
try {
|
|
1519
|
+
const response = await fetch(`${CLAUDETTE_API}/api/workflow/pr`, {
|
|
1520
|
+
method: "POST",
|
|
1521
|
+
headers: { "Content-Type": "application/json" },
|
|
1522
|
+
body: JSON.stringify({ path: workspacePath, title, body }),
|
|
1523
|
+
});
|
|
1524
|
+
const result = await response.json();
|
|
1525
|
+
if (result.status === 'passed' || result.url) {
|
|
1526
|
+
return { content: [{ type: "text", text: `✅ Pull Request created!\n\nURL: ${result.url}\nPR #${result.prNumber}\n\nWorkflow advanced to code review.` }] };
|
|
1527
|
+
}
|
|
1528
|
+
else {
|
|
1529
|
+
return { content: [{ type: "text", text: `❌ Failed to create PR: ${result.error}` }] };
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
catch (err) {
|
|
1533
|
+
return { content: [{ type: "text", text: `Error: ${err.message}` }] };
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
case "get_branch_info": {
|
|
1537
|
+
const workspacePath = args?.workspace_path;
|
|
1538
|
+
const doFetch = args?.fetch ?? false;
|
|
1539
|
+
if (!workspacePath) {
|
|
1540
|
+
return { content: [{ type: "text", text: "Error: workspace_path is required" }] };
|
|
1541
|
+
}
|
|
1542
|
+
try {
|
|
1543
|
+
const response = await fetch(`${CLAUDETTE_API}/api/workflow/branch?path=${encodeURIComponent(workspacePath)}&fetch=${doFetch}`);
|
|
1544
|
+
const info = await response.json();
|
|
1545
|
+
let output = `Branch Info\n${'='.repeat(50)}\n\n`;
|
|
1546
|
+
output += `Current Branch: ${info.current}\n`;
|
|
1547
|
+
output += `Is Main/Master: ${info.isMain ? 'Yes' : 'No'}\n`;
|
|
1548
|
+
output += `Main Branch: ${info.mainBranch}\n`;
|
|
1549
|
+
output += `Has Remote Tracking: ${info.hasRemote ? 'Yes' : 'No'}\n`;
|
|
1550
|
+
if (!info.isMain) {
|
|
1551
|
+
output += `\nSync Status:\n`;
|
|
1552
|
+
output += `────────────────────────────────────────\n`;
|
|
1553
|
+
if (info.behindMain > 0) {
|
|
1554
|
+
output += `⚠️ Behind ${info.mainBranch}: ${info.behindMain} commit(s)\n`;
|
|
1555
|
+
output += ` Run sync_branch to update\n`;
|
|
1556
|
+
}
|
|
1557
|
+
else {
|
|
1558
|
+
output += `✅ Up to date with ${info.mainBranch}\n`;
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
if (info.hasRemote) {
|
|
1562
|
+
output += `\nRemote Status:\n`;
|
|
1563
|
+
output += `────────────────────────────────────────\n`;
|
|
1564
|
+
if (info.behindRemote > 0) {
|
|
1565
|
+
output += `⚠️ Behind origin: ${info.behindRemote} commit(s) - pull needed\n`;
|
|
1566
|
+
}
|
|
1567
|
+
if (info.aheadRemote > 0) {
|
|
1568
|
+
output += `📤 Ahead of origin: ${info.aheadRemote} commit(s) - push needed\n`;
|
|
1569
|
+
}
|
|
1570
|
+
if (info.behindRemote === 0 && info.aheadRemote === 0) {
|
|
1571
|
+
output += `✅ In sync with origin\n`;
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
if (info.isMain) {
|
|
1575
|
+
output += `\n⚠️ Best Practice: Create a feature branch instead of committing to ${info.mainBranch}\n`;
|
|
1576
|
+
output += ` Use create_branch to start a new feature branch\n`;
|
|
1577
|
+
}
|
|
1578
|
+
return { content: [{ type: "text", text: output }] };
|
|
1579
|
+
}
|
|
1580
|
+
catch (err) {
|
|
1581
|
+
return { content: [{ type: "text", text: `Error: ${err.message}` }] };
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
case "create_branch": {
|
|
1585
|
+
const workspacePath = args?.workspace_path;
|
|
1586
|
+
const branchName = args?.branch_name;
|
|
1587
|
+
if (!workspacePath) {
|
|
1588
|
+
return { content: [{ type: "text", text: "Error: workspace_path is required" }] };
|
|
1589
|
+
}
|
|
1590
|
+
if (!branchName) {
|
|
1591
|
+
return { content: [{ type: "text", text: "Error: branch_name is required" }] };
|
|
1592
|
+
}
|
|
1593
|
+
try {
|
|
1594
|
+
const response = await fetch(`${CLAUDETTE_API}/api/workflow/branch`, {
|
|
1595
|
+
method: "POST",
|
|
1596
|
+
headers: { "Content-Type": "application/json" },
|
|
1597
|
+
body: JSON.stringify({ path: workspacePath, name: branchName }),
|
|
1598
|
+
});
|
|
1599
|
+
const result = await response.json();
|
|
1600
|
+
if (result.success) {
|
|
1601
|
+
return { content: [{ type: "text", text: `✅ Created and switched to branch: ${result.branch}\n\nYou can now make changes and commit to this branch.` }] };
|
|
1602
|
+
}
|
|
1603
|
+
else {
|
|
1604
|
+
return { content: [{ type: "text", text: `❌ Failed to create branch: ${result.error}` }] };
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
catch (err) {
|
|
1608
|
+
return { content: [{ type: "text", text: `Error: ${err.message}` }] };
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
case "sync_branch": {
|
|
1612
|
+
const workspacePath = args?.workspace_path;
|
|
1613
|
+
const method = args?.method ?? 'rebase';
|
|
1614
|
+
if (!workspacePath) {
|
|
1615
|
+
return { content: [{ type: "text", text: "Error: workspace_path is required" }] };
|
|
1616
|
+
}
|
|
1617
|
+
try {
|
|
1618
|
+
const response = await fetch(`${CLAUDETTE_API}/api/workflow/sync`, {
|
|
1619
|
+
method: "POST",
|
|
1620
|
+
headers: { "Content-Type": "application/json" },
|
|
1621
|
+
body: JSON.stringify({ path: workspacePath, method }),
|
|
1622
|
+
});
|
|
1623
|
+
const result = await response.json();
|
|
1624
|
+
if (result.success) {
|
|
1625
|
+
return { content: [{ type: "text", text: `✅ Branch synced successfully using ${method}!\n\nYour branch is now up to date with main.` }] };
|
|
1626
|
+
}
|
|
1627
|
+
else {
|
|
1628
|
+
return { content: [{ type: "text", text: `❌ Sync failed: ${result.error}` }] };
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
catch (err) {
|
|
1632
|
+
return { content: [{ type: "text", text: `Error: ${err.message}` }] };
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1344
1635
|
default:
|
|
1345
1636
|
return { content: [{ type: "text", text: `Unknown tool: ${name}` }] };
|
|
1346
1637
|
}
|
package/package.json
CHANGED