aidevops 2.78.0 → 2.79.1

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 (4) hide show
  1. package/VERSION +1 -1
  2. package/aidevops.sh +1 -1
  3. package/package.json +1 -1
  4. package/setup.sh +283 -87
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.78.0
1
+ 2.79.1
package/aidevops.sh CHANGED
@@ -3,7 +3,7 @@
3
3
  # AI DevOps Framework CLI
4
4
  # Usage: aidevops <command> [options]
5
5
  #
6
- # Version: 2.78.0
6
+ # Version: 2.79.1
7
7
 
8
8
  set -euo pipefail
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "2.78.0",
3
+ "version": "2.79.1",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/setup.sh CHANGED
@@ -3,7 +3,7 @@
3
3
  # AI Assistant Server Access Framework Setup Script
4
4
  # Helps developers set up the framework for their infrastructure
5
5
  #
6
- # Version: 2.78.0
6
+ # Version: 2.79.1
7
7
  #
8
8
  # Quick Install (one-liner):
9
9
  # bash <(curl -fsSL https://aidevops.dev/install)
@@ -168,6 +168,124 @@ cleanup_deprecated_paths() {
168
168
  return 0
169
169
  }
170
170
 
171
+ # Remove deprecated MCP entries from opencode.json
172
+ # These MCPs have been replaced by curl-based subagents (zero context cost)
173
+ cleanup_deprecated_mcps() {
174
+ local opencode_config="$HOME/.config/opencode/opencode.json"
175
+
176
+ if [[ ! -f "$opencode_config" ]]; then
177
+ return 0
178
+ fi
179
+
180
+ if ! command -v jq &> /dev/null; then
181
+ return 0
182
+ fi
183
+
184
+ # MCPs replaced by curl subagents in v2.79.0
185
+ local deprecated_mcps=(
186
+ "hetzner-awardsapp"
187
+ "hetzner-brandlight"
188
+ "hetzner-marcusquinn"
189
+ "hetzner-storagebox"
190
+ "ahrefs"
191
+ "serper"
192
+ "dataforseo"
193
+ "hostinger-api"
194
+ "shadcn"
195
+ )
196
+
197
+ # Tool rules to remove (for MCPs that no longer exist)
198
+ local deprecated_tools=(
199
+ "hetzner-*"
200
+ "hostinger-api_*"
201
+ "ahrefs_*"
202
+ "dataforseo_*"
203
+ "serper_*"
204
+ "shadcn_*"
205
+ )
206
+
207
+ local cleaned=0
208
+ local tmp_config
209
+ tmp_config=$(mktemp)
210
+
211
+ cp "$opencode_config" "$tmp_config"
212
+
213
+ for mcp in "${deprecated_mcps[@]}"; do
214
+ if jq -e ".mcp[\"$mcp\"]" "$tmp_config" > /dev/null 2>&1; then
215
+ jq "del(.mcp[\"$mcp\"])" "$tmp_config" > "${tmp_config}.new" && mv "${tmp_config}.new" "$tmp_config"
216
+ ((cleaned++))
217
+ fi
218
+ done
219
+
220
+ for tool in "${deprecated_tools[@]}"; do
221
+ if jq -e ".tools[\"$tool\"]" "$tmp_config" > /dev/null 2>&1; then
222
+ jq "del(.tools[\"$tool\"])" "$tmp_config" > "${tmp_config}.new" && mv "${tmp_config}.new" "$tmp_config"
223
+ fi
224
+ done
225
+
226
+ # Also remove deprecated tool refs from SEO agent
227
+ if jq -e '.agent.SEO.tools["dataforseo_*"]' "$tmp_config" > /dev/null 2>&1; then
228
+ jq 'del(.agent.SEO.tools["dataforseo_*"]) | del(.agent.SEO.tools["serper_*"]) | del(.agent.SEO.tools["ahrefs_*"])' "$tmp_config" > "${tmp_config}.new" && mv "${tmp_config}.new" "$tmp_config"
229
+ fi
230
+
231
+ # Migrate npx/pipx commands to bare binary names (faster startup)
232
+ # Maps: package-name -> binary-name
233
+ local -A mcp_migrations=(
234
+ ["chrome-devtools-mcp"]="chrome-devtools-mcp"
235
+ ["mcp-server-gsc"]="mcp-server-gsc"
236
+ ["repomix"]="repomix"
237
+ ["playwriter"]="playwriter"
238
+ ["@steipete/macos-automator-mcp"]="macos-automator-mcp"
239
+ ["@steipete/claude-code-mcp"]="claude-code-mcp"
240
+ ["analytics-mcp"]="analytics-mcp"
241
+ )
242
+
243
+ for pkg in "${!mcp_migrations[@]}"; do
244
+ local bin_name="${mcp_migrations[$pkg]}"
245
+ # Check if any MCP entry uses npx/bunx with this package
246
+ if jq -e ".mcp | to_entries[] | select(.value.command != null) | select(.value.command | join(\" \") | test(\"npx.*${pkg}|bunx.*${pkg}|pipx.*run.*${pkg}\"))" "$tmp_config" > /dev/null 2>&1; then
247
+ if command -v "$bin_name" &> /dev/null; then
248
+ # Find the MCP key and update its command to bare binary
249
+ local mcp_key
250
+ mcp_key=$(jq -r ".mcp | to_entries[] | select(.value.command != null) | select(.value.command | join(\" \") | test(\"npx.*${pkg}|bunx.*${pkg}|pipx.*run.*${pkg}\")) | .key" "$tmp_config" 2>/dev/null | head -1)
251
+ if [[ -n "$mcp_key" ]]; then
252
+ # Preserve --mcp flag for repomix
253
+ if [[ "$bin_name" == "repomix" ]]; then
254
+ jq ".mcp[\"$mcp_key\"].command = [\"$bin_name\", \"--mcp\"]" "$tmp_config" > "${tmp_config}.new" && mv "${tmp_config}.new" "$tmp_config"
255
+ else
256
+ jq ".mcp[\"$mcp_key\"].command = [\"$bin_name\"]" "$tmp_config" > "${tmp_config}.new" && mv "${tmp_config}.new" "$tmp_config"
257
+ fi
258
+ ((cleaned++))
259
+ fi
260
+ fi
261
+ fi
262
+ done
263
+
264
+ # Migrate outscraper from bash -c wrapper to bare binary
265
+ if jq -e '.mcp.outscraper.command | join(" ") | test("bash.*outscraper")' "$tmp_config" > /dev/null 2>&1; then
266
+ if command -v outscraper-mcp-server &> /dev/null; then
267
+ # Source the API key and set it in environment
268
+ local outscraper_key=""
269
+ if [[ -f "$HOME/.config/aidevops/mcp-env.sh" ]]; then
270
+ # shellcheck source=/dev/null
271
+ outscraper_key=$(source "$HOME/.config/aidevops/mcp-env.sh" && echo "${OUTSCRAPER_API_KEY:-}")
272
+ fi
273
+ jq --arg key "$outscraper_key" '.mcp.outscraper.command = ["outscraper-mcp-server"] | .mcp.outscraper.environment = {"OUTSCRAPER_API_KEY": $key}' "$tmp_config" > "${tmp_config}.new" && mv "${tmp_config}.new" "$tmp_config"
274
+ ((cleaned++))
275
+ fi
276
+ fi
277
+
278
+ if [[ $cleaned -gt 0 ]]; then
279
+ create_backup_with_rotation "$opencode_config" "opencode"
280
+ mv "$tmp_config" "$opencode_config"
281
+ print_info "Updated $cleaned MCP entry/entries in opencode.json (removed npx overhead, using global binaries)"
282
+ else
283
+ rm -f "$tmp_config"
284
+ fi
285
+
286
+ return 0
287
+ }
288
+
171
289
  # Migrate old config-backups to new per-type backup structure
172
290
  # This runs once to clean up the legacy backup directory
173
291
  migrate_old_backups() {
@@ -2014,6 +2132,89 @@ setup_nodejs_env() {
2014
2132
  fi
2015
2133
  }
2016
2134
 
2135
+ # Install MCP servers globally for fast startup (no npx/pipx overhead)
2136
+ install_mcp_packages() {
2137
+ print_info "Installing MCP server packages globally (eliminates npx startup delay)..."
2138
+
2139
+ # Node.js MCP packages (prefer bun, fallback to npm)
2140
+ local node_mcps=(
2141
+ "chrome-devtools-mcp"
2142
+ "mcp-server-gsc"
2143
+ "repomix"
2144
+ "playwriter"
2145
+ "@steipete/macos-automator-mcp"
2146
+ "@steipete/claude-code-mcp"
2147
+ )
2148
+
2149
+ local installer=""
2150
+ local install_cmd=""
2151
+
2152
+ if command -v bun &> /dev/null; then
2153
+ installer="bun"
2154
+ install_cmd="bun install -g"
2155
+ elif command -v npm &> /dev/null; then
2156
+ installer="npm"
2157
+ install_cmd="npm install -g"
2158
+ else
2159
+ print_warning "Neither bun nor npm found - cannot install MCP packages"
2160
+ print_info "Install bun (recommended): curl -fsSL https://bun.sh/install | bash"
2161
+ return 0
2162
+ fi
2163
+
2164
+ print_info "Using $installer for Node.js MCP packages..."
2165
+
2166
+ local installed=0
2167
+ local skipped=0
2168
+ for pkg in "${node_mcps[@]}"; do
2169
+ # Extract binary name from package name (strip @scope/ prefix)
2170
+ local bin_name
2171
+ bin_name="${pkg##*/}"
2172
+ if command -v "$bin_name" &> /dev/null; then
2173
+ ((skipped++))
2174
+ continue
2175
+ fi
2176
+ if $install_cmd "$pkg" > /dev/null 2>&1; then
2177
+ ((installed++))
2178
+ else
2179
+ print_warning "Failed to install $pkg"
2180
+ fi
2181
+ done
2182
+
2183
+ if [[ $installed -gt 0 ]]; then
2184
+ print_success "Installed $installed Node.js MCP packages via $installer"
2185
+ fi
2186
+ if [[ $skipped -gt 0 ]]; then
2187
+ print_info "$skipped Node.js MCP packages already installed"
2188
+ fi
2189
+
2190
+ # Python MCP packages
2191
+ if command -v pipx &> /dev/null; then
2192
+ if ! command -v analytics-mcp &> /dev/null; then
2193
+ print_info "Installing analytics-mcp via pipx..."
2194
+ if pipx install analytics-mcp > /dev/null 2>&1; then
2195
+ print_success "analytics-mcp installed"
2196
+ else
2197
+ print_warning "Failed to install analytics-mcp"
2198
+ fi
2199
+ fi
2200
+ fi
2201
+
2202
+ if command -v uv &> /dev/null; then
2203
+ if ! command -v outscraper-mcp-server &> /dev/null; then
2204
+ print_info "Installing outscraper-mcp-server via uv..."
2205
+ if uv tool install outscraper-mcp-server > /dev/null 2>&1; then
2206
+ print_success "outscraper-mcp-server installed"
2207
+ else
2208
+ print_warning "Failed to install outscraper-mcp-server"
2209
+ fi
2210
+ fi
2211
+ fi
2212
+
2213
+ print_info "MCP servers will start instantly (no registry lookups on each launch)"
2214
+ print_info "Run 'aidevops update-tools' to check for updates"
2215
+ return 0
2216
+ }
2217
+
2017
2218
  # Setup LocalWP MCP server for AI database access
2018
2219
  setup_localwp_mcp() {
2019
2220
  print_info "Setting up LocalWP MCP server..."
@@ -2662,98 +2863,48 @@ EOF
2662
2863
  }
2663
2864
 
2664
2865
  setup_seo_mcps() {
2665
- print_info "Setting up SEO MCP servers..."
2666
-
2667
- local has_node=false
2668
- local has_python=false
2669
- local has_uv=false
2670
-
2671
- # Check Node.js
2672
- if command -v node &> /dev/null; then
2673
- has_node=true
2674
- fi
2675
-
2676
- # Check Python (prefer Homebrew/pyenv over system)
2677
- if find_python3 &> /dev/null; then
2678
- has_python=true
2679
- fi
2680
-
2681
- # Check uv (Python package manager)
2682
- if command -v uv &> /dev/null; then
2683
- has_uv=true
2684
- elif command -v uvx &> /dev/null; then
2685
- has_uv=true
2686
- fi
2687
-
2688
- # DataForSEO MCP (Node.js based)
2689
- if [[ "$has_node" == "true" ]]; then
2690
- print_info "DataForSEO MCP available via: npx dataforseo-mcp-server"
2691
- print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
2692
- print_info " DATAFORSEO_USERNAME and DATAFORSEO_PASSWORD"
2693
- else
2694
- print_warning "Node.js not found - DataForSEO MCP requires Node.js"
2695
- fi
2696
-
2697
- # Serper MCP (Python based, uses uv/uvx)
2698
- if [[ "$has_uv" == "true" ]]; then
2699
- print_info "Serper MCP available via: uvx serper-mcp-server"
2700
- print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
2701
- print_info " SERPER_API_KEY"
2702
- elif [[ "$has_python" == "true" ]]; then
2703
- print_info "Serper MCP available via: pip install serper-mcp-server"
2704
- print_info "Then run: python3 -m serper_mcp_server"
2705
- print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
2706
- print_info " SERPER_API_KEY"
2707
-
2708
- # Offer to install uv for better experience
2709
- read -r -p "Install uv (recommended Python package manager)? (y/n): " install_uv
2710
- if [[ "$install_uv" == "y" ]]; then
2711
- print_info "Installing uv..."
2712
- curl -LsSf https://astral.sh/uv/install.sh | sh
2713
- if [[ $? -eq 0 ]]; then
2714
- print_success "uv installed successfully"
2715
- print_info "Restart your terminal or run: source ~/.bashrc (or ~/.zshrc)"
2716
- else
2717
- print_warning "Failed to install uv"
2718
- fi
2719
- fi
2720
- else
2721
- print_warning "Python not found - Serper MCP requires Python 3.11+"
2722
- fi
2723
-
2866
+ print_info "Setting up SEO integrations..."
2867
+
2868
+ # SEO services use curl-based subagents (no MCP needed)
2869
+ # Subagents: serper.md, dataforseo.md, ahrefs.md, google-search-console.md
2870
+ print_info "SEO uses curl-based subagents (zero context cost until invoked)"
2871
+
2724
2872
  # Check if credentials are configured
2725
2873
  if [[ -f "$HOME/.config/aidevops/mcp-env.sh" ]]; then
2726
2874
  # shellcheck source=/dev/null
2727
2875
  source "$HOME/.config/aidevops/mcp-env.sh"
2728
2876
 
2729
- if [[ -n "$DATAFORSEO_USERNAME" && -n "$DATAFORSEO_PASSWORD" ]]; then
2730
- print_success "DataForSEO credentials configured"
2731
- else
2732
- print_info "DataForSEO: Set credentials with:"
2733
- print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set DATAFORSEO_USERNAME your_username"
2734
- print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set DATAFORSEO_PASSWORD your_password"
2735
- fi
2877
+ [[ -n "$DATAFORSEO_USERNAME" ]] && print_success "DataForSEO credentials configured" || \
2878
+ print_info "DataForSEO: set DATAFORSEO_USERNAME and DATAFORSEO_PASSWORD in mcp-env.sh"
2736
2879
 
2737
- if [[ -n "$SERPER_API_KEY" ]]; then
2738
- print_success "Serper API key configured"
2739
- else
2740
- print_info "Serper: Set API key with:"
2741
- print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set SERPER_API_KEY your_key"
2742
- fi
2880
+ [[ -n "$SERPER_API_KEY" ]] && print_success "Serper API key configured" || \
2881
+ print_info "Serper: set SERPER_API_KEY in mcp-env.sh"
2882
+
2883
+ [[ -n "$AHREFS_API_KEY" ]] && print_success "Ahrefs API key configured" || \
2884
+ print_info "Ahrefs: set AHREFS_API_KEY in mcp-env.sh"
2885
+ else
2886
+ print_info "Configure SEO API credentials in ~/.config/aidevops/mcp-env.sh"
2887
+ fi
2888
+
2889
+ # GSC uses MCP (OAuth2 complexity warrants it)
2890
+ local gsc_creds="$HOME/.config/aidevops/gsc-credentials.json"
2891
+ if [[ -f "$gsc_creds" ]]; then
2892
+ print_success "Google Search Console credentials configured"
2743
2893
  else
2744
- print_info "Configure SEO API credentials:"
2745
- print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh setup"
2894
+ print_info "GSC: Create service account JSON at $gsc_creds"
2895
+ print_info " See: ~/.aidevops/agents/seo/google-search-console.md"
2746
2896
  fi
2747
2897
 
2748
- print_info "SEO MCP documentation: ~/.aidevops/agents/seo/"
2898
+ print_info "SEO documentation: ~/.aidevops/agents/seo/"
2749
2899
  return 0
2750
2900
  }
2751
2901
 
2752
- # Setup Google Analytics MCP (disabled by default)
2902
+ # Setup Google Analytics MCP (uses shared GSC service account credentials)
2753
2903
  setup_google_analytics_mcp() {
2754
2904
  print_info "Setting up Google Analytics MCP..."
2755
2905
 
2756
2906
  local opencode_config="$HOME/.config/opencode/opencode.json"
2907
+ local gsc_creds="$HOME/.config/aidevops/gsc-credentials.json"
2757
2908
 
2758
2909
  # Check if opencode.json exists
2759
2910
  if [[ ! -f "$opencode_config" ]]; then
@@ -2776,28 +2927,66 @@ setup_google_analytics_mcp() {
2776
2927
  return 0
2777
2928
  fi
2778
2929
 
2930
+ # Auto-detect credentials from shared GSC service account
2931
+ local creds_path=""
2932
+ local project_id=""
2933
+ local enable_mcp="false"
2934
+
2935
+ if [[ -f "$gsc_creds" ]]; then
2936
+ creds_path="$gsc_creds"
2937
+ # Extract project_id from service account JSON
2938
+ project_id=$(jq -r '.project_id // empty' "$gsc_creds" 2>/dev/null)
2939
+ if [[ -n "$project_id" ]]; then
2940
+ enable_mcp="true"
2941
+ print_success "Found GSC credentials - sharing with Google Analytics MCP"
2942
+ print_info "Project: $project_id"
2943
+ fi
2944
+ fi
2945
+
2779
2946
  # Check if google-analytics-mcp already exists in config
2780
2947
  if jq -e '.mcp["google-analytics-mcp"]' "$opencode_config" > /dev/null 2>&1; then
2781
- print_info "Google Analytics MCP already configured in OpenCode"
2948
+ # Update existing entry if we have credentials now
2949
+ if [[ "$enable_mcp" == "true" ]]; then
2950
+ local tmp_config
2951
+ tmp_config=$(mktemp)
2952
+ if jq --arg creds "$creds_path" --arg proj "$project_id" \
2953
+ '.mcp["google-analytics-mcp"].environment.GOOGLE_APPLICATION_CREDENTIALS = $creds |
2954
+ .mcp["google-analytics-mcp"].environment.GOOGLE_PROJECT_ID = $proj |
2955
+ .mcp["google-analytics-mcp"].enabled = true' \
2956
+ "$opencode_config" > "$tmp_config" 2>/dev/null; then
2957
+ mv "$tmp_config" "$opencode_config"
2958
+ print_success "Updated Google Analytics MCP with GSC credentials (enabled)"
2959
+ else
2960
+ rm -f "$tmp_config"
2961
+ print_warning "Failed to update Google Analytics MCP config"
2962
+ fi
2963
+ else
2964
+ print_info "Google Analytics MCP already configured in OpenCode"
2965
+ fi
2782
2966
  return 0
2783
2967
  fi
2784
2968
 
2785
- # Add google-analytics-mcp to opencode.json (disabled by default)
2969
+ # Add google-analytics-mcp to opencode.json
2786
2970
  local tmp_config
2787
2971
  tmp_config=$(mktemp)
2788
2972
 
2789
- if jq '.mcp["google-analytics-mcp"] = {
2973
+ if jq --arg creds "$creds_path" --arg proj "$project_id" --argjson enabled "$enable_mcp" \
2974
+ '.mcp["google-analytics-mcp"] = {
2790
2975
  "type": "local",
2791
- "command": ["pipx", "run", "analytics-mcp"],
2976
+ "command": ["analytics-mcp"],
2792
2977
  "environment": {
2793
- "GOOGLE_APPLICATION_CREDENTIALS": "",
2794
- "GOOGLE_PROJECT_ID": ""
2978
+ "GOOGLE_APPLICATION_CREDENTIALS": $creds,
2979
+ "GOOGLE_PROJECT_ID": $proj
2795
2980
  },
2796
- "enabled": false
2981
+ "enabled": $enabled
2797
2982
  }' "$opencode_config" > "$tmp_config" 2>/dev/null; then
2798
2983
  mv "$tmp_config" "$opencode_config"
2799
- print_success "Added Google Analytics MCP to OpenCode (disabled by default)"
2800
- print_info "To enable: Set credentials and change enabled to true in opencode.json"
2984
+ if [[ "$enable_mcp" == "true" ]]; then
2985
+ print_success "Added Google Analytics MCP to OpenCode (enabled with GSC credentials)"
2986
+ else
2987
+ print_success "Added Google Analytics MCP to OpenCode (disabled - no credentials found)"
2988
+ print_info "To enable: Create service account JSON at $gsc_creds"
2989
+ fi
2801
2990
  print_info "Or use the google-analytics subagent which enables it automatically"
2802
2991
  else
2803
2992
  rm -f "$tmp_config"
@@ -2956,6 +3145,7 @@ main() {
2956
3145
  confirm_step "Migrate old backups to new structure" && migrate_old_backups
2957
3146
  confirm_step "Migrate loop state from .claude/ to .agent/loop-state/" && migrate_loop_state_directories
2958
3147
  confirm_step "Cleanup deprecated agent paths" && cleanup_deprecated_paths
3148
+ confirm_step "Cleanup deprecated MCP entries (hetzner, serper, etc.)" && cleanup_deprecated_mcps
2959
3149
  confirm_step "Extract OpenCode prompts" && extract_opencode_prompts
2960
3150
  confirm_step "Check OpenCode prompt drift" && check_opencode_prompt_drift
2961
3151
  confirm_step "Deploy aidevops agents to ~/.aidevops/agents/" && deploy_aidevops_agents
@@ -2966,11 +3156,12 @@ main() {
2966
3156
  confirm_step "Update OpenCode configuration" && update_opencode_config
2967
3157
  confirm_step "Setup Python environment (DSPy, crawl4ai)" && setup_python_env
2968
3158
  confirm_step "Setup Node.js environment" && setup_nodejs_env
3159
+ confirm_step "Install MCP packages globally (fast startup)" && install_mcp_packages
2969
3160
  confirm_step "Setup LocalWP MCP server" && setup_localwp_mcp
2970
3161
  confirm_step "Setup Augment Context Engine MCP" && setup_augment_context_engine
2971
3162
  confirm_step "Setup osgrep (local semantic search)" && setup_osgrep
2972
3163
  confirm_step "Setup Beads task management" && setup_beads
2973
- confirm_step "Setup SEO MCP servers (DataForSEO, Serper)" && setup_seo_mcps
3164
+ confirm_step "Setup SEO integrations (curl subagents)" && setup_seo_mcps
2974
3165
  confirm_step "Setup Google Analytics MCP" && setup_google_analytics_mcp
2975
3166
  confirm_step "Setup browser automation tools" && setup_browser_tools
2976
3167
  confirm_step "Setup AI orchestration frameworks info" && setup_ai_orchestration
@@ -3017,8 +3208,13 @@ echo " aidevops uninstall - Remove aidevops"
3017
3208
  echo "• Augment Context Engine - Cloud semantic codebase retrieval"
3018
3209
  echo "• Context7 - Real-time library documentation"
3019
3210
  echo "• osgrep - Local semantic search (100% private)"
3211
+ echo "• GSC - Google Search Console (MCP + OAuth2)"
3212
+ echo "• Google Analytics - Analytics data (shared GSC credentials)"
3213
+ echo ""
3214
+ echo "SEO Integrations (curl subagents - no MCP overhead):"
3020
3215
  echo "• DataForSEO - Comprehensive SEO data APIs"
3021
3216
  echo "• Serper - Google Search API"
3217
+ echo "• Ahrefs - Backlink and keyword data"
3022
3218
  echo ""
3023
3219
  echo "DSPy & DSPyGround Integration:"
3024
3220
  echo "• ./.agent/scripts/dspy-helper.sh - DSPy prompt optimization toolkit"