own-rag-cli 0.0.6-snapshot → 0.0.7-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.
@@ -123,10 +123,22 @@ PYEOF
123
123
  }
124
124
 
125
125
  ensure_codex_mcp_config() {
126
+ if command -v codex >/dev/null 2>&1; then
127
+ codex mcp remove rag-codebase >/dev/null 2>&1 || true
128
+ if codex mcp add rag-codebase \
129
+ --env "OWN_RAG_CLI_CONFIG_FILE=${OWN_RAG_CONFIG_FILE}" \
130
+ --env "TOKENIZERS_PARALLELISM=false" \
131
+ --env "MCP_FORCE_SEMANTIC_FALLBACK=true" \
132
+ -- "${MCP_SERVER_COMMAND}" >/dev/null 2>&1; then
133
+ log_info "Codex MCP configurado via codex mcp add."
134
+ return 0
135
+ fi
136
+ log_warn "Falha ao configurar Codex MCP via codex CLI. Tentando fallback em config.toml..."
137
+ fi
138
+
126
139
  local update_result
127
140
  if ! update_result="$(
128
141
  python3 - "${CODEX_CONFIG_FILE}" "${MCP_SERVER_COMMAND}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
129
- import re
130
142
  import sys
131
143
  from pathlib import Path
132
144
 
@@ -150,15 +162,25 @@ block = (
150
162
  'MCP_FORCE_SEMANTIC_FALLBACK = "true"\n'
151
163
  )
152
164
 
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}"
165
+ target_headers = {"[mcp_servers.rag-codebase]", "[mcp_servers.rag-codebase.env]"}
166
+ lines = text.splitlines()
167
+ cleaned_lines: list[str] = []
168
+ skipping = False
169
+
170
+ for line in lines:
171
+ stripped = line.strip()
172
+ is_header = stripped.startswith("[") and stripped.endswith("]")
173
+ if is_header and stripped in target_headers:
174
+ skipping = True
175
+ continue
176
+ if is_header and skipping:
177
+ skipping = False
178
+ if not skipping:
179
+ cleaned_lines.append(line)
180
+
181
+ cleaned = "\n".join(cleaned_lines).strip()
182
+ prefix = f"{cleaned}\n\n" if cleaned else ""
183
+ new_text = f"{prefix}{block}\n"
162
184
 
163
185
  if new_text == text:
164
186
  print("skip:already_set")
@@ -276,18 +298,18 @@ ensure_own_rag_cli_config
276
298
  log_info "Config criada/ok: ${OWN_RAG_CONFIG_FILE}"
277
299
 
278
300
  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"
301
+ ensure_mcp_json_config "${CURSOR_MCP_CONFIG_1}" "Cursor" || true
302
+ ensure_mcp_json_config "${CURSOR_MCP_CONFIG_2}" "Cursor" || true
281
303
  ensure_cursor_semantic_rule_files
282
304
  ensure_cursor_force_fallback_env
283
305
  fi
284
306
 
285
307
  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"
308
+ ensure_mcp_json_config "${CLAUDE_CONFIG_FILE}" "Claude" || true
287
309
  fi
288
310
 
289
311
  if command -v codex >/dev/null 2>&1 || [[ -d "${HOME}/.codex" ]] || [[ -f "${CODEX_CONFIG_FILE}" ]]; then
290
- ensure_codex_mcp_config
312
+ ensure_codex_mcp_config || true
291
313
  fi
292
314
 
293
315
  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.7-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,125 @@ 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 command -v codex &>/dev/null; then
1108
+ codex mcp remove rag-codebase >/dev/null 2>&1 || true
1109
+ if codex mcp add rag-codebase \
1110
+ --env "OWN_RAG_CLI_CONFIG_FILE=${OWN_RAG_CONFIG_FILE}" \
1111
+ --env "TOKENIZERS_PARALLELISM=false" \
1112
+ --env "MCP_FORCE_SEMANTIC_FALLBACK=true" \
1113
+ -- "${MCP_SERVER_DEST}" >/dev/null 2>&1; then
1114
+ echo "ok:updated_rag_codebase"
1115
+ return 0
1116
+ fi
1117
+ fi
1118
+
1119
+ python3 - "${CODEX_CONFIG_TOML}" "${MCP_SERVER_DEST}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1120
+ import sys
1121
+ from pathlib import Path
1122
+
1123
+ cfg_path = Path(sys.argv[1]).expanduser()
1124
+ mcp_server_command = sys.argv[2]
1125
+ own_rag_cli_config_file = sys.argv[3]
1126
+
1127
+ cfg_path.parent.mkdir(parents=True, exist_ok=True)
1128
+ text = cfg_path.read_text(encoding="utf-8") if cfg_path.exists() else ""
1129
+
1130
+ block = (
1131
+ "[mcp_servers.rag-codebase]\n"
1132
+ f'command = "{mcp_server_command}"\n'
1133
+ "args = []\n\n"
1134
+ "[mcp_servers.rag-codebase.env]\n"
1135
+ f'OWN_RAG_CLI_CONFIG_FILE = "{own_rag_cli_config_file}"\n'
1136
+ 'TOKENIZERS_PARALLELISM = "false"\n'
1137
+ 'MCP_FORCE_SEMANTIC_FALLBACK = "true"\n'
1138
+ )
1139
+
1140
+ target_headers = {"[mcp_servers.rag-codebase]", "[mcp_servers.rag-codebase.env]"}
1141
+ lines = text.splitlines()
1142
+ cleaned_lines = []
1143
+ skipping = False
1144
+
1145
+ for line in lines:
1146
+ stripped = line.strip()
1147
+ is_header = stripped.startswith("[") and stripped.endswith("]")
1148
+ if is_header and stripped in target_headers:
1149
+ skipping = True
1150
+ continue
1151
+ if is_header and skipping:
1152
+ skipping = False
1153
+ if not skipping:
1154
+ cleaned_lines.append(line)
1155
+
1156
+ cleaned = "\n".join(cleaned_lines).strip()
1157
+ prefix = f"{cleaned}\n\n" if cleaned else ""
1158
+ new_text = f"{prefix}{block}\n"
1159
+
1160
+ if new_text == text:
1161
+ print("ok:already_exists")
1162
+ raise SystemExit(0)
1163
+
1164
+ cfg_path.write_text(new_text, encoding="utf-8")
1165
+ print("ok:updated_rag_codebase")
1166
+ PYEOF
1167
+ }
1168
+
1169
+ check_codex_mcp_up_to_date() {
1170
+ if command -v codex &>/dev/null && codex mcp get rag-codebase >/dev/null 2>&1; then
1171
+ return 0
1172
+ fi
1173
+ if [[ ! -f "${CODEX_CONFIG_TOML}" ]]; then
1174
+ return 1
1175
+ fi
1176
+ local check_result
1177
+ check_result="$(
1178
+ python3 - "${CODEX_CONFIG_TOML}" "${MCP_SERVER_DEST}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1179
+ import sys
1180
+ from pathlib import Path
1181
+
1182
+ cfg_path = Path(sys.argv[1]).expanduser()
1183
+ mcp_server_command = sys.argv[2]
1184
+ own_rag_cli_config_file = sys.argv[3]
1185
+
1186
+ try:
1187
+ text = cfg_path.read_text(encoding="utf-8")
1188
+ except Exception:
1189
+ print("needs_update")
1190
+ raise SystemExit(0)
1191
+
1192
+ if text.count("[mcp_servers.rag-codebase]") != 1:
1193
+ print("needs_update")
1194
+ raise SystemExit(0)
1195
+ if text.count("[mcp_servers.rag-codebase.env]") != 1:
1196
+ print("needs_update")
1197
+ raise SystemExit(0)
1198
+ if f'command = "{mcp_server_command}"' not in text:
1199
+ print("needs_update")
1200
+ raise SystemExit(0)
1201
+ if f'OWN_RAG_CLI_CONFIG_FILE = "{own_rag_cli_config_file}"' not in text:
1202
+ print("needs_update")
1203
+ raise SystemExit(0)
1204
+ if 'TOKENIZERS_PARALLELISM = "false"' not in text:
1205
+ print("needs_update")
1206
+ raise SystemExit(0)
1207
+ if 'MCP_FORCE_SEMANTIC_FALLBACK = "true"' not in text:
1208
+ print("needs_update")
1209
+ raise SystemExit(0)
1210
+
1211
+ print("already_up_to_date")
1212
+ PYEOF
1213
+ )"
1214
+ [[ "${check_result}" == "already_up_to_date" ]]
1215
+ }
1216
+
1100
1217
  TARGET_CONFIGS=()
1101
1218
  TARGET_LABELS=()
1102
1219
 
@@ -1122,7 +1239,12 @@ if [[ -f "${CURSOR_MCP_JSON_2}" ]]; then
1122
1239
  _append_target "${CURSOR_MCP_JSON_2}" "Cursor"
1123
1240
  fi
1124
1241
 
1125
- if [[ "${#TARGET_CONFIGS[@]}" -eq 0 ]]; then
1242
+ HAS_TARGETS=false
1243
+ if [[ "${#TARGET_CONFIGS[@]}" -gt 0 || "${CODEX_APP_INSTALLED}" == "true" ]]; then
1244
+ HAS_TARGETS=true
1245
+ fi
1246
+
1247
+ if [[ "${HAS_TARGETS}" != "true" ]]; then
1126
1248
  log_info "$(t no_cfg_files)"
1127
1249
  else
1128
1250
  PENDING_CONFIGS=()
@@ -1165,6 +1287,7 @@ desired = {
1165
1287
  "env": {
1166
1288
  "OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
1167
1289
  "TOKENIZERS_PARALLELISM": "false",
1290
+ "MCP_FORCE_SEMANTIC_FALLBACK": "true",
1168
1291
  },
1169
1292
  "version": mcp_version,
1170
1293
  }
@@ -1194,6 +1317,11 @@ PYEOF
1194
1317
  fi
1195
1318
  done
1196
1319
 
1320
+ if [[ "${CODEX_APP_INSTALLED}" == "true" ]] && ! check_codex_mcp_up_to_date; then
1321
+ PENDING_CONFIGS+=("${CODEX_CONFIG_TOML}")
1322
+ PENDING_LABELS+=("Codex")
1323
+ fi
1324
+
1197
1325
  if [[ "${#PENDING_CONFIGS[@]}" -eq 0 ]]; then
1198
1326
  log_info "$(t cfg_all_current)"
1199
1327
  else
@@ -1216,7 +1344,12 @@ PYEOF
1216
1344
  CFG_PATH="${PENDING_CONFIGS[$i]}"
1217
1345
  CFG_LABEL="${PENDING_LABELS[$i]}"
1218
1346
 
1219
- if ! RESULT=$(
1347
+ if [[ "${CFG_LABEL}" == "Codex" ]]; then
1348
+ if ! RESULT="$(configure_codex_mcp)"; then
1349
+ log_warn "$(t cannot_update_cfg) ${CFG_LABEL} (${CFG_PATH}): ${RESULT}"
1350
+ continue
1351
+ fi
1352
+ elif ! RESULT=$(
1220
1353
  python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1221
1354
  import json
1222
1355
  import sys
@@ -1250,6 +1383,7 @@ desired = {
1250
1383
  "env": {
1251
1384
  "OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
1252
1385
  "TOKENIZERS_PARALLELISM": "false",
1386
+ "MCP_FORCE_SEMANTIC_FALLBACK": "true",
1253
1387
  },
1254
1388
  "version": mcp_version,
1255
1389
  }
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,140 @@ 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 command -v codex &>/dev/null; then
1146
+ codex mcp remove rag-codebase >/dev/null 2>&1 || true
1147
+ if codex mcp add rag-codebase \
1148
+ --env "OWN_RAG_CLI_CONFIG_FILE=${OWN_RAG_CONFIG_FILE}" \
1149
+ --env "TOKENIZERS_PARALLELISM=false" \
1150
+ --env "MCP_FORCE_SEMANTIC_FALLBACK=true" \
1151
+ -- "${MCP_SERVER_DEST}" >/dev/null 2>&1; then
1152
+ echo "ok:updated_rag_codebase"
1153
+ return 0
1154
+ fi
1155
+ fi
1156
+
1157
+ python3 - "${CODEX_CONFIG_TOML}" "${MCP_SERVER_DEST}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1158
+ import sys
1159
+ from pathlib import Path
1160
+
1161
+ cfg_path = Path(sys.argv[1]).expanduser()
1162
+ mcp_server_command = sys.argv[2]
1163
+ own_rag_cli_config_file = sys.argv[3]
1164
+
1165
+ cfg_path.parent.mkdir(parents=True, exist_ok=True)
1166
+ text = cfg_path.read_text(encoding="utf-8") if cfg_path.exists() else ""
1167
+
1168
+ block = (
1169
+ "[mcp_servers.rag-codebase]\n"
1170
+ f'command = "{mcp_server_command}"\n'
1171
+ "args = []\n\n"
1172
+ "[mcp_servers.rag-codebase.env]\n"
1173
+ f'OWN_RAG_CLI_CONFIG_FILE = "{own_rag_cli_config_file}"\n'
1174
+ 'TOKENIZERS_PARALLELISM = "false"\n'
1175
+ 'MCP_FORCE_SEMANTIC_FALLBACK = "true"\n'
1176
+ )
1177
+
1178
+ target_headers = {"[mcp_servers.rag-codebase]", "[mcp_servers.rag-codebase.env]"}
1179
+ lines = text.splitlines()
1180
+ cleaned_lines = []
1181
+ skipping = False
1182
+
1183
+ for line in lines:
1184
+ stripped = line.strip()
1185
+ is_header = stripped.startswith("[") and stripped.endswith("]")
1186
+ if is_header and stripped in target_headers:
1187
+ skipping = True
1188
+ continue
1189
+ if is_header and skipping:
1190
+ skipping = False
1191
+ if not skipping:
1192
+ cleaned_lines.append(line)
1193
+
1194
+ cleaned = "\n".join(cleaned_lines).strip()
1195
+ prefix = f"{cleaned}\n\n" if cleaned else ""
1196
+ new_text = f"{prefix}{block}\n"
1197
+
1198
+ if new_text == text:
1199
+ print("ok:already_exists")
1200
+ raise SystemExit(0)
1201
+
1202
+ cfg_path.write_text(new_text, encoding="utf-8")
1203
+ print("ok:updated_rag_codebase")
1204
+ PYEOF
1205
+ }
1206
+
1207
+ check_codex_mcp_up_to_date() {
1208
+ if command -v codex &>/dev/null && codex mcp get rag-codebase >/dev/null 2>&1; then
1209
+ return 0
1210
+ fi
1211
+ if [[ ! -f "${CODEX_CONFIG_TOML}" ]]; then
1212
+ return 1
1213
+ fi
1214
+ local check_result
1215
+ check_result="$(
1216
+ python3 - "${CODEX_CONFIG_TOML}" "${MCP_SERVER_DEST}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1217
+ import sys
1218
+ from pathlib import Path
1219
+
1220
+ cfg_path = Path(sys.argv[1]).expanduser()
1221
+ mcp_server_command = sys.argv[2]
1222
+ own_rag_cli_config_file = sys.argv[3]
1223
+
1224
+ try:
1225
+ text = cfg_path.read_text(encoding="utf-8")
1226
+ except Exception:
1227
+ print("needs_update")
1228
+ raise SystemExit(0)
1229
+
1230
+ if text.count("[mcp_servers.rag-codebase]") != 1:
1231
+ print("needs_update")
1232
+ raise SystemExit(0)
1233
+ if text.count("[mcp_servers.rag-codebase.env]") != 1:
1234
+ print("needs_update")
1235
+ raise SystemExit(0)
1236
+ if f'command = "{mcp_server_command}"' not in text:
1237
+ print("needs_update")
1238
+ raise SystemExit(0)
1239
+ if f'OWN_RAG_CLI_CONFIG_FILE = "{own_rag_cli_config_file}"' not in text:
1240
+ print("needs_update")
1241
+ raise SystemExit(0)
1242
+ if 'TOKENIZERS_PARALLELISM = "false"' not in text:
1243
+ print("needs_update")
1244
+ raise SystemExit(0)
1245
+ if 'MCP_FORCE_SEMANTIC_FALLBACK = "true"' not in text:
1246
+ print("needs_update")
1247
+ raise SystemExit(0)
1248
+
1249
+ print("already_up_to_date")
1250
+ PYEOF
1251
+ )"
1252
+ [[ "${check_result}" == "already_up_to_date" ]]
1253
+ }
1138
1254
 
1139
1255
  TARGET_CONFIGS=()
1140
1256
  TARGET_LABELS=()
@@ -1161,7 +1277,12 @@ if [[ "$CURSOR_APP_INSTALLED" == "true" ]] && [[ -f "${CURSOR_MCP_JSON_2}" ]]; t
1161
1277
  _append_target "${CURSOR_MCP_JSON_2}" "Cursor"
1162
1278
  fi
1163
1279
 
1164
- if [[ "${#TARGET_CONFIGS[@]}" -eq 0 ]]; then
1280
+ HAS_TARGETS=false
1281
+ if [[ "${#TARGET_CONFIGS[@]}" -gt 0 || "${CODEX_APP_INSTALLED}" == "true" ]]; then
1282
+ HAS_TARGETS=true
1283
+ fi
1284
+
1285
+ if [[ "${HAS_TARGETS}" != "true" ]]; then
1165
1286
  log_info "$(t no_default_cfg)"
1166
1287
  else
1167
1288
  PENDING_CONFIGS=()
@@ -1204,6 +1325,7 @@ desired = {
1204
1325
  "env": {
1205
1326
  "OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
1206
1327
  "TOKENIZERS_PARALLELISM": "false",
1328
+ "MCP_FORCE_SEMANTIC_FALLBACK": "true",
1207
1329
  },
1208
1330
  "version": mcp_version,
1209
1331
  }
@@ -1233,34 +1355,45 @@ PYEOF
1233
1355
  fi
1234
1356
  done
1235
1357
 
1358
+ if [[ "${CODEX_APP_INSTALLED}" == "true" ]] && ! check_codex_mcp_up_to_date; then
1359
+ PENDING_CONFIGS+=("${CODEX_CONFIG_TOML}")
1360
+ PENDING_LABELS+=("Codex")
1361
+ fi
1362
+
1236
1363
  if [[ "${#PENDING_CONFIGS[@]}" -eq 0 ]]; then
1237
1364
  log_info "$(t mcp_cfg_all_current)"
1238
1365
  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
1366
  echo ""
1248
- if ask_yes_no_loop "$(t ask_apply_cfg)"; then
1249
- APPLY_MCP_CONFIG=true
1367
+ log_info "$(t detected_cfg_files)"
1368
+ for i in "${!PENDING_CONFIGS[@]}"; do
1369
+ echo -e " - ${PENDING_LABELS[$i]}: ${PENDING_CONFIGS[$i]}"
1370
+ done
1371
+
1372
+ APPLY_MCP_CONFIG=false
1373
+ if [[ -t 0 ]]; then
1374
+ echo ""
1375
+ if ask_yes_no_loop "$(t ask_apply_cfg)"; then
1376
+ APPLY_MCP_CONFIG=true
1377
+ else
1378
+ APPLY_MCP_CONFIG=false
1379
+ fi
1250
1380
  else
1251
- APPLY_MCP_CONFIG=false
1381
+ log_info "$(t non_interactive_cfg_skip)"
1252
1382
  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
1383
 
1262
- if ! RESULT=$(
1263
- python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1384
+ if [[ "$APPLY_MCP_CONFIG" == "true" ]]; then
1385
+ for i in "${!PENDING_CONFIGS[@]}"; do
1386
+ CFG_PATH="${PENDING_CONFIGS[$i]}"
1387
+ CFG_LABEL="${PENDING_LABELS[$i]}"
1388
+
1389
+ if [[ "${CFG_LABEL}" == "Codex" ]]; then
1390
+ if ! RESULT="$(configure_codex_mcp)"; then
1391
+ log_warn "$(t cannot_update_cfg) ${CFG_LABEL} (${CFG_PATH}): ${RESULT}"
1392
+ continue
1393
+ fi
1394
+ else
1395
+ if ! RESULT=$(
1396
+ python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
1264
1397
  import json
1265
1398
  import sys
1266
1399
  from pathlib import Path
@@ -1293,6 +1426,7 @@ desired = {
1293
1426
  "env": {
1294
1427
  "OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
1295
1428
  "TOKENIZERS_PARALLELISM": "false",
1429
+ "MCP_FORCE_SEMANTIC_FALLBACK": "true",
1296
1430
  },
1297
1431
  "version": mcp_version,
1298
1432
  }
@@ -1332,33 +1466,34 @@ data["mcpServers"] = mcp_servers
1332
1466
  cfg_path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
1333
1467
  print("ok:added")
1334
1468
  PYEOF
1335
- ); then
1336
- log_warn "$(t cannot_update_cfg) ${CFG_LABEL} (${CFG_PATH}): ${RESULT}"
1337
- continue
1338
- fi
1469
+ ); then
1470
+ log_warn "$(t cannot_update_cfg) ${CFG_LABEL} (${CFG_PATH}): ${RESULT}"
1471
+ continue
1472
+ fi
1473
+ fi
1339
1474
 
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
1475
+ case "${RESULT}" in
1476
+ ok:already_exists)
1477
+ log_info "${CFG_LABEL}: $(t already_updated)"
1478
+ ;;
1479
+ ok:updated_rag_codebase)
1480
+ log_info "${CFG_LABEL}: $(t updated_version) ${MCP_VERSION}."
1481
+ ;;
1482
+ ok:replaced_old:*)
1483
+ OLD_KEY="${RESULT#ok:replaced_old:}"
1484
+ log_info "${CFG_LABEL}: $(t replaced_old) ${MCP_VERSION})."
1485
+ ;;
1486
+ ok:added)
1487
+ log_info "${CFG_LABEL}: $(t added_cfg) ${MCP_VERSION})."
1488
+ ;;
1489
+ *)
1490
+ log_warn "${CFG_LABEL}: $(t unexpected_return) ${RESULT}"
1491
+ ;;
1492
+ esac
1493
+ done
1494
+ else
1495
+ log_info "$(t user_skipped_cfg)"
1496
+ fi
1362
1497
  fi
1363
1498
  fi
1364
1499