create-bk-agent 0.16.0 → 0.17.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 +93 -29
- package/dist/src/add/detector.js +80 -0
- package/dist/src/add/index.js +67 -0
- package/dist/src/add/modules/mcp-client.js +65 -0
- package/dist/src/add/modules/server.js +100 -0
- package/dist/src/add/modules/specialist.js +98 -0
- package/dist/src/add/modules/tools.js +102 -0
- package/dist/src/add/patcher.js +168 -0
- package/dist/src/index.js +65 -10
- package/dist/src/prompts.js +102 -25
- package/dist/src/scaffold.js +90 -21
- package/package.json +1 -1
- package/templates/autonomous/package.json +1 -1
- package/templates/autonomous/tsconfig.json +2 -1
- package/templates/coding/package.json +1 -1
- package/templates/coding/tsconfig.json +2 -1
- package/templates/domain-agent/package.json +1 -1
- package/templates/domain-agent/tsconfig.json +2 -1
- package/templates/mcp-server/package.json +1 -1
- package/templates/mcp-server/tsconfig.json +2 -1
- package/templates/minimal/package.json +1 -1
- package/templates/minimal/tsconfig.json +2 -1
package/README.md
CHANGED
|
@@ -1,54 +1,118 @@
|
|
|
1
1
|
# create-bk-agent
|
|
2
2
|
|
|
3
|
-
Scaffold a new [BackendKit agent](https://github.com/BackendKit-labs/backendkit-agent-framework) project in seconds.
|
|
3
|
+
Scaffold a new [BackendKit agent](https://github.com/BackendKit-labs/backendkit-agent-framework) project in seconds — or add capabilities to an existing one.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Create a project
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npx create-bk-agent my-project
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
The CLI asks three questions and generates a production-ready project:
|
|
12
|
+
|
|
11
13
|
```
|
|
12
|
-
✨ create-bk-agent v0.
|
|
14
|
+
✨ create-bk-agent v0.17.0
|
|
13
15
|
|
|
14
|
-
? Project name:
|
|
15
|
-
?
|
|
16
|
-
?
|
|
16
|
+
? Project name: my-project
|
|
17
|
+
? Architecture: Multi-agent (orchestrator + specialists)
|
|
18
|
+
? Skill packs: Node.js / TypeScript
|
|
19
|
+
? How will it be used? MCP Server (HTTP)
|
|
17
20
|
|
|
18
|
-
Creating
|
|
21
|
+
Creating Multi-agent — MCP Server (HTTP) agent in ./my-project...
|
|
19
22
|
Installing dependencies...
|
|
20
23
|
|
|
21
|
-
✅ Done!
|
|
24
|
+
✅ Done! Your agent is ready.
|
|
25
|
+
|
|
22
26
|
cd my-project
|
|
23
|
-
cp .env.example .env
|
|
24
|
-
npm run
|
|
27
|
+
cp .env.example .env # add your API key
|
|
28
|
+
npm run server # starts HTTP MCP on port 3001
|
|
25
29
|
```
|
|
26
30
|
|
|
27
|
-
##
|
|
31
|
+
## Architectures
|
|
32
|
+
|
|
33
|
+
| Architecture | What it gives you | Best for |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `multi-agent` | Orchestrator + specialists with delegation | Domain agents (DevOps, finance, data, etc.) |
|
|
36
|
+
| `single` | One agent with a tool registry | Simple task automation |
|
|
37
|
+
| `coding` | 10 pre-built agents + all coding tools | Coding assistants, ready out of the box |
|
|
38
|
+
| `autonomous` | Trigger system (cron / webhook / event) | Scheduled or event-driven daemons |
|
|
39
|
+
| `minimal` | Bare engine, no entry point | Library embedding |
|
|
28
40
|
|
|
29
|
-
|
|
30
|
-
10 specialized agents (backend, frontend, QA, security, architecture…) and all
|
|
31
|
-
coding tools (read/write files, run commands, git, search) are already configured.
|
|
32
|
-
Add your API key, describe your project in `AGENT.md`, and it works out of the box.
|
|
33
|
-
**Choose this when you want a coding assistant, not when you want to build one.**
|
|
41
|
+
## Deploy modes
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
Orchestrator + specialists pattern with no pre-built agents or tools. You define
|
|
37
|
-
the agents and tools for your specific domain (Docker, AWS, databases, APIs, etc.).
|
|
38
|
-
The framework handles orchestration, delegation, and parallel execution.
|
|
39
|
-
**Choose this when you are building a new type of agent from scratch.**
|
|
43
|
+
Available for `multi-agent` and `single` architectures:
|
|
40
44
|
|
|
41
|
-
|
|
|
42
|
-
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
45
|
+
| Mode | Entry point | Use case |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `repl` | `src/index.ts` — readline loop | Local terminal tool |
|
|
48
|
+
| `mcp-http` | `src/server.ts` — HTTP MCP server | Connect to Claude Desktop, Cursor, etc. |
|
|
49
|
+
| `mcp-stdio` | `src/server.ts` — stdio MCP server | Subprocess / pipe-based MCP |
|
|
50
|
+
| `hybrid` | Both `index.ts` + `server.ts` | REPL for dev, server for production |
|
|
51
|
+
| `library` | Only `src/engine.ts` exported | Import the engine in your own app |
|
|
48
52
|
|
|
49
53
|
## Providers
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
Anthropic (Claude), OpenAI, DeepSeek / any OpenAI-compatible endpoint, and Ollama (local).
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Add capabilities to an existing project
|
|
60
|
+
|
|
61
|
+
Once a project is created, use `add` to extend it without editing code manually:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx create-bk-agent add <module> [options]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### `add server` — expose the agent as an HTTP MCP server
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx create-bk-agent add server
|
|
71
|
+
npx create-bk-agent add server --port 4000 --name my-agent
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- Generates `src/server.ts` wired to the existing engine
|
|
75
|
+
- Adds `@backendkit-labs/mcp-server` to `dependencies`
|
|
76
|
+
- Adds `"server"` script to `package.json`
|
|
77
|
+
|
|
78
|
+
### `add specialist <name>` — add a specialist agent (multi-agent projects)
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npx create-bk-agent add specialist data-analyst
|
|
82
|
+
npx create-bk-agent add specialist git-expert
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- Creates `src/agents/<name>.ts` with an `AgentProfile` stub
|
|
86
|
+
- Patches `src/engine.ts`: adds the import and `agents.register()`
|
|
87
|
+
|
|
88
|
+
### `add tools <domain>` — add a tool file for a new domain
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npx create-bk-agent add tools github
|
|
92
|
+
npx create-bk-agent add tools my-database
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- Creates `src/tools/<domain>-tools.ts` with two stub tools (action + query)
|
|
96
|
+
- Patches `src/engine.ts`: adds the import and `tools.register()`
|
|
97
|
+
|
|
98
|
+
### `add mcp-client <url>` — connect to a remote MCP server
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npx create-bk-agent add mcp-client http://localhost:3001/mcp
|
|
102
|
+
npx create-bk-agent add mcp-client http://billing-agent/mcp --name billing
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- Patches `src/engine.ts`: adds the entry to `mcpServers: [...]` inside `AgentEngine`
|
|
106
|
+
- Creates the `mcpServers` array if it doesn't exist yet
|
|
107
|
+
|
|
108
|
+
All `add` commands are **idempotent** — running the same command twice won't duplicate entries.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Requirements
|
|
113
|
+
|
|
114
|
+
- Node.js >= 20
|
|
115
|
+
- An API key for your chosen provider (Anthropic, OpenAI, DeepSeek, or Ollama)
|
|
52
116
|
|
|
53
117
|
## License
|
|
54
118
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.detectProject = detectProject;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
function detectProject(cwd) {
|
|
40
|
+
const pkgFile = path.join(cwd, 'package.json');
|
|
41
|
+
if (!fs.existsSync(pkgFile))
|
|
42
|
+
return null;
|
|
43
|
+
let pkg;
|
|
44
|
+
try {
|
|
45
|
+
pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf-8'));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const deps = {
|
|
51
|
+
...(pkg.dependencies ?? {}),
|
|
52
|
+
...(pkg.devDependencies ?? {}),
|
|
53
|
+
};
|
|
54
|
+
if (!deps['@backendkit-labs/agent-core'])
|
|
55
|
+
return null;
|
|
56
|
+
const engineFile = path.join(cwd, 'src', 'engine.ts');
|
|
57
|
+
let architecture = 'unknown';
|
|
58
|
+
let engineFnName = 'createEngine';
|
|
59
|
+
if (fs.existsSync(engineFile)) {
|
|
60
|
+
const content = fs.readFileSync(engineFile, 'utf-8');
|
|
61
|
+
if (content.includes('ORCHESTRATOR_PROFILE') || content.includes("id: 'orchestrator'")) {
|
|
62
|
+
architecture = 'multi-agent';
|
|
63
|
+
}
|
|
64
|
+
else if (content.includes('export function create')) {
|
|
65
|
+
architecture = 'single';
|
|
66
|
+
}
|
|
67
|
+
const match = content.match(/export function (\w+)\s*\(/);
|
|
68
|
+
if (match)
|
|
69
|
+
engineFnName = match[1];
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
cwd,
|
|
73
|
+
architecture,
|
|
74
|
+
engineFile,
|
|
75
|
+
indexFile: path.join(cwd, 'src', 'index.ts'),
|
|
76
|
+
serverFile: path.join(cwd, 'src', 'server.ts'),
|
|
77
|
+
pkgFile,
|
|
78
|
+
engineFnName,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runAdd = runAdd;
|
|
4
|
+
const detector_1 = require("./detector");
|
|
5
|
+
const server_1 = require("./modules/server");
|
|
6
|
+
const specialist_1 = require("./modules/specialist");
|
|
7
|
+
const tools_1 = require("./modules/tools");
|
|
8
|
+
const mcp_client_1 = require("./modules/mcp-client");
|
|
9
|
+
const HELP = `
|
|
10
|
+
Usage: npx create-bk-agent add <module> [options]
|
|
11
|
+
|
|
12
|
+
Modules:
|
|
13
|
+
server Add an HTTP MCP server (src/server.ts)
|
|
14
|
+
--port <n> Port to listen on (default: 3001)
|
|
15
|
+
--name <s> MCP server name (default: project directory name)
|
|
16
|
+
|
|
17
|
+
specialist <name> Add a new specialist agent to a multi-agent project
|
|
18
|
+
(creates src/agents/<name>.ts and patches engine.ts)
|
|
19
|
+
|
|
20
|
+
tools <domain> Add a tool file for a new domain
|
|
21
|
+
(creates src/tools/<domain>-tools.ts and patches engine.ts)
|
|
22
|
+
|
|
23
|
+
mcp-client <url> Add a remote MCP server to the engine
|
|
24
|
+
--name <s> Name for the mcpServers entry (default: last URL segment)
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
npx create-bk-agent add server --port 4000
|
|
28
|
+
npx create-bk-agent add specialist data-analyst
|
|
29
|
+
npx create-bk-agent add tools github
|
|
30
|
+
npx create-bk-agent add mcp-client http://localhost:3001/mcp --name billing
|
|
31
|
+
`;
|
|
32
|
+
function runAdd(args, cwd) {
|
|
33
|
+
const [module, ...rest] = args;
|
|
34
|
+
if (!module || module === '--help' || module === '-h') {
|
|
35
|
+
console.log(HELP);
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
const info = (0, detector_1.detectProject)(cwd);
|
|
39
|
+
if (!info) {
|
|
40
|
+
console.error('\n✗ No bk-agent project detected in the current directory.\n' +
|
|
41
|
+
' Make sure you are inside a project created with npx create-bk-agent.\n');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
switch (module) {
|
|
45
|
+
case 'server':
|
|
46
|
+
(0, server_1.addServer)(info, rest);
|
|
47
|
+
break;
|
|
48
|
+
case 'specialist':
|
|
49
|
+
if (info.architecture !== 'multi-agent') {
|
|
50
|
+
console.error(`\n⚠ "add specialist" is designed for multi-agent projects.\n` +
|
|
51
|
+
` Detected architecture: ${info.architecture}.\n` +
|
|
52
|
+
` Proceeding anyway — verify engine.ts manually.\n`);
|
|
53
|
+
}
|
|
54
|
+
(0, specialist_1.addSpecialist)(info, rest);
|
|
55
|
+
break;
|
|
56
|
+
case 'tools':
|
|
57
|
+
(0, tools_1.addTools)(info, rest);
|
|
58
|
+
break;
|
|
59
|
+
case 'mcp-client':
|
|
60
|
+
(0, mcp_client_1.addMcpClient)(info, rest);
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
console.error(`\n✗ Unknown module: "${module}"\n`);
|
|
64
|
+
console.log(HELP);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.addMcpClient = addMcpClient;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const patcher_1 = require("../patcher");
|
|
39
|
+
function addMcpClient(info, args) {
|
|
40
|
+
const url = args[0];
|
|
41
|
+
if (!url) {
|
|
42
|
+
console.error('\n✗ Usage: add mcp-client <url> [--name <name>]\n');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
let name = url.split('/').filter(Boolean).pop() ?? 'remote-agent';
|
|
46
|
+
for (let i = 1; i < args.length; i++) {
|
|
47
|
+
if (args[i] === '--name' && args[i + 1]) {
|
|
48
|
+
name = args[++i];
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!fs.existsSync(info.engineFile)) {
|
|
53
|
+
console.error('\n✗ src/engine.ts not found.\n');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
const ok = (0, patcher_1.addMcpServerEntry)(info.engineFile, name, url);
|
|
57
|
+
if (ok) {
|
|
58
|
+
console.log(`\n✓ Patched src/engine.ts (mcpServers: { name: '${name}', url: '${url}' })`);
|
|
59
|
+
console.log(`\nNext steps:\n npm run dev\n`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.error('\n✗ Could not locate AgentEngine constructor to inject mcpServers.\n');
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.addServer = addServer;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const patcher_1 = require("../patcher");
|
|
40
|
+
function parseArgs(args, defaultName) {
|
|
41
|
+
let port = 3001;
|
|
42
|
+
let name = defaultName;
|
|
43
|
+
for (let i = 0; i < args.length; i++) {
|
|
44
|
+
if (args[i] === '--port' && args[i + 1])
|
|
45
|
+
port = parseInt(args[++i]);
|
|
46
|
+
if (args[i] === '--name' && args[i + 1])
|
|
47
|
+
name = args[++i];
|
|
48
|
+
}
|
|
49
|
+
return { port, name };
|
|
50
|
+
}
|
|
51
|
+
function generateServerTs(info, opts) {
|
|
52
|
+
return `import 'dotenv/config';
|
|
53
|
+
import { AgentMCPServer } from '@backendkit-labs/mcp-server';
|
|
54
|
+
import { CallbackTransport } from '@backendkit-labs/agent-core';
|
|
55
|
+
import { z } from 'zod';
|
|
56
|
+
import { ${info.engineFnName} } from './engine';
|
|
57
|
+
|
|
58
|
+
const server = new AgentMCPServer({
|
|
59
|
+
name: '${opts.name}',
|
|
60
|
+
version: '1.0.0',
|
|
61
|
+
port: parseInt(process.env.MCP_PORT ?? '${opts.port}'),
|
|
62
|
+
|
|
63
|
+
tools: [
|
|
64
|
+
{
|
|
65
|
+
name: 'agent_request',
|
|
66
|
+
description: 'TODO: describe what requests this agent handles',
|
|
67
|
+
schema: {
|
|
68
|
+
request: z.string().describe('Natural-language request for the agent'),
|
|
69
|
+
},
|
|
70
|
+
buildPrompt: ({ request }: { request: string }) => request,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
|
|
74
|
+
engineFactory: (transport: CallbackTransport) => ${info.engineFnName}(transport),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await server.start();
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
function addServer(info, args) {
|
|
81
|
+
const opts = parseArgs(args, path.basename(info.cwd));
|
|
82
|
+
if (fs.existsSync(info.serverFile)) {
|
|
83
|
+
console.error(`\n✗ src/server.ts already exists. Remove it first to regenerate.\n`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
fs.writeFileSync(info.serverFile, generateServerTs(info, opts));
|
|
87
|
+
console.log(`\n✓ Created src/server.ts (HTTP MCP on port ${opts.port})`);
|
|
88
|
+
const added = (0, patcher_1.addPackageDependency)(info.pkgFile, '@backendkit-labs/mcp-server', '^0.16.0');
|
|
89
|
+
(0, patcher_1.addPackageDependency)(info.pkgFile, 'zod', '^3.25.0');
|
|
90
|
+
(0, patcher_1.addPackageScript)(info.pkgFile, 'server', 'ts-node src/server.ts');
|
|
91
|
+
if (added) {
|
|
92
|
+
console.log(`✓ package.json (@backendkit-labs/mcp-server added)`);
|
|
93
|
+
}
|
|
94
|
+
console.log(`✓ package.json (script "server" added)`);
|
|
95
|
+
console.log(`
|
|
96
|
+
Next steps:
|
|
97
|
+
npm install
|
|
98
|
+
npm run server # starts HTTP MCP on port ${opts.port}
|
|
99
|
+
`);
|
|
100
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.addSpecialist = addSpecialist;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const patcher_1 = require("../patcher");
|
|
40
|
+
function toConstName(name) {
|
|
41
|
+
return name.replace(/-/g, '_').toUpperCase() + '_PROFILE';
|
|
42
|
+
}
|
|
43
|
+
function toDisplayName(name) {
|
|
44
|
+
return name.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
|
|
45
|
+
}
|
|
46
|
+
function generateSpecialistTs(name) {
|
|
47
|
+
const constName = toConstName(name);
|
|
48
|
+
return `import type { AgentProfile } from '@backendkit-labs/agent-core';
|
|
49
|
+
|
|
50
|
+
// TODO: Rename this file and export to match your domain
|
|
51
|
+
export const ${constName}: AgentProfile = {
|
|
52
|
+
id: '${name}',
|
|
53
|
+
name: '${toDisplayName(name)}',
|
|
54
|
+
icon: '🔧',
|
|
55
|
+
description: 'TODO: describe what this specialist does',
|
|
56
|
+
delegatesTo: [],
|
|
57
|
+
allowedTools: [
|
|
58
|
+
// TODO: list the tool names this agent can use
|
|
59
|
+
],
|
|
60
|
+
systemPrompt: \`You are a specialist in TODO: <your domain area>.
|
|
61
|
+
|
|
62
|
+
Use the available tools to complete the task delegated to you.
|
|
63
|
+
Be precise and report results clearly.\`,
|
|
64
|
+
};
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
function addSpecialist(info, args) {
|
|
68
|
+
const name = args[0];
|
|
69
|
+
if (!name) {
|
|
70
|
+
console.error('\n✗ Usage: add specialist <name>\n');
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
const agentFile = path.join(info.cwd, 'src', 'agents', `${name}.ts`);
|
|
74
|
+
if (fs.existsSync(agentFile)) {
|
|
75
|
+
console.error(`\n✗ src/agents/${name}.ts already exists.\n`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
fs.writeFileSync(agentFile, generateSpecialistTs(name));
|
|
79
|
+
console.log(`\n✓ Created src/agents/${name}.ts`);
|
|
80
|
+
if (fs.existsSync(info.engineFile)) {
|
|
81
|
+
const constName = toConstName(name);
|
|
82
|
+
(0, patcher_1.addImportLine)(info.engineFile, `import { ${constName} } from './agents/${name}';`);
|
|
83
|
+
// Primary: insert after TODO comment; fallback: after last .register( call
|
|
84
|
+
const inserted = (0, patcher_1.insertAfterPattern)(info.engineFile, /\/\/ TODO: register more specialists/, ` agents.register(${constName});`) ||
|
|
85
|
+
(0, patcher_1.insertAfterPattern)(info.engineFile, /agents\.register\(/, ` agents.register(${constName});`);
|
|
86
|
+
if (inserted) {
|
|
87
|
+
console.log(`✓ Patched src/engine.ts (agents.register(${constName}))`);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.log(`⚠ Could not auto-patch engine.ts — add manually: agents.register(${constName})`);
|
|
91
|
+
}
|
|
92
|
+
const orchestratorFile = path.join(info.cwd, 'src', 'agents', 'orchestrator.ts');
|
|
93
|
+
if (fs.existsSync(orchestratorFile)) {
|
|
94
|
+
console.log(`\n Reminder: add '${name}' to orchestrator.ts delegatesTo[] and update the systemPrompt.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
console.log(`\nNext steps:\n Implement src/agents/${name}.ts\n npm run dev\n`);
|
|
98
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.addTools = addTools;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const patcher_1 = require("../patcher");
|
|
40
|
+
function toCamelCase(name) {
|
|
41
|
+
return name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
42
|
+
}
|
|
43
|
+
function generateToolsTs(domain) {
|
|
44
|
+
const fn = toCamelCase(domain);
|
|
45
|
+
return `import { defineTool, z } from '@backendkit-labs/agent-core';
|
|
46
|
+
|
|
47
|
+
// TODO: replace with real ${domain} SDK/API calls
|
|
48
|
+
|
|
49
|
+
export const ${fn}Action = defineTool({
|
|
50
|
+
name: '${domain}_action',
|
|
51
|
+
description: 'TODO: describe what this tool does',
|
|
52
|
+
input: z.object({
|
|
53
|
+
target: z.string().describe('Target to act on'),
|
|
54
|
+
// TODO: add more parameters
|
|
55
|
+
}),
|
|
56
|
+
execute: async ({ target }) => {
|
|
57
|
+
// TODO: implement
|
|
58
|
+
return \`${domain} action on: \${target}\`;
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const ${fn}Query = defineTool({
|
|
63
|
+
name: '${domain}_query',
|
|
64
|
+
description: 'TODO: describe what this query returns',
|
|
65
|
+
input: z.object({
|
|
66
|
+
filter: z.string().optional().describe('Optional filter'),
|
|
67
|
+
}),
|
|
68
|
+
execute: async ({ filter }) => {
|
|
69
|
+
// TODO: implement
|
|
70
|
+
return JSON.stringify({ results: [], filter });
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
function addTools(info, args) {
|
|
76
|
+
const domain = args[0];
|
|
77
|
+
if (!domain) {
|
|
78
|
+
console.error('\n✗ Usage: add tools <domain>\n');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const toolsFile = path.join(info.cwd, 'src', 'tools', `${domain}-tools.ts`);
|
|
82
|
+
if (fs.existsSync(toolsFile)) {
|
|
83
|
+
console.error(`\n✗ src/tools/${domain}-tools.ts already exists.\n`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
fs.mkdirSync(path.dirname(toolsFile), { recursive: true });
|
|
87
|
+
fs.writeFileSync(toolsFile, generateToolsTs(domain));
|
|
88
|
+
console.log(`\n✓ Created src/tools/${domain}-tools.ts`);
|
|
89
|
+
if (fs.existsSync(info.engineFile)) {
|
|
90
|
+
const fn = toCamelCase(domain);
|
|
91
|
+
(0, patcher_1.addImportLine)(info.engineFile, `import { ${fn}Action, ${fn}Query } from './tools/${domain}-tools';`);
|
|
92
|
+
const inserted = (0, patcher_1.insertAfterPattern)(info.engineFile, /\/\/ TODO: register more tools/, ` tools.register(${fn}Action).register(${fn}Query);`) ||
|
|
93
|
+
(0, patcher_1.insertAfterPattern)(info.engineFile, /tools\.register\(/, ` tools.register(${fn}Action).register(${fn}Query);`);
|
|
94
|
+
if (inserted) {
|
|
95
|
+
console.log(`✓ Patched src/engine.ts (tools.register(${fn}Action, ${fn}Query))`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log(`⚠ Could not auto-patch engine.ts — add manually: tools.register(${fn}Action).register(${fn}Query)`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
console.log(`\nNext steps:\n Implement src/tools/${domain}-tools.ts\n npm run dev\n`);
|
|
102
|
+
}
|