@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.
- package/CHANGELOG.md +10 -0
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +3 -3
- package/dist/handlers/mcp-aql/OperationSchema.js +2 -2
- package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/evaluatePermission.js +6 -3
- package/dist/services/BuildInfoService.d.ts +5 -0
- package/dist/services/BuildInfoService.d.ts.map +1 -1
- package/dist/services/BuildInfoService.js +44 -8
- package/dist/utils/permissionHookInstallers.d.ts +27 -0
- package/dist/utils/permissionHookInstallers.d.ts.map +1 -0
- package/dist/utils/permissionHookInstallers.js +465 -0
- package/dist/utils/permissionHookShared.d.ts +165 -0
- package/dist/utils/permissionHookShared.d.ts.map +1 -0
- package/dist/utils/permissionHookShared.js +425 -0
- package/dist/utils/permissionHookStatus.d.ts +10 -0
- package/dist/utils/permissionHookStatus.d.ts.map +1 -0
- package/dist/utils/permissionHookStatus.js +260 -0
- package/dist/utils/permissionHooks.d.ts +3 -91
- package/dist/utils/permissionHooks.d.ts.map +1 -1
- package/dist/utils/permissionHooks.js +4 -947
- package/dist/web/routes/healthRoutes.d.ts +3 -0
- package/dist/web/routes/healthRoutes.d.ts.map +1 -1
- package/dist/web/routes/healthRoutes.js +24 -2
- package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
- package/dist/web/routes/permissionRoutes.js +21 -2
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +9 -2
- package/package.json +3 -1
- package/scripts/permission-hook-config.sh +67 -0
- package/scripts/pretooluse-dollhouse.sh +185 -38
- package/scripts/pretooluse-vscode.sh +23 -10
- package/scripts/pretooluse-windsurf.sh +6 -6
- 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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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: "
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
32
|
+
"version": "2.0.31",
|
|
33
33
|
"transport": {
|
|
34
34
|
"type": "stdio"
|
|
35
35
|
}
|