@redaksjon/protokoll 1.0.2 → 1.0.7
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/BUG_FIX_CONTEXT_DIRECTORY.md +147 -0
- package/README.md +4 -0
- package/dist/main.js +3 -3
- package/dist/main.js.map +1 -1
- package/dist/mcp/server.js +621 -186
- package/dist/mcp/server.js.map +1 -1
- package/dist/term-assist.js +1 -1
- package/dist/term-context.js +1 -1
- package/dist/transcript.js +137 -44
- package/dist/transcript.js.map +1 -1
- package/docs/MCP_OVERVIEW.md +475 -0
- package/docs/MCP_RESOURCES.md +301 -0
- package/docs/MCP_RESOURCES_IMPLEMENTATION.md +278 -0
- package/docs/MCP_RESOURCES_QUICK_START.md +280 -0
- package/docs/MCP_RESOURCES_REFACTOR.md +200 -0
- package/docs/MCP_SMART_TRANSCRIPT_LOOKUP.md +562 -0
- package/docs/MCP_WORKSPACE_CONFIG.md +355 -0
- package/guide/architecture.md +2 -2
- package/guide/development.md +2 -2
- package/package.json +6 -6
- package/vite.config.ts +2 -2
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# Workspace-Level Configuration
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Protokoll's MCP server now uses **workspace-level configuration** instead of having each tool navigate up the directory tree to find configuration. This provides:
|
|
6
|
+
|
|
7
|
+
1. **Better Performance** - Configuration is loaded once at startup
|
|
8
|
+
2. **Consistency** - All tools use the same configuration
|
|
9
|
+
3. **Simplicity** - No need to pass `contextDirectory` to every tool
|
|
10
|
+
4. **Predictability** - Configuration comes from the workspace root
|
|
11
|
+
|
|
12
|
+
## How It Works
|
|
13
|
+
|
|
14
|
+
### 1. Server Initialization
|
|
15
|
+
|
|
16
|
+
When the MCP server starts:
|
|
17
|
+
|
|
18
|
+
1. It receives workspace roots from the client (via MCP roots capability)
|
|
19
|
+
2. It uses the first workspace root to find `.protokoll` configuration
|
|
20
|
+
3. It loads the configuration once and caches it
|
|
21
|
+
4. All tools use this cached configuration
|
|
22
|
+
|
|
23
|
+
### 2. Configuration Discovery
|
|
24
|
+
|
|
25
|
+
The server looks for `.protokoll/config.yaml` in the workspace root:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
/Users/me/workspace/
|
|
29
|
+
└── .protokoll/
|
|
30
|
+
└── config.yaml
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 3. Directory Resolution
|
|
34
|
+
|
|
35
|
+
Configuration values are resolved relative to the workspace root:
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
# .protokoll/config.yaml
|
|
39
|
+
inputDirectory: ./recordings # → /Users/me/workspace/recordings
|
|
40
|
+
outputDirectory: ~/notes # → /Users/me/notes (absolute)
|
|
41
|
+
processedDirectory: ./processed # → /Users/me/workspace/processed
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Configuration Structure
|
|
45
|
+
|
|
46
|
+
### Workspace Root
|
|
47
|
+
|
|
48
|
+
The workspace root is determined by:
|
|
49
|
+
|
|
50
|
+
1. **MCP Roots** (preferred): First root provided by the client
|
|
51
|
+
2. **Environment Variable**: `WORKSPACE_ROOT` if set
|
|
52
|
+
3. **Fallback**: Current working directory
|
|
53
|
+
|
|
54
|
+
### Directory Configuration
|
|
55
|
+
|
|
56
|
+
Three directories are configured at the workspace level:
|
|
57
|
+
|
|
58
|
+
| Directory | Purpose | Default |
|
|
59
|
+
|-----------|---------|---------|
|
|
60
|
+
| `inputDirectory` | Where audio files are stored | `./recordings` |
|
|
61
|
+
| `outputDirectory` | Where transcripts are saved | `./notes` |
|
|
62
|
+
| `processedDirectory` | Where processed audio is moved | `./processed` |
|
|
63
|
+
|
|
64
|
+
### Context Instance
|
|
65
|
+
|
|
66
|
+
The server also loads and caches a context instance, providing access to:
|
|
67
|
+
- Projects
|
|
68
|
+
- People
|
|
69
|
+
- Terms
|
|
70
|
+
- Companies
|
|
71
|
+
- Smart assistance configuration
|
|
72
|
+
|
|
73
|
+
## Tool Simplification
|
|
74
|
+
|
|
75
|
+
### Before (Per-Tool Navigation)
|
|
76
|
+
|
|
77
|
+
Each tool had to:
|
|
78
|
+
1. Accept a `contextDirectory` parameter
|
|
79
|
+
2. Navigate up the directory tree to find `.protokoll`
|
|
80
|
+
3. Load configuration independently
|
|
81
|
+
4. Resolve directories relative to the found configuration
|
|
82
|
+
|
|
83
|
+
**Example**:
|
|
84
|
+
```typescript
|
|
85
|
+
await client.callTool('protokoll_process_audio', {
|
|
86
|
+
audioFile: 'recording.m4a',
|
|
87
|
+
contextDirectory: '/Users/me/workspace/.protokoll' // ❌ Required
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### After (Workspace-Level)
|
|
92
|
+
|
|
93
|
+
Tools now:
|
|
94
|
+
1. Use the pre-loaded workspace configuration
|
|
95
|
+
2. No need to navigate or search
|
|
96
|
+
3. Consistent configuration across all tools
|
|
97
|
+
4. Faster execution (no repeated discovery)
|
|
98
|
+
|
|
99
|
+
**Example**:
|
|
100
|
+
```typescript
|
|
101
|
+
await client.callTool('protokoll_process_audio', {
|
|
102
|
+
audioFile: 'recording.m4a' // ✅ Just the filename
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Removed Parameters
|
|
107
|
+
|
|
108
|
+
The following parameters have been removed from tools (no longer needed):
|
|
109
|
+
|
|
110
|
+
### Audio Tools
|
|
111
|
+
- `protokoll_process_audio`: Removed `contextDirectory`
|
|
112
|
+
- `protokoll_batch_process`: Removed `contextDirectory`
|
|
113
|
+
|
|
114
|
+
### Transcript Tools
|
|
115
|
+
- All transcript tools: `contextDirectory` is now optional and rarely needed
|
|
116
|
+
|
|
117
|
+
## Server Configuration API
|
|
118
|
+
|
|
119
|
+
The server exposes a configuration API for internal use:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import * as ServerConfig from './serverConfig';
|
|
123
|
+
|
|
124
|
+
// Get the full configuration
|
|
125
|
+
const config = ServerConfig.getServerConfig();
|
|
126
|
+
console.log(config.workspaceRoot);
|
|
127
|
+
console.log(config.inputDirectory);
|
|
128
|
+
console.log(config.outputDirectory);
|
|
129
|
+
|
|
130
|
+
// Get specific directories
|
|
131
|
+
const inputDir = ServerConfig.getInputDirectory();
|
|
132
|
+
const outputDir = ServerConfig.getOutputDirectory();
|
|
133
|
+
const processedDir = ServerConfig.getProcessedDirectory(); // may be null
|
|
134
|
+
|
|
135
|
+
// Get the context instance
|
|
136
|
+
const context = ServerConfig.getContext();
|
|
137
|
+
if (context) {
|
|
138
|
+
const projects = context.getAllProjects();
|
|
139
|
+
const people = context.getAllPeople();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Check if initialized
|
|
143
|
+
if (ServerConfig.isInitialized()) {
|
|
144
|
+
// Configuration is ready
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Configuration Lifecycle
|
|
149
|
+
|
|
150
|
+
### Initialization
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// Server startup
|
|
154
|
+
const roots = await client.listRoots();
|
|
155
|
+
await ServerConfig.initializeServerConfig(roots);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Reload
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// When workspace changes
|
|
162
|
+
const roots = await client.listRoots();
|
|
163
|
+
await ServerConfig.reloadServerConfig(roots);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Clear
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// When shutting down
|
|
170
|
+
ServerConfig.clearServerConfig();
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Error Handling
|
|
174
|
+
|
|
175
|
+
### No Context Available
|
|
176
|
+
|
|
177
|
+
If no `.protokoll` directory is found in the workspace:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
Protokoll context not available. Ensure .protokoll directory exists in workspace.
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Solution**: Create a `.protokoll` directory in your workspace root with a `config.yaml` file.
|
|
184
|
+
|
|
185
|
+
### Configuration Not Initialized
|
|
186
|
+
|
|
187
|
+
If tools are called before server initialization:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
Server configuration not initialized. Call initializeServerConfig() first.
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Solution**: This is a server-side error. The server should initialize configuration on startup.
|
|
194
|
+
|
|
195
|
+
## Fallback Behavior
|
|
196
|
+
|
|
197
|
+
If configuration cannot be loaded, the server uses defaults:
|
|
198
|
+
|
|
199
|
+
| Setting | Default |
|
|
200
|
+
|---------|---------|
|
|
201
|
+
| `workspaceRoot` | Current working directory |
|
|
202
|
+
| `inputDirectory` | `./recordings` (relative to workspace) |
|
|
203
|
+
| `outputDirectory` | `./notes` (relative to workspace) |
|
|
204
|
+
| `processedDirectory` | `./processed` (relative to workspace) |
|
|
205
|
+
|
|
206
|
+
## Benefits
|
|
207
|
+
|
|
208
|
+
### 1. Performance
|
|
209
|
+
|
|
210
|
+
- Configuration loaded once, not on every tool call
|
|
211
|
+
- No repeated directory tree navigation
|
|
212
|
+
- Faster tool execution
|
|
213
|
+
|
|
214
|
+
### 2. Consistency
|
|
215
|
+
|
|
216
|
+
- All tools use the same configuration
|
|
217
|
+
- No risk of tools finding different `.protokoll` directories
|
|
218
|
+
- Predictable behavior
|
|
219
|
+
|
|
220
|
+
### 3. Simplicity
|
|
221
|
+
|
|
222
|
+
- Fewer parameters to pass
|
|
223
|
+
- Cleaner tool signatures
|
|
224
|
+
- Easier to use
|
|
225
|
+
|
|
226
|
+
### 4. Workspace Awareness
|
|
227
|
+
|
|
228
|
+
- Respects workspace boundaries
|
|
229
|
+
- Uses workspace-relative paths
|
|
230
|
+
- Integrates with IDE/editor workspace concept
|
|
231
|
+
|
|
232
|
+
## Migration from Per-Tool Configuration
|
|
233
|
+
|
|
234
|
+
### Code Changes
|
|
235
|
+
|
|
236
|
+
**Before**:
|
|
237
|
+
```typescript
|
|
238
|
+
// Every tool needed contextDirectory
|
|
239
|
+
await client.callTool('protokoll_process_audio', {
|
|
240
|
+
audioFile: '/path/to/audio.m4a',
|
|
241
|
+
contextDirectory: '/path/to/.protokoll'
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
await client.callTool('protokoll_read_transcript', {
|
|
245
|
+
transcriptPath: '/path/to/transcript.md',
|
|
246
|
+
contextDirectory: '/path/to/.protokoll'
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**After**:
|
|
251
|
+
```typescript
|
|
252
|
+
// No contextDirectory needed - uses workspace config
|
|
253
|
+
await client.callTool('protokoll_process_audio', {
|
|
254
|
+
audioFile: 'audio.m4a'
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
await client.callTool('protokoll_read_transcript', {
|
|
258
|
+
transcriptPath: 'transcript.md'
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Configuration Changes
|
|
263
|
+
|
|
264
|
+
No changes needed to your `.protokoll/config.yaml` files. The server automatically discovers and uses them from the workspace root.
|
|
265
|
+
|
|
266
|
+
## Implementation Details
|
|
267
|
+
|
|
268
|
+
### Server Configuration Module
|
|
269
|
+
|
|
270
|
+
New module: `src/mcp/serverConfig.ts`
|
|
271
|
+
|
|
272
|
+
**Key Functions**:
|
|
273
|
+
- `initializeServerConfig(roots)` - Initialize from workspace roots
|
|
274
|
+
- `reloadServerConfig(roots)` - Reload when workspace changes
|
|
275
|
+
- `getServerConfig()` - Get full configuration
|
|
276
|
+
- `getInputDirectory()` - Get input directory
|
|
277
|
+
- `getOutputDirectory()` - Get output directory
|
|
278
|
+
- `getProcessedDirectory()` - Get processed directory
|
|
279
|
+
- `getContext()` - Get context instance
|
|
280
|
+
- `getWorkspaceRoot()` - Get workspace root
|
|
281
|
+
|
|
282
|
+
### Integration Points
|
|
283
|
+
|
|
284
|
+
1. **Server Startup** (`src/mcp/server.ts`):
|
|
285
|
+
- Initializes configuration from workspace roots
|
|
286
|
+
- Handles WORKSPACE_ROOT environment variable
|
|
287
|
+
|
|
288
|
+
2. **Tool Handlers** (`src/mcp/tools/*.ts`):
|
|
289
|
+
- Import and use `ServerConfig` module
|
|
290
|
+
- No longer navigate directory tree
|
|
291
|
+
- Use cached configuration
|
|
292
|
+
|
|
293
|
+
3. **Shared Utilities** (`src/mcp/tools/shared.ts`):
|
|
294
|
+
- `getConfiguredDirectory()` now uses `ServerConfig`
|
|
295
|
+
- Simplified implementation
|
|
296
|
+
- No context parameter needed
|
|
297
|
+
|
|
298
|
+
## Testing
|
|
299
|
+
|
|
300
|
+
### Manual Testing
|
|
301
|
+
|
|
302
|
+
1. Start MCP server in a workspace with `.protokoll/config.yaml`
|
|
303
|
+
2. Verify configuration is loaded correctly
|
|
304
|
+
3. Call tools without `contextDirectory` parameter
|
|
305
|
+
4. Verify tools use workspace configuration
|
|
306
|
+
|
|
307
|
+
### Unit Testing
|
|
308
|
+
|
|
309
|
+
Tests should mock the `ServerConfig` module to provide test configuration:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import * as ServerConfig from '@/mcp/serverConfig';
|
|
313
|
+
|
|
314
|
+
// Mock configuration for tests
|
|
315
|
+
vi.mock('@/mcp/serverConfig', () => ({
|
|
316
|
+
getInputDirectory: () => '/test/recordings',
|
|
317
|
+
getOutputDirectory: () => '/test/notes',
|
|
318
|
+
getProcessedDirectory: () => '/test/processed',
|
|
319
|
+
getContext: () => mockContext,
|
|
320
|
+
}));
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Future Enhancements
|
|
324
|
+
|
|
325
|
+
### Configuration Hot Reload
|
|
326
|
+
|
|
327
|
+
When workspace roots change, the server could automatically reload configuration:
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
server.onNotification('notifications/roots/list_changed', async () => {
|
|
331
|
+
const roots = await client.listRoots();
|
|
332
|
+
await ServerConfig.reloadServerConfig(roots);
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Multi-Workspace Support
|
|
337
|
+
|
|
338
|
+
For workspaces with multiple projects, the server could:
|
|
339
|
+
- Detect which project a file belongs to
|
|
340
|
+
- Use project-specific configuration
|
|
341
|
+
- Switch configuration based on file location
|
|
342
|
+
|
|
343
|
+
### Configuration Validation
|
|
344
|
+
|
|
345
|
+
On initialization, validate that:
|
|
346
|
+
- Configured directories exist
|
|
347
|
+
- Directories are writable
|
|
348
|
+
- Audio extensions are valid
|
|
349
|
+
- Required dependencies are available
|
|
350
|
+
|
|
351
|
+
## See Also
|
|
352
|
+
|
|
353
|
+
- [Smart File Lookup](./MCP_SMART_TRANSCRIPT_LOOKUP.md)
|
|
354
|
+
- [MCP Resources](./MCP_RESOURCES.md)
|
|
355
|
+
- [MCP Tools](./MCP_TOOLS.md)
|
package/guide/architecture.md
CHANGED
|
@@ -208,8 +208,8 @@ interface PipelineInstance {
|
|
|
208
208
|
|
|
209
209
|
| Package | Purpose |
|
|
210
210
|
|---------|---------|
|
|
211
|
-
| `@
|
|
212
|
-
| `@
|
|
211
|
+
| `@utilarium/dreadcabinet` | Filesystem structure patterns |
|
|
212
|
+
| `@utilarium/cardigantime` | Hierarchical config discovery |
|
|
213
213
|
| `@riotprompt/riotprompt` | Prompt building and agentic execution |
|
|
214
214
|
| `openai` | Whisper and GPT APIs |
|
|
215
215
|
| `@anthropic-ai/sdk` | Claude API |
|
package/guide/development.md
CHANGED
|
@@ -226,8 +226,8 @@ npm run lint:fix
|
|
|
226
226
|
|
|
227
227
|
| Package | Purpose |
|
|
228
228
|
|---------|---------|
|
|
229
|
-
| `@
|
|
230
|
-
| `@
|
|
229
|
+
| `@utilarium/dreadcabinet` | Filesystem patterns |
|
|
230
|
+
| `@utilarium/cardigantime` | Hierarchical config discovery |
|
|
231
231
|
| `@riotprompt/riotprompt` | Prompt building and agentic execution |
|
|
232
232
|
| `openai` | OpenAI API (Whisper and GPT) |
|
|
233
233
|
| `@anthropic-ai/sdk` | Anthropic API (Claude) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redaksjon/protokoll",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Focused audio transcription with intelligent context integration",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"type": "module",
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
"@anthropic-ai/sdk": "^0.71.2",
|
|
46
46
|
"@google/generative-ai": "^0.24.1",
|
|
47
47
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
48
|
-
"@redaksjon/context": "^0.0.
|
|
48
|
+
"@redaksjon/context": "^0.0.4",
|
|
49
49
|
"@riotprompt/riotprompt": "^0.0.21",
|
|
50
|
-
"@
|
|
51
|
-
"@
|
|
52
|
-
"@
|
|
50
|
+
"@utilarium/cardigantime": "^0.0.24",
|
|
51
|
+
"@utilarium/dreadcabinet": "^0.0.16",
|
|
52
|
+
"@utilarium/overcontext": "^0.0.4",
|
|
53
53
|
"@types/fluent-ffmpeg": "^2.1.28",
|
|
54
54
|
"cli-table3": "^0.6.5",
|
|
55
55
|
"commander": "^14.0.2",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"moment-timezone": "^0.6.0",
|
|
64
64
|
"openai": "^6.9.0",
|
|
65
65
|
"winston": "^3.18.3",
|
|
66
|
-
"zod": "^4.
|
|
66
|
+
"zod": "^4.3.6"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@eslint/eslintrc": "^3.3.1",
|
package/vite.config.ts
CHANGED
|
@@ -62,8 +62,8 @@ export default defineConfig({
|
|
|
62
62
|
'@modelcontextprotocol/sdk/server/stdio.js',
|
|
63
63
|
'@modelcontextprotocol/sdk/types.js',
|
|
64
64
|
'@riotprompt/riotprompt',
|
|
65
|
-
'@
|
|
66
|
-
'@
|
|
65
|
+
'@utilarium/cardigantime',
|
|
66
|
+
'@utilarium/dreadcabinet',
|
|
67
67
|
'@types/fluent-ffmpeg',
|
|
68
68
|
'commander',
|
|
69
69
|
'dayjs',
|