kanbrawl 0.0.1 → 1.0.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/LICENSE +21 -0
- package/README.md +207 -29
- package/bin/cli.js +5 -0
- package/dist/cli/cli.d.ts +1 -0
- package/dist/cli/cli.js +36 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +136 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/start.d.ts +5 -0
- package/dist/cli/commands/start.js +15 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/task.d.ts +9 -0
- package/dist/cli/commands/task.js +37 -0
- package/dist/cli/commands/task.js.map +1 -0
- package/dist/client/assets/index-zl0eZYEM.js +1674 -0
- package/dist/client/index.html +26 -0
- package/dist/server/api.d.ts +3 -0
- package/dist/server/api.js +95 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +70 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/sse.d.ts +8 -0
- package/dist/server/sse.js +25 -0
- package/dist/server/sse.js.map +1 -0
- package/dist/server/store.d.ts +25 -0
- package/dist/server/store.js +154 -0
- package/dist/server/store.js.map +1 -0
- package/dist/server/tools.d.ts +3 -0
- package/dist/server/tools.js +285 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/server/types.d.ts +36 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/package.json +108 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yohan Lasorsa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,45 +1,223 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# 🥊 Kanbrawl
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**A minimal live kanban board built for AI agents**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[](https://github.com/sinedied/kanbrawl/actions/workflows/ci.yml)
|
|
8
|
+
[](https://www.typescriptlang.org)
|
|
9
|
+
[](https://nodejs.org)
|
|
10
|
+
[](LICENSE)
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
[Features](#features) · [Getting Started](#getting-started) · [CLI](#cli) · [Configuration](#configuration) · [MCP Tools](#mcp-tools) · [Architecture](#architecture) · [Development](#development)
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
1. Configure OIDC trusted publishing for the package name `kanbrawl`
|
|
13
|
-
2. Enable secure, token-less publishing from CI/CD workflows
|
|
14
|
-
3. Establish provenance for packages published under this name
|
|
14
|
+
</div>
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
---
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
AI agents manage tasks on a kanban board through [MCP](https://modelcontextprotocol.io) tools. Humans follow along in a live web UI that updates in real-time via Server-Sent Events. Both agents and humans can create, edit, move, and delete tasks — all changes sync instantly.
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## Features
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
- 🤖 **MCP Server** — Exposes kanban operations as MCP tools via HTTP or stdio
|
|
23
|
+
- 🖥️ **Live Web UI** — View updates in real-time and edit/update tasks with drag-and-drop
|
|
24
|
+
- ⌨️ **CLI** — Easy setup to configure your AI tools, create and update tasks from the terminal
|
|
25
|
+
- 📄 **Single JSON file** — All board config and task data lives in `kanbrawl.json`
|
|
26
|
+
- 🔧 **Customizable** — Configure columns to fit your workflow
|
|
27
|
+
- 📦 **Zero infrastructure** — No database, no external services
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
2. Configure the trusted publisher (e.g., GitHub Actions)
|
|
26
|
-
3. Specify the repository and workflow that should be allowed to publish
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
29
|
+
## Getting Started
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
### Prerequisites
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
- Contains no executable code
|
|
33
|
-
- Provides no functionality
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
33
|
+
- [Node.js](https://nodejs.org) >= 22
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
### Quick Start
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
- [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
|
|
41
|
-
- [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
|
|
37
|
+
Run the interactive setup in your project directory:
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
```bash
|
|
40
|
+
npx kanbrawl init
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This will:
|
|
44
|
+
1. Let you select your AI tools (VS Code Copilot, Claude Code, Cursor, Gemini CLI, Windsurf)
|
|
45
|
+
2. Generate the appropriate MCP config files using stdio transport
|
|
46
|
+
3. Create a `kanbrawl.json` board file with default columns
|
|
47
|
+
4. Append a Kanbrawl usage section to `AGENTS.md`
|
|
48
|
+
|
|
49
|
+
That's it — your AI agent can now use MCP tools to manage tasks on the board.
|
|
50
|
+
|
|
51
|
+
### View the Board
|
|
52
|
+
|
|
53
|
+
To launch the web UI and HTTP MCP server:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx kanbrawl start
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Open [http://localhost:3000](http://localhost:3000) to view the board.
|
|
60
|
+
|
|
61
|
+
### Manual MCP Configuration
|
|
62
|
+
|
|
63
|
+
If you prefer to configure your MCP client manually instead of using `kanbrawl init`:
|
|
64
|
+
|
|
65
|
+
**Stdio transport** (recommended):
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"kanbrawl": {
|
|
71
|
+
"command": "npx",
|
|
72
|
+
"args": ["-y", "kanbrawl", "start", "--stdio"]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**HTTP transport** (requires a running server):
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"mcpServers": {
|
|
83
|
+
"kanbrawl": {
|
|
84
|
+
"type": "http",
|
|
85
|
+
"url": "http://localhost:3000/mcp"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## CLI
|
|
92
|
+
|
|
93
|
+
The `kanbrawl` CLI (also aliased as `kb`) provides the following commands:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
kanbrawl # Start HTTP server (default)
|
|
97
|
+
kanbrawl start # Start HTTP server
|
|
98
|
+
kanbrawl start --stdio # Start MCP server over stdio transport
|
|
99
|
+
kanbrawl task "title" # Create a task
|
|
100
|
+
kanbrawl task "title" -u # Update existing task by title match
|
|
101
|
+
kanbrawl init # Interactive setup for AI tools
|
|
102
|
+
kanbrawl --version # Show version
|
|
103
|
+
kanbrawl --help # Show help
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `task` command
|
|
107
|
+
|
|
108
|
+
Create or update tasks directly from the terminal:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
kanbrawl task "Fix login bug" -p 0 -a alice -c "In progress"
|
|
112
|
+
kanbrawl task "Fix login bug" -u -c "Done"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
| Option | Description |
|
|
116
|
+
|--------|-------------|
|
|
117
|
+
| `-d, --description <text>` | Task description |
|
|
118
|
+
| `-c, --column <name>` | Target column |
|
|
119
|
+
| `-p, --priority <level>` | Priority (0, 1, or 2; default 1) |
|
|
120
|
+
| `-a, --assignee <name>` | Task assignee |
|
|
121
|
+
| `-u, --update` | Update existing task by title match |
|
|
122
|
+
|
|
123
|
+
### `init` command
|
|
124
|
+
|
|
125
|
+
Interactive setup that:
|
|
126
|
+
1. Prompts to select AI tools (VS Code Copilot, Claude Code, Cursor, Gemini CLI, Windsurf)
|
|
127
|
+
2. Generates MCP config files with stdio transport for each selected tool
|
|
128
|
+
3. Creates `kanbrawl.json` with default columns if missing
|
|
129
|
+
4. Appends a Kanbrawl usage section to `AGENTS.md`
|
|
130
|
+
|
|
131
|
+
## Configuration
|
|
132
|
+
|
|
133
|
+
All configuration and data is stored in `kanbrawl.json`, auto-created on first run:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"columns": ["Todo", "In progress", "Blocked", "Done"],
|
|
138
|
+
"theme": "dark",
|
|
139
|
+
"tasks": []
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
| Field | Type | Default | Description |
|
|
144
|
+
|-------|------|---------|-------------|
|
|
145
|
+
| `columns` | `string[]` | `["Todo", "In progress", "Blocked", "Done"]` | Column names and order |
|
|
146
|
+
| `theme` | `"light"` \| `"dark"` | System preference | UI theme override |
|
|
147
|
+
| `tasks` | `Task[]` | `[]` | Task objects (managed by the app) |
|
|
148
|
+
|
|
149
|
+
> [!TIP]
|
|
150
|
+
> Edit the `columns` array to customize your board layout. Changes take effect on restart.
|
|
151
|
+
|
|
152
|
+
## MCP Tools
|
|
153
|
+
|
|
154
|
+
All tools are available via the `/mcp` endpoint.
|
|
155
|
+
|
|
156
|
+
| Tool | Description | Read-only |
|
|
157
|
+
|------|-------------|-----------|
|
|
158
|
+
| `get_columns` | Get columns with task counts | ✅ |
|
|
159
|
+
| `list_tasks` | List tasks, filtered by column (default: first) and priority | ✅ |
|
|
160
|
+
| `create_task` | Create a new task (with priority, assignee) | ❌ |
|
|
161
|
+
| `move_task` | Move a task to a different column | ❌ |
|
|
162
|
+
| `update_task` | Update task fields (title, description, priority, assignee) | ❌ |
|
|
163
|
+
| `delete_task` | Delete a task | ❌ |
|
|
164
|
+
|
|
165
|
+
## Architecture
|
|
166
|
+
|
|
167
|
+
```mermaid
|
|
168
|
+
graph LR
|
|
169
|
+
subgraph Clients
|
|
170
|
+
A["🤖 AI Agents"]
|
|
171
|
+
B["🖥️ Web Browser"]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
subgraph Server ["Express 5 Server"]
|
|
175
|
+
MCP["MCP Endpoint<br/><code>/mcp</code>"]
|
|
176
|
+
API["REST API<br/><code>/api/*</code>"]
|
|
177
|
+
SSE["SSE Endpoint<br/><code>/events</code>"]
|
|
178
|
+
Store["BoardStore"]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
DB[("kanbrawl.json")]
|
|
182
|
+
|
|
183
|
+
A -- "MCP tools<br/>(Streamable HTTP)" --> MCP
|
|
184
|
+
B -- "REST calls" --> API
|
|
185
|
+
B -. "real-time events" .-o SSE
|
|
186
|
+
|
|
187
|
+
MCP --> Store
|
|
188
|
+
API --> Store
|
|
189
|
+
Store -- "read/write" --> DB
|
|
190
|
+
Store -- "emit events" --> SSE
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**How it works:**
|
|
194
|
+
|
|
195
|
+
1. **AI agents** call MCP tools (e.g. `create_task`) via the `/mcp` Streamable HTTP endpoint
|
|
196
|
+
2. **Humans** interact through the web UI, which calls the REST API at `/api/*`
|
|
197
|
+
3. All mutations flow through the **BoardStore**, which persists data to `kanbrawl.json` and emits change events
|
|
198
|
+
4. The **SSE manager** broadcasts events to all connected browser clients for real-time updates
|
|
199
|
+
|
|
200
|
+
## Development
|
|
201
|
+
|
|
202
|
+
### Dev Mode
|
|
203
|
+
|
|
204
|
+
Runs the Express server with auto-reload and Vite dev server with HMR:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npm run dev
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
| Service | URL | Description |
|
|
211
|
+
|---------|-----|-------------|
|
|
212
|
+
| Server | [localhost:3000](http://localhost:3000) | API, MCP, SSE |
|
|
213
|
+
| Client | [localhost:5173](http://localhost:5173) | Vite dev with proxy |
|
|
214
|
+
|
|
215
|
+
### Build
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npm run build # Build both server and client
|
|
219
|
+
npm run build:server # Build server only (tsc)
|
|
220
|
+
npm run build:client # Build client only (vite)
|
|
221
|
+
npm run clean # Remove dist/
|
|
222
|
+
```
|
|
44
223
|
|
|
45
|
-
**Maintained for OIDC setup purposes only**
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function run(arguments_: string[]): void;
|
package/dist/cli/cli.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { startAction } from './commands/start.js';
|
|
6
|
+
import { taskAction } from './commands/task.js';
|
|
7
|
+
import { initAction } from './commands/init.js';
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const { version } = JSON.parse(readFileSync(resolve(__dirname, '../../package.json'), 'utf8'));
|
|
10
|
+
export function run(arguments_) {
|
|
11
|
+
const program = new Command();
|
|
12
|
+
program
|
|
13
|
+
.name('kanbrawl')
|
|
14
|
+
.description('A minimal live kanban board for AI agents, powered by MCP')
|
|
15
|
+
.version(version);
|
|
16
|
+
program
|
|
17
|
+
.command('start', { isDefault: true })
|
|
18
|
+
.description('start the Kanbrawl server')
|
|
19
|
+
.option('--stdio', 'use stdio transport for MCP (instead of HTTP server)')
|
|
20
|
+
.action(startAction);
|
|
21
|
+
program
|
|
22
|
+
.command('task <title>')
|
|
23
|
+
.description('create or update a task on the board')
|
|
24
|
+
.option('-d, --description <text>', 'task description')
|
|
25
|
+
.option('-c, --column <name>', 'target column')
|
|
26
|
+
.option('-p, --priority <level>', 'priority level (0, 1, or 2)', '1')
|
|
27
|
+
.option('-a, --assignee <name>', 'task assignee')
|
|
28
|
+
.option('-u, --update', 'update existing task by title match')
|
|
29
|
+
.action(taskAction);
|
|
30
|
+
program
|
|
31
|
+
.command('init')
|
|
32
|
+
.description('initialize Kanbrawl configuration for your AI tools')
|
|
33
|
+
.action(initAction);
|
|
34
|
+
program.parse(arguments_);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CACxC,CAAC;AAEzB,MAAM,UAAU,GAAG,CAAC,UAAoB;IACtC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,UAAU,CAAC;SAChB,WAAW,CAAC,2DAA2D,CAAC;SACxE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,OAAO;SACJ,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;SACrC,WAAW,CAAC,2BAA2B,CAAC;SACxC,MAAM,CAAC,SAAS,EAAE,sDAAsD,CAAC;SACzE,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvB,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,sCAAsC,CAAC;SACnD,MAAM,CAAC,0BAA0B,EAAE,kBAAkB,CAAC;SACtD,MAAM,CAAC,qBAAqB,EAAE,eAAe,CAAC;SAC9C,MAAM,CAAC,wBAAwB,EAAE,6BAA6B,EAAE,GAAG,CAAC;SACpE,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;SAChD,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC;SAC7D,MAAM,CAAC,UAAU,CAAC,CAAC;IAEtB,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,qDAAqD,CAAC;SAClE,MAAM,CAAC,UAAU,CAAC,CAAC;IAEtB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type McpConfig = {
|
|
2
|
+
name: string;
|
|
3
|
+
configPath: string;
|
|
4
|
+
serversKey: string;
|
|
5
|
+
generateEntry: () => Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
export declare function writeConfigFile(config: McpConfig, cwd: string): void;
|
|
8
|
+
export declare function updateAgentsMd(cwd: string): void;
|
|
9
|
+
export declare function initAction(): Promise<void>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { resolve, dirname } from 'node:path';
|
|
4
|
+
import { checkbox } from '@inquirer/prompts';
|
|
5
|
+
import { BoardStore } from '../../server/store.js';
|
|
6
|
+
const STDIO_COMMAND = 'npx';
|
|
7
|
+
const STDIO_ARGS = ['-y', 'kanbrawl', 'start', '--stdio'];
|
|
8
|
+
const MCP_CONFIGS = [
|
|
9
|
+
{
|
|
10
|
+
name: 'VS Code / GitHub Copilot',
|
|
11
|
+
configPath: '.vscode/mcp.json',
|
|
12
|
+
serversKey: 'servers',
|
|
13
|
+
generateEntry: () => ({
|
|
14
|
+
type: 'stdio',
|
|
15
|
+
command: STDIO_COMMAND,
|
|
16
|
+
args: STDIO_ARGS,
|
|
17
|
+
}),
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Claude Code',
|
|
21
|
+
configPath: '.mcp.json',
|
|
22
|
+
serversKey: 'mcpServers',
|
|
23
|
+
generateEntry: () => ({
|
|
24
|
+
command: STDIO_COMMAND,
|
|
25
|
+
args: STDIO_ARGS,
|
|
26
|
+
}),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'Cursor',
|
|
30
|
+
configPath: '.cursor/mcp.json',
|
|
31
|
+
serversKey: 'mcpServers',
|
|
32
|
+
generateEntry: () => ({
|
|
33
|
+
command: STDIO_COMMAND,
|
|
34
|
+
args: STDIO_ARGS,
|
|
35
|
+
}),
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'Gemini CLI',
|
|
39
|
+
configPath: '.gemini/settings.json',
|
|
40
|
+
serversKey: 'mcpServers',
|
|
41
|
+
generateEntry: () => ({
|
|
42
|
+
command: STDIO_COMMAND,
|
|
43
|
+
args: STDIO_ARGS,
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Windsurf',
|
|
48
|
+
configPath: '.windsurf/mcp.json',
|
|
49
|
+
serversKey: 'mcpServers',
|
|
50
|
+
generateEntry: () => ({
|
|
51
|
+
command: STDIO_COMMAND,
|
|
52
|
+
args: STDIO_ARGS,
|
|
53
|
+
}),
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
const AGENTS_MD_SECTION = `
|
|
57
|
+
## Task Management
|
|
58
|
+
|
|
59
|
+
Use the Kanbrawl MCP tools for task management when working on this project.
|
|
60
|
+
|
|
61
|
+
### Workflow
|
|
62
|
+
|
|
63
|
+
- Check existing tasks with \`list_tasks\` before creating to avoid duplicates
|
|
64
|
+
- Move tasks between columns with \`move_task\` to track progress
|
|
65
|
+
- Always set your name as assignee when working on a task
|
|
66
|
+
- When building a plan, include task creation in it
|
|
67
|
+
`;
|
|
68
|
+
export function writeConfigFile(config, cwd) {
|
|
69
|
+
const fullPath = resolve(cwd, config.configPath);
|
|
70
|
+
const dir = dirname(fullPath);
|
|
71
|
+
if (!existsSync(dir)) {
|
|
72
|
+
mkdirSync(dir, { recursive: true });
|
|
73
|
+
}
|
|
74
|
+
let existing = {};
|
|
75
|
+
if (existsSync(fullPath)) {
|
|
76
|
+
try {
|
|
77
|
+
existing = JSON.parse(readFileSync(fullPath, 'utf8'));
|
|
78
|
+
}
|
|
79
|
+
catch { }
|
|
80
|
+
}
|
|
81
|
+
const servers = existing[config.serversKey] ?? {};
|
|
82
|
+
servers.kanbrawl = config.generateEntry();
|
|
83
|
+
existing[config.serversKey] = servers;
|
|
84
|
+
writeFileSync(fullPath, JSON.stringify(existing, null, 2) + '\n', 'utf8');
|
|
85
|
+
console.log(` ✅ ${config.configPath}`);
|
|
86
|
+
}
|
|
87
|
+
export function updateAgentsMd(cwd) {
|
|
88
|
+
const agentsPath = resolve(cwd, 'AGENTS.md');
|
|
89
|
+
if (existsSync(agentsPath)) {
|
|
90
|
+
const content = readFileSync(agentsPath, 'utf8');
|
|
91
|
+
if (content.includes('Kanbrawl MCP tools')) {
|
|
92
|
+
console.log(' ⏭️ AGENTS.md already contains Kanbrawl section, skipping');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
writeFileSync(agentsPath, content.trimEnd() + '\n' + AGENTS_MD_SECTION, 'utf8');
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
writeFileSync(agentsPath, `# AGENTS.md\n${AGENTS_MD_SECTION}`, 'utf8');
|
|
99
|
+
}
|
|
100
|
+
console.log(' ✅ AGENTS.md');
|
|
101
|
+
}
|
|
102
|
+
export async function initAction() {
|
|
103
|
+
console.log('🥊 Kanbrawl Setup\n');
|
|
104
|
+
const selected = await checkbox({
|
|
105
|
+
message: 'Select AI tools to configure:',
|
|
106
|
+
choices: MCP_CONFIGS.map((config) => ({
|
|
107
|
+
name: config.name,
|
|
108
|
+
value: config,
|
|
109
|
+
})),
|
|
110
|
+
});
|
|
111
|
+
if (selected.length === 0) {
|
|
112
|
+
console.log('No tools selected. Exiting.');
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const cwd = process.cwd();
|
|
116
|
+
// Create kanbrawl.json if it doesn't exist
|
|
117
|
+
console.log('\n📋 Setting up board...');
|
|
118
|
+
const boardPath = resolve(cwd, 'kanbrawl.json');
|
|
119
|
+
if (existsSync(boardPath)) {
|
|
120
|
+
console.log(' ⏭️ kanbrawl.json already exists, skipping');
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
new BoardStore(boardPath); // eslint-disable-line no-new
|
|
124
|
+
console.log(' ✅ kanbrawl.json');
|
|
125
|
+
}
|
|
126
|
+
// Write MCP config files
|
|
127
|
+
console.log('\n🔧 Writing MCP configuration...');
|
|
128
|
+
for (const config of selected) {
|
|
129
|
+
writeConfigFile(config, cwd);
|
|
130
|
+
}
|
|
131
|
+
// Update AGENTS.md
|
|
132
|
+
console.log('\n📝 Updating AGENTS.md...');
|
|
133
|
+
updateAgentsMd(cwd);
|
|
134
|
+
console.log('\n🎉 Kanbrawl is ready! Run `kanbrawl start` to launch the server.');
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
|
+
import { BoardStore } from '../../server/store.js';
|
|
3
|
+
import { createMcpServer, startServer } from '../../server/index.js';
|
|
4
|
+
export async function startAction(options) {
|
|
5
|
+
if (options.stdio) {
|
|
6
|
+
const store = new BoardStore();
|
|
7
|
+
const mcpServer = createMcpServer(store);
|
|
8
|
+
const transport = new StdioServerTransport();
|
|
9
|
+
await mcpServer.connect(transport);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
startServer();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAMrE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAqB;IACrD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACN,WAAW,EAAE,CAAC;IAChB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { BoardStore } from '../../server/store.js';
|
|
3
|
+
export function taskAction(title, options) {
|
|
4
|
+
const store = new BoardStore();
|
|
5
|
+
const priority = options.priority
|
|
6
|
+
? `P${options.priority}`
|
|
7
|
+
: undefined;
|
|
8
|
+
if (options.update) {
|
|
9
|
+
const tasks = store.getTasks();
|
|
10
|
+
const existing = tasks.find((t) => t.title.toLowerCase() === title.toLowerCase());
|
|
11
|
+
if (!existing) {
|
|
12
|
+
console.error(`Error: No task found with title "${title}"`);
|
|
13
|
+
process.exitCode = 1;
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const updates = {};
|
|
17
|
+
if (options.description !== undefined) {
|
|
18
|
+
updates.description = options.description;
|
|
19
|
+
}
|
|
20
|
+
if (priority !== undefined) {
|
|
21
|
+
updates.priority = priority;
|
|
22
|
+
}
|
|
23
|
+
if (options.assignee !== undefined) {
|
|
24
|
+
updates.assignee = options.assignee;
|
|
25
|
+
}
|
|
26
|
+
const updated = store.updateTask(existing.id, updates);
|
|
27
|
+
if (options.column) {
|
|
28
|
+
store.moveTask(existing.id, options.column);
|
|
29
|
+
}
|
|
30
|
+
console.log(`✅ Task updated: ${updated.title} (${updated.id})`);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const task = store.createTask(title, options.description, options.column, priority, options.assignee);
|
|
34
|
+
console.log(`✅ Task created: ${task.title} (${task.id})`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../../src/cli/commands/task.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAUnD,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,OAAoB;IAC5D,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ;QAC/B,CAAC,CAAE,IAAI,OAAO,CAAC,QAAQ,EAAY;QACnC,CAAC,CAAC,SAAS,CAAC;IAEd,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,CACrD,CAAC;QAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,oCAAoC,KAAK,GAAG,CAAC,CAAC;YAC5D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAuC,EAAE,CAAC;QACvD,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QAC5C,CAAC;QAED,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC9B,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACtC,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAEvD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAC3B,KAAK,EACL,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,MAAM,EACd,QAAQ,EACR,OAAO,CAAC,QAAQ,CACjB,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
|