Skip to main content
hooksSource-backedReview first Safety Privacy

MCP Server URL Allowlist - Claude Code Hook

PreToolUse hook that blocks edits adding remote MCP server URLs unless their host appears in an explicit allowlist, reducing accidental connection to unreviewed OAuth, SSE, or Streamable HTTP MCP endpoints.

by JSONbored·added 2026-06-05·
Claude Code
HarnessClaude Code
Trigger:PreToolUse
Review first review before installing

Open the source and read safety notes before installing.

Safety notes

  • This hook blocks unreviewed remote hosts in MCP-related config edits; it does not prove an allowed host is safe.
  • Run a separate authorization and source review before adding a new host to the allowlist.
  • The hook fails open when jq is unavailable, so CI or pre-commit checks should cover high-assurance environments.

Privacy notes

  • The hook reads pending config text from Claude Code tool input but does not write files or call the network.
  • Blocked hostnames are printed to stderr and may reveal internal MCP endpoints in the local terminal.

Prerequisites

  • Claude Code CLI with hooks enabled.
  • bash, jq, grep, awk, and sed available locally.
  • ALLOWED_MCP_HOSTS set to a comma-separated list of reviewed remote MCP hosts.

Schema details

Install type
cli
Troubleshooting
No
Runtime and command metadata
Trigger
PreToolUse
Script language
bash
Script body
#!/usr/bin/env bash
set -u

if ! command -v jq >/dev/null 2>&1; then
  exit 0
fi

input=$(cat)
file=$(printf '%s' "$input" | jq -r '.tool_input.file_path // .tool_input.path // ""')
text=$(printf '%s' "$input" | jq -r '[.tool_input.content, .tool_input.new_string, (.tool_input.edits[]?.new_string)] | map(select(. != null)) | join(" ")')
normalized_text=$(printf '%s' "$text" | sed 's#\\/#/#g')

case "$file" in
  *mcp*.json|*.mcp.json|*.claude/settings.json|*/settings.json) ;;
  *) exit 0 ;;
esac

hosts=$(printf '%s' "$normalized_text" | grep -Eo 'https?://[^"[:space:]]+' | awk -F/ '{print $3}' | sort -u)
[ -z "$hosts" ] && exit 0

allowlist=$(printf '%s' "${ALLOWED_MCP_HOSTS:-}" | tr ',' ' ')
for host in $hosts; do
  case " $allowlist " in
    *" $host "*) ;;
    *)
      echo "Blocked remote MCP URL: $host is not in ALLOWED_MCP_HOSTS." >&2
      exit 2
      ;;
  esac
done

exit 0
Full copyable content
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/mcp-server-url-allowlist.sh"
          }
        ]
      }
    ]
  }
}

About this resource

Features

  • Watches Write, Edit, and MultiEdit calls before MCP-related config reaches disk.
  • Extracts HTTP and HTTPS hosts from pending text.
  • Blocks hosts not listed in ALLOWED_MCP_HOSTS.
  • Makes remote MCP additions intentional and reviewable.
  • Runs locally with bash and jq.

Why use it

Remote MCP servers can sit behind OAuth and expose account data or write-capable tools. This hook adds a small local control: Claude cannot casually paste a new remote endpoint into config unless that host has already been reviewed and added to the local allowlist.

References

#mcp#hooks#allowlist#security#remote-mcp

Source citations

Signals

Loading live community signals…

More like this, weekly

A short, calm digest of reviewed Claude resources. Unsubscribe any time.