@redaksjon/protokoll-cli 0.1.1-dev.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/.nvmrc +1 -0
- package/README.md +252 -0
- package/dist/main.js +1131 -0
- package/dist/main.js.map +1 -0
- package/eslint.config.mjs +84 -0
- package/package.json +61 -0
- package/vite.config.ts +83 -0
- package/vitest.config.ts +36 -0
package/dist/main.js
ADDED
|
@@ -0,0 +1,1131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
4
|
+
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
5
|
+
|
|
6
|
+
class ProtokolMCPClient {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
this.options.serverCommand = options.serverCommand || "protokoll-mcp";
|
|
10
|
+
this.options.serverArgs = options.serverArgs || [];
|
|
11
|
+
}
|
|
12
|
+
client = null;
|
|
13
|
+
transport = null;
|
|
14
|
+
connected = false;
|
|
15
|
+
async connect() {
|
|
16
|
+
if (this.connected) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
this.transport = new StdioClientTransport({
|
|
21
|
+
command: this.options.serverCommand,
|
|
22
|
+
args: this.options.serverArgs,
|
|
23
|
+
stderr: "inherit"
|
|
24
|
+
});
|
|
25
|
+
this.client = new Client({
|
|
26
|
+
name: "protokoll-cli",
|
|
27
|
+
version: "0.1.0"
|
|
28
|
+
});
|
|
29
|
+
await this.client.connect(this.transport);
|
|
30
|
+
this.connected = true;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
await this.cleanup();
|
|
33
|
+
throw new Error(`Failed to connect to MCP server: ${error}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async callTool(name, args = {}, progressToken) {
|
|
37
|
+
if (!this.client || !this.connected) {
|
|
38
|
+
throw new Error("Client not connected. Call connect() first.");
|
|
39
|
+
}
|
|
40
|
+
const params = { name, arguments: args };
|
|
41
|
+
if (progressToken) {
|
|
42
|
+
params._meta = { progressToken };
|
|
43
|
+
}
|
|
44
|
+
return await this.client.callTool(params);
|
|
45
|
+
}
|
|
46
|
+
async listTools() {
|
|
47
|
+
if (!this.client || !this.connected) {
|
|
48
|
+
throw new Error("Client not connected. Call connect() first.");
|
|
49
|
+
}
|
|
50
|
+
return await this.client.listTools();
|
|
51
|
+
}
|
|
52
|
+
async readResource(uri) {
|
|
53
|
+
if (!this.client || !this.connected) {
|
|
54
|
+
throw new Error("Client not connected. Call connect() first.");
|
|
55
|
+
}
|
|
56
|
+
return await this.client.readResource({ uri });
|
|
57
|
+
}
|
|
58
|
+
async listResources() {
|
|
59
|
+
if (!this.client || !this.connected) {
|
|
60
|
+
throw new Error("Client not connected. Call connect() first.");
|
|
61
|
+
}
|
|
62
|
+
return await this.client.listResources();
|
|
63
|
+
}
|
|
64
|
+
async getPrompt(name, args) {
|
|
65
|
+
if (!this.client || !this.connected) {
|
|
66
|
+
throw new Error("Client not connected. Call connect() first.");
|
|
67
|
+
}
|
|
68
|
+
return await this.client.getPrompt({ name, arguments: args });
|
|
69
|
+
}
|
|
70
|
+
async listPrompts() {
|
|
71
|
+
if (!this.client || !this.connected) {
|
|
72
|
+
throw new Error("Client not connected. Call connect() first.");
|
|
73
|
+
}
|
|
74
|
+
return await this.client.listPrompts();
|
|
75
|
+
}
|
|
76
|
+
async disconnect() {
|
|
77
|
+
await this.cleanup();
|
|
78
|
+
}
|
|
79
|
+
async cleanup() {
|
|
80
|
+
this.connected = false;
|
|
81
|
+
if (this.client) {
|
|
82
|
+
try {
|
|
83
|
+
await this.client.close();
|
|
84
|
+
} catch (_error) {
|
|
85
|
+
}
|
|
86
|
+
this.client = null;
|
|
87
|
+
}
|
|
88
|
+
if (this.transport) {
|
|
89
|
+
try {
|
|
90
|
+
await this.transport.close();
|
|
91
|
+
} catch (_error) {
|
|
92
|
+
}
|
|
93
|
+
this.transport = null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function createMCPClient(options) {
|
|
98
|
+
const client = new ProtokolMCPClient(options);
|
|
99
|
+
await client.connect();
|
|
100
|
+
return client;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const registerStatusCommands = (program) => {
|
|
104
|
+
const status = program.command("status").description("Manage transcript lifecycle status");
|
|
105
|
+
status.command("set <transcriptPath> <newStatus>").description("Set the lifecycle status of a transcript").addHelpText("after", `
|
|
106
|
+
Valid statuses: initial, enhanced, reviewed, in_progress, closed, archived
|
|
107
|
+
|
|
108
|
+
Examples:
|
|
109
|
+
protokoll status set meeting-notes.md reviewed
|
|
110
|
+
protokoll status set 2026/02/03-meeting.md closed
|
|
111
|
+
protokoll status set ~/notes/planning.md in_progress
|
|
112
|
+
`).action(async (transcriptPath, newStatus) => {
|
|
113
|
+
const client = await createMCPClient();
|
|
114
|
+
try {
|
|
115
|
+
const result = await client.callTool("protokoll_set_status", {
|
|
116
|
+
transcriptPath,
|
|
117
|
+
status: newStatus
|
|
118
|
+
});
|
|
119
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
120
|
+
const content = result.content[0];
|
|
121
|
+
if (content.type === "text") {
|
|
122
|
+
const data = JSON.parse(content.text);
|
|
123
|
+
if (data.changed) {
|
|
124
|
+
console.log(`✓ Status changed: ${data.previousStatus} → ${data.newStatus}`);
|
|
125
|
+
} else {
|
|
126
|
+
console.log(`ℹ Status is already '${data.newStatus}'`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
} finally {
|
|
134
|
+
await client.disconnect();
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
status.command("show <transcriptPath>").description("Show the current status of a transcript").action(async (transcriptPath) => {
|
|
138
|
+
const client = await createMCPClient();
|
|
139
|
+
try {
|
|
140
|
+
const result = await client.callTool("protokoll_read_transcript", {
|
|
141
|
+
transcriptPath
|
|
142
|
+
});
|
|
143
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
144
|
+
const content = result.content[0];
|
|
145
|
+
if (content.type === "text") {
|
|
146
|
+
const data = JSON.parse(content.text);
|
|
147
|
+
const status2 = data.metadata?.status || "reviewed";
|
|
148
|
+
console.log(`File: ${data.filePath}`);
|
|
149
|
+
console.log(`Title: ${data.title}`);
|
|
150
|
+
console.log(`Status: ${status2}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
} finally {
|
|
157
|
+
await client.disconnect();
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const registerTaskCommands = (program) => {
|
|
163
|
+
const task = program.command("task").description("Manage transcript tasks");
|
|
164
|
+
task.command("add <transcriptPath> <description>").description("Add a new task to a transcript").addHelpText("after", `
|
|
165
|
+
Examples:
|
|
166
|
+
protokoll task add meeting.md "Follow up with client"
|
|
167
|
+
protokoll task add notes/planning.md "Review budget proposal"
|
|
168
|
+
`).action(async (transcriptPath, description) => {
|
|
169
|
+
const client = await createMCPClient();
|
|
170
|
+
try {
|
|
171
|
+
const result = await client.callTool("protokoll_create_task", {
|
|
172
|
+
transcriptPath,
|
|
173
|
+
description
|
|
174
|
+
});
|
|
175
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
176
|
+
const content = result.content[0];
|
|
177
|
+
if (content.type === "text") {
|
|
178
|
+
const data = JSON.parse(content.text);
|
|
179
|
+
console.log(`✓ Task created: ${data.task.id}`);
|
|
180
|
+
console.log(` Description: ${data.task.description}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
} finally {
|
|
187
|
+
await client.disconnect();
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
task.command("complete <transcriptPath> <taskId>").description("Mark a task as done").addHelpText("after", `
|
|
191
|
+
Examples:
|
|
192
|
+
protokoll task complete meeting.md task-1234567890-abc123
|
|
193
|
+
`).action(async (transcriptPath, taskId) => {
|
|
194
|
+
const client = await createMCPClient();
|
|
195
|
+
try {
|
|
196
|
+
const result = await client.callTool("protokoll_complete_task", {
|
|
197
|
+
transcriptPath,
|
|
198
|
+
taskId
|
|
199
|
+
});
|
|
200
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
201
|
+
const content = result.content[0];
|
|
202
|
+
if (content.type === "text") {
|
|
203
|
+
const data = JSON.parse(content.text);
|
|
204
|
+
console.log(`✓ Task completed: ${data.taskId}`);
|
|
205
|
+
console.log(` ${data.description}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
} catch (error) {
|
|
209
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
} finally {
|
|
212
|
+
await client.disconnect();
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
task.command("delete <transcriptPath> <taskId>").description("Remove a task from a transcript").addHelpText("after", `
|
|
216
|
+
Examples:
|
|
217
|
+
protokoll task delete meeting.md task-1234567890-abc123
|
|
218
|
+
`).action(async (transcriptPath, taskId) => {
|
|
219
|
+
const client = await createMCPClient();
|
|
220
|
+
try {
|
|
221
|
+
const result = await client.callTool("protokoll_delete_task", {
|
|
222
|
+
transcriptPath,
|
|
223
|
+
taskId
|
|
224
|
+
});
|
|
225
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
226
|
+
const content = result.content[0];
|
|
227
|
+
if (content.type === "text") {
|
|
228
|
+
const data = JSON.parse(content.text);
|
|
229
|
+
console.log(`✓ Task deleted: ${data.taskId}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} catch (error) {
|
|
233
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
234
|
+
process.exit(1);
|
|
235
|
+
} finally {
|
|
236
|
+
await client.disconnect();
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const registerTranscriptCommands = (program) => {
|
|
242
|
+
const transcript = program.command("transcript").description("Read and manage transcripts");
|
|
243
|
+
transcript.command("read <transcriptPath>").description("Read a transcript file").addHelpText("after", `
|
|
244
|
+
Examples:
|
|
245
|
+
protokoll transcript read meeting-notes.md
|
|
246
|
+
protokoll transcript read 2026/02/03-meeting.md
|
|
247
|
+
`).action(async (transcriptPath) => {
|
|
248
|
+
const client = await createMCPClient();
|
|
249
|
+
try {
|
|
250
|
+
const result = await client.callTool("protokoll_read_transcript", {
|
|
251
|
+
transcriptPath
|
|
252
|
+
});
|
|
253
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
254
|
+
const content = result.content[0];
|
|
255
|
+
if (content.type === "text") {
|
|
256
|
+
const data = JSON.parse(content.text);
|
|
257
|
+
console.log(`📄 ${data.title}`);
|
|
258
|
+
console.log(` File: ${data.filePath}`);
|
|
259
|
+
console.log(` Length: ${data.contentLength} characters`);
|
|
260
|
+
console.log(`
|
|
261
|
+
${data.content}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
266
|
+
process.exit(1);
|
|
267
|
+
} finally {
|
|
268
|
+
await client.disconnect();
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
transcript.command("list").option("-l, --limit <number>", "Maximum number of results (default: 50)", "50").option("-s, --search <text>", "Search within transcripts").option("--sort <field>", "Sort by field: date, filename, title (default: date)", "date").description("List transcripts").addHelpText("after", `
|
|
272
|
+
Examples:
|
|
273
|
+
protokoll transcript list
|
|
274
|
+
protokoll transcript list --limit 20
|
|
275
|
+
protokoll transcript list --search meeting
|
|
276
|
+
protokoll transcript list --sort title
|
|
277
|
+
`).action(async (options) => {
|
|
278
|
+
const client = await createMCPClient();
|
|
279
|
+
try {
|
|
280
|
+
const result = await client.callTool("protokoll_list_transcripts", {
|
|
281
|
+
limit: parseInt(options.limit),
|
|
282
|
+
search: options.search,
|
|
283
|
+
sortBy: options.sort
|
|
284
|
+
});
|
|
285
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
286
|
+
const content = result.content[0];
|
|
287
|
+
if (content.type === "text") {
|
|
288
|
+
const data = JSON.parse(content.text);
|
|
289
|
+
console.log(`
|
|
290
|
+
📚 Transcripts (${data.pagination.total} total):`);
|
|
291
|
+
console.log(` Directory: ${data.directory}
|
|
292
|
+
`);
|
|
293
|
+
for (const t of data.transcripts) {
|
|
294
|
+
const dateTime = t.date ? `${t.date}${t.time ? ` ${t.time}` : ""}` : "unknown date";
|
|
295
|
+
console.log(` • ${t.title}`);
|
|
296
|
+
console.log(` Path: ${t.path}`);
|
|
297
|
+
console.log(` Date: ${dateTime}
|
|
298
|
+
`);
|
|
299
|
+
}
|
|
300
|
+
if (data.pagination.hasMore) {
|
|
301
|
+
console.log(` ... and ${data.pagination.total - data.transcripts.length} more`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
} catch (error) {
|
|
306
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
307
|
+
process.exit(1);
|
|
308
|
+
} finally {
|
|
309
|
+
await client.disconnect();
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const registerContextCommands = (program) => {
|
|
315
|
+
const context = program.command("context").description("Show context system overview");
|
|
316
|
+
context.command("status").description("Show context system status").action(async () => {
|
|
317
|
+
const client = await createMCPClient();
|
|
318
|
+
try {
|
|
319
|
+
const result = await client.callTool("protokoll_context_status", {});
|
|
320
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
321
|
+
const content = result.content[0];
|
|
322
|
+
if (content.type === "text") {
|
|
323
|
+
const data = JSON.parse(content.text);
|
|
324
|
+
console.log("\n[Context System Status]\n");
|
|
325
|
+
if (data.directories && data.directories.length > 0) {
|
|
326
|
+
console.log("Discovered context directories:");
|
|
327
|
+
for (const dir of data.directories) {
|
|
328
|
+
const marker = dir.level === 0 ? "→" : " ";
|
|
329
|
+
console.log(` ${marker} ${dir.path} (level ${dir.level})`);
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
console.log("No .protokoll directories found.");
|
|
333
|
+
console.log('Run "protokoll --init-config" to create one.');
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
console.log("\nLoaded entities:");
|
|
337
|
+
console.log(` Projects: ${data.counts?.projects || 0}`);
|
|
338
|
+
console.log(` People: ${data.counts?.people || 0}`);
|
|
339
|
+
console.log(` Terms: ${data.counts?.terms || 0}`);
|
|
340
|
+
console.log(` Companies: ${data.counts?.companies || 0}`);
|
|
341
|
+
console.log(` Ignored: ${data.counts?.ignored || 0}`);
|
|
342
|
+
console.log("");
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
} catch (error) {
|
|
346
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
347
|
+
process.exit(1);
|
|
348
|
+
} finally {
|
|
349
|
+
await client.disconnect();
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
context.command("search <query>").description("Search across all entity types").action(async (query) => {
|
|
353
|
+
const client = await createMCPClient();
|
|
354
|
+
try {
|
|
355
|
+
const result = await client.callTool("protokoll_search_context", { query });
|
|
356
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
357
|
+
const content = result.content[0];
|
|
358
|
+
if (content.type === "text") {
|
|
359
|
+
const data = JSON.parse(content.text);
|
|
360
|
+
if (!data.results || data.results.length === 0) {
|
|
361
|
+
console.log(`No results found for "${query}".`);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
console.log(`
|
|
365
|
+
Results for "${query}" (${data.results.length}):
|
|
366
|
+
`);
|
|
367
|
+
for (const entity of data.results) {
|
|
368
|
+
console.log(` [${entity.type}] ${entity.id} - ${entity.name}`);
|
|
369
|
+
}
|
|
370
|
+
console.log("");
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
} catch (error) {
|
|
374
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
375
|
+
process.exit(1);
|
|
376
|
+
} finally {
|
|
377
|
+
await client.disconnect();
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
const project = program.command("project").description("Manage projects");
|
|
381
|
+
project.command("list").description("List all projects").option("-v, --verbose", "Show full details").action(async (options) => {
|
|
382
|
+
const client = await createMCPClient();
|
|
383
|
+
try {
|
|
384
|
+
const result = await client.callTool("protokoll_list_projects", {});
|
|
385
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
386
|
+
const content = result.content[0];
|
|
387
|
+
if (content.type === "text") {
|
|
388
|
+
const data = JSON.parse(content.text);
|
|
389
|
+
if (!data.projects || data.projects.length === 0) {
|
|
390
|
+
console.log("No projects found.");
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
console.log(`
|
|
394
|
+
Projects (${data.projects.length}):
|
|
395
|
+
`);
|
|
396
|
+
for (const p of data.projects) {
|
|
397
|
+
if (options.verbose) {
|
|
398
|
+
console.log(` ${p.id}`);
|
|
399
|
+
console.log(` Name: ${p.name}`);
|
|
400
|
+
if (p.description) console.log(` Description: ${p.description}`);
|
|
401
|
+
if (p.routing?.destination) console.log(` Destination: ${p.routing.destination}`);
|
|
402
|
+
console.log(` Active: ${p.active !== false}`);
|
|
403
|
+
console.log("");
|
|
404
|
+
} else {
|
|
405
|
+
const status = p.active === false ? " [inactive]" : "";
|
|
406
|
+
const dest = p.routing?.destination ? ` → ${p.routing.destination}` : "";
|
|
407
|
+
console.log(` ${p.id} - ${p.name}${dest}${status}`);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
} catch (error) {
|
|
413
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
414
|
+
process.exit(1);
|
|
415
|
+
} finally {
|
|
416
|
+
await client.disconnect();
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
project.command("show <id>").description("Show details of a project").action(async (id) => {
|
|
420
|
+
const client = await createMCPClient();
|
|
421
|
+
try {
|
|
422
|
+
const result = await client.callTool("protokoll_get_entity", {
|
|
423
|
+
entityType: "project",
|
|
424
|
+
entityId: id
|
|
425
|
+
});
|
|
426
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
427
|
+
const content = result.content[0];
|
|
428
|
+
if (content.type === "text") {
|
|
429
|
+
const data = JSON.parse(content.text);
|
|
430
|
+
console.log("\n" + JSON.stringify(data.entity, null, 2));
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
} catch (error) {
|
|
434
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
435
|
+
process.exit(1);
|
|
436
|
+
} finally {
|
|
437
|
+
await client.disconnect();
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
project.command("add").description("Add a new project").requiredOption("--name <name>", "Project name").option("--id <id>", "Project ID (auto-calculated from name if not provided)").option("--description <text>", "Project description").option("--destination <path>", "Output destination path").option("--structure <type>", "Directory structure: none, year, month, day").action(async (options) => {
|
|
441
|
+
const client = await createMCPClient();
|
|
442
|
+
try {
|
|
443
|
+
const result = await client.callTool("protokoll_add_project", {
|
|
444
|
+
name: options.name,
|
|
445
|
+
id: options.id,
|
|
446
|
+
description: options.description,
|
|
447
|
+
destination: options.destination,
|
|
448
|
+
structure: options.structure
|
|
449
|
+
});
|
|
450
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
451
|
+
const content = result.content[0];
|
|
452
|
+
if (content.type === "text") {
|
|
453
|
+
const data = JSON.parse(content.text);
|
|
454
|
+
console.log(`✓ Project created: ${data.project?.id || data.id}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
} catch (error) {
|
|
458
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
459
|
+
process.exit(1);
|
|
460
|
+
} finally {
|
|
461
|
+
await client.disconnect();
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
project.command("delete <id>").description("Delete a project").action(async (id) => {
|
|
465
|
+
const client = await createMCPClient();
|
|
466
|
+
try {
|
|
467
|
+
const result = await client.callTool("protokoll_delete_entity", {
|
|
468
|
+
entityType: "project",
|
|
469
|
+
entityId: id
|
|
470
|
+
});
|
|
471
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
472
|
+
const content = result.content[0];
|
|
473
|
+
if (content.type === "text") {
|
|
474
|
+
const data = JSON.parse(content.text);
|
|
475
|
+
if (data.success) {
|
|
476
|
+
console.log(`✓ Project "${id}" deleted.`);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
} catch (error) {
|
|
481
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
482
|
+
process.exit(1);
|
|
483
|
+
} finally {
|
|
484
|
+
await client.disconnect();
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
const person = program.command("person").description("Manage people");
|
|
488
|
+
person.command("list").description("List all people").option("-v, --verbose", "Show full details").action(async (options) => {
|
|
489
|
+
const client = await createMCPClient();
|
|
490
|
+
try {
|
|
491
|
+
const result = await client.callTool("protokoll_list_people", {});
|
|
492
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
493
|
+
const content = result.content[0];
|
|
494
|
+
if (content.type === "text") {
|
|
495
|
+
const data = JSON.parse(content.text);
|
|
496
|
+
if (!data.people || data.people.length === 0) {
|
|
497
|
+
console.log("No people found.");
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
console.log(`
|
|
501
|
+
People (${data.people.length}):
|
|
502
|
+
`);
|
|
503
|
+
for (const p of data.people) {
|
|
504
|
+
if (options.verbose) {
|
|
505
|
+
console.log(` ${p.id}`);
|
|
506
|
+
console.log(` Name: ${p.name}`);
|
|
507
|
+
if (p.role) console.log(` Role: ${p.role}`);
|
|
508
|
+
if (p.company) console.log(` Company: ${p.company}`);
|
|
509
|
+
console.log("");
|
|
510
|
+
} else {
|
|
511
|
+
const details = [];
|
|
512
|
+
if (p.role) details.push(p.role);
|
|
513
|
+
if (p.company) details.push(`@${p.company}`);
|
|
514
|
+
const suffix = details.length > 0 ? ` (${details.join(" · ")})` : "";
|
|
515
|
+
console.log(` ${p.id} - ${p.name}${suffix}`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
} catch (error) {
|
|
521
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
522
|
+
process.exit(1);
|
|
523
|
+
} finally {
|
|
524
|
+
await client.disconnect();
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
person.command("show <id>").description("Show details of a person").action(async (id) => {
|
|
528
|
+
const client = await createMCPClient();
|
|
529
|
+
try {
|
|
530
|
+
const result = await client.callTool("protokoll_get_entity", {
|
|
531
|
+
entityType: "person",
|
|
532
|
+
entityId: id
|
|
533
|
+
});
|
|
534
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
535
|
+
const content = result.content[0];
|
|
536
|
+
if (content.type === "text") {
|
|
537
|
+
const data = JSON.parse(content.text);
|
|
538
|
+
console.log("\n" + JSON.stringify(data.entity, null, 2));
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
} catch (error) {
|
|
542
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
543
|
+
process.exit(1);
|
|
544
|
+
} finally {
|
|
545
|
+
await client.disconnect();
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
person.command("add").description("Add a new person").requiredOption("--name <name>", "Person name").option("--id <id>", "Person ID (auto-calculated from name if not provided)").option("--role <role>", "Role/title").option("--company <company>", "Company name").action(async (options) => {
|
|
549
|
+
const client = await createMCPClient();
|
|
550
|
+
try {
|
|
551
|
+
const result = await client.callTool("protokoll_add_person", {
|
|
552
|
+
name: options.name,
|
|
553
|
+
id: options.id,
|
|
554
|
+
role: options.role,
|
|
555
|
+
company: options.company
|
|
556
|
+
});
|
|
557
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
558
|
+
const content = result.content[0];
|
|
559
|
+
if (content.type === "text") {
|
|
560
|
+
const data = JSON.parse(content.text);
|
|
561
|
+
console.log(`✓ Person created: ${data.person?.id || data.id}`);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
} catch (error) {
|
|
565
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
566
|
+
process.exit(1);
|
|
567
|
+
} finally {
|
|
568
|
+
await client.disconnect();
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
person.command("delete <id>").description("Delete a person").action(async (id) => {
|
|
572
|
+
const client = await createMCPClient();
|
|
573
|
+
try {
|
|
574
|
+
const result = await client.callTool("protokoll_delete_entity", {
|
|
575
|
+
entityType: "person",
|
|
576
|
+
entityId: id
|
|
577
|
+
});
|
|
578
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
579
|
+
const content = result.content[0];
|
|
580
|
+
if (content.type === "text") {
|
|
581
|
+
const data = JSON.parse(content.text);
|
|
582
|
+
if (data.success) {
|
|
583
|
+
console.log(`✓ Person "${id}" deleted.`);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
} catch (error) {
|
|
588
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
589
|
+
process.exit(1);
|
|
590
|
+
} finally {
|
|
591
|
+
await client.disconnect();
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
const term = program.command("term").description("Manage terms");
|
|
595
|
+
term.command("list").description("List all terms").option("-v, --verbose", "Show full details").action(async (options) => {
|
|
596
|
+
const client = await createMCPClient();
|
|
597
|
+
try {
|
|
598
|
+
const result = await client.callTool("protokoll_list_terms", {});
|
|
599
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
600
|
+
const content = result.content[0];
|
|
601
|
+
if (content.type === "text") {
|
|
602
|
+
const data = JSON.parse(content.text);
|
|
603
|
+
if (!data.terms || data.terms.length === 0) {
|
|
604
|
+
console.log("No terms found.");
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
console.log(`
|
|
608
|
+
Terms (${data.terms.length}):
|
|
609
|
+
`);
|
|
610
|
+
for (const t of data.terms) {
|
|
611
|
+
if (options.verbose) {
|
|
612
|
+
console.log(` ${t.id}`);
|
|
613
|
+
console.log(` Name: ${t.name}`);
|
|
614
|
+
if (t.expansion) console.log(` Expansion: ${t.expansion}`);
|
|
615
|
+
if (t.domain) console.log(` Domain: ${t.domain}`);
|
|
616
|
+
console.log("");
|
|
617
|
+
} else {
|
|
618
|
+
const expansion = t.expansion ? ` (${t.expansion})` : "";
|
|
619
|
+
console.log(` ${t.id} - ${t.name}${expansion}`);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
} catch (error) {
|
|
625
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
626
|
+
process.exit(1);
|
|
627
|
+
} finally {
|
|
628
|
+
await client.disconnect();
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
term.command("show <id>").description("Show details of a term").action(async (id) => {
|
|
632
|
+
const client = await createMCPClient();
|
|
633
|
+
try {
|
|
634
|
+
const result = await client.callTool("protokoll_get_entity", {
|
|
635
|
+
entityType: "term",
|
|
636
|
+
entityId: id
|
|
637
|
+
});
|
|
638
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
639
|
+
const content = result.content[0];
|
|
640
|
+
if (content.type === "text") {
|
|
641
|
+
const data = JSON.parse(content.text);
|
|
642
|
+
console.log("\n" + JSON.stringify(data.entity, null, 2));
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
} catch (error) {
|
|
646
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
647
|
+
process.exit(1);
|
|
648
|
+
} finally {
|
|
649
|
+
await client.disconnect();
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
term.command("add").description("Add a new term").requiredOption("--name <name>", "Term name").option("--id <id>", "Term ID (auto-calculated from name if not provided)").option("--expansion <text>", "Full expansion if acronym").option("--domain <domain>", "Domain category").option("--description <text>", "Term description").action(async (options) => {
|
|
653
|
+
const client = await createMCPClient();
|
|
654
|
+
try {
|
|
655
|
+
const result = await client.callTool("protokoll_add_term", {
|
|
656
|
+
name: options.name,
|
|
657
|
+
id: options.id,
|
|
658
|
+
expansion: options.expansion,
|
|
659
|
+
domain: options.domain,
|
|
660
|
+
description: options.description
|
|
661
|
+
});
|
|
662
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
663
|
+
const content = result.content[0];
|
|
664
|
+
if (content.type === "text") {
|
|
665
|
+
const data = JSON.parse(content.text);
|
|
666
|
+
console.log(`✓ Term created: ${data.term?.id || data.id}`);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
} catch (error) {
|
|
670
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
671
|
+
process.exit(1);
|
|
672
|
+
} finally {
|
|
673
|
+
await client.disconnect();
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
term.command("merge <sourceId> <targetId>").description("Merge two terms (combines metadata, deletes source)").action(async (sourceId, targetId) => {
|
|
677
|
+
const client = await createMCPClient();
|
|
678
|
+
try {
|
|
679
|
+
const result = await client.callTool("protokoll_merge_terms", {
|
|
680
|
+
sourceId,
|
|
681
|
+
targetId
|
|
682
|
+
});
|
|
683
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
684
|
+
const content = result.content[0];
|
|
685
|
+
if (content.type === "text") {
|
|
686
|
+
const data = JSON.parse(content.text);
|
|
687
|
+
if (data.success) {
|
|
688
|
+
console.log(`✓ Merged "${sourceId}" into "${targetId}"`);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
} catch (error) {
|
|
693
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
694
|
+
process.exit(1);
|
|
695
|
+
} finally {
|
|
696
|
+
await client.disconnect();
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
term.command("delete <id>").description("Delete a term").action(async (id) => {
|
|
700
|
+
const client = await createMCPClient();
|
|
701
|
+
try {
|
|
702
|
+
const result = await client.callTool("protokoll_delete_entity", {
|
|
703
|
+
entityType: "term",
|
|
704
|
+
entityId: id
|
|
705
|
+
});
|
|
706
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
707
|
+
const content = result.content[0];
|
|
708
|
+
if (content.type === "text") {
|
|
709
|
+
const data = JSON.parse(content.text);
|
|
710
|
+
if (data.success) {
|
|
711
|
+
console.log(`✓ Term "${id}" deleted.`);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
} catch (error) {
|
|
716
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
717
|
+
process.exit(1);
|
|
718
|
+
} finally {
|
|
719
|
+
await client.disconnect();
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
const company = program.command("company").description("Manage companies");
|
|
723
|
+
company.command("list").description("List all companies").option("-v, --verbose", "Show full details").action(async (options) => {
|
|
724
|
+
const client = await createMCPClient();
|
|
725
|
+
try {
|
|
726
|
+
const result = await client.callTool("protokoll_list_companies", {});
|
|
727
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
728
|
+
const content = result.content[0];
|
|
729
|
+
if (content.type === "text") {
|
|
730
|
+
const data = JSON.parse(content.text);
|
|
731
|
+
if (!data.companies || data.companies.length === 0) {
|
|
732
|
+
console.log("No companies found.");
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
console.log(`
|
|
736
|
+
Companies (${data.companies.length}):
|
|
737
|
+
`);
|
|
738
|
+
for (const c of data.companies) {
|
|
739
|
+
if (options.verbose) {
|
|
740
|
+
console.log(` ${c.id}`);
|
|
741
|
+
console.log(` Name: ${c.name}`);
|
|
742
|
+
if (c.industry) console.log(` Industry: ${c.industry}`);
|
|
743
|
+
console.log("");
|
|
744
|
+
} else {
|
|
745
|
+
const industry = c.industry ? ` [${c.industry}]` : "";
|
|
746
|
+
console.log(` ${c.id} - ${c.name}${industry}`);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
} catch (error) {
|
|
752
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
753
|
+
process.exit(1);
|
|
754
|
+
} finally {
|
|
755
|
+
await client.disconnect();
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
company.command("show <id>").description("Show details of a company").action(async (id) => {
|
|
759
|
+
const client = await createMCPClient();
|
|
760
|
+
try {
|
|
761
|
+
const result = await client.callTool("protokoll_get_entity", {
|
|
762
|
+
entityType: "company",
|
|
763
|
+
entityId: id
|
|
764
|
+
});
|
|
765
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
766
|
+
const content = result.content[0];
|
|
767
|
+
if (content.type === "text") {
|
|
768
|
+
const data = JSON.parse(content.text);
|
|
769
|
+
console.log("\n" + JSON.stringify(data.entity, null, 2));
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
} catch (error) {
|
|
773
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
774
|
+
process.exit(1);
|
|
775
|
+
} finally {
|
|
776
|
+
await client.disconnect();
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
company.command("add").description("Add a new company").requiredOption("--name <name>", "Company name").option("--id <id>", "Company ID (auto-calculated from name if not provided)").option("--industry <industry>", "Industry sector").action(async (options) => {
|
|
780
|
+
const client = await createMCPClient();
|
|
781
|
+
try {
|
|
782
|
+
const result = await client.callTool("protokoll_add_company", {
|
|
783
|
+
name: options.name,
|
|
784
|
+
id: options.id,
|
|
785
|
+
industry: options.industry
|
|
786
|
+
});
|
|
787
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
788
|
+
const content = result.content[0];
|
|
789
|
+
if (content.type === "text") {
|
|
790
|
+
const data = JSON.parse(content.text);
|
|
791
|
+
console.log(`✓ Company created: ${data.company?.id || data.id}`);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
} catch (error) {
|
|
795
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
796
|
+
process.exit(1);
|
|
797
|
+
} finally {
|
|
798
|
+
await client.disconnect();
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
company.command("delete <id>").description("Delete a company").action(async (id) => {
|
|
802
|
+
const client = await createMCPClient();
|
|
803
|
+
try {
|
|
804
|
+
const result = await client.callTool("protokoll_delete_entity", {
|
|
805
|
+
entityType: "company",
|
|
806
|
+
entityId: id
|
|
807
|
+
});
|
|
808
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
809
|
+
const content = result.content[0];
|
|
810
|
+
if (content.type === "text") {
|
|
811
|
+
const data = JSON.parse(content.text);
|
|
812
|
+
if (data.success) {
|
|
813
|
+
console.log(`✓ Company "${id}" deleted.`);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
} catch (error) {
|
|
818
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
819
|
+
process.exit(1);
|
|
820
|
+
} finally {
|
|
821
|
+
await client.disconnect();
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
const registerActionCommands = (program) => {
|
|
827
|
+
const action = program.command("action").description("Perform actions on transcripts");
|
|
828
|
+
action.command("combine <files...>").description("Combine multiple transcripts into one").option("-t, --title <title>", "Title for combined transcript").option("-p, --project <projectId>", "Project ID to assign").addHelpText("after", `
|
|
829
|
+
Examples:
|
|
830
|
+
protokoll action combine meeting-1.md meeting-2.md
|
|
831
|
+
protokoll action combine notes/*.md --title "Weekly Summary"
|
|
832
|
+
protokoll action combine 2026/02/*.md --project weekly-review
|
|
833
|
+
`).action(async (files, options) => {
|
|
834
|
+
const client = await createMCPClient();
|
|
835
|
+
try {
|
|
836
|
+
const result = await client.callTool("protokoll_combine_transcripts", {
|
|
837
|
+
transcriptPaths: files,
|
|
838
|
+
title: options.title,
|
|
839
|
+
projectId: options.project
|
|
840
|
+
});
|
|
841
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
842
|
+
const content = result.content[0];
|
|
843
|
+
if (content.type === "text") {
|
|
844
|
+
const data = JSON.parse(content.text);
|
|
845
|
+
console.log(`✓ Combined ${data.sourceFiles?.length || files.length} transcripts`);
|
|
846
|
+
console.log(` Output: ${data.outputPath}`);
|
|
847
|
+
if (data.deletedFiles?.length > 0) {
|
|
848
|
+
console.log(` Deleted: ${data.deletedFiles.length} source files`);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
} catch (error) {
|
|
853
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
854
|
+
process.exit(1);
|
|
855
|
+
} finally {
|
|
856
|
+
await client.disconnect();
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
action.command("edit <transcriptPath>").description("Edit transcript metadata").option("-t, --title <title>", "New title (renames file)").option("-p, --project <projectId>", "New project ID").option("--add-tag <tag>", "Add a tag (can be repeated)", collect, []).option("--remove-tag <tag>", "Remove a tag (can be repeated)", collect, []).option("-s, --status <status>", "New status (initial, enhanced, reviewed, in_progress, closed, archived)").addHelpText("after", `
|
|
860
|
+
Examples:
|
|
861
|
+
protokoll action edit meeting.md --title "Q1 Planning Meeting"
|
|
862
|
+
protokoll action edit notes.md --project quarterly-review
|
|
863
|
+
protokoll action edit notes.md --add-tag important --add-tag review
|
|
864
|
+
protokoll action edit notes.md --status reviewed
|
|
865
|
+
`).action(async (transcriptPath, options) => {
|
|
866
|
+
const client = await createMCPClient();
|
|
867
|
+
try {
|
|
868
|
+
const result = await client.callTool("protokoll_edit_transcript", {
|
|
869
|
+
transcriptPath,
|
|
870
|
+
title: options.title,
|
|
871
|
+
projectId: options.project,
|
|
872
|
+
tagsToAdd: options.addTag?.length > 0 ? options.addTag : void 0,
|
|
873
|
+
tagsToRemove: options.removeTag?.length > 0 ? options.removeTag : void 0,
|
|
874
|
+
status: options.status
|
|
875
|
+
});
|
|
876
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
877
|
+
const content = result.content[0];
|
|
878
|
+
if (content.type === "text") {
|
|
879
|
+
const data = JSON.parse(content.text);
|
|
880
|
+
console.log(`✓ ${data.message}`);
|
|
881
|
+
if (data.renamed) {
|
|
882
|
+
console.log(` New path: ${data.outputPath}`);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
} catch (error) {
|
|
887
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
888
|
+
process.exit(1);
|
|
889
|
+
} finally {
|
|
890
|
+
await client.disconnect();
|
|
891
|
+
}
|
|
892
|
+
});
|
|
893
|
+
action.command("change-date <transcriptPath> <newDate>").description("Change the date of a transcript (moves file)").addHelpText("after", `
|
|
894
|
+
Examples:
|
|
895
|
+
protokoll action change-date meeting.md 2026-02-01
|
|
896
|
+
protokoll action change-date notes.md 2026-01-15T10:30:00Z
|
|
897
|
+
`).action(async (transcriptPath, newDate) => {
|
|
898
|
+
const client = await createMCPClient();
|
|
899
|
+
try {
|
|
900
|
+
const result = await client.callTool("protokoll_change_transcript_date", {
|
|
901
|
+
transcriptPath,
|
|
902
|
+
newDate
|
|
903
|
+
});
|
|
904
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
905
|
+
const content = result.content[0];
|
|
906
|
+
if (content.type === "text") {
|
|
907
|
+
const data = JSON.parse(content.text);
|
|
908
|
+
if (data.moved) {
|
|
909
|
+
console.log(`✓ Transcript moved`);
|
|
910
|
+
console.log(` From: ${data.originalPath}`);
|
|
911
|
+
console.log(` To: ${data.outputPath}`);
|
|
912
|
+
} else {
|
|
913
|
+
console.log(`ℹ ${data.message}`);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
} catch (error) {
|
|
918
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
919
|
+
process.exit(1);
|
|
920
|
+
} finally {
|
|
921
|
+
await client.disconnect();
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
action.command("create-note").description("Create a new note/transcript").requiredOption("-t, --title <title>", "Note title").option("-c, --content <content>", "Note content").option("-p, --project <projectId>", "Project ID to assign").option("--tag <tag>", "Add a tag (can be repeated)", collect, []).option("-d, --date <date>", "Date for the note (ISO format, defaults to now)").addHelpText("after", `
|
|
925
|
+
Examples:
|
|
926
|
+
protokoll action create-note --title "Meeting Notes"
|
|
927
|
+
protokoll action create-note --title "Planning" --project quarterly-review
|
|
928
|
+
protokoll action create-note --title "Ideas" --tag brainstorm --tag important
|
|
929
|
+
`).action(async (options) => {
|
|
930
|
+
const client = await createMCPClient();
|
|
931
|
+
try {
|
|
932
|
+
const result = await client.callTool("protokoll_create_note", {
|
|
933
|
+
title: options.title,
|
|
934
|
+
content: options.content,
|
|
935
|
+
projectId: options.project,
|
|
936
|
+
tags: options.tag?.length > 0 ? options.tag : void 0,
|
|
937
|
+
date: options.date
|
|
938
|
+
});
|
|
939
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
940
|
+
const content = result.content[0];
|
|
941
|
+
if (content.type === "text") {
|
|
942
|
+
const data = JSON.parse(content.text);
|
|
943
|
+
console.log(`✓ ${data.message}`);
|
|
944
|
+
console.log(` Path: ${data.filePath}`);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
} catch (error) {
|
|
948
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
949
|
+
process.exit(1);
|
|
950
|
+
} finally {
|
|
951
|
+
await client.disconnect();
|
|
952
|
+
}
|
|
953
|
+
});
|
|
954
|
+
};
|
|
955
|
+
function collect(value, previous) {
|
|
956
|
+
return previous.concat([value]);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
const registerFeedbackCommands = (program) => {
|
|
960
|
+
program.command("feedback <transcriptPath> <feedback>").description("Provide natural language feedback to correct a transcript").option("-m, --model <model>", "LLM model for processing feedback").addHelpText("after", `
|
|
961
|
+
The feedback command processes natural language corrections using AI.
|
|
962
|
+
It can fix spelling, add terms to context, change project assignment, etc.
|
|
963
|
+
|
|
964
|
+
Examples:
|
|
965
|
+
protokoll feedback meeting.md "YB should be Wibey"
|
|
966
|
+
protokoll feedback notes.md "San Jay Grouper is actually Sanjay Gupta"
|
|
967
|
+
protokoll feedback notes.md "This should be assigned to the quarterly-review project"
|
|
968
|
+
protokoll feedback notes.md "Add 'kubernetes' as a technical term"
|
|
969
|
+
`).action(async (transcriptPath, feedback, options) => {
|
|
970
|
+
const client = await createMCPClient();
|
|
971
|
+
try {
|
|
972
|
+
console.log("Processing feedback...");
|
|
973
|
+
const result = await client.callTool("protokoll_provide_feedback", {
|
|
974
|
+
transcriptPath,
|
|
975
|
+
feedback,
|
|
976
|
+
model: options.model
|
|
977
|
+
});
|
|
978
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
979
|
+
const content = result.content[0];
|
|
980
|
+
if (content.type === "text") {
|
|
981
|
+
const data = JSON.parse(content.text);
|
|
982
|
+
if (data.changesApplied > 0) {
|
|
983
|
+
console.log(`
|
|
984
|
+
✓ Applied ${data.changesApplied} change(s):`);
|
|
985
|
+
for (const change of data.changes) {
|
|
986
|
+
console.log(` • ${change.type}: ${change.description}`);
|
|
987
|
+
}
|
|
988
|
+
if (data.moved) {
|
|
989
|
+
console.log(`
|
|
990
|
+
File moved to: ${data.outputPath}`);
|
|
991
|
+
}
|
|
992
|
+
} else {
|
|
993
|
+
console.log("\nℹ No changes were applied.");
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
} catch (error) {
|
|
998
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
999
|
+
process.exit(1);
|
|
1000
|
+
} finally {
|
|
1001
|
+
await client.disconnect();
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
};
|
|
1005
|
+
|
|
1006
|
+
const registerAudioCommands = (program) => {
|
|
1007
|
+
program.command("process <audioFile>").description("Process an audio file through transcription pipeline").option("-p, --project <projectId>", "Specific project ID for routing").option("-o, --output <directory>", "Override output directory").option("-m, --model <model>", "LLM model for enhancement").option("--transcription-model <model>", "Transcription model (default: whisper-1)").addHelpText("after", `
|
|
1008
|
+
Examples:
|
|
1009
|
+
protokoll process recording.m4a
|
|
1010
|
+
protokoll process audio.m4a --project weekly-review
|
|
1011
|
+
protokoll process /path/to/audio.wav --output ~/transcripts
|
|
1012
|
+
`).action(async (audioFile, options) => {
|
|
1013
|
+
const client = await createMCPClient();
|
|
1014
|
+
try {
|
|
1015
|
+
console.log("Processing audio file...\n");
|
|
1016
|
+
const result = await client.callTool("protokoll_process_audio", {
|
|
1017
|
+
audioFile,
|
|
1018
|
+
projectId: options.project,
|
|
1019
|
+
outputDirectory: options.output,
|
|
1020
|
+
model: options.model,
|
|
1021
|
+
transcriptionModel: options["transcription-model"]
|
|
1022
|
+
});
|
|
1023
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
1024
|
+
const content = result.content[0];
|
|
1025
|
+
if (content.type === "text") {
|
|
1026
|
+
const data = JSON.parse(content.text);
|
|
1027
|
+
console.log("\n✓ Audio processed successfully\n");
|
|
1028
|
+
if (data.outputPath) {
|
|
1029
|
+
console.log(`Output: ${data.outputPath}`);
|
|
1030
|
+
}
|
|
1031
|
+
if (data.title) {
|
|
1032
|
+
console.log(`Title: ${data.title}`);
|
|
1033
|
+
}
|
|
1034
|
+
if (data.project) {
|
|
1035
|
+
console.log(`Project: ${data.project}`);
|
|
1036
|
+
}
|
|
1037
|
+
if (data.duration) {
|
|
1038
|
+
console.log(`Duration: ${data.duration}`);
|
|
1039
|
+
}
|
|
1040
|
+
if (data.message) {
|
|
1041
|
+
console.log(`
|
|
1042
|
+
${data.message}`);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
} catch (error) {
|
|
1047
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1048
|
+
process.exit(1);
|
|
1049
|
+
} finally {
|
|
1050
|
+
await client.disconnect();
|
|
1051
|
+
}
|
|
1052
|
+
});
|
|
1053
|
+
program.command("batch <inputDirectory>").description("Process multiple audio files in a directory").option("-o, --output <directory>", "Override output directory").option("-e, --extensions <list>", "Audio extensions (comma-separated, default: m4a,mp3,wav,webm)").addHelpText("after", `
|
|
1054
|
+
Examples:
|
|
1055
|
+
protokoll batch ~/recordings
|
|
1056
|
+
protokoll batch /media/audio --output ~/transcripts
|
|
1057
|
+
`).action(async (inputDirectory, options) => {
|
|
1058
|
+
const client = await createMCPClient();
|
|
1059
|
+
try {
|
|
1060
|
+
console.log("Batch processing audio files...\n");
|
|
1061
|
+
const extensions = options.extensions ? options.extensions.split(",").map((ext) => ext.trim()) : void 0;
|
|
1062
|
+
const result = await client.callTool("protokoll_batch_process", {
|
|
1063
|
+
inputDirectory,
|
|
1064
|
+
outputDirectory: options.output,
|
|
1065
|
+
extensions
|
|
1066
|
+
});
|
|
1067
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
1068
|
+
const content = result.content[0];
|
|
1069
|
+
if (content.type === "text") {
|
|
1070
|
+
const data = JSON.parse(content.text);
|
|
1071
|
+
console.log(`
|
|
1072
|
+
✓ Batch processing complete
|
|
1073
|
+
`);
|
|
1074
|
+
console.log(`Processed: ${data.processedCount || 0} files`);
|
|
1075
|
+
console.log(`Failed: ${data.failedCount || 0} files`);
|
|
1076
|
+
if (data.results && Array.isArray(data.results)) {
|
|
1077
|
+
console.log("\nResults:");
|
|
1078
|
+
for (const result2 of data.results) {
|
|
1079
|
+
const status = result2.success ? "✓" : "✗";
|
|
1080
|
+
console.log(` ${status} ${result2.filename || result2.file}`);
|
|
1081
|
+
if (result2.outputPath) {
|
|
1082
|
+
console.log(` → ${result2.outputPath}`);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1090
|
+
process.exit(1);
|
|
1091
|
+
} finally {
|
|
1092
|
+
await client.disconnect();
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
};
|
|
1096
|
+
|
|
1097
|
+
const program = new Command();
|
|
1098
|
+
const VERSION = "0.1.1-dev.0";
|
|
1099
|
+
const GIT_INFO = "working 6754a2d ";
|
|
1100
|
+
program.name("protokoll").description("Protokoll CLI - MCP client for transcription and context management").version(VERSION);
|
|
1101
|
+
program.command("version").description("Show version information from MCP server").action(async () => {
|
|
1102
|
+
const client = await createMCPClient();
|
|
1103
|
+
try {
|
|
1104
|
+
const result = await client.callTool("protokoll_get_version");
|
|
1105
|
+
console.log("Protokoll CLI:", VERSION);
|
|
1106
|
+
console.log("Git:", GIT_INFO);
|
|
1107
|
+
console.log("\nMCP Server:");
|
|
1108
|
+
if (result.content && Array.isArray(result.content) && result.content.length > 0) {
|
|
1109
|
+
const content = result.content[0];
|
|
1110
|
+
if (content.type === "text") {
|
|
1111
|
+
console.log(content.text);
|
|
1112
|
+
}
|
|
1113
|
+
} else {
|
|
1114
|
+
console.log("No version information returned from server");
|
|
1115
|
+
}
|
|
1116
|
+
} catch (error) {
|
|
1117
|
+
console.error("Error calling MCP server:", error);
|
|
1118
|
+
process.exit(1);
|
|
1119
|
+
} finally {
|
|
1120
|
+
await client.disconnect();
|
|
1121
|
+
}
|
|
1122
|
+
});
|
|
1123
|
+
registerStatusCommands(program);
|
|
1124
|
+
registerTaskCommands(program);
|
|
1125
|
+
registerTranscriptCommands(program);
|
|
1126
|
+
registerContextCommands(program);
|
|
1127
|
+
registerActionCommands(program);
|
|
1128
|
+
registerFeedbackCommands(program);
|
|
1129
|
+
registerAudioCommands(program);
|
|
1130
|
+
program.parse();
|
|
1131
|
+
//# sourceMappingURL=main.js.map
|