own-rag-cli 0.0.6-snapshot → 0.0.8-snapshot

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.
@@ -35,6 +35,14 @@ ALIAS_LINE="alias rag='~/.local/bin/rag-wrapper.sh'"
35
35
  log_info() { printf "[+] %s\n" "$*"; }
36
36
  log_warn() { printf "[!] %s\n" "$*" >&2; }
37
37
 
38
+ ask_yes_no_default_no() {
39
+ local prompt="$1"
40
+ local answer=""
41
+ read -r -p "${prompt} [y/N] " answer || return 1
42
+ answer="$(printf "%s" "${answer}" | tr '[:upper:]' '[:lower:]')"
43
+ [[ "${answer}" == "y" || "${answer}" == "yes" || "${answer}" == "s" || "${answer}" == "sim" ]]
44
+ }
45
+
38
46
  ensure_own_rag_cli_config() {
39
47
  python3 - "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
40
48
  import json
@@ -123,10 +131,22 @@ PYEOF
123
131
  }
124
132
 
125
133
  ensure_codex_mcp_config() {
134
+ if command -v codex >/dev/null 2>&1; then
135
+ codex mcp remove rag-codebase >/dev/null 2>&1 || true
136
+ if codex mcp add rag-codebase \
137
+ --env "OWN_RAG_CLI_CONFIG_FILE=${OWN_RAG_CONFIG_FILE}" \
138
+ --env "TOKENIZERS_PARALLELISM=false" \
139
+ --env "MCP_FORCE_SEMANTIC_FALLBACK=true" \
140
+ -- "${MCP_SERVER_COMMAND}" >/dev/null 2>&1; then
141
+ log_info "Codex MCP configurado via codex mcp add."
142
+ return 0
143
+ fi
144
+ log_warn "Falha ao configurar Codex MCP via codex CLI. Tentando fallback em config.toml..."
145
+ fi
146
+
126
147
  local update_result
127
148
  if ! update_result="$(
128
149
  python3 - "${CODEX_CONFIG_FILE}" "${MCP_SERVER_COMMAND}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
129
- import re
130
150
  import sys
131
151
  from pathlib import Path
132
152
 
@@ -150,15 +170,25 @@ block = (
150
170
  'MCP_FORCE_SEMANTIC_FALLBACK = "true"\n'
151
171
  )
152
172
 
153
- pattern = re.compile(
154
- r"(?ms)^\[mcp_servers\.rag-codebase\]\n.*?(?=^\[mcp_servers\.|^\[[^\]]+\]|$)"
155
- )
156
-
157
- if pattern.search(text):
158
- new_text = pattern.sub(block + "\n", text, count=1)
159
- else:
160
- suffix = "" if not text or text.endswith("\n") else "\n"
161
- new_text = f"{text}{suffix}\n{block}"
173
+ target_headers = {"[mcp_servers.rag-codebase]", "[mcp_servers.rag-codebase.env]"}
174
+ lines = text.splitlines()
175
+ cleaned_lines: list[str] = []
176
+ skipping = False
177
+
178
+ for line in lines:
179
+ stripped = line.strip()
180
+ is_header = stripped.startswith("[") and stripped.endswith("]")
181
+ if is_header and stripped in target_headers:
182
+ skipping = True
183
+ continue
184
+ if is_header and skipping:
185
+ skipping = False
186
+ if not skipping:
187
+ cleaned_lines.append(line)
188
+
189
+ cleaned = "\n".join(cleaned_lines).strip()
190
+ prefix = f"{cleaned}\n\n" if cleaned else ""
191
+ new_text = f"{prefix}{block}\n"
162
192
 
163
193
  if new_text == text:
164
194
  print("skip:already_set")
@@ -276,18 +306,26 @@ ensure_own_rag_cli_config
276
306
  log_info "Config criada/ok: ${OWN_RAG_CONFIG_FILE}"
277
307
 
278
308
  if command -v cursor >/dev/null 2>&1 || [[ -d "${HOME}/.cursor" ]] || [[ -d "${HOME}/.config/Cursor" ]]; then
279
- ensure_mcp_json_config "${CURSOR_MCP_CONFIG_1}" "Cursor"
280
- ensure_mcp_json_config "${CURSOR_MCP_CONFIG_2}" "Cursor"
309
+ ensure_mcp_json_config "${CURSOR_MCP_CONFIG_1}" "Cursor" || true
310
+ ensure_mcp_json_config "${CURSOR_MCP_CONFIG_2}" "Cursor" || true
281
311
  ensure_cursor_semantic_rule_files
282
312
  ensure_cursor_force_fallback_env
283
313
  fi
284
314
 
285
315
  if command -v claude >/dev/null 2>&1 || [[ -d "${HOME}/.claude" ]] || [[ -f "${CLAUDE_CONFIG_FILE}" ]]; then
286
- ensure_mcp_json_config "${CLAUDE_CONFIG_FILE}" "Claude"
316
+ ensure_mcp_json_config "${CLAUDE_CONFIG_FILE}" "Claude" || true
287
317
  fi
288
318
 
289
319
  if command -v codex >/dev/null 2>&1 || [[ -d "${HOME}/.codex" ]] || [[ -f "${CODEX_CONFIG_FILE}" ]]; then
290
- ensure_codex_mcp_config
320
+ if [[ -t 0 ]]; then
321
+ if ask_yes_no_default_no "Deseja adicionar/atualizar o MCP 'rag-codebase' no Codex?"; then
322
+ ensure_codex_mcp_config || true
323
+ else
324
+ log_info "Configuração MCP do Codex ignorada por escolha do usuário."
325
+ fi
326
+ else
327
+ log_info "Sem terminal interativo: pulando configuração automática do MCP no Codex."
328
+ fi
291
329
  fi
292
330
 
293
331
  if [[ -f "${WRAPPER_SRC}" ]]; then
package/bin/rag-remove.sh CHANGED
@@ -131,7 +131,8 @@ done
131
131
 
132
132
  python3 - <<'PY'
133
133
  import json
134
- import re
134
+ import shutil
135
+ import subprocess
135
136
  from pathlib import Path
136
137
 
137
138
  home = Path.home()
@@ -157,6 +158,23 @@ for path in config_paths:
157
158
  except Exception as exc:
158
159
  print(f"[!] Não foi possível atualizar {path}: {exc}")
159
160
 
161
+ codex_bin = shutil.which("codex")
162
+ if codex_bin:
163
+ try:
164
+ proc = subprocess.run(
165
+ [codex_bin, "mcp", "remove", "rag-codebase"],
166
+ stdout=subprocess.PIPE,
167
+ stderr=subprocess.PIPE,
168
+ text=True,
169
+ check=False,
170
+ )
171
+ if proc.returncode == 0:
172
+ print("[+] MCP removido do Codex via codex mcp remove.")
173
+ else:
174
+ print(f"[!] codex mcp remove falhou (fallback para config.toml): {proc.stderr.strip()}")
175
+ except Exception as exc:
176
+ print(f"[!] Falha ao executar codex mcp remove (fallback para config.toml): {exc}")
177
+
160
178
  codex_toml = home / ".codex" / "config.toml"
161
179
  if codex_toml.exists():
162
180
  try:
@@ -165,13 +183,24 @@ if codex_toml.exists():
165
183
  text = ""
166
184
 
167
185
  if text:
168
- # Remove bloco [mcp_servers.rag-codebase] até o próximo cabeçalho TOML.
169
- pattern = re.compile(
170
- r"(?ms)^\[mcp_servers\.rag-codebase\]\n.*?(?=^\[mcp_servers\.|^\[[^\]]+\]|$)"
171
- )
172
- new_text = pattern.sub("", text)
173
- # Compacta excesso de linhas em branco para manter o arquivo limpo.
174
- new_text = re.sub(r"\n{3,}", "\n\n", new_text).rstrip() + "\n"
186
+ target_headers = {"[mcp_servers.rag-codebase]", "[mcp_servers.rag-codebase.env]"}
187
+ lines = text.splitlines()
188
+ cleaned_lines = []
189
+ skipping = False
190
+
191
+ for line in lines:
192
+ stripped = line.strip()
193
+ is_header = stripped.startswith("[") and stripped.endswith("]")
194
+ if is_header and stripped in target_headers:
195
+ skipping = True
196
+ continue
197
+ if is_header and skipping:
198
+ skipping = False
199
+ if not skipping:
200
+ cleaned_lines.append(line)
201
+
202
+ new_text = "\n".join(cleaned_lines).strip()
203
+ new_text = f"{new_text}\n" if new_text else ""
175
204
  if new_text != text:
176
205
  try:
177
206
  codex_toml.write_text(new_text, encoding="utf-8")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "own-rag-cli",
3
- "version": "0.0.6-snapshot",
3
+ "version": "0.0.8-snapshot",
4
4
  "description": "Local RAG setup with ChromaDB + MCP server (Jina/BGE hybrid support).",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -152,7 +152,7 @@ t() {
152
152
  mod_ms_installed) echo "Optional provider module installed" ;;
153
153
  shebang_set) echo "Shebang" ;;
154
154
  path_added) echo "Added ~/.local/bin to PATH in" ;;
155
- section_mcp_cfg) echo "Optional MCP configuration (Claude/Cursor)" ;;
155
+ section_mcp_cfg) echo "Optional MCP configuration (Claude/Cursor/Codex)" ;;
156
156
  no_cfg_files) echo "No config files detected for automatic MCP update." ;;
157
157
  cfg_all_current) echo "MCP 'rag-codebase' already up to date in detected files. Skipping." ;;
158
158
  cfg_detected) echo "Config files pending update" ;;
@@ -244,7 +244,7 @@ t() {
244
244
  mod_ms_installed) echo "Módulo de provider opcional instalado" ;;
245
245
  shebang_set) echo "Shebang" ;;
246
246
  path_added) echo "Adicionado ~/.local/bin ao PATH em" ;;
247
- section_mcp_cfg) echo "Configuração opcional de MCP (Claude/Cursor)" ;;
247
+ section_mcp_cfg) echo "Configuração opcional de MCP (Claude/Cursor/Codex)" ;;
248
248
  no_cfg_files) echo "Nenhum arquivo de config detectado para atualização automática do MCP." ;;
249
249
  cfg_all_current) echo "MCP 'rag-codebase' já está atualizado nos arquivos detectados. Pulando." ;;
250
250
  cfg_detected) echo "Arquivos de config pendentes de atualização" ;;
@@ -1095,8 +1095,130 @@ log_info "$(t section_mcp_cfg)"
1095
1095
  CLAUDE_JSON="${USER_HOME}/.claude.json"
1096
1096
  CURSOR_MCP_JSON_1="${USER_HOME}/.cursor/mcp.json"
1097
1097
  CURSOR_MCP_JSON_2="${USER_HOME}/Library/Application Support/Cursor/User/mcp.json"
1098
+ CODEX_CONFIG_TOML="${USER_HOME}/.codex/config.toml"
1098
1099
  MCP_VERSION="$(detect_current_mcp_version)"
1099
1100
 
1101
+ CODEX_APP_INSTALLED=false
1102
+ if command -v codex &>/dev/null || [[ -d "${USER_HOME}/.codex" ]]; then
1103
+ CODEX_APP_INSTALLED=true
1104
+ fi
1105
+
1106
+ configure_codex_mcp() {
1107
+ if check_codex_mcp_up_to_date; then
1108
+ echo "ok:already_exists"
1109
+ return 0
1110
+ fi
1111
+
1112
+ if command -v codex &>/dev/null; then
1113
+ codex mcp remove rag-codebase >/dev/null 2>&1 || true
1114
+ if codex mcp add rag-codebase \
1115
+ --env "OWN_RAG_CLI_CONFIG_FILE=${OWN_RAG_CONFIG_FILE}" \
1116
+ --env "TOKENIZERS_PARALLELISM=false" \
1117
+ --env "MCP_FORCE_SEMANTIC_FALLBACK=true" \
1118
+ -- "${MCP_SERVER_DEST}" >/dev/null 2>&1; then
1119
+ echo "ok:updated_rag_codebase"
1120
+ return 0
1121
+ fi
1122
+ fi
1123
+
1124
+ python3 - "${CODEX_CONFIG_TOML}" "${MCP_SERVER_DEST}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1125
+ import sys
1126
+ from pathlib import Path
1127
+
1128
+ cfg_path = Path(sys.argv[1]).expanduser()
1129
+ mcp_server_command = sys.argv[2]
1130
+ own_rag_cli_config_file = sys.argv[3]
1131
+
1132
+ cfg_path.parent.mkdir(parents=True, exist_ok=True)
1133
+ text = cfg_path.read_text(encoding="utf-8") if cfg_path.exists() else ""
1134
+
1135
+ block = (
1136
+ "[mcp_servers.rag-codebase]\n"
1137
+ f'command = "{mcp_server_command}"\n'
1138
+ "args = []\n\n"
1139
+ "[mcp_servers.rag-codebase.env]\n"
1140
+ f'OWN_RAG_CLI_CONFIG_FILE = "{own_rag_cli_config_file}"\n'
1141
+ 'TOKENIZERS_PARALLELISM = "false"\n'
1142
+ 'MCP_FORCE_SEMANTIC_FALLBACK = "true"\n'
1143
+ )
1144
+
1145
+ target_headers = {"[mcp_servers.rag-codebase]", "[mcp_servers.rag-codebase.env]"}
1146
+ lines = text.splitlines()
1147
+ cleaned_lines = []
1148
+ skipping = False
1149
+
1150
+ for line in lines:
1151
+ stripped = line.strip()
1152
+ is_header = stripped.startswith("[") and stripped.endswith("]")
1153
+ if is_header and stripped in target_headers:
1154
+ skipping = True
1155
+ continue
1156
+ if is_header and skipping:
1157
+ skipping = False
1158
+ if not skipping:
1159
+ cleaned_lines.append(line)
1160
+
1161
+ cleaned = "\n".join(cleaned_lines).strip()
1162
+ prefix = f"{cleaned}\n\n" if cleaned else ""
1163
+ new_text = f"{prefix}{block}\n"
1164
+
1165
+ if new_text == text:
1166
+ print("ok:already_exists")
1167
+ raise SystemExit(0)
1168
+
1169
+ cfg_path.write_text(new_text, encoding="utf-8")
1170
+ print("ok:updated_rag_codebase")
1171
+ PYEOF
1172
+ }
1173
+
1174
+ check_codex_mcp_up_to_date() {
1175
+ if command -v codex &>/dev/null && codex mcp get rag-codebase >/dev/null 2>&1; then
1176
+ return 0
1177
+ fi
1178
+ if [[ ! -f "${CODEX_CONFIG_TOML}" ]]; then
1179
+ return 1
1180
+ fi
1181
+ local check_result
1182
+ check_result="$(
1183
+ python3 - "${CODEX_CONFIG_TOML}" "${MCP_SERVER_DEST}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1184
+ import sys
1185
+ from pathlib import Path
1186
+
1187
+ cfg_path = Path(sys.argv[1]).expanduser()
1188
+ mcp_server_command = sys.argv[2]
1189
+ own_rag_cli_config_file = sys.argv[3]
1190
+
1191
+ try:
1192
+ text = cfg_path.read_text(encoding="utf-8")
1193
+ except Exception:
1194
+ print("needs_update")
1195
+ raise SystemExit(0)
1196
+
1197
+ if text.count("[mcp_servers.rag-codebase]") != 1:
1198
+ print("needs_update")
1199
+ raise SystemExit(0)
1200
+ if text.count("[mcp_servers.rag-codebase.env]") != 1:
1201
+ print("needs_update")
1202
+ raise SystemExit(0)
1203
+ if f'command = "{mcp_server_command}"' not in text:
1204
+ print("needs_update")
1205
+ raise SystemExit(0)
1206
+ if f'OWN_RAG_CLI_CONFIG_FILE = "{own_rag_cli_config_file}"' not in text:
1207
+ print("needs_update")
1208
+ raise SystemExit(0)
1209
+ if 'TOKENIZERS_PARALLELISM = "false"' not in text:
1210
+ print("needs_update")
1211
+ raise SystemExit(0)
1212
+ if 'MCP_FORCE_SEMANTIC_FALLBACK = "true"' not in text:
1213
+ print("needs_update")
1214
+ raise SystemExit(0)
1215
+
1216
+ print("already_up_to_date")
1217
+ PYEOF
1218
+ )"
1219
+ [[ "${check_result}" == "already_up_to_date" ]]
1220
+ }
1221
+
1100
1222
  TARGET_CONFIGS=()
1101
1223
  TARGET_LABELS=()
1102
1224
 
@@ -1122,7 +1244,12 @@ if [[ -f "${CURSOR_MCP_JSON_2}" ]]; then
1122
1244
  _append_target "${CURSOR_MCP_JSON_2}" "Cursor"
1123
1245
  fi
1124
1246
 
1125
- if [[ "${#TARGET_CONFIGS[@]}" -eq 0 ]]; then
1247
+ HAS_TARGETS=false
1248
+ if [[ "${#TARGET_CONFIGS[@]}" -gt 0 || "${CODEX_APP_INSTALLED}" == "true" ]]; then
1249
+ HAS_TARGETS=true
1250
+ fi
1251
+
1252
+ if [[ "${HAS_TARGETS}" != "true" ]]; then
1126
1253
  log_info "$(t no_cfg_files)"
1127
1254
  else
1128
1255
  PENDING_CONFIGS=()
@@ -1165,6 +1292,7 @@ desired = {
1165
1292
  "env": {
1166
1293
  "OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
1167
1294
  "TOKENIZERS_PARALLELISM": "false",
1295
+ "MCP_FORCE_SEMANTIC_FALLBACK": "true",
1168
1296
  },
1169
1297
  "version": mcp_version,
1170
1298
  }
@@ -1194,6 +1322,11 @@ PYEOF
1194
1322
  fi
1195
1323
  done
1196
1324
 
1325
+ if [[ "${CODEX_APP_INSTALLED}" == "true" ]]; then
1326
+ PENDING_CONFIGS+=("${CODEX_CONFIG_TOML}")
1327
+ PENDING_LABELS+=("Codex")
1328
+ fi
1329
+
1197
1330
  if [[ "${#PENDING_CONFIGS[@]}" -eq 0 ]]; then
1198
1331
  log_info "$(t cfg_all_current)"
1199
1332
  else
@@ -1216,7 +1349,12 @@ PYEOF
1216
1349
  CFG_PATH="${PENDING_CONFIGS[$i]}"
1217
1350
  CFG_LABEL="${PENDING_LABELS[$i]}"
1218
1351
 
1219
- if ! RESULT=$(
1352
+ if [[ "${CFG_LABEL}" == "Codex" ]]; then
1353
+ if ! RESULT="$(configure_codex_mcp)"; then
1354
+ log_warn "$(t cannot_update_cfg) ${CFG_LABEL} (${CFG_PATH}): ${RESULT}"
1355
+ continue
1356
+ fi
1357
+ elif ! RESULT=$(
1220
1358
  python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1221
1359
  import json
1222
1360
  import sys
@@ -1250,6 +1388,7 @@ desired = {
1250
1388
  "env": {
1251
1389
  "OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
1252
1390
  "TOKENIZERS_PARALLELISM": "false",
1391
+ "MCP_FORCE_SEMANTIC_FALLBACK": "true",
1253
1392
  },
1254
1393
  "version": mcp_version,
1255
1394
  }
package/rag-setup.run CHANGED
@@ -176,8 +176,8 @@ t() {
176
176
  mod_provider_installed) echo "Optional provider module installed:" ;;
177
177
  shebang) echo "Shebang:" ;;
178
178
  path_added) echo "Added ~/.local/bin to PATH in" ;;
179
- section_mcp_cfg) echo "Optional MCP setup (Claude/Cursor)" ;;
180
- no_default_cfg) echo "No default config file detected for automatic setup (Claude/Cursor)." ;;
179
+ section_mcp_cfg) echo "Optional MCP setup (Claude/Cursor/Codex)" ;;
180
+ no_default_cfg) echo "No default config file detected for automatic setup (Claude/Cursor/Codex)." ;;
181
181
  detected_cfg_files) echo "Detected files available for configuration:" ;;
182
182
  ask_apply_cfg) echo "Do you want to add/update MCP 'rag-codebase' in these files? $YES_NO_HINT " ;;
183
183
  non_interactive_cfg_skip) echo "No interactive terminal; automatic MCP setup will not be applied." ;;
@@ -288,8 +288,8 @@ t() {
288
288
  mod_provider_installed) echo "Módulo de provider opcional instalado:" ;;
289
289
  shebang) echo "Shebang:" ;;
290
290
  path_added) echo "Adicionado ~/.local/bin ao PATH em" ;;
291
- section_mcp_cfg) echo "Configuração opcional de MCP (Claude/Cursor)" ;;
292
- no_default_cfg) echo "Nenhum arquivo default detectado para configuração automática (Claude/Cursor)." ;;
291
+ section_mcp_cfg) echo "Configuração opcional de MCP (Claude/Cursor/Codex)" ;;
292
+ no_default_cfg) echo "Nenhum arquivo default detectado para configuração automática (Claude/Cursor/Codex)." ;;
293
293
  detected_cfg_files) echo "Arquivos detectados para possível configuração:" ;;
294
294
  ask_apply_cfg) echo "Deseja adicionar/atualizar o MCP 'rag-codebase' nesses arquivos? $YES_NO_HINT " ;;
295
295
  non_interactive_cfg_skip) echo "Sem terminal interativo; configuração automática de MCP não será aplicada." ;;
@@ -1117,24 +1117,145 @@ for RC in "${USER_HOME}/.bashrc" "${USER_HOME}/.zshrc"; do
1117
1117
  done
1118
1118
 
1119
1119
  # ---------------------------------------------------------------------------
1120
- # Configuração opcional do MCP no Claude/Cursor
1120
+ # Configuração opcional do MCP no Claude/Cursor/Codex
1121
1121
  # ---------------------------------------------------------------------------
1122
1122
  log_section "$(t section_mcp_cfg)"
1123
1123
 
1124
1124
  CLAUDE_JSON="${USER_HOME}/.claude.json"
1125
1125
  CURSOR_MCP_JSON_1="${USER_HOME}/.cursor/mcp.json"
1126
1126
  CURSOR_MCP_JSON_2="${USER_HOME}/.config/Cursor/User/mcp.json"
1127
+ CODEX_CONFIG_TOML="${USER_HOME}/.codex/config.toml"
1127
1128
  MCP_VERSION="$(detect_current_mcp_version)"
1128
1129
  log_info "$(t mcp_version_detected) ${MCP_VERSION}"
1129
1130
 
1130
1131
  CLAUDE_APP_INSTALLED=false
1131
1132
  CURSOR_APP_INSTALLED=false
1133
+ CODEX_APP_INSTALLED=false
1132
1134
  if command -v claude &>/dev/null || [[ -d "${USER_HOME}/.claude" ]] || [[ -d "${USER_HOME}/.config/Claude" ]]; then
1133
1135
  CLAUDE_APP_INSTALLED=true
1134
1136
  fi
1135
1137
  if command -v cursor &>/dev/null || [[ -d "${USER_HOME}/.cursor" ]] || [[ -d "${USER_HOME}/.config/Cursor" ]]; then
1136
1138
  CURSOR_APP_INSTALLED=true
1137
1139
  fi
1140
+ if command -v codex &>/dev/null || [[ -d "${USER_HOME}/.codex" ]]; then
1141
+ CODEX_APP_INSTALLED=true
1142
+ fi
1143
+
1144
+ configure_codex_mcp() {
1145
+ if check_codex_mcp_up_to_date; then
1146
+ echo "ok:already_exists"
1147
+ return 0
1148
+ fi
1149
+
1150
+ if command -v codex &>/dev/null; then
1151
+ codex mcp remove rag-codebase >/dev/null 2>&1 || true
1152
+ if codex mcp add rag-codebase \
1153
+ --env "OWN_RAG_CLI_CONFIG_FILE=${OWN_RAG_CONFIG_FILE}" \
1154
+ --env "TOKENIZERS_PARALLELISM=false" \
1155
+ --env "MCP_FORCE_SEMANTIC_FALLBACK=true" \
1156
+ -- "${MCP_SERVER_DEST}" >/dev/null 2>&1; then
1157
+ echo "ok:updated_rag_codebase"
1158
+ return 0
1159
+ fi
1160
+ fi
1161
+
1162
+ python3 - "${CODEX_CONFIG_TOML}" "${MCP_SERVER_DEST}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1163
+ import sys
1164
+ from pathlib import Path
1165
+
1166
+ cfg_path = Path(sys.argv[1]).expanduser()
1167
+ mcp_server_command = sys.argv[2]
1168
+ own_rag_cli_config_file = sys.argv[3]
1169
+
1170
+ cfg_path.parent.mkdir(parents=True, exist_ok=True)
1171
+ text = cfg_path.read_text(encoding="utf-8") if cfg_path.exists() else ""
1172
+
1173
+ block = (
1174
+ "[mcp_servers.rag-codebase]\n"
1175
+ f'command = "{mcp_server_command}"\n'
1176
+ "args = []\n\n"
1177
+ "[mcp_servers.rag-codebase.env]\n"
1178
+ f'OWN_RAG_CLI_CONFIG_FILE = "{own_rag_cli_config_file}"\n'
1179
+ 'TOKENIZERS_PARALLELISM = "false"\n'
1180
+ 'MCP_FORCE_SEMANTIC_FALLBACK = "true"\n'
1181
+ )
1182
+
1183
+ target_headers = {"[mcp_servers.rag-codebase]", "[mcp_servers.rag-codebase.env]"}
1184
+ lines = text.splitlines()
1185
+ cleaned_lines = []
1186
+ skipping = False
1187
+
1188
+ for line in lines:
1189
+ stripped = line.strip()
1190
+ is_header = stripped.startswith("[") and stripped.endswith("]")
1191
+ if is_header and stripped in target_headers:
1192
+ skipping = True
1193
+ continue
1194
+ if is_header and skipping:
1195
+ skipping = False
1196
+ if not skipping:
1197
+ cleaned_lines.append(line)
1198
+
1199
+ cleaned = "\n".join(cleaned_lines).strip()
1200
+ prefix = f"{cleaned}\n\n" if cleaned else ""
1201
+ new_text = f"{prefix}{block}\n"
1202
+
1203
+ if new_text == text:
1204
+ print("ok:already_exists")
1205
+ raise SystemExit(0)
1206
+
1207
+ cfg_path.write_text(new_text, encoding="utf-8")
1208
+ print("ok:updated_rag_codebase")
1209
+ PYEOF
1210
+ }
1211
+
1212
+ check_codex_mcp_up_to_date() {
1213
+ if command -v codex &>/dev/null && codex mcp get rag-codebase >/dev/null 2>&1; then
1214
+ return 0
1215
+ fi
1216
+ if [[ ! -f "${CODEX_CONFIG_TOML}" ]]; then
1217
+ return 1
1218
+ fi
1219
+ local check_result
1220
+ check_result="$(
1221
+ python3 - "${CODEX_CONFIG_TOML}" "${MCP_SERVER_DEST}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1222
+ import sys
1223
+ from pathlib import Path
1224
+
1225
+ cfg_path = Path(sys.argv[1]).expanduser()
1226
+ mcp_server_command = sys.argv[2]
1227
+ own_rag_cli_config_file = sys.argv[3]
1228
+
1229
+ try:
1230
+ text = cfg_path.read_text(encoding="utf-8")
1231
+ except Exception:
1232
+ print("needs_update")
1233
+ raise SystemExit(0)
1234
+
1235
+ if text.count("[mcp_servers.rag-codebase]") != 1:
1236
+ print("needs_update")
1237
+ raise SystemExit(0)
1238
+ if text.count("[mcp_servers.rag-codebase.env]") != 1:
1239
+ print("needs_update")
1240
+ raise SystemExit(0)
1241
+ if f'command = "{mcp_server_command}"' not in text:
1242
+ print("needs_update")
1243
+ raise SystemExit(0)
1244
+ if f'OWN_RAG_CLI_CONFIG_FILE = "{own_rag_cli_config_file}"' not in text:
1245
+ print("needs_update")
1246
+ raise SystemExit(0)
1247
+ if 'TOKENIZERS_PARALLELISM = "false"' not in text:
1248
+ print("needs_update")
1249
+ raise SystemExit(0)
1250
+ if 'MCP_FORCE_SEMANTIC_FALLBACK = "true"' not in text:
1251
+ print("needs_update")
1252
+ raise SystemExit(0)
1253
+
1254
+ print("already_up_to_date")
1255
+ PYEOF
1256
+ )"
1257
+ [[ "${check_result}" == "already_up_to_date" ]]
1258
+ }
1138
1259
 
1139
1260
  TARGET_CONFIGS=()
1140
1261
  TARGET_LABELS=()
@@ -1161,7 +1282,12 @@ if [[ "$CURSOR_APP_INSTALLED" == "true" ]] && [[ -f "${CURSOR_MCP_JSON_2}" ]]; t
1161
1282
  _append_target "${CURSOR_MCP_JSON_2}" "Cursor"
1162
1283
  fi
1163
1284
 
1164
- if [[ "${#TARGET_CONFIGS[@]}" -eq 0 ]]; then
1285
+ HAS_TARGETS=false
1286
+ if [[ "${#TARGET_CONFIGS[@]}" -gt 0 || "${CODEX_APP_INSTALLED}" == "true" ]]; then
1287
+ HAS_TARGETS=true
1288
+ fi
1289
+
1290
+ if [[ "${HAS_TARGETS}" != "true" ]]; then
1165
1291
  log_info "$(t no_default_cfg)"
1166
1292
  else
1167
1293
  PENDING_CONFIGS=()
@@ -1204,6 +1330,7 @@ desired = {
1204
1330
  "env": {
1205
1331
  "OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
1206
1332
  "TOKENIZERS_PARALLELISM": "false",
1333
+ "MCP_FORCE_SEMANTIC_FALLBACK": "true",
1207
1334
  },
1208
1335
  "version": mcp_version,
1209
1336
  }
@@ -1233,34 +1360,45 @@ PYEOF
1233
1360
  fi
1234
1361
  done
1235
1362
 
1363
+ if [[ "${CODEX_APP_INSTALLED}" == "true" ]]; then
1364
+ PENDING_CONFIGS+=("${CODEX_CONFIG_TOML}")
1365
+ PENDING_LABELS+=("Codex")
1366
+ fi
1367
+
1236
1368
  if [[ "${#PENDING_CONFIGS[@]}" -eq 0 ]]; then
1237
1369
  log_info "$(t mcp_cfg_all_current)"
1238
1370
  else
1239
- echo ""
1240
- log_info "$(t detected_cfg_files)"
1241
- for i in "${!PENDING_CONFIGS[@]}"; do
1242
- echo -e " - ${PENDING_LABELS[$i]}: ${PENDING_CONFIGS[$i]}"
1243
- done
1244
-
1245
- APPLY_MCP_CONFIG=false
1246
- if [[ -t 0 ]]; then
1247
1371
  echo ""
1248
- if ask_yes_no_loop "$(t ask_apply_cfg)"; then
1249
- APPLY_MCP_CONFIG=true
1372
+ log_info "$(t detected_cfg_files)"
1373
+ for i in "${!PENDING_CONFIGS[@]}"; do
1374
+ echo -e " - ${PENDING_LABELS[$i]}: ${PENDING_CONFIGS[$i]}"
1375
+ done
1376
+
1377
+ APPLY_MCP_CONFIG=false
1378
+ if [[ -t 0 ]]; then
1379
+ echo ""
1380
+ if ask_yes_no_loop "$(t ask_apply_cfg)"; then
1381
+ APPLY_MCP_CONFIG=true
1382
+ else
1383
+ APPLY_MCP_CONFIG=false
1384
+ fi
1250
1385
  else
1251
- APPLY_MCP_CONFIG=false
1386
+ log_info "$(t non_interactive_cfg_skip)"
1252
1387
  fi
1253
- else
1254
- log_info "$(t non_interactive_cfg_skip)"
1255
- fi
1256
-
1257
- if [[ "$APPLY_MCP_CONFIG" == "true" ]]; then
1258
- for i in "${!PENDING_CONFIGS[@]}"; do
1259
- CFG_PATH="${PENDING_CONFIGS[$i]}"
1260
- CFG_LABEL="${PENDING_LABELS[$i]}"
1261
1388
 
1262
- if ! RESULT=$(
1263
- python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1389
+ if [[ "$APPLY_MCP_CONFIG" == "true" ]]; then
1390
+ for i in "${!PENDING_CONFIGS[@]}"; do
1391
+ CFG_PATH="${PENDING_CONFIGS[$i]}"
1392
+ CFG_LABEL="${PENDING_LABELS[$i]}"
1393
+
1394
+ if [[ "${CFG_LABEL}" == "Codex" ]]; then
1395
+ if ! RESULT="$(configure_codex_mcp)"; then
1396
+ log_warn "$(t cannot_update_cfg) ${CFG_LABEL} (${CFG_PATH}): ${RESULT}"
1397
+ continue
1398
+ fi
1399
+ else
1400
+ if ! RESULT=$(
1401
+ python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1264
1402
  import json
1265
1403
  import sys
1266
1404
  from pathlib import Path
@@ -1293,6 +1431,7 @@ desired = {
1293
1431
  "env": {
1294
1432
  "OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
1295
1433
  "TOKENIZERS_PARALLELISM": "false",
1434
+ "MCP_FORCE_SEMANTIC_FALLBACK": "true",
1296
1435
  },
1297
1436
  "version": mcp_version,
1298
1437
  }
@@ -1332,33 +1471,34 @@ data["mcpServers"] = mcp_servers
1332
1471
  cfg_path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
1333
1472
  print("ok:added")
1334
1473
  PYEOF
1335
- ); then
1336
- log_warn "$(t cannot_update_cfg) ${CFG_LABEL} (${CFG_PATH}): ${RESULT}"
1337
- continue
1338
- fi
1474
+ ); then
1475
+ log_warn "$(t cannot_update_cfg) ${CFG_LABEL} (${CFG_PATH}): ${RESULT}"
1476
+ continue
1477
+ fi
1478
+ fi
1339
1479
 
1340
- case "${RESULT}" in
1341
- ok:already_exists)
1342
- log_info "${CFG_LABEL}: $(t already_updated)"
1343
- ;;
1344
- ok:updated_rag_codebase)
1345
- log_info "${CFG_LABEL}: $(t updated_version) ${MCP_VERSION}."
1346
- ;;
1347
- ok:replaced_old:*)
1348
- OLD_KEY="${RESULT#ok:replaced_old:}"
1349
- log_info "${CFG_LABEL}: $(t replaced_old) ${MCP_VERSION})."
1350
- ;;
1351
- ok:added)
1352
- log_info "${CFG_LABEL}: $(t added_cfg) ${MCP_VERSION})."
1353
- ;;
1354
- *)
1355
- log_warn "${CFG_LABEL}: $(t unexpected_return) ${RESULT}"
1356
- ;;
1357
- esac
1358
- done
1359
- else
1360
- log_info "$(t user_skipped_cfg)"
1361
- fi
1480
+ case "${RESULT}" in
1481
+ ok:already_exists)
1482
+ log_info "${CFG_LABEL}: $(t already_updated)"
1483
+ ;;
1484
+ ok:updated_rag_codebase)
1485
+ log_info "${CFG_LABEL}: $(t updated_version) ${MCP_VERSION}."
1486
+ ;;
1487
+ ok:replaced_old:*)
1488
+ OLD_KEY="${RESULT#ok:replaced_old:}"
1489
+ log_info "${CFG_LABEL}: $(t replaced_old) ${MCP_VERSION})."
1490
+ ;;
1491
+ ok:added)
1492
+ log_info "${CFG_LABEL}: $(t added_cfg) ${MCP_VERSION})."
1493
+ ;;
1494
+ *)
1495
+ log_warn "${CFG_LABEL}: $(t unexpected_return) ${RESULT}"
1496
+ ;;
1497
+ esac
1498
+ done
1499
+ else
1500
+ log_info "$(t user_skipped_cfg)"
1501
+ fi
1362
1502
  fi
1363
1503
  fi
1364
1504