@dollhousemcp/mcp-server 2.0.29 → 2.0.31

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 (34) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/generated/version.d.ts +2 -2
  3. package/dist/generated/version.js +3 -3
  4. package/dist/handlers/mcp-aql/OperationSchema.js +2 -2
  5. package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -1
  6. package/dist/handlers/mcp-aql/evaluatePermission.js +6 -3
  7. package/dist/services/BuildInfoService.d.ts +5 -0
  8. package/dist/services/BuildInfoService.d.ts.map +1 -1
  9. package/dist/services/BuildInfoService.js +44 -8
  10. package/dist/utils/permissionHookInstallers.d.ts +27 -0
  11. package/dist/utils/permissionHookInstallers.d.ts.map +1 -0
  12. package/dist/utils/permissionHookInstallers.js +465 -0
  13. package/dist/utils/permissionHookShared.d.ts +165 -0
  14. package/dist/utils/permissionHookShared.d.ts.map +1 -0
  15. package/dist/utils/permissionHookShared.js +425 -0
  16. package/dist/utils/permissionHookStatus.d.ts +10 -0
  17. package/dist/utils/permissionHookStatus.d.ts.map +1 -0
  18. package/dist/utils/permissionHookStatus.js +260 -0
  19. package/dist/utils/permissionHooks.d.ts +3 -91
  20. package/dist/utils/permissionHooks.d.ts.map +1 -1
  21. package/dist/utils/permissionHooks.js +4 -947
  22. package/dist/web/routes/healthRoutes.d.ts +3 -0
  23. package/dist/web/routes/healthRoutes.d.ts.map +1 -1
  24. package/dist/web/routes/healthRoutes.js +24 -2
  25. package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
  26. package/dist/web/routes/permissionRoutes.js +21 -2
  27. package/dist/web/server.d.ts.map +1 -1
  28. package/dist/web/server.js +9 -2
  29. package/package.json +3 -1
  30. package/scripts/permission-hook-config.sh +67 -0
  31. package/scripts/pretooluse-dollhouse.sh +185 -38
  32. package/scripts/pretooluse-vscode.sh +23 -10
  33. package/scripts/pretooluse-windsurf.sh +6 -6
  34. package/server.json +2 -2
@@ -17,16 +17,31 @@
17
17
  # Set DOLLHOUSE_HOOK_PLATFORM to override the platform sent to the server.
18
18
 
19
19
  RUN_DIR="$HOME/.dollhouse/run"
20
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
+ # shellcheck disable=SC1091 # Resolved at runtime via SCRIPT_DIR.
22
+ source "$SCRIPT_DIR/permission-hook-config.sh"
23
+ # shellcheck disable=SC2034 # Consumed by permission-port-discovery.sh after sourcing.
20
24
  PORT_FILE="$RUN_DIR/permission-server.port"
21
25
  AUTHORITY_FILE="$RUN_DIR/permission-authority.json"
22
- AUTHORITY_CACHE_TTL_SECONDS=2
23
- MAX_RETRIES="${DOLLHOUSE_HOOK_MAX_RETRIES:-2}"
24
- INITIAL_TIMEOUT="${DOLLHOUSE_HOOK_INITIAL_TIMEOUT:-5}"
25
26
  HOOK_PLATFORM="${DOLLHOUSE_HOOK_PLATFORM:-claude_code}"
26
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
27
-
28
- [[ "$MAX_RETRIES" =~ ^[0-9]+$ ]] || MAX_RETRIES=2
29
- [[ "$INITIAL_TIMEOUT" =~ ^[0-9]+$ ]] || INITIAL_TIMEOUT=5
27
+ permission_hook_load_runtime_config
28
+ DIAGNOSTICS_LOG="${DOLLHOUSE_HOOK_DIAGNOSTICS_LOG:-$RUN_DIR/permission-hook-diagnostics.jsonl}"
29
+ INVOCATION_ID="$(date +%s)-$$-${RANDOM:-0}"
30
+
31
+ INPUT=""
32
+ TOOL_NAME=""
33
+ TOOL_INPUT=""
34
+ AUTHORITY_HOST=""
35
+ AUTHORITY_MODE=""
36
+ PAYLOAD=""
37
+ RESPONSE=""
38
+ NORMALIZED_RESPONSE=""
39
+ EMITTED_RESPONSE=""
40
+ PORT=""
41
+ ENDPOINT=""
42
+ LAST_ATTEMPT="0"
43
+ LAST_CURL_EXIT=""
44
+ CURRENT_TIMEOUT="$INITIAL_TIMEOUT"
30
45
 
31
46
  # Debug logging helper — writes to stderr so it doesn't pollute stdout
32
47
  debug() {
@@ -36,6 +51,126 @@ debug() {
36
51
  return 0
37
52
  }
38
53
 
54
+ append_diagnostic_record() {
55
+ local event="$1"
56
+ local stage="$2"
57
+ local outcome="${3:-}"
58
+ local reason="${4:-}"
59
+ local diagnostic_json
60
+
61
+ mkdir -p "$(dirname "$DIAGNOSTICS_LOG")" 2>/dev/null || return 0
62
+
63
+ diagnostic_json=$(
64
+ jq -cn \
65
+ --arg timestamp "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \
66
+ --arg invocationId "$INVOCATION_ID" \
67
+ --arg event "$event" \
68
+ --arg platform "$HOOK_PLATFORM" \
69
+ --arg stage "$stage" \
70
+ --arg outcome "$outcome" \
71
+ --arg reason "$reason" \
72
+ --arg hookPath "$0" \
73
+ --arg diagnosticsLogPath "$DIAGNOSTICS_LOG" \
74
+ --arg sessionId "${DOLLHOUSE_SESSION_ID:-}" \
75
+ --arg toolName "${TOOL_NAME:-}" \
76
+ --arg toolInput "${TOOL_INPUT:-}" \
77
+ --arg rawInput "${INPUT:-}" \
78
+ --arg authorityHost "${AUTHORITY_HOST:-}" \
79
+ --arg authorityMode "${AUTHORITY_MODE:-}" \
80
+ --arg endpoint "${ENDPOINT:-}" \
81
+ --arg port "${PORT:-}" \
82
+ --arg payload "${PAYLOAD:-}" \
83
+ --arg response "${RESPONSE:-}" \
84
+ --arg normalizedResponse "${NORMALIZED_RESPONSE:-}" \
85
+ --arg emittedResponse "${EMITTED_RESPONSE:-}" \
86
+ --arg attempt "${LAST_ATTEMPT:-}" \
87
+ --arg maxRetries "${MAX_RETRIES:-}" \
88
+ --arg timeoutSeconds "${CURRENT_TIMEOUT:-}" \
89
+ --arg curlExit "${LAST_CURL_EXIT:-}" \
90
+ --argjson rawInputLength "${#INPUT}" \
91
+ --argjson normalizedResponseLength "${#NORMALIZED_RESPONSE}" \
92
+ --argjson emittedResponseLength "${#EMITTED_RESPONSE}" \
93
+ --argjson responseLength "${#RESPONSE}" \
94
+ '{
95
+ timestamp: $timestamp,
96
+ invocationId: $invocationId,
97
+ event: $event,
98
+ platform: $platform,
99
+ stage: $stage,
100
+ rawInputLength: $rawInputLength,
101
+ normalizedResponseLength: $normalizedResponseLength,
102
+ emittedResponseLength: $emittedResponseLength,
103
+ responseLength: $responseLength
104
+ }
105
+ + (if $outcome != "" then { outcome: $outcome } else {} end)
106
+ + (if $reason != "" then { reason: $reason } else {} end)
107
+ + (if $hookPath != "" then { hookPath: $hookPath } else {} end)
108
+ + (if $diagnosticsLogPath != "" then { diagnosticsLogPath: $diagnosticsLogPath } else {} end)
109
+ + (if $sessionId != "" then { sessionId: $sessionId } else {} end)
110
+ + (if $toolName != "" then { toolName: $toolName } else {} end)
111
+ + (if $toolInput != "" then { toolInput: $toolInput } else {} end)
112
+ + (if $rawInput != "" then { rawInput: $rawInput } else {} end)
113
+ + (if $authorityHost != "" then { authorityHost: $authorityHost } else {} end)
114
+ + (if $authorityMode != "" then { authorityMode: $authorityMode } else {} end)
115
+ + (if $endpoint != "" then { endpoint: $endpoint } else {} end)
116
+ + (if $port != "" then { port: $port } else {} end)
117
+ + (if $payload != "" then { payload: $payload } else {} end)
118
+ + (if $response != "" then { response: $response } else {} end)
119
+ + (if $normalizedResponse != "" then { normalizedResponse: $normalizedResponse } else {} end)
120
+ + (if $emittedResponse != "" then { emittedResponse: $emittedResponse } else {} end)
121
+ + (if $attempt != "" then { attempt: $attempt } else {} end)
122
+ + (if $maxRetries != "" then { maxRetries: $maxRetries } else {} end)
123
+ + (if $timeoutSeconds != "" then { timeoutSeconds: $timeoutSeconds } else {} end)
124
+ + (if $curlExit != "" then { curlExit: $curlExit } else {} end)'
125
+ ) || return 0
126
+
127
+ printf '%s\n' "$diagnostic_json" >> "$DIAGNOSTICS_LOG" 2>/dev/null || true
128
+ return 0
129
+ }
130
+
131
+ emit_response() {
132
+ local response="$1"
133
+
134
+ EMITTED_RESPONSE="$response"
135
+ if [[ -n "$response" ]]; then
136
+ printf '%s\n' "$response"
137
+ fi
138
+
139
+ return 0
140
+ }
141
+
142
+ build_allow_response() {
143
+ case "$HOOK_PLATFORM" in
144
+ claude_code|vscode)
145
+ printf '%s' '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'
146
+ ;;
147
+ codex)
148
+ printf '%s' ''
149
+ ;;
150
+ cursor)
151
+ printf '%s' '{"permission":"allow"}'
152
+ ;;
153
+ gemini)
154
+ printf '%s' '{"decision":"allow"}'
155
+ ;;
156
+ *)
157
+ printf '%s' '{}'
158
+ ;;
159
+ esac
160
+
161
+ return 0
162
+ }
163
+
164
+ fail_open() {
165
+ local stage="$1"
166
+ local message="$2"
167
+ debug "$message"
168
+ EMITTED_RESPONSE=$(build_allow_response)
169
+ append_diagnostic_record "complete" "$stage" "fail_open" "$message"
170
+ emit_response "$EMITTED_RESPONSE"
171
+ return 0
172
+ }
173
+
39
174
  authority_host_for_platform() {
40
175
  case "$HOOK_PLATFORM" in
41
176
  claude_code) echo "claude-code" ;;
@@ -120,29 +255,28 @@ normalize_response() {
120
255
  codex)
121
256
  echo "$response" | jq -c '
122
257
  if type == "object" and (keys | length) == 0 then
258
+ empty
259
+ elif (.hookSpecificOutput.permissionDecision? | type) == "string" and .hookSpecificOutput.permissionDecision == "deny" then
123
260
  {
124
261
  hookSpecificOutput: {
125
262
  hookEventName: "PreToolUse",
126
- permissionDecision: "allow",
127
- permissionDecisionReason: ""
128
- }
129
- }
130
- elif (.hookSpecificOutput.permissionDecision? | type) == "string" then
131
- {
132
- hookSpecificOutput: {
133
- hookEventName: "PreToolUse",
134
- permissionDecision: (if .hookSpecificOutput.permissionDecision == "allow" then "allow" else "deny" end),
263
+ permissionDecision: "deny",
135
264
  permissionDecisionReason: (.hookSpecificOutput.permissionDecisionReason // .hookSpecificOutput.reason // .reason // .message // "")
136
265
  }
137
266
  }
267
+ elif (.hookSpecificOutput.permissionDecision? | type) == "string" then
268
+ empty
138
269
  elif (.decision? | type) == "string" and (.decision | IN("allow", "deny", "ask")) then
139
- {
140
- hookSpecificOutput: {
141
- hookEventName: "PreToolUse",
142
- permissionDecision: (if .decision == "allow" then "allow" else "deny" end),
143
- permissionDecisionReason: (.reason // .message // "")
270
+ if .decision == "deny"
271
+ then {
272
+ hookSpecificOutput: {
273
+ hookEventName: "PreToolUse",
274
+ permissionDecision: "deny",
275
+ permissionDecisionReason: (.reason // .message // "")
276
+ }
144
277
  }
145
- }
278
+ else empty
279
+ end
146
280
  else
147
281
  empty
148
282
  end
@@ -156,19 +290,12 @@ normalize_response() {
156
290
  return 0
157
291
  }
158
292
 
293
+ # shellcheck disable=SC1091 # Resolved at runtime via SCRIPT_DIR.
159
294
  source "$SCRIPT_DIR/permission-port-discovery.sh"
160
295
 
161
- # Discover the port from the shared file or the newest live PID-keyed file
162
- if ! PORT=$(resolve_permission_port); then
163
- debug "No usable permission server port file found — fail open"
164
- exit 0
165
- fi
166
-
167
- ENDPOINT="http://127.0.0.1:${PORT}/api/evaluate_permission"
168
- debug "Endpoint: $ENDPOINT"
169
-
170
296
  # Read the hook input from stdin
171
297
  INPUT=$(cat)
298
+ append_diagnostic_record "received_input" "received_input"
172
299
 
173
300
  # Extract tool_name and tool_input from the hook payload
174
301
  TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // .toolName // .tool // .name // empty' 2>/dev/null)
@@ -176,10 +303,19 @@ TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // .toolInput // .input // {}' 2
176
303
 
177
304
  # If we can't parse the input, fail open
178
305
  if [[ -z "$TOOL_NAME" ]]; then
179
- debug "Could not parse tool_name from input — fail open"
306
+ fail_open "parse_tool_name_failed" "Could not parse tool_name from input — fail open"
180
307
  exit 0
181
308
  fi
182
309
 
310
+ # Discover the port from the shared file or the newest live PID-keyed file
311
+ if ! PORT=$(resolve_permission_port); then
312
+ fail_open "port_discovery_failed" "No usable permission server port file found — fail open"
313
+ exit 0
314
+ fi
315
+
316
+ ENDPOINT="http://127.0.0.1:${PORT}/api/evaluate_permission"
317
+ debug "Endpoint: $ENDPOINT"
318
+
183
319
  debug "Evaluating: $TOOL_NAME"
184
320
  debug "Platform: $HOOK_PLATFORM"
185
321
 
@@ -188,7 +324,7 @@ AUTHORITY_MODE=$(resolve_authority_mode "$AUTHORITY_HOST")
188
324
  debug "Authority mode for ${AUTHORITY_HOST:-unknown}: $AUTHORITY_MODE"
189
325
 
190
326
  if [[ "$AUTHORITY_MODE" == "off" ]]; then
191
- debug "Authority mode is off — hook no-op"
327
+ fail_open "authority_off" "Authority mode is off — hook no-op"
192
328
  exit 0
193
329
  fi
194
330
 
@@ -213,23 +349,32 @@ ATTEMPT=0
213
349
  TIMEOUT=$INITIAL_TIMEOUT
214
350
 
215
351
  while [[ $ATTEMPT -le $MAX_RETRIES ]]; do
352
+ LAST_ATTEMPT="$ATTEMPT"
353
+ CURRENT_TIMEOUT="$TIMEOUT"
216
354
  RESPONSE=$(curl -s --max-time "$TIMEOUT" -X POST "$ENDPOINT" \
217
355
  -H "Content-Type: application/json" \
218
356
  -d "$PAYLOAD" \
219
357
  2>/dev/null)
220
358
  CURL_EXIT=$?
359
+ LAST_CURL_EXIT="$CURL_EXIT"
221
360
 
222
361
  if [[ $CURL_EXIT -eq 0 ]] && [[ -n "$RESPONSE" ]]; then
223
362
  debug "Response (attempt $((ATTEMPT+1))): $RESPONSE"
224
363
  if ! echo "$RESPONSE" | jq -e . >/dev/null 2>&1; then
225
- debug "Non-JSON response for platform $HOOK_PLATFORM — fail open"
364
+ fail_open "response_not_json" "Non-JSON response for platform $HOOK_PLATFORM — fail open"
226
365
  exit 0
227
366
  fi
228
367
  NORMALIZED_RESPONSE=$(normalize_response "$RESPONSE")
229
368
  if [[ -n "$NORMALIZED_RESPONSE" ]]; then
230
- echo "$NORMALIZED_RESPONSE"
369
+ EMITTED_RESPONSE="$NORMALIZED_RESPONSE"
370
+ append_diagnostic_record "complete" "response_normalized" "success"
371
+ emit_response "$NORMALIZED_RESPONSE"
372
+ elif [[ "$HOOK_PLATFORM" == "codex" ]]; then
373
+ EMITTED_RESPONSE=""
374
+ append_diagnostic_record "complete" "response_allowed_without_output" "success"
231
375
  else
232
- debug "Malformed response for platform $HOOK_PLATFORM — fail open"
376
+ fail_open "response_malformed" "Malformed response for platform $HOOK_PLATFORM — fail open"
377
+ exit 0
233
378
  fi
234
379
  exit 0
235
380
  fi
@@ -237,12 +382,14 @@ while [[ $ATTEMPT -le $MAX_RETRIES ]]; do
237
382
  ATTEMPT=$((ATTEMPT + 1))
238
383
  if [[ $ATTEMPT -le $MAX_RETRIES ]]; then
239
384
  BACKOFF=$((TIMEOUT * ATTEMPT))
240
- debug "Attempt $ATTEMPT failed (curl exit $CURL_EXIT) — retrying in ${BACKOFF}s (timeout ${TIMEOUT}s → $((TIMEOUT * 2))s)"
385
+ RETRY_MESSAGE="Attempt $ATTEMPT failed (curl exit $CURL_EXIT) — retrying in ${BACKOFF}s (timeout ${TIMEOUT}s → $((TIMEOUT * 2))s)"
386
+ debug "$RETRY_MESSAGE"
387
+ append_diagnostic_record "retry" "curl_retry" "retrying" "$RETRY_MESSAGE"
241
388
  sleep "$BACKOFF"
242
389
  TIMEOUT=$((TIMEOUT * 2))
243
390
  fi
244
391
  done
245
392
 
246
393
  # All retries exhausted — fail open
247
- debug "All $((MAX_RETRIES + 1)) attempts failed — fail open"
394
+ fail_open "curl_attempts_exhausted" "All $((MAX_RETRIES + 1)) attempts failed — fail open"
248
395
  exit 0
@@ -6,14 +6,13 @@
6
6
  # most relevant built-in tool names into Dollhouse's existing permission model.
7
7
 
8
8
  RUN_DIR="$HOME/.dollhouse/run"
9
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
+ # shellcheck disable=SC1091 # Resolved at runtime via SCRIPT_DIR.
11
+ source "$SCRIPT_DIR/permission-hook-config.sh"
12
+ # shellcheck disable=SC2034 # Consumed by permission-port-discovery.sh after sourcing.
9
13
  PORT_FILE="$RUN_DIR/permission-server.port"
10
- MAX_RETRIES="${DOLLHOUSE_HOOK_MAX_RETRIES:-2}"
11
- INITIAL_TIMEOUT="${DOLLHOUSE_HOOK_INITIAL_TIMEOUT:-5}"
12
14
  HOOK_PLATFORM="vscode"
13
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
-
15
- [[ "$MAX_RETRIES" =~ ^[0-9]+$ ]] || MAX_RETRIES=2
16
- [[ "$INITIAL_TIMEOUT" =~ ^[0-9]+$ ]] || INITIAL_TIMEOUT=5
15
+ permission_hook_load_runtime_config
17
16
 
18
17
  debug() {
19
18
  if [[ "${DOLLHOUSE_HOOK_DEBUG:-0}" == "1" ]]; then
@@ -22,10 +21,23 @@ debug() {
22
21
  return 0
23
22
  }
24
23
 
24
+ emit_allow_response() {
25
+ printf '%s\n' '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'
26
+ return 0
27
+ }
28
+
29
+ fail_open() {
30
+ local message="$1"
31
+ debug "$message"
32
+ emit_allow_response
33
+ return 0
34
+ }
35
+
36
+ # shellcheck disable=SC1091 # Resolved at runtime via SCRIPT_DIR.
25
37
  source "$SCRIPT_DIR/permission-port-discovery.sh"
26
38
 
27
39
  if ! PORT=$(resolve_permission_port); then
28
- debug "No usable permission server port file found — fail open"
40
+ fail_open "No usable permission server port file found — fail open"
29
41
  exit 0
30
42
  fi
31
43
 
@@ -84,7 +96,7 @@ case "$RAW_TOOL_NAME" in
84
96
  esac
85
97
 
86
98
  if [[ -z "$TOOL_NAME" ]]; then
87
- debug "Could not parse VS Code tool name — fail open"
99
+ fail_open "Could not parse VS Code tool name — fail open"
88
100
  exit 0
89
101
  fi
90
102
 
@@ -147,7 +159,8 @@ while [[ $ATTEMPT -le $MAX_RETRIES ]]; do
147
159
  if [[ -n "$HOOK_RESPONSE" ]]; then
148
160
  echo "$HOOK_RESPONSE"
149
161
  else
150
- debug "Permission evaluation returned an unrecognized response — fail open"
162
+ fail_open "Permission evaluation returned an unrecognized response — fail open"
163
+ exit 0
151
164
  fi
152
165
  exit 0
153
166
  fi
@@ -159,5 +172,5 @@ while [[ $ATTEMPT -le $MAX_RETRIES ]]; do
159
172
  fi
160
173
  done
161
174
 
162
- debug "Permission evaluation failed — fail open"
175
+ fail_open "Permission evaluation failed — fail open"
163
176
  exit 0
@@ -6,14 +6,13 @@
6
6
  # evaluations and then maps the response back to Windsurf exit codes.
7
7
 
8
8
  RUN_DIR="$HOME/.dollhouse/run"
9
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
+ # shellcheck disable=SC1091 # Resolved at runtime via SCRIPT_DIR.
11
+ source "$SCRIPT_DIR/permission-hook-config.sh"
12
+ # shellcheck disable=SC2034 # Consumed by permission-port-discovery.sh after sourcing.
9
13
  PORT_FILE="$RUN_DIR/permission-server.port"
10
- MAX_RETRIES="${DOLLHOUSE_HOOK_MAX_RETRIES:-2}"
11
- INITIAL_TIMEOUT="${DOLLHOUSE_HOOK_INITIAL_TIMEOUT:-5}"
12
14
  HOOK_PLATFORM="windsurf"
13
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
-
15
- [[ "$MAX_RETRIES" =~ ^[0-9]+$ ]] || MAX_RETRIES=2
16
- [[ "$INITIAL_TIMEOUT" =~ ^[0-9]+$ ]] || INITIAL_TIMEOUT=5
15
+ permission_hook_load_runtime_config
17
16
 
18
17
  debug() {
19
18
  if [[ "${DOLLHOUSE_HOOK_DEBUG:-0}" == "1" ]]; then
@@ -22,6 +21,7 @@ debug() {
22
21
  return 0
23
22
  }
24
23
 
24
+ # shellcheck disable=SC1091 # Resolved at runtime via SCRIPT_DIR.
25
25
  source "$SCRIPT_DIR/permission-port-discovery.sh"
26
26
 
27
27
  if ! PORT=$(resolve_permission_port); then
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.DollhouseMCP/mcp-server",
4
4
  "title": "DollhouseMCP",
5
5
  "description": "OSS to create Personas, Skills, Templates, Agents, and Memories to customize your AI experience.",
6
- "version": "2.0.29",
6
+ "version": "2.0.31",
7
7
  "homepage": "https://dollhousemcp.com",
8
8
  "repository": {
9
9
  "type": "git",
@@ -29,7 +29,7 @@
29
29
  {
30
30
  "registryType": "npm",
31
31
  "identifier": "@dollhousemcp/mcp-server",
32
- "version": "2.0.29",
32
+ "version": "2.0.31",
33
33
  "transport": {
34
34
  "type": "stdio"
35
35
  }