본문으로 이동

도움말:S3 연구 메모리/문제 해결: 두 판 사이의 차이

S3 연구 메모리
S3 연구 메모리 저장소 문서 게시
 
S3 연구 메모리 저장소 문서 동기화
 
(같은 사용자의 중간 판 하나는 보이지 않습니다)
380번째 줄: 380번째 줄:
</nowiki></pre>
</nowiki></pre>


주요 시작 오류는 잘못된 쓰기 인증 모드, <code><nowiki>token</nowiki></code> 모드에서 잘못되거나 빠진 64자리 토큰 해시, <code><nowiki>/mcp</nowiki></code>로 끝나지 않는 공개 URL, 명시적인 허용 없이 쓴 비-loopback HTTP, 이미 사용 중인 bind port입니다. <code><nowiki>.env</nowiki></code>를 고치고 <code><nowiki>docker compose config --quiet</nowiki></code>를 실행한 뒤 <code><nowiki>mcp-http</nowiki></code>만 다시 만듭니다. 일반 설정은 URL <code><nowiki>https://s3wiki.yonsei.ac.kr/mcp</nowiki></code>, bind <code><nowiki>127.0.0.1</nowiki></code>, allow flag <code><nowiki>false</nowiki></code>입니다. 같은 endpoint에서 세 변경 도구에 공용 Bearer 토큰을 사용합니다.
주요 시작 오류는 잘못된 쓰기 인증 모드, <code><nowiki>token</nowiki></code> 모드에서 잘못되거나 빠진 64자리 토큰 해시, <code><nowiki>github</nowiki></code> 모드에서 빠진 client ID·secret·allowlist, <code><nowiki>/mcp</nowiki></code>로 끝나지 않는 공개 URL, 명시적인 허용 없이 쓴 비-loopback HTTP, 이미 사용 중인 bind port입니다. <code><nowiki>.env</nowiki></code>를 고치고 <code><nowiki>docker compose config --quiet</nowiki></code>를 실행한 뒤 <code><nowiki>mcp-http</nowiki></code>만 다시 만듭니다.
 
=== GitHub OAuth 연결이 실패함 ===
 
GitHub OAuth App callback URL이 다음 값과 정확히 같은지 확인합니다.
 
<pre><nowiki>
https://s3wiki.yonsei.ac.kr/oauth/github/callback
</nowiki></pre>
 
<code><nowiki>S3RM_GITHUB_ALLOWED_USERS</nowiki></code>와 <code><nowiki>S3RM_GITHUB_ALLOWED_ORGS</nowiki></code>는 GitHub 로그인 이름을 쉼표로 구분합니다. private 조직 membership을 확인하려면 사용자가 GitHub 승인 화면에서 <code><nowiki>read:org</nowiki></code>를 허용해야 합니다. <code><nowiki>mcp-http</nowiki></code>를 다시 만들면 메모리에 있던 OAuth client와 token이 사라지므로 ChatGPT 앱 인증을 다시 진행합니다. 일반 설정은 URL <code><nowiki>https://s3wiki.yonsei.ac.kr/mcp</nowiki></code>, bind <code><nowiki>127.0.0.1</nowiki></code>, allow flag <code><nowiki>false</nowiki></code>입니다. 같은 endpoint에서 세 변경 도구에 공용 Bearer 토큰을 사용합니다.


health는 성공하지만 공용 <code><nowiki>/mcp</nowiki></code>가 실패하면 프로세스는 살아 있습니다. 직접 IP 경로와 아래 HTTP 상태 항목을 확인합니다. <code><nowiki>/healthz</nowiki></code>는 변경 자격 증명이나 위키 로그인을 확인하지 않습니다.
health는 성공하지만 공용 <code><nowiki>/mcp</nowiki></code>가 실패하면 프로세스는 살아 있습니다. 직접 IP 경로와 아래 HTTP 상태 항목을 확인합니다. <code><nowiki>/healthz</nowiki></code>는 변경 자격 증명이나 위키 로그인을 확인하지 않습니다.
441번째 줄: 451번째 줄:
=== 결과가 잘렸거나 <code><nowiki>limit</nowiki></code>보다 적음 ===
=== 결과가 잘렸거나 <code><nowiki>limit</nowiki></code>보다 적음 ===


모든 직렬화 결과에는 크기 제한이 있습니다. 목록 페이지에는 <code><nowiki>page_limited_by_output</nowiki></code>, 모든 결과에는 <code><nowiki>output_truncated</nowiki></code>가 표시될 수 있습니다. field 수나 <code><nowiki>limit</nowiki></code>을 줄이고 <code><nowiki>next_cursor</nowiki></code>를 이어서 사용합니다. 목록 <code><nowiki>limit</nowiki></code>은 1~20이며 기본값은 5입니다. <code><nowiki>S3RM_MAX_OUTPUT_BYTES</nowiki></code> 기본값은 32768이고 2048~65536만 받습니다. 그보다 높은 hard limit으로 올릴 수 없습니다. SDK 검증 오류를 포함한 전체 JSON-RPC HTTP body에는 별도 147456바이트 제한이 있습니다.
모든 직렬화 결과에는 크기 제한이 있습니다. 목록 페이지에는 <code><nowiki>page_limited_by_output</nowiki></code>, 모든 결과에는 <code><nowiki>output_truncated</nowiki></code>가 표시될 수 있습니다. field 수나 <code><nowiki>limit</nowiki></code>을 줄이고 <code><nowiki>next_cursor</nowiki></code>를 이어서 사용합니다. 목록 <code><nowiki>limit</nowiki></code>은 1~20이며 기본값은 5입니다. <code><nowiki>S3RM_MAX_OUTPUT_BYTES</nowiki></code> 기본값은 32768이고 2048~65536만 받습니다. 그보다 높은 hard limit으로 올릴 수 없습니다. SDK 검증 오류를 포함한 전체 JSON-RPC HTTP body에는 별도 212992바이트 제한이 있습니다.


큰 결과를 한 번에 받으려고 제한을 높이지 마세요. 먼저 검색 요약을 받고, 추린 결과에 대해 선택 field로 <code><nowiki>get_lesson</nowiki></code>을 호출합니다.
큰 결과를 한 번에 받으려고 제한을 높이지 마세요. 먼저 검색 요약을 받고, 추린 결과에 대해 선택 field로 <code><nowiki>get_lesson</nowiki></code>을 호출합니다.

2026년 7월 16일 (목) 23:32 기준 최신판

이 페이지는 저장소 문서에서 자동으로 동기화됩니다. 위키에서 직접 편집하지 마세요.

실패한 상태를 보존하고, 출력 길이를 제한한 진단부터 실행합니다. 원인을 찾는 동안 볼륨을 지우거나, DB 테이블을 직접 고치거나, LocalSettings.php를 다시 만들거나, 백업의 유일한 사본으로 복원을 반복하지 마세요.

docker compose config --quiet
docker compose ps -a
docker compose logs --tail=200 db mediawiki bootstrap mcp-http caddy

출력을 전달할 때는 비밀번호, session cookie, Bearer 토큰, 전체 환경 dump를 지웁니다. Lesson 내용은 공개 대상이지만 운영 자격 증명은 공개하지 않습니다.

Compose에서 필수 변수가 없다고 나옴

예상 메시지:

required variable MARIADB_PASSWORD is missing a value

파일 이름이 compose.yaml 옆의 .env인지 확인하고, 필수 change-me 비밀번호를 모두 바꿉니다. 토큰을 출력하지 않고 공용 MCP 설정을 마칩니다.

test -f .env
grep -n 'change-me' .env
./scripts/configure-public-domain.sh s3wiki.yonsei.ac.kr \
  --expected-ip 165.132.118.220
docker compose config --quiet

저장소 밖에서 Compose를 실행한다면 절대 프로젝트 경로를 적습니다.

docker compose --project-directory /ABS/PATH/TO/s3wiki config --quiet

해석된 설정에는 비밀번호와 토큰 해시가 있으므로 일반 확인에는 config --quiet를 사용합니다.

호스트 포트 8765를 이미 사용 중임

8765는 도메인 배포의 loopback 진단 포트입니다. Caddy는 Compose 네트워크에서 mcp-http:8000에 연결하므로 호스트 진단 포트를 바꿔도 클라이언트 주소는 그대로입니다.

S3RM_MCP_PUBLIC_URL=https://s3wiki.yonsei.ac.kr/mcp
S3RM_MCP_BIND_ADDRESS=127.0.0.1
S3RM_MCP_HTTP_PORT=18765
S3RM_MCP_ALLOW_INSECURE_HTTP=false

공용 MCP를 다시 만들고 127.0.0.1:18765/healthz로 프로세스를 확인합니다.

docker compose up -d --force-recreate mcp-http

클라이언트 주소는 계속 https://s3wiki.yonsei.ac.kr/mcp입니다. 새 진단 포트를 외부에 열거나 로컬 대체 MCP를 시작하지 마세요.

호스트 포트 8080을 이미 사용 중임

사용하지 않는 포트를 고르고 외부 URL은 그대로 둡니다.

S3RM_HTTP_PORT=8090
MW_SERVER_URL=https://s3wiki.yonsei.ac.kr

MediaWiki를 다시 만듭니다.

docker compose up -d --force-recreate mediawiki bootstrap

이 포트는 직접 진단용입니다. 브라우저 링크와 리디렉션은 계속 https://s3wiki.yonsei.ac.kr/를 사용해야 합니다.

호스트 포트 80 또는 443을 이미 사용 중임

공개 배포에서는 Caddy가 두 포트를 모두 사용해야 합니다. 관련 없는 서비스를 바로 멈추지 말고 리스너부터 확인합니다.

ss -ltnp '( sport = :80 or sport = :443 )'
docker compose ps caddy
docker compose logs --tail=200 caddy

충돌하는 서비스를 옮기거나 설정을 바꾼 뒤 Caddy를 다시 만듭니다. 공개 포트를 다른 번호로 우회하면 일반 HTTPS URL과 인증서 검증이 실패합니다.

DNS는 맞지만 루트 주소가 연결 재설정 또는 거부로 열리지 않음

브라우저에서 루트 주소가 ERR_CONNECTION_RESET 또는 Connection refused로 끝나고 DNS가 165.132.118.220을 가리킨다면 실제 리스너부터 확인합니다.

getent ahostsv4 s3wiki.yonsei.ac.kr
ss -ltn '( sport = :80 or sport = :443 or sport = :8080 or sport = :8765 )'
docker compose ps -a

80/443은 없고 8080/8765만 보이면 MediaWiki와 MCP의 진단 포트만 열린 상태입니다. Caddy가 든 Compose domain 프로필이 시작되지 않은 것이므로 방화벽이나 커널 설정을 먼저 바꾸지 마세요.

기본 도메인 설정에서는 8080을 127.0.0.1에만 게시하므로 다른 컴퓨터에서 접속할 수 없습니다. 서버 담당자가 직접 HTTP 화면도 열기로 했다면 다음 두 값을 함께 설정하고 MediaWiki를 다시 만듭니다.

S3RM_WIKI_BIND_ADDRESS=0.0.0.0
S3RM_WIKI_DIRECT_URL=http://165.132.118.220:8080
docker compose up -d --no-deps --force-recreate mediawiki

이후 서버에서 직접 주소가 자기 주소로 이동하는지 확인합니다.

curl --silent --show-error --head http://165.132.118.220:8080/

Location이 같은 IP의 8080을 가리키면 도메인과 직접 주소가 분리된 것입니다. 이 설정은 Docker 리스너만 엽니다. 외부 여러 지역에서 계속 timeout이면 학교 경계에서 TCP 8080이 차단된 상태이므로 보안정책에 8080을 별도로 추가해야 합니다. 직접 HTTP 주소를 MCP에 등록하지 마세요. MCP는 계속 HTTPS 도메인 하나만 사용합니다.

Docker socket 접근이 permission denied로 실패하고 sudo 암호가 필요한 서버에서는 대화형 셸에서 다음 한 줄을 실행합니다.

cd /home/mrcha033/Projects/s3wiki; sudo -v; make domain-up COMPOSE='sudo docker compose'

sudo -v는 자격을 먼저 확인합니다. COMPOSE에만 sudo를 붙이면 저장소 파일과 .env는 현재 사용자 소유로 남습니다. sudo make domain-up을 실행하거나 /var/run/docker.sock을 mode 666으로 바꾸지 마세요. 이 증상 때문에 sysctl을 바꾸지 않습니다.

실행 뒤 서비스, Caddy 로그, 공개 포트, HTTPS 응답을 차례로 확인합니다.

sudo docker compose --profile domain ps -a
sudo docker compose --profile domain logs --tail=200 caddy
ss -ltn '( sport = :80 or sport = :443 )'
curl --fail --silent --show-error --head https://s3wiki.yonsei.ac.kr/
curl --fail --silent --show-error \
  'https://s3wiki.yonsei.ac.kr/api.php?action=query&meta=siteinfo&format=json' \
  >/dev/null

caddy가 실행 중이고 80/443이 리슨하며 두 curl이 성공해야 외부 브라우저에서 확인합니다. 실패하면 Caddy 로그의 인증서 또는 포트 오류를 먼저 해결합니다.

HTTPS 인증서가 발급되지 않음

DNS가 이 서버를 가리키고 두 공개 포트가 서버까지 들어오는지 확인합니다.

getent ahostsv4 s3wiki.yonsei.ac.kr
docker compose ps caddy
docker compose logs --tail=300 caddy

예상 IPv4는 165.132.118.220입니다. DNS가 맞다면 캠퍼스·호스트 방화벽과 포트 소유 프로세스를 확인합니다. caddy_data를 지워도 DNS나 라우팅은 고쳐지지 않으며 불필요한 인증서 요청만 늘어날 수 있습니다. 외부 연결을 고친 뒤 Caddy만 다시 만들고 다른 네트워크에서 확인합니다.

docker compose up -d --force-recreate caddy
curl --fail --silent --show-error --head https://s3wiki.yonsei.ac.kr/

Caddy가 80/443을 리슨하고 서버 안에서는 HTTP 308이 나오는데 로그에 다음 문구가 있다면 애플리케이션 문제가 아닙니다.

Timeout during connect (likely firewall problem)

Let’s Encrypt의 http-01tls-alpn-01이 모두 이 오류라면 외부에서 서버의 TCP 80과 443에 들어오지 못하는 상태입니다. 연세대학교 정보통신처의 보안정책서비스 안내에 따라 보안정책 신청을 합니다. 네트워크 PORT 신청은 벽면 네트워크 포트 설치 절차이므로 이 문제와 다릅니다. 신청 화면에는 다음 값을 적습니다. 소속, 성명, 연락처, 이메일은 신청자가 직접 입력합니다. 개인 연락처나 계정 정보는 이 저장소에 남기지 않습니다.

신청 항목 입력값
소속 신청자 소속 직접 입력
성명 신청자 성명 직접 입력
연락처 신청자 연락처 직접 입력
이메일 신청자 연세 이메일 직접 입력
시작일 2026-07-16
종료일 2029-07-15
출발지 IP 공개 웹서비스 80/443 예외 적용 요청. 출발지는 공개 웹서비스이므로 특정할 수 없습니다.
목적지 IP 165.132.118.220
프로토콜 TCP만 선택
사용포트 80, 443
요청사유 및 특이사항 아래 문안 붙여넣기

정책 기간은 최대 3년이므로 위 종료일은 시작일로부터 3년 이내입니다. 출발지 IP 칸이 숫자 주소만 받는다면 임의의 IP를 넣지 말고 보안정책 담당자 02-2123-6419에 공개 웹서비스 예외 입력 방법을 확인합니다.

요청사유 및 특이사항에는 다음 내용을 붙여넣습니다.

S3 연구실에서 함께 사용하는 위키(s3wiki.yonsei.ac.kr)를 운영하려고 합니다.
DNS는 165.132.118.220으로 등록되어 있고 서버도 80/443 포트에서 대기 중이지만,
현재 외부 연결이 차단되어 HTTPS 인증서 검증이 실패합니다.

HTTPS 접속과 인증서 자동 발급·갱신을 위해 목적지
165.132.118.220의 TCP 80, 443에 대한 외부 인바운드 허용을 요청드립니다.
출발지는 공개 웹서비스이므로 특정할 수 없습니다. 80은 인증서 검증과 HTTPS 전환,
443은 위키와 MCP 접속에 사용합니다. 그 밖의 포트 개방은 요청하지 않습니다.

공식 안내에는 필요한 웹서비스의 80/443은 출발지 IP 특정 조건의 예외라고 적혀 있습니다. 보안정책 문의는 정보통신처 02-2123-6419, 인터넷 문의는 02-2123-3411입니다.

포트가 열리면 Caddy가 인증서 발급을 자동으로 다시 시도합니다. Caddy 로그의 certificate obtained successfully와 서버의 make verify-domain을 확인한 뒤 학교 밖 네트워크의 브라우저를 다시 여세요. 인증서 볼륨을 지우거나 자체 서명 인증서로 바꾸지 마세요.

docker compose --profile domain logs --follow caddy
make verify-domain

/etc/group에는 이미 사용자가 docker 그룹에 있는데 현재 셸만 Docker 권한을 읽지 못한다면 로그아웃한 뒤 다시 로그인합니다. 바로 새 셸에서 작업하려면 newgrp docker를 실행한 뒤 위 명령을 사용합니다.

MariaDB가 unhealthy 상태임

관련 상태와 로그 끝부분만 확인합니다.

docker compose ps db
docker compose logs --tail=200 db

주요 원인은 비어 있거나 잘못된 필수 비밀번호, 디스크 부족, 볼륨 소유권 문제, db_data 초기화 뒤 .env의 DB 비밀번호만 바꾼 경우입니다. 환경 변수만 바꿔도 기존 MariaDB 계정은 바뀌지 않습니다. 이전에 맞던 .env를 복구하거나 계획된 DB 계정 교체를 수행하세요. 오류를 없애려고 db_data를 지우지 마세요.

MediaWiki가 unhealthy 상태임

첫 빌드와 마이그레이션에는 몇 분이 걸릴 수 있습니다. 의존 서비스와 로컬 상태 경로를 확인합니다.

docker compose ps -a
docker compose logs --tail=300 mediawiki
curl --fail --silent --show-error \
  'https://s3wiki.yonsei.ac.kr/api.php?action=query&meta=siteinfo&format=json'

DB 인증 불일치, 호환되지 않는 고정 확장 기능, Composer 빌드 실패, 디스크 부족, 잘못된 MW_SERVER_URL을 확인합니다. 로그의 원인을 고치고 서비스를 다시 만드세요. 생성된 설정 볼륨을 직접 편집하지 않습니다.

브라우저에 설치 세션 만료가 표시됨

이 메시지는 MediaWiki의 대화형 /mw-config/ 설치 화면에서 나옵니다. 이 배포는 해당 화면을 사용하지 않습니다. mediawiki entrypoint가 Apache를 시작하기 전에 CLI로 설치하고, 생성된 설정은 mediawiki_config 볼륨에 저장합니다. 세션 만료는 지원하지 않는 경로를 연 증상이지 원인이 아닙니다.

<!-- Contract marker: Do not increase session.gc_maxlifetime --> session.gc_maxlifetime를 늘리거나, 브라우저 설치를 다시 시작하거나, LocalSettings.php를 내려받거나, 볼륨을 지우지 마세요. 세션 수명만 늘려도 CLI 설정은 고쳐지지 않습니다.

설치 탭을 닫고 상태와 로그를 확인합니다.

docker compose ps -a
docker compose logs --tail=300 mediawiki bootstrap

mediawiki가 실행 중이면 설정 내용을 출력하지 않고 영구 설정과 이미지의 symlink를 확인합니다.

docker compose exec mediawiki \
  sh -c 'test -s /var/www/data/LocalSettings.php &&
    test "$(readlink -f /var/www/html/LocalSettings.php)" = /var/www/data/LocalSettings.php &&
    stat -c "%a %U %G %n" /var/www/data /var/www/data/LocalSettings.php \
      /opt/s3wiki/LocalSettings.s3.php /var/www/html/LocalSettings.php'

이미지는 시작할 때마다 다음 권한을 맞춥니다. 설정 디렉터리는 750 root:www-data, 생성된 LocalSettings.php640 root:www-data, web root symlink는 www-data 소유입니다. 비밀 정보가 없는 이미지 설정 파일은 Apache가 읽을 수 있습니다. upstream web root가 sticky이고 Linux의 보호된 symlink 동작이 있으므로 symlink 소유권도 필요합니다. API healthcheck는 설치 화면의 200 OK HTML이 아니라 MediaWiki JSON을 확인합니다.

위 검사가 성공하면 mediawiki가 healthy, bootstrap이 코드 0이 될 때까지 기다린 뒤 /mw-config/가 아니라 MW_SERVER_URL을 엽니다.

기준 데이터가 한 번도 없었던 새 시험 스택이라면 이미지와 서비스를 다시 만들어 CLI 설치를 실행합니다.

docker compose up -d --build --force-recreate mediawiki bootstrap
docker compose logs -f mediawiki bootstrap

운영하던 배포에서 LocalSettings.php를 잃었다면 여기서 진단을 멈춥니다. 기존 DB에 다시 설치하거나 볼륨을 지우지 마세요. S3RM1에 따라 같은 시점의 DB, 설정, 업로드 백업을 복원합니다.

bootstrapExited (0)

정상입니다. bootstrap은 daemon이 아니라 일회성 동기화 작업입니다. 평소에는 db, mediawiki, mcp-http가 healthy이고 bootstrap은 코드 0으로 종료됩니다.

bootstrap이 0이 아닌 코드로 끝남

docker compose logs --tail=300 bootstrap

주요 원인은 다음과 같습니다.

  • administrator login failed: .envMW_ADMIN_PASSWORD가 설치된 위키와 다릅니다. 이 값은 최초 설치 때만 관리자 계정을 만듭니다. .env만 바꿔도 위키 비밀번호는 바뀌지 않습니다.
  • manifest source is missing: 이미지 또는 저장소가 불완전합니다. 온전한 checkout에서 다시 빌드합니다.
  • edit failed/permission denied: 관리자 권한이 없어졌거나 관리 페이지가 예상과 다르게 보호되어 있습니다.
  • account provisioning failed: S3RM_WIKI_USERNAME을 확인합니다. DB 테이블을 직접 고치지 말고 MediaWiki 절차로 전용 계정을 교체합니다.

원인을 고친 뒤 다시 실행합니다.

docker compose up -d --build --force-recreate bootstrap
docker compose logs --tail=200 bootstrap

bootstrap은 관리 스키마와 양식을 맞추지만 일반 Lesson revision을 덮어쓰지 않습니다. 동기화 경고가 반복되면 우회하지 말고 원인을 확인하세요.

관리자 비밀번호가 .env와 맞지 않음

첫 설치 뒤 MW_ADMIN_PASSWORD만 바꿔도 MediaWiki에 저장된 비밀번호는 바뀌지 않습니다. 기존 비밀번호를 알고 있다면 .env 값을 다시 맞춥니다. 알 수 없다면 권한이 있는 서버 담당자가 고정된 MediaWiki 버전의 명령 도움말을 확인한 뒤 재설정합니다.

docker compose exec mediawiki \
  php maintenance/run.php resetPassword --help

현재 이미지가 출력한 문법만 사용합니다. 복구 작업을 기록하고, 추적하지 않는 .env를 갱신한 뒤 bootstrap을 다시 실행합니다. 새 비밀번호를 셸 기록에 직접 넣지 마세요.

양식이 없거나 Lesson이 template 원문으로 표시됨

  1. bootstrap이 코드 0으로 끝났는지 확인합니다.
  2. /index.php/Special:Version에서 Semantic MediaWiki, Page Forms, S3 Research Memory가 로드되었는지 확인합니다.
  3. Form:Lesson과 기준 template이 있는지 확인합니다.
  4. bootstrap을 다시 실행하고 로그를 봅니다.
docker compose up -d --force-recreate bootstrap
docker compose logs --tail=200 bootstrap

관리 양식이나 template 페이지를 직접 고치지 마세요. bootstrap이 이미지의 원본으로 맞춥니다.

Lesson ID 또는 양식 검증이 실패함

기준 ID 형식은 다음과 같습니다.

Lesson:<lowercase_slug>

slug는 소문자, 숫자, _, -만 사용할 수 있습니다. 첫 글자는 문자나 숫자이고 최대 128자입니다. 화면 제목인 title은 별도 필드이며 일반적인 대문자를 쓸 수 있습니다. 필수 연구 필드는 비울 수 없습니다. confidence는 low, medium, high 중 하나입니다.

새 Lesson이 검색되지 않음

페이지를 직접 열어 Lesson: 네임스페이스인지 먼저 확인합니다. /index.php/Special:Search에서 제목이나 본문의 구별되는 정확한 단어로 검색합니다. 먼저 대기 중인 MediaWiki·Semantic MediaWiki 작업을 실행합니다. 색인이 손상되었거나 DB 복원 뒤 누락된 경우에만 검색 색인을 다시 만듭니다.

docker compose exec mediawiki \
  php maintenance/run.php runJobs --maxjobs 100
docker compose exec mediawiki \
  php maintenance/run.php rebuildtextindex --quiet

현재 검색은 vector가 아니라 띄어쓰기와 단어 기반이므로 비슷한 뜻의 다른 단어까지 찾는다고 보장하지 않습니다. 도메인을 넘는 연결은 관계나 find_analogies를 사용합니다. MCP 검색만 실패한다면 어댑터와 namespace ID를 확인하고 Action API 요청에 srwhat=text가 포함되는지 확인합니다. 조회에는 Bearer 토큰이 필요하지 않습니다.

MCP 클라이언트가 끊겼거나 도구가 보이지 않음

모든 클라이언트는 같은 공용 Streamable HTTP URL을 사용해야 합니다. 서버에서 자격 증명을 출력하지 않고 전체 상태와 프로세스 경로를 확인합니다.

docker compose ps -a caddy mcp-http mediawiki bootstrap db
curl --fail --silent --show-error http://127.0.0.1:8765/healthz
docker compose logs --tail=200 mcp-http caddy

로컬 health 요청은 프로세스 실행만 확인합니다. 다른 PC에서 S3RM0의 토큰 없는 초기화를 정확한 https://s3wiki.yonsei.ac.kr/mcp 주소로 실행합니다. Authorization 없이 초기화되어야 하며 도구 목록과 네 조회 도구도 공개되어야 합니다.

다음 값을 확인합니다.

S3RM_MCP_PUBLIC_URL=https://s3wiki.yonsei.ac.kr/mcp
S3RM_MCP_WRITE_AUTH_MODE=token
S3RM_MCP_BIND_ADDRESS=127.0.0.1
S3RM_MCP_ALLOW_INSECURE_HTTP=false

먼저 Authorization 없이 공개 조회를 시험합니다. 로컬 health만 성공하고 원격 초기화가 실패하면 Caddy 로그, TLS, DNS, 80/443을 확인합니다. 클라이언트를 localhost에 연결하거나 별도 MCP 프로세스를 만들지 마세요.

클라이언트 주소는 정확히 공용 URL이어야 합니다. token 모드에서 변경 도구를 쓸 때만 공용 Bearer 토큰을 불러옵니다. open 모드에서는 조회와 세 변경 도구 모두 인증이 필요하지 않습니다. 클라이언트 사용자에게 Docker 명령, MediaWiki API URL, 위키 자격 증명을 전달하지 마세요. 플랫폼별 확인은 S3RM2를 봅니다.

MCP /healthz가 실패함

서버에서 Connection refused가 나오면 mcp-http가 설정된 bind·port에 리슨하지 않는 상태입니다. timeout은 호스트 방화벽이나 멈춘 프로세스일 수 있습니다.

docker compose ps mcp-http
docker compose logs --tail=200 mcp-http
docker compose up -d --force-recreate mcp-http

주요 시작 오류는 잘못된 쓰기 인증 모드, token 모드에서 잘못되거나 빠진 64자리 토큰 해시, github 모드에서 빠진 client ID·secret·allowlist, /mcp로 끝나지 않는 공개 URL, 명시적인 허용 없이 쓴 비-loopback HTTP, 이미 사용 중인 bind port입니다. .env를 고치고 docker compose config --quiet를 실행한 뒤 mcp-http만 다시 만듭니다.

GitHub OAuth 연결이 실패함

GitHub OAuth App callback URL이 다음 값과 정확히 같은지 확인합니다.

https://s3wiki.yonsei.ac.kr/oauth/github/callback

S3RM_GITHUB_ALLOWED_USERSS3RM_GITHUB_ALLOWED_ORGS는 GitHub 로그인 이름을 쉼표로 구분합니다. private 조직 membership을 확인하려면 사용자가 GitHub 승인 화면에서 read:org를 허용해야 합니다. mcp-http를 다시 만들면 메모리에 있던 OAuth client와 token이 사라지므로 ChatGPT 앱 인증을 다시 진행합니다. 일반 설정은 URL https://s3wiki.yonsei.ac.kr/mcp, bind 127.0.0.1, allow flag false입니다. 같은 endpoint에서 세 변경 도구에 공용 Bearer 토큰을 사용합니다.

health는 성공하지만 공용 /mcp가 실패하면 프로세스는 살아 있습니다. 직접 IP 경로와 아래 HTTP 상태 항목을 확인합니다. /healthz는 변경 자격 증명이나 위키 로그인을 확인하지 않습니다.

MCP 변경 도구에서 인증 오류가 남

먼저 .envS3RM_MCP_WRITE_AUTH_MODE를 확인합니다. open인데 인증 오류가 남는다면 설정 변경 뒤 mcp-http를 다시 만들지 않은 상태일 수 있습니다.

docker compose up -d --build --force-recreate mcp-http

아래 토큰 진단은 token 모드에만 적용합니다.

이 오류가 있어도 익명 초기화, 도구 목록, 조회는 동작해야 합니다. create_lesson_draft, link_lessons, attach_evidence의 인증 오류는 Bearer 헤더가 없거나 형식이 틀리거나 S3RM_MCP_TOKEN_SHA256과 맞지 않는다는 뜻입니다. 비교할 때 어느 값도 출력하지 마세요.

서버에서 기존 HTTPS 토큰과 해시를 바꾸거나 출력하지 않고 확인합니다.

./scripts/configure-mcp-token.sh \
  --public-url https://s3wiki.yonsei.ac.kr/mcp

비공개 클라이언트 토큰이 없거나 맞지 않는다고 나오면 기존 전달 사본에서 원문을 복구합니다. 모든 쓰기 클라이언트를 함께 바꿀 수 있을 때만 --rotate를 사용하세요. mcp-http를 다시 만들면 이전 토큰이 무효가 됩니다.

쓰기 클라이언트에서는 시작 전에 지원하는 secret 또는 환경 설정으로 토큰을 불러옵니다. 추적되는 JSON·TOML이나 공개 진단에 넣지 마세요. 정적 헤더를 저장하지 못하는 호스팅 커넥터에는 OAuth 진입점이 필요합니다.

MCP가 HTTP 403을 반환함

이 파일럿에서 403은 보통 요청 Origin이 정확히 허용되지 않았다는 뜻입니다. 민감한 값을 지운 요청 Origin을 S3RM_MCP_PUBLIC_URL, S3RM_MCP_ALLOWED_ORIGINS와 비교합니다. 의도한 정확한 HTTP(S) Origin만 쉼표로 추가하고 서비스를 다시 만듭니다.

docker compose up -d --force-recreate mcp-http

*를 추가하거나 Origin 검사를 끄지 마세요. Origin은 전체 /mcp URL이 아닙니다. CLI 클라이언트는 보통 Origin을 생략하지만 호스팅형·브라우저형 클라이언트는 보낼 수 있습니다.

MCP가 HTTP 421을 반환함

421은 정확한 Host 헤더가 공개 URL host 또는 S3RM_MCP_ALLOWED_HOSTS 항목과 맞지 않는다는 뜻입니다. 프록시가 Host를 바꾸거나, 클라이언트가 이전 IP URL을 쓰거나, 공개 URL의 포트가 틀린 경우가 많습니다.

클라이언트 주소를 S3RM_MCP_PUBLIC_URL과 맞춥니다. 저장소의 Caddyfile은 공개 Host를 보존하므로 Caddy를 통과한 421은 보통 .env나 클라이언트가 이전 주소를 쓰는 경우입니다. 도메인 스크립트를 다시 실행하고 mcp-http와 Caddy를 다시 만듭니다. 등록된 공용 URL 대신 localhost나 IP를 쓰지 마세요.

MCP HTTP는 열리지만 도구가 위키 인증에 실패함

초기화는 성공하지만 조회와 변경 도구에서 위키 인증 오류가 나오면 S3RM_WIKI_USERNAME 또는 S3RM_WIKI_PASSWORDbootstrap이 만든 계정과 맞지 않을 수 있습니다. 전용 계정을 맞추고 공용 어댑터를 다시 만듭니다.

docker compose up -d --force-recreate bootstrap
docker compose logs --tail=100 bootstrap
docker compose up -d --force-recreate mcp-http

Compose 내부 API 주소는 http://mediawiki/api.php입니다. 호스트의 localhost 주소가 아닙니다. 관리자 자격 증명을 넣거나, api.php를 클라이언트에 직접 열거나, MCP 변경 인증을 끄는 방식으로 우회하지 마세요.

Cursor가 잘못되었거나 요청과 맞지 않음

Cursor는 불투명한 값이며, 이를 만든 도구, query, filter, 선택 field, analogy threshold에 묶입니다. next_cursor를 바꾸지 말고 그대로 넘깁니다. 다른 parameter를 하나라도 바꿨다면 이전 cursor를 버리고 첫 페이지부터 시작합니다. Cursor는 Lesson ID가 아니며 해독하거나 편집하지 않습니다.

결과가 잘렸거나 limit보다 적음

모든 직렬화 결과에는 크기 제한이 있습니다. 목록 페이지에는 page_limited_by_output, 모든 결과에는 output_truncated가 표시될 수 있습니다. field 수나 limit을 줄이고 next_cursor를 이어서 사용합니다. 목록 limit은 1~20이며 기본값은 5입니다. S3RM_MAX_OUTPUT_BYTES 기본값은 32768이고 2048~65536만 받습니다. 그보다 높은 hard limit으로 올릴 수 없습니다. SDK 검증 오류를 포함한 전체 JSON-RPC HTTP body에는 별도 212992바이트 제한이 있습니다.

큰 결과를 한 번에 받으려고 제한을 높이지 마세요. 먼저 검색 요약을 받고, 추린 결과에 대해 선택 field로 get_lesson을 호출합니다.

관계 추가가 거부됨

양쪽 Lesson이 이미 있어야 하고 기준 ID 형식이어야 합니다. 자기 자신으로 향하는 관계, 같은 edge 중복, 일곱 개 어휘 밖의 관계 이름은 거부합니다. analogous_to는 양방향으로 조회하지만 한 번만 저장합니다. 양끝을 바꾼 edge를 따로 만들 필요가 없습니다.

supersedes 관계를 추가해도 연결만 기록합니다. 두 Lesson의 호환 상태는 바꾸지 않습니다.

근거 첨부가 거부됨

다음을 확인합니다.

  • 대상 Lesson이 있습니다.
  • citation은 추적 가능한 3~500자의 사람이 읽을 수 있는 참고문헌입니다.
  • kindpaper, code, dataset, log, benchmark, other 중 하나입니다.
  • 선택 사항인 evidence ID는 해당 Lesson에서 고유하고 영문·숫자·._:-만 사용합니다.
  • 선택 URL은 HTTP(S)이며 사용자 이름과 비밀번호가 없습니다.
  • note는 2000자 이하입니다.

검증을 없애거나 관리자 자격 증명을 넣지 마세요. 근거 위치를 고치고 다시 시도합니다. 이전 Lesson을 MCP로 바꿀 수 없다면 일반 브라우저 계정으로 편집합니다.

백업이 실패함

완료되지 않은 출력은 진단을 위해 보존하되 복구 지점으로 표시하지 않습니다. 디스크 여유 공간, 대상 권한, 서비스 상태, 마지막 오류를 확인합니다. 이전 정상 백업을 지우지 마세요. 원인을 고친 뒤 새 시각의 디렉터리로 다시 실행합니다.

복원 스크립트가 백업을 거부함

checksum, manifest, archive, version 검증 실패는 현재 기준 데이터를 보호합니다. --yes를 반복해서 붙이거나, manifest를 고치거나, 다른 시각의 파일을 섞거나, SQL만 직접 가져오지 마세요. 복구 세트의 작업 사본에서 출처나 전송 손상을 조사하고, 가장 최근의 온전하고 호환되는 백업을 사용합니다. S3RM1를 참고하세요.

디스크 사용량이 갑자기 늘어남

DB, upload, build cache, log, 보관 백업을 나눠 확인합니다. 이름이 있는 볼륨을 지우지 마세요. 업로드 근거 기준과 백업 보관 정책을 확인합니다. 다시 만들 수 있는 Docker build cache·image만 서버 담당자의 확인 뒤 정리합니다. 큰 원본 파일은 정해진 object store로 옮기고 Lesson에는 오래 유지되는 인용을 남깁니다.

그래도 문제가 남으면 버전, 정확한 명령, 종료 코드, 민감한 값을 지운 로그 끝부분, docker compose ps -a, 비파괴 재시작 뒤에도 재현되는지를 기록합니다.