trabuco-mcp 1.5.4
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 +100 -0
- package/install.js +131 -0
- package/package.json +46 -0
- package/run.js +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# trabuco-mcp
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for [Trabuco](https://github.com/arianlopezc/Trabuco) — generate and manage production-ready Java multi-module Maven projects via AI coding agents.
|
|
4
|
+
|
|
5
|
+
## Quick Setup
|
|
6
|
+
|
|
7
|
+
### Claude Code
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
claude mcp add trabuco -- npx -y trabuco-mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or add to `.mcp.json` in your project root:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"trabuco": {
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["-y", "trabuco-mcp"]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Cursor
|
|
27
|
+
|
|
28
|
+
Add to `.cursor/mcp.json`:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"trabuco": {
|
|
34
|
+
"command": "npx",
|
|
35
|
+
"args": ["-y", "trabuco-mcp"]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### VS Code / GitHub Copilot
|
|
42
|
+
|
|
43
|
+
Add to `.vscode/mcp.json`:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"servers": {
|
|
48
|
+
"trabuco": {
|
|
49
|
+
"command": "npx",
|
|
50
|
+
"args": ["-y", "trabuco-mcp"]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Windsurf
|
|
57
|
+
|
|
58
|
+
Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"mcpServers": {
|
|
63
|
+
"trabuco": {
|
|
64
|
+
"command": "npx",
|
|
65
|
+
"args": ["-y", "trabuco-mcp"]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Available Tools
|
|
72
|
+
|
|
73
|
+
| Tool | Description |
|
|
74
|
+
|------|-------------|
|
|
75
|
+
| `init_project` | Generate a new Java project with specified modules, database, and options |
|
|
76
|
+
| `add_module` | Add a module to an existing Trabuco project (with dry-run support) |
|
|
77
|
+
| `run_doctor` | Run health checks on a project and optionally auto-fix issues |
|
|
78
|
+
| `get_project_info` | Read project metadata from `.trabuco.json` or inferred from POM |
|
|
79
|
+
| `list_modules` | List all available modules with descriptions and dependency info |
|
|
80
|
+
| `check_docker` | Check if Docker is installed and running |
|
|
81
|
+
| `get_version` | Get the Trabuco CLI version |
|
|
82
|
+
| `scan_project` | Analyze a legacy Java project's structure and dependencies |
|
|
83
|
+
| `migrate_project` | Full AI-powered migration of a legacy project |
|
|
84
|
+
| `auth_status` | Check which AI providers have credentials configured |
|
|
85
|
+
| `list_providers` | List supported AI providers with pricing and model info |
|
|
86
|
+
|
|
87
|
+
## How It Works
|
|
88
|
+
|
|
89
|
+
This package wraps the [Trabuco CLI](https://github.com/arianlopezc/Trabuco). On install, it downloads the correct Go binary for your platform. The `trabuco-mcp` command starts the MCP server over stdio — your AI agent handles the rest.
|
|
90
|
+
|
|
91
|
+
## Requirements
|
|
92
|
+
|
|
93
|
+
- **Node.js 16+** (for npx/npm)
|
|
94
|
+
- **Java 17+** (for generated projects)
|
|
95
|
+
- **Maven 3.8+** (for generated projects)
|
|
96
|
+
- **Docker** (for Testcontainers and local development)
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
package/install.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { execFileSync } = require("child_process");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const https = require("https");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
|
|
9
|
+
const VERSION = require("./package.json").version;
|
|
10
|
+
const MAX_REDIRECTS = 5;
|
|
11
|
+
const MAX_RETRIES = 3;
|
|
12
|
+
const RETRY_BASE_MS = 1000;
|
|
13
|
+
|
|
14
|
+
const PLATFORM_MAP = { darwin: "darwin", linux: "linux", win32: "windows" };
|
|
15
|
+
const ARCH_MAP = { x64: "amd64", arm64: "arm64" };
|
|
16
|
+
|
|
17
|
+
function getBinaryName() {
|
|
18
|
+
const os = PLATFORM_MAP[process.platform];
|
|
19
|
+
const arch = ARCH_MAP[process.arch];
|
|
20
|
+
if (!os || !arch) {
|
|
21
|
+
console.error(
|
|
22
|
+
`Unsupported platform: ${process.platform}-${process.arch}\n` +
|
|
23
|
+
"Supported: darwin-x64, darwin-arm64, linux-x64, linux-arm64, win32-x64, win32-arm64"
|
|
24
|
+
);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
28
|
+
return { remote: `trabuco-${os}-${arch}${ext}`, local: `trabuco${ext}` };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getBinDir() {
|
|
32
|
+
const dir = path.join(__dirname, "bin");
|
|
33
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
34
|
+
return dir;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function versionMatches(binaryPath) {
|
|
38
|
+
try {
|
|
39
|
+
const out = execFileSync(binaryPath, ["version"], {
|
|
40
|
+
encoding: "utf8",
|
|
41
|
+
timeout: 5000,
|
|
42
|
+
}).trim();
|
|
43
|
+
// Output may be "trabuco version v1.5.3" or just "v1.5.3"
|
|
44
|
+
return out.includes(VERSION) || out.includes(`v${VERSION}`);
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function download(url, dest) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
followRedirects(url, 0, (err, res) => {
|
|
53
|
+
if (err) return reject(err);
|
|
54
|
+
if (res.statusCode !== 200) {
|
|
55
|
+
res.resume();
|
|
56
|
+
return reject(new Error(`HTTP ${res.statusCode} from ${url}`));
|
|
57
|
+
}
|
|
58
|
+
const file = fs.createWriteStream(dest);
|
|
59
|
+
res.pipe(file);
|
|
60
|
+
file.on("finish", () => file.close(resolve));
|
|
61
|
+
file.on("error", (e) => {
|
|
62
|
+
fs.unlink(dest, () => {});
|
|
63
|
+
reject(e);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function followRedirects(url, hops, cb) {
|
|
70
|
+
if (hops >= MAX_REDIRECTS) return cb(new Error("Too many redirects"));
|
|
71
|
+
const get = url.startsWith("https://") ? https.get : require("http").get;
|
|
72
|
+
get(url, (res) => {
|
|
73
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
74
|
+
res.resume();
|
|
75
|
+
return followRedirects(res.headers.location, hops + 1, cb);
|
|
76
|
+
}
|
|
77
|
+
cb(null, res);
|
|
78
|
+
}).on("error", cb);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function downloadWithRetry(url, dest) {
|
|
82
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
83
|
+
try {
|
|
84
|
+
await download(url, dest);
|
|
85
|
+
return;
|
|
86
|
+
} catch (err) {
|
|
87
|
+
if (attempt === MAX_RETRIES) throw err;
|
|
88
|
+
const delay = RETRY_BASE_MS * Math.pow(2, attempt - 1);
|
|
89
|
+
console.log(
|
|
90
|
+
`Download attempt ${attempt}/${MAX_RETRIES} failed: ${err.message}. Retrying in ${delay}ms...`
|
|
91
|
+
);
|
|
92
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function main() {
|
|
98
|
+
const { remote, local } = getBinaryName();
|
|
99
|
+
const binDir = getBinDir();
|
|
100
|
+
const binaryPath = path.join(binDir, local);
|
|
101
|
+
|
|
102
|
+
// Skip download if binary exists and version matches
|
|
103
|
+
if (fs.existsSync(binaryPath) && versionMatches(binaryPath)) {
|
|
104
|
+
console.log(`trabuco v${VERSION} already installed.`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const url = `https://github.com/arianlopezc/Trabuco/releases/download/v${VERSION}/${remote}`;
|
|
109
|
+
console.log(`Downloading trabuco v${VERSION} for ${process.platform}-${process.arch}...`);
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
await downloadWithRetry(url, binaryPath);
|
|
113
|
+
} catch (err) {
|
|
114
|
+
console.error(
|
|
115
|
+
`Failed to download trabuco binary.\n` +
|
|
116
|
+
` URL: ${url}\n` +
|
|
117
|
+
` Error: ${err.message}\n\n` +
|
|
118
|
+
`You can install the CLI manually:\n` +
|
|
119
|
+
` curl -sSL https://raw.githubusercontent.com/arianlopezc/Trabuco/main/scripts/install.sh | bash`
|
|
120
|
+
);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (process.platform !== "win32") {
|
|
125
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log(`trabuco v${VERSION} installed successfully.`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "trabuco-mcp",
|
|
3
|
+
"version": "1.5.4",
|
|
4
|
+
"description": "Generate production-ready Java projects via AI coding agents — MCP server for Trabuco CLI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/arianlopezc/Trabuco.git",
|
|
9
|
+
"directory": "npm"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/arianlopezc/Trabuco#cli-mcp-server",
|
|
12
|
+
"bugs": "https://github.com/arianlopezc/Trabuco/issues",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"model-context-protocol",
|
|
16
|
+
"java",
|
|
17
|
+
"maven",
|
|
18
|
+
"spring-boot",
|
|
19
|
+
"code-generation",
|
|
20
|
+
"ai",
|
|
21
|
+
"trabuco"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"trabuco-mcp": "./run.js"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"postinstall": "node install.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"install.js",
|
|
31
|
+
"run.js",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"os": [
|
|
35
|
+
"darwin",
|
|
36
|
+
"linux",
|
|
37
|
+
"win32"
|
|
38
|
+
],
|
|
39
|
+
"cpu": [
|
|
40
|
+
"x64",
|
|
41
|
+
"arm64"
|
|
42
|
+
],
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=16"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/run.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { spawn } = require("child_process");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
|
|
7
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
8
|
+
const binaryPath = path.join(__dirname, "bin", `trabuco${ext}`);
|
|
9
|
+
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
if (!fs.existsSync(binaryPath)) {
|
|
12
|
+
console.error(
|
|
13
|
+
"trabuco binary not found. This usually means npm was run with --ignore-scripts.\n" +
|
|
14
|
+
"Run the postinstall script manually:\n\n" +
|
|
15
|
+
" cd " + path.dirname(__filename) + " && node install.js\n"
|
|
16
|
+
);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const child = spawn(binaryPath, ["mcp"], {
|
|
21
|
+
stdio: "inherit",
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Forward signals to child process
|
|
25
|
+
for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
26
|
+
process.on(sig, () => {
|
|
27
|
+
if (!child.killed) child.kill(sig);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
child.on("close", (code, signal) => {
|
|
32
|
+
if (signal) {
|
|
33
|
+
// Re-raise the signal so the parent sees the correct exit reason
|
|
34
|
+
process.kill(process.pid, signal);
|
|
35
|
+
} else {
|
|
36
|
+
process.exit(code ?? 1);
|
|
37
|
+
}
|
|
38
|
+
});
|