takumi-cli 1.2.3 → 1.2.9

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 CHANGED
@@ -89,15 +89,51 @@ takumi info ./videos
89
89
 
90
90
  takumi includes an MCP server so AI clients like Claude Code and Kiro can use all commands as tools. No syntax to remember, just describe what you want.
91
91
 
92
- ```bash
93
- takumi mcp-config
92
+ Run `takumi mcp-config` to get the config block for your client, or copy from below.
93
+
94
+ ### VS Code
95
+
96
+ Create or edit `.vscode/mcp.json` in your project:
97
+
98
+ ```json
99
+ {
100
+ "servers": {
101
+ "takumi": {
102
+ "command": "takumi-mcp"
103
+ }
104
+ }
105
+ }
94
106
  ```
95
107
 
96
- This prints the JSON config block for each client. Paste the relevant one into:
108
+ ### Claude Code
109
+
110
+ Add to `~/.claude.json` or create `.mcp.json` in your project root:
111
+
112
+ ```json
113
+ {
114
+ "mcpServers": {
115
+ "takumi": {
116
+ "command": "takumi-mcp"
117
+ }
118
+ }
119
+ }
120
+ ```
121
+
122
+ ### Kiro
123
+
124
+ Create or edit `.kiro/settings/mcp.json` in your project:
125
+
126
+ ```json
127
+ {
128
+ "mcpServers": {
129
+ "takumi": {
130
+ "command": "takumi-mcp"
131
+ }
132
+ }
133
+ }
134
+ ```
97
135
 
98
- - **VS Code:** `.vscode/mcp.json` (uses `"servers"`)
99
- - **Claude Code:** `~/.claude.json` or project `.mcp.json` (uses `"mcpServers"`)
100
- - **Kiro:** `.kiro/settings/mcp.json` (uses `"mcpServers"`)
136
+ > **Note:** If your editor can't find `takumi-mcp`, use the full path from `takumi mcp-config` instead.
101
137
 
102
138
  Once configured, just ask in natural language:
103
139
 
package/bin/takumi-mcp ADDED
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+ # Wrapper to start the takumi MCP server.
3
+ # Finds node even when launched outside a login shell (VS Code, Kiro, etc.)
4
+
5
+ find_node() {
6
+ # Check PATH first
7
+ if command -v node &>/dev/null; then
8
+ command -v node
9
+ return
10
+ fi
11
+
12
+ # nvm (macOS/Linux)
13
+ if [ -d "$HOME/.nvm/versions/node" ]; then
14
+ local latest
15
+ latest="$(ls -v "$HOME/.nvm/versions/node" | tail -1)"
16
+ if [ -n "$latest" ] && [ -x "$HOME/.nvm/versions/node/$latest/bin/node" ]; then
17
+ echo "$HOME/.nvm/versions/node/$latest/bin/node"
18
+ return
19
+ fi
20
+ fi
21
+
22
+ # fnm
23
+ if [ -d "$HOME/.fnm" ]; then
24
+ local latest
25
+ latest="$(ls -v "$HOME/.fnm/node-versions" 2>/dev/null | tail -1)"
26
+ if [ -n "$latest" ] && [ -x "$HOME/.fnm/node-versions/$latest/installation/bin/node" ]; then
27
+ echo "$HOME/.fnm/node-versions/$latest/installation/bin/node"
28
+ return
29
+ fi
30
+ fi
31
+
32
+ # Homebrew
33
+ if [ -x "/opt/homebrew/bin/node" ]; then
34
+ echo "/opt/homebrew/bin/node"
35
+ return
36
+ fi
37
+ if [ -x "/usr/local/bin/node" ]; then
38
+ echo "/usr/local/bin/node"
39
+ return
40
+ fi
41
+
42
+ # Volta
43
+ if [ -x "$HOME/.volta/bin/node" ]; then
44
+ echo "$HOME/.volta/bin/node"
45
+ return
46
+ fi
47
+
48
+ return 1
49
+ }
50
+
51
+ NODE="$(find_node)"
52
+ if [ -z "$NODE" ]; then
53
+ echo "Error: node not found. Install Node.js: https://nodejs.org" >&2
54
+ exit 1
55
+ fi
56
+
57
+ if [ -z "${SCRIPT_DIR:-}" ]; then
58
+ REAL_PATH="$(realpath "$0" 2>/dev/null || readlink -f "$0" 2>/dev/null || echo "$0")"
59
+ SCRIPT_DIR="$(cd "$(dirname "$REAL_PATH")/.." && pwd)"
60
+ fi
61
+ exec "$NODE" "$SCRIPT_DIR/mcp/server.js"
@@ -2,12 +2,12 @@
2
2
  # ── MCP Config: Print MCP server configuration JSON ─────────────────────────
3
3
 
4
4
  cmd_mcp-config() {
5
- local MCP_SERVER
6
- MCP_SERVER="$(realpath "${SCRIPT_DIR}/mcp/server.js")"
5
+ local MCP_CMD
6
+ MCP_CMD="$(command -v takumi-mcp 2>/dev/null || realpath "${SCRIPT_DIR}/bin/takumi-mcp")"
7
7
 
8
- if [ ! -f "$MCP_SERVER" ]; then
9
- echo "❌ MCP server not found at: ${MCP_SERVER}"
10
- echo " Run 'takumi setup' first."
8
+ if [ ! -x "$MCP_CMD" ]; then
9
+ echo "❌ takumi-mcp not found."
10
+ echo " Reinstall takumi: brew upgrade takumi / npm install -g takumi-cli"
11
11
  return 1
12
12
  fi
13
13
 
@@ -17,8 +17,7 @@ cmd_mcp-config() {
17
17
  {
18
18
  "servers": {
19
19
  "takumi": {
20
- "command": "node",
21
- "args": ["${MCP_SERVER}"]
20
+ "command": "${MCP_CMD}"
22
21
  }
23
22
  }
24
23
  }
@@ -31,8 +30,7 @@ EOF
31
30
  {
32
31
  "mcpServers": {
33
32
  "takumi": {
34
- "command": "node",
35
- "args": ["${MCP_SERVER}"]
33
+ "command": "${MCP_CMD}"
36
34
  }
37
35
  }
38
36
  }
@@ -45,8 +43,7 @@ EOF
45
43
  {
46
44
  "mcpServers": {
47
45
  "takumi": {
48
- "command": "node",
49
- "args": ["${MCP_SERVER}"]
46
+ "command": "${MCP_CMD}"
50
47
  }
51
48
  }
52
49
  }
package/mcp/server.js CHANGED
@@ -11,22 +11,38 @@ const BASH = findBash();
11
11
  const TAKUMI = path.resolve(__dirname, "..", "takumi.sh");
12
12
  const ENV = { ...process.env, SCRIPT_DIR: path.resolve(__dirname, "..") };
13
13
 
14
+ function result(text, isError = false) {
15
+ return {
16
+ content: [{ type: "text", text }],
17
+ isError,
18
+ };
19
+ }
20
+
14
21
  function run(args) {
15
22
  if (!BASH) {
16
- return Promise.resolve({
17
- text: "Error: bash not found. On Windows, install Git for Windows: https://git-scm.com/download/win",
18
- isError: true,
19
- });
23
+ return Promise.resolve(
24
+ result("Error: bash not found. On Windows, install Git for Windows: https://git-scm.com/download/win", true)
25
+ );
20
26
  }
27
+
28
+ // Validate that file path args exist before running
29
+ const filePath = args[1];
30
+ if (filePath) {
31
+ const fs = require("fs");
32
+ if (!fs.existsSync(filePath)) {
33
+ return Promise.resolve(result(`Error: file or folder not found: ${filePath}`, true));
34
+ }
35
+ }
36
+
21
37
  return new Promise((resolve) => {
22
38
  execFile(BASH, [TAKUMI, ...args], { timeout: 300_000, env: ENV }, (err, stdout, stderr) => {
23
39
  const output = [stdout, stderr].filter(Boolean).join("\n").trim();
24
40
  if (err && !output) {
25
- resolve({ text: `Error: ${err.message}`, isError: true });
41
+ resolve(result(`Error (exit code ${err.code}): ${err.message}`, true));
26
42
  } else if (err) {
27
- resolve({ text: output, isError: true });
43
+ resolve(result(`Error (exit code ${err.code}):\n${output}`, true));
28
44
  } else {
29
- resolve({ text: output || "Done.", isError: false });
45
+ resolve(result(output || "Done."));
30
46
  }
31
47
  });
32
48
  });
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "takumi-cli",
3
- "version": "1.2.3",
3
+ "version": "1.2.9",
4
4
  "description": "The craftsman's toolkit for shaping video assets",
5
5
  "bin": {
6
- "takumi": "bin/takumi.js"
6
+ "takumi": "bin/takumi.js",
7
+ "takumi-mcp": "bin/takumi-mcp"
7
8
  },
8
9
  "files": [
9
10
  "bin/",
package/test.sh CHANGED
@@ -131,6 +131,45 @@ assert "640x480 capped 240 → 320:240" "320:240" "$OUT"
131
131
  OUT=$(get_best_mod16 3840 2160 1080)
132
132
  assert "4K capped 1080 → 1920:1080" "1920:1080" "$OUT"
133
133
 
134
+ # ── Paths with spaces ──────────────────────────────────────────────────────
135
+
136
+ echo ""
137
+ echo "🔧 Paths with spaces"
138
+
139
+ TMP_DIR=$(mktemp -d)
140
+ SPACE_DIR="${TMP_DIR}/folder with spaces"
141
+ mkdir -p "$SPACE_DIR"
142
+
143
+ OUT=$(run info "$SPACE_DIR/nonexistent file.mp4")
144
+ assert "info handles spaces in path" "not found" "$OUT"
145
+
146
+ OUT=$(run convert "$SPACE_DIR/nonexistent file.mp4")
147
+ assert "convert handles spaces in path" "not found" "$OUT"
148
+
149
+ OUT=$(run trim "$SPACE_DIR/nonexistent file.mp4" 00:00:00 00:00:05)
150
+ assert "trim handles spaces in path" "not found" "$OUT"
151
+
152
+ OUT=$(run thumb "$SPACE_DIR/nonexistent file.mp4")
153
+ assert "thumb handles spaces in path" "not found" "$OUT"
154
+
155
+ OUT=$(run gif "$SPACE_DIR/nonexistent file.mp4" 00:00:00 00:00:05)
156
+ assert "gif handles spaces in path" "not found" "$OUT"
157
+
158
+ OUT=$(run strip "$SPACE_DIR/nonexistent file.mp4" audio)
159
+ assert "strip handles spaces in path" "not found" "$OUT"
160
+
161
+ rm -rf "$TMP_DIR"
162
+
163
+ # ── MCP server ──────────────────────────────────────────────────────────────
164
+
165
+ echo ""
166
+ echo "🔧 MCP server"
167
+
168
+ MCP_INIT='{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}'
169
+ OUT=$(echo "$MCP_INIT" | node mcp/server.js 2>/dev/null || true)
170
+ assert "MCP server initializes" "takumi" "$OUT"
171
+ assert "MCP server reports tools capability" "tools" "$OUT"
172
+
134
173
  # ── All commands listed in help ──────────────────────────────────────────────
135
174
 
136
175
  echo ""
@@ -141,6 +180,7 @@ for CMD in "${COMMANDS[@]}"; do
141
180
  assert "$CMD listed in help" "$CMD" "$HELP"
142
181
  done
143
182
  assert "setup listed in help" "setup" "$HELP"
183
+ assert "mcp-config listed in help" "mcp-config" "$HELP"
144
184
 
145
185
  # ── Results ──────────────────────────────────────────────────────────────────
146
186