@dollhousemcp/mcp-server 2.0.14 → 2.0.16

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/generated/version.d.ts +2 -2
  3. package/dist/generated/version.js +3 -3
  4. package/dist/handlers/ElementCRUDHandler.d.ts.map +1 -1
  5. package/dist/handlers/ElementCRUDHandler.js +7 -3
  6. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
  7. package/dist/handlers/mcp-aql/MCPAQLHandler.js +35 -19
  8. package/dist/handlers/mcp-aql/OperationSchema.d.ts.map +1 -1
  9. package/dist/handlers/mcp-aql/OperationSchema.js +4 -3
  10. package/dist/handlers/mcp-aql/evaluatePermission.d.ts +2 -1
  11. package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -1
  12. package/dist/handlers/mcp-aql/evaluatePermission.js +22 -11
  13. package/dist/handlers/strategies/BaseActivationStrategy.d.ts.map +1 -1
  14. package/dist/handlers/strategies/BaseActivationStrategy.js +12 -3
  15. package/dist/handlers/strategies/PersonaActivationStrategy.js +2 -2
  16. package/dist/utils/permissionHooks.d.ts +38 -0
  17. package/dist/utils/permissionHooks.d.ts.map +1 -0
  18. package/dist/utils/permissionHooks.js +194 -0
  19. package/dist/web/public/index.html +12 -6
  20. package/dist/web/public/permissions.css +11 -0
  21. package/dist/web/public/permissions.js +43 -12
  22. package/dist/web/public/setup.css +172 -1
  23. package/dist/web/public/setup.js +353 -20
  24. package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
  25. package/dist/web/routes/permissionRoutes.js +64 -15
  26. package/dist/web/routes/setupRoutes.d.ts +3 -0
  27. package/dist/web/routes/setupRoutes.d.ts.map +1 -1
  28. package/dist/web/routes/setupRoutes.js +14 -3
  29. package/package.json +6 -1
  30. package/scripts/pretooluse-codex.sh +6 -0
  31. package/scripts/pretooluse-cursor.sh +6 -0
  32. package/scripts/pretooluse-dollhouse.sh +110 -0
  33. package/scripts/pretooluse-gemini.sh +6 -0
  34. package/scripts/pretooluse-windsurf.sh +6 -0
  35. package/server.json +2 -2
@@ -77,6 +77,10 @@
77
77
  <strong>Pinned version</strong>
78
78
  <span>Lock to a specific version, update when you choose</span>
79
79
  </button>
80
+ <button class="setup-method-btn" data-method="permissions" aria-pressed="false">
81
+ <strong>Permissions &amp; Security</strong>
82
+ <span>Manual hook assets and enforcement guidance</span>
83
+ </button>
80
84
  </fieldset>
81
85
 
82
86
  <fieldset class="setup-channel-toggle" id="setup-channel-toggle">
@@ -119,6 +123,8 @@ npm install @dollhousemcp/mcp-server</code></pre>
119
123
  </div>
120
124
  </div>
121
125
 
126
+ <div class="setup-permissions-intro" id="setup-permissions-intro" hidden></div>
127
+
122
128
  <div class="setup-platforms" id="setup-platforms" role="tablist" aria-label="Platform install instructions">
123
129
  <button class="setup-platform-tab is-active" role="tab" aria-selected="true" aria-controls="setup-panel-claude-desktop" id="setup-tab-claude-desktop">Claude Desktop</button>
124
130
  <button class="setup-platform-tab" role="tab" aria-selected="false" aria-controls="setup-panel-claude-code" id="setup-tab-claude-code">Claude Code</button>
@@ -133,7 +139,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
133
139
 
134
140
  <!-- Claude Desktop -->
135
141
  <section class="setup-panel is-active" role="tabpanel" id="setup-panel-claude-desktop" aria-labelledby="setup-tab-claude-desktop">
136
- <div class="setup-method setup-method-primary">
142
+ <div class="setup-method setup-method-primary" data-setup-modes="npx global">
137
143
  <h3>Auto-configure <span class="setup-method-badge setup-badge">auto-updating</span></h3>
138
144
  <p class="setup-method-desc">Pulls the latest version of DollhouseMCP on every startup. Uses <code>npx @latest</code> under the hood. Restart Claude Desktop after.</p>
139
145
  <div class="setup-install-row">
@@ -141,12 +147,12 @@ npm install @dollhousemcp/mcp-server</code></pre>
141
147
  <span class="setup-install-status" data-install-status="claude"></span>
142
148
  </div>
143
149
  </div>
144
- <div class="setup-method setup-mcpb-option" id="setup-mcpb-section" hidden>
150
+ <div class="setup-method setup-mcpb-option" id="setup-mcpb-section" data-setup-modes="global" hidden>
145
151
  <h3>Or install via Desktop Extension <span class="setup-badge">pinned version</span></h3>
146
152
  <p>Download the <code>.mcpb</code> bundle and double-click it to install. Claude Desktop handles everything automatically &mdash; no terminal, no config editing. This installs a pinned copy that won't auto-update.</p>
147
153
  <a class="setup-btn setup-btn-secondary" href="/api/setup/mcpb" id="pinned-mcpb-btn">Download .mcpb <span id="pinned-mcpb-version"></span></a>
148
154
  </div>
149
- <div class="setup-method">
155
+ <div class="setup-method" data-setup-modes="npx global">
150
156
  <h3>Or add manually
151
157
  <button class="setup-open-btn" type="button" data-open-client="claude">Open config file</button>
152
158
  </h3>
@@ -173,7 +179,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
173
179
 
174
180
  <!-- Claude Code -->
175
181
  <section class="setup-panel" role="tabpanel" id="setup-panel-claude-code" aria-labelledby="setup-tab-claude-code" hidden>
176
- <div class="setup-method setup-method-primary">
182
+ <div class="setup-method setup-method-primary" data-setup-modes="npx global">
177
183
  <h3>Auto-configure <span class="setup-method-badge setup-badge">auto-updating</span></h3>
178
184
  <p class="setup-method-desc">Adds DollhouseMCP to Claude Code, pulling the latest version on every startup.</p>
179
185
  <div class="setup-install-row">
@@ -181,7 +187,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
181
187
  <span class="setup-install-status" data-install-status="claude-code"></span>
182
188
  </div>
183
189
  </div>
184
- <div class="setup-method">
190
+ <div class="setup-method" data-setup-modes="npx global">
185
191
  <h3>Or run in your terminal</h3>
186
192
  <p>Start a new conversation and you're ready.</p>
187
193
  <div class="setup-code-block">
@@ -189,7 +195,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
189
195
  <pre><code>claude mcp add dollhousemcp -- npx -y @dollhousemcp/mcp-server@latest</code></pre>
190
196
  </div>
191
197
  </div>
192
- <div class="setup-method">
198
+ <div class="setup-method" data-setup-modes="npx global">
193
199
  <h3>Or add manually
194
200
  <button class="setup-open-btn" type="button" data-open-client="claude-code">Open config file</button>
195
201
  </h3>
@@ -46,6 +46,11 @@
46
46
  box-shadow: 0 0 6px rgba(239, 68, 68, 0.5);
47
47
  }
48
48
 
49
+ .perm-status-dot[data-status="warning"] {
50
+ background: #f59e0b;
51
+ box-shadow: 0 0 6px rgba(245, 158, 11, 0.45);
52
+ }
53
+
49
54
  .perm-status-spacer {
50
55
  flex: 1;
51
56
  }
@@ -54,6 +59,12 @@
54
59
  color: var(--ink-400, #64748b);
55
60
  }
56
61
 
62
+ .perm-inline-advisory {
63
+ display: inline-block;
64
+ color: var(--signal-4-ink, #b45309);
65
+ margin-top: 0.35rem;
66
+ }
67
+
57
68
  /* ── Dashboard Grid ────────────────────────────────────────── */
58
69
 
59
70
  .perm-dashboard {
@@ -116,6 +116,7 @@
116
116
  function render(data, selectedData) {
117
117
  renderStatusBar(data);
118
118
  renderSummaryStats(data);
119
+ renderAdvisory(data);
119
120
  renderPolicySources(data, selectedData);
120
121
  renderSelectedSessionDetail(selectedData);
121
122
  renderDenyPatterns(data);
@@ -137,6 +138,7 @@
137
138
  const serverDot = document.getElementById('perm-dot-server');
138
139
  const ensembleDot = document.getElementById('perm-dot-ensemble');
139
140
  const hookDot = document.getElementById('perm-dot-hook');
141
+ const hookLabel = hookDot ? hookDot.parentElement.querySelector('.perm-status-label') : null;
140
142
  const updated = document.getElementById('perm-last-updated');
141
143
 
142
144
  if (serverDot) {
@@ -149,11 +151,23 @@
149
151
  ensembleDot.parentElement.querySelector('.perm-status-label').textContent =
150
152
  hasElements ? `${data.activeElementCount} elements` : 'No ensemble';
151
153
  }
152
- if (hookDot) {
153
- const hasPatterns = (data.denyPatterns?.length || 0) + (data.allowPatterns?.length || 0) > 0;
154
- hookDot.dataset.status = hasPatterns ? 'active' : 'inactive';
155
- hookDot.parentElement.querySelector('.perm-status-label').textContent =
156
- hasPatterns ? 'Policies active' : 'No policies';
154
+ if (hookDot && hookLabel) {
155
+ const hasPatterns = (data.denyPatterns?.length || 0)
156
+ + (data.allowPatterns?.length || 0)
157
+ + (data.confirmPatterns?.length || 0) > 0;
158
+ if (!hasPatterns) {
159
+ hookDot.dataset.status = 'inactive';
160
+ hookLabel.textContent = 'No policies';
161
+ } else if (data.permissionPromptActive) {
162
+ hookDot.dataset.status = 'active';
163
+ hookLabel.textContent = 'Prompt tool active';
164
+ } else if (data.hookInstalled) {
165
+ hookDot.dataset.status = 'active';
166
+ hookLabel.textContent = data.hookHost ? `Hook installed (${data.hookHost})` : 'Hook installed';
167
+ } else {
168
+ hookDot.dataset.status = 'warning';
169
+ hookLabel.textContent = 'Policies loaded, not enforced';
170
+ }
157
171
  }
158
172
  if (updated) {
159
173
  updated.textContent = new Date().toLocaleTimeString();
@@ -176,6 +190,19 @@
176
190
  setText('perm-stat-asked', asked);
177
191
  }
178
192
 
193
+ function renderAdvisory(data) {
194
+ const advisory = document.getElementById('perm-all-sessions-advisory');
195
+ if (!advisory) return;
196
+
197
+ if (data && data.advisory) {
198
+ advisory.hidden = false;
199
+ advisory.textContent = ` ${data.advisory}`;
200
+ } else {
201
+ advisory.hidden = true;
202
+ advisory.textContent = '';
203
+ }
204
+ }
205
+
179
206
  function renderPolicySources(data, selectedData) {
180
207
  const list = document.getElementById('perm-source-list');
181
208
  if (!list) return;
@@ -190,7 +217,7 @@
190
217
  list.innerHTML = elements.map(el => `
191
218
  <li class="perm-source-item${elementMatchesSelected(el, selectedSessionId) ? ' perm-source-item--selected' : ''}">
192
219
  <span class="perm-source-type">${esc(el.type)}</span>
193
- <span class="perm-source-name">${esc(el.element_name)}</span>
220
+ <span class="perm-source-name">${esc(el.element_name || el.name || '')}</span>
194
221
  ${el.description ? `<span style="color:var(--ink-400);font-size:0.75rem;margin-left:auto">${esc(el.description)}</span>` : ''}
195
222
  </li>
196
223
  `).join('');
@@ -239,7 +266,7 @@
239
266
  : elements.map(el => `
240
267
  <li class="perm-source-item perm-source-item--detail">
241
268
  <span class="perm-source-type">${esc(el.type)}</span>
242
- <span class="perm-source-name">${esc(el.element_name)}</span>
269
+ <span class="perm-source-name">${esc(el.element_name || el.name || '')}</span>
243
270
  ${el.description ? `<span style="color:var(--ink-400);font-size:0.75rem;margin-left:auto">${esc(el.description)}</span>` : ''}
244
271
  </li>
245
272
  `).join('');
@@ -374,10 +401,10 @@
374
401
  <span class="perm-status-dot" id="perm-dot-ensemble" data-status="inactive"></span>
375
402
  <span class="perm-status-label">Ensemble</span>
376
403
  </div>
377
- <div class="perm-status-indicator">
378
- <span class="perm-status-dot" id="perm-dot-hook" data-status="inactive"></span>
379
- <span class="perm-status-label">Policies</span>
380
- </div>
404
+ <div class="perm-status-indicator">
405
+ <span class="perm-status-dot" id="perm-dot-hook" data-status="inactive"></span>
406
+ <span class="perm-status-label">Policies</span>
407
+ </div>
381
408
  <span class="perm-status-spacer"></span>
382
409
  <span class="perm-status-updated">Updated: <span id="perm-last-updated">--:--:--</span></span>
383
410
  </div>
@@ -504,7 +531,7 @@
504
531
  <div class="perm-selected-header perm-selected-header--compact">
505
532
  <div>
506
533
  <div class="perm-selected-title">All Sessions</div>
507
- <div class="perm-selected-subtitle">Aggregate policy state across all live and persisted sessions. The decision feed below is currently aggregate, not selection-scoped.</div>
534
+ <div class="perm-selected-subtitle">${esc('Aggregate policy state across all live and persisted sessions. The decision feed below is currently aggregate, not selection-scoped.')}${dataAdvisoryPlaceholder()}</div>
508
535
  </div>
509
536
  </div>
510
537
 
@@ -654,4 +681,8 @@
654
681
  return str.length > len ? str.slice(0, len) + '...' : str;
655
682
  }
656
683
 
684
+ function dataAdvisoryPlaceholder() {
685
+ return '<span id="perm-all-sessions-advisory" class="perm-inline-advisory" hidden></span>';
686
+ }
687
+
657
688
  })();
@@ -70,7 +70,7 @@
70
70
 
71
71
  .setup-method-toggle {
72
72
  display: grid;
73
- grid-template-columns: 1fr 1fr;
73
+ grid-template-columns: repeat(3, minmax(0, 1fr));
74
74
  gap: 0.5rem;
75
75
  border: none;
76
76
  padding: 0;
@@ -162,6 +162,41 @@
162
162
  margin-bottom: 1.2rem;
163
163
  }
164
164
 
165
+ .setup-permissions-intro {
166
+ display: grid;
167
+ gap: 1.2rem;
168
+ margin-bottom: 1.2rem;
169
+ }
170
+
171
+ .setup-permissions-intro[hidden] {
172
+ display: none !important;
173
+ }
174
+
175
+ .setup-permissions-note {
176
+ padding: 1rem 1.2rem;
177
+ border: 1px solid var(--line);
178
+ border-radius: var(--radius-md);
179
+ background: var(--surface-2);
180
+ min-width: 0;
181
+ overflow: hidden;
182
+ }
183
+
184
+ .setup-permissions-note strong {
185
+ display: block;
186
+ font-family: var(--font-heading);
187
+ font-size: var(--step-0);
188
+ font-weight: 700;
189
+ color: var(--ink-950);
190
+ margin-bottom: 0.35rem;
191
+ }
192
+
193
+ .setup-permissions-note p {
194
+ margin: 0;
195
+ color: var(--ink-700);
196
+ font-size: var(--step--1);
197
+ line-height: 1.55;
198
+ }
199
+
165
200
  .setup-method h4 {
166
201
  font-family: var(--font-heading);
167
202
  font-size: var(--step-0);
@@ -217,6 +252,7 @@
217
252
  .setup-panel {
218
253
  display: grid;
219
254
  gap: 1.2rem;
255
+ min-width: 0;
220
256
  }
221
257
 
222
258
  .setup-panel[hidden] {
@@ -230,6 +266,7 @@
230
266
  border: 1px solid var(--line);
231
267
  border-radius: var(--radius-md);
232
268
  padding: 1.2rem 1.4rem;
269
+ min-width: 0;
233
270
  }
234
271
 
235
272
  .setup-method-primary {
@@ -259,6 +296,131 @@
259
296
  margin-bottom: 0;
260
297
  }
261
298
 
299
+ .setup-security-mode code {
300
+ word-break: break-word;
301
+ }
302
+
303
+ .setup-security-mode {
304
+ min-width: 0;
305
+ overflow: hidden;
306
+ }
307
+
308
+ .setup-manual-fallback {
309
+ border: 1px solid var(--line);
310
+ border-radius: var(--radius-sm);
311
+ background: var(--surface-1);
312
+ overflow: hidden;
313
+ }
314
+
315
+ .setup-manual-fallback summary {
316
+ cursor: pointer;
317
+ list-style: none;
318
+ padding: 0.9rem 1rem;
319
+ font-family: var(--font-heading);
320
+ font-size: var(--step-0);
321
+ font-weight: 600;
322
+ color: var(--ink-900);
323
+ }
324
+
325
+ .setup-manual-fallback summary::-webkit-details-marker {
326
+ display: none;
327
+ }
328
+
329
+ .setup-manual-fallback summary::after {
330
+ content: '+';
331
+ float: right;
332
+ color: var(--ink-500);
333
+ }
334
+
335
+ .setup-manual-fallback[open] summary::after {
336
+ content: '-';
337
+ }
338
+
339
+ .setup-manual-fallback-body {
340
+ padding: 0 1rem 1rem;
341
+ border-top: 1px solid var(--line);
342
+ }
343
+
344
+ .setup-permission-status {
345
+ margin: 0 0 0.8rem;
346
+ padding: 0.85rem 1rem;
347
+ border-radius: var(--radius-sm);
348
+ border: 1px solid var(--line);
349
+ background: color-mix(in srgb, var(--surface-1) 85%, white);
350
+ }
351
+
352
+ .setup-permission-status-title {
353
+ display: block;
354
+ margin-bottom: 0.3rem;
355
+ color: var(--ink-900);
356
+ }
357
+
358
+ .setup-permission-status-msg {
359
+ margin: 0;
360
+ color: var(--ink-700);
361
+ }
362
+
363
+ .setup-permission-status[data-state="warning"] {
364
+ border-color: color-mix(in srgb, #f59e0b 40%, var(--line));
365
+ background: color-mix(in srgb, #f59e0b 10%, var(--surface-2));
366
+ }
367
+
368
+ .setup-permission-status[data-state="warning"] .setup-permission-status-title {
369
+ color: #b45309;
370
+ }
371
+
372
+ .setup-permission-status[data-state="info"] {
373
+ border-color: color-mix(in srgb, var(--signal) 30%, var(--line));
374
+ background: color-mix(in srgb, var(--signal-2) 10%, var(--surface-2));
375
+ }
376
+
377
+ .setup-permission-status[data-state="info"] .setup-permission-status-title {
378
+ color: var(--signal);
379
+ }
380
+
381
+ [data-theme="dark"] .setup-permission-status[data-state="warning"] .setup-permission-status-title {
382
+ color: #fbbf24;
383
+ }
384
+
385
+ .setup-support-badge {
386
+ display: inline-flex;
387
+ align-items: center;
388
+ margin-left: 0.45rem;
389
+ padding: 0.18rem 0.5rem;
390
+ border-radius: 999px;
391
+ font-family: var(--font-mono);
392
+ font-size: 0.7rem;
393
+ font-weight: 700;
394
+ text-transform: uppercase;
395
+ letter-spacing: 0.02em;
396
+ }
397
+
398
+ .setup-support-badge--verified {
399
+ background: color-mix(in srgb, #22c55e 18%, var(--surface-2));
400
+ color: #15803d;
401
+ border: 1px solid color-mix(in srgb, #22c55e 45%, var(--line));
402
+ }
403
+
404
+ .setup-support-badge--manual {
405
+ background: color-mix(in srgb, #f59e0b 14%, var(--surface-2));
406
+ color: #b45309;
407
+ border: 1px solid color-mix(in srgb, #f59e0b 40%, var(--line));
408
+ }
409
+
410
+ .setup-support-badge--unsupported {
411
+ background: color-mix(in srgb, #64748b 14%, var(--surface-2));
412
+ color: var(--ink-600);
413
+ border: 1px solid color-mix(in srgb, #64748b 35%, var(--line));
414
+ }
415
+
416
+ [data-theme="dark"] .setup-support-badge--verified {
417
+ color: #4ade80;
418
+ }
419
+
420
+ [data-theme="dark"] .setup-support-badge--manual {
421
+ color: #fbbf24;
422
+ }
423
+
262
424
  .setup-paths {
263
425
  list-style: none;
264
426
  margin: 0 0 0.8rem;
@@ -292,6 +454,8 @@
292
454
  .setup-code-block {
293
455
  position: relative;
294
456
  margin: 0.5rem 0;
457
+ min-width: 0;
458
+ max-width: 100%;
295
459
  }
296
460
 
297
461
  .setup-code-block pre {
@@ -307,6 +471,9 @@
307
471
  overflow-x: auto;
308
472
  white-space: pre;
309
473
  tab-size: 2;
474
+ max-width: 100%;
475
+ min-width: 0;
476
+ box-sizing: border-box;
310
477
  }
311
478
 
312
479
  [data-theme="dark"] .setup-code-block pre {
@@ -667,6 +834,10 @@
667
834
  padding: 1rem;
668
835
  }
669
836
 
837
+ .setup-method-toggle {
838
+ grid-template-columns: 1fr;
839
+ }
840
+
670
841
  .setup-platforms {
671
842
  gap: 0.25rem;
672
843
  }