From 8571db5beebb3e9877792ab12f9d2c2deedab0b1 Mon Sep 17 00:00:00 2001 From: lee-hyeon-cheol Date: Mon, 21 Sep 2026 10:43:49 +0900 Subject: [PATCH] =?UTF-8?q?feat(backend):=20SAP=20MCP=20=EB=A5=BC=20env=20?= =?UTF-8?q?=EB=A1=9C=20=EC=BC=9C=EA=B3=A0=20=EB=81=84=EA=B2=8C=20=E2=80=94?= =?UTF-8?q?=20=EA=B3=A0=EA=B0=9D=EC=82=AC=20-12=20=EC=97=90=20=EB=B3=84?= =?UTF-8?q?=EB=8F=84=20=EA=B8=B0=EB=8F=99=20=EC=A0=88=EC=B0=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit opencode.fabrix.json.tmpl 의 sap-icf 를 MCP_PORT/MCP_API_KEY 로 렌더, 키 없으면 enabled:false. .env.example 에 SAP_*·MCP_* 블록. README 에 -13 번들 재활용 절차(컨테이너 간 통신 금지라 -12 에 따로). Co-Authored-By: Claude Fable 5.1 --- 5_django_backend/.env.example | 12 +++++++++ 5_django_backend/README.md | 25 +++++++++++++++++++ .../opencode/opencode.fabrix.json.tmpl | 6 ++--- 5_django_backend/opencode/render_opencode.py | 6 ++++- z-my-docs/work-log/2026-09/2026-09-21.md | 8 ++++++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 z-my-docs/work-log/2026-09/2026-09-21.md diff --git a/5_django_backend/.env.example b/5_django_backend/.env.example index 608c5e4..1aeef2a 100644 --- a/5_django_backend/.env.example +++ b/5_django_backend/.env.example @@ -35,3 +35,15 @@ AAF_RELAY_STREAM_USAGE= AAF_GATEWAY_KEY= # OpenCode 가 붙을 이 서버 포트 (render_opencode.py 가 씀) BACKEND_PORT=8001 + +# ── SAP 조회 MCP (고객사 전용, -12 에 따로 띄움. ABAP_OPENCODE mcp.bundle.cjs 재활용) ── +# MCP_API_KEY 가 있으면 render_opencode.py 가 OpenCode 에 sap-icf 를 켬. 비우면 꺼짐(로컬). +MCP_PORT=8888 +MCP_API_KEY= +# 아래는 MCP 프로세스가 읽는 SAP 접속값 — ABAP_OPENCODE bare/.env 와 같은 키 +SAP_HOST_ICF= +SAP_USERNAME_ICF= +SAP_PASSWORD_ICF= +SAP_CLIENT_ICF=100 +SAP_VERIFY_SSL_ICF=false +SAP_API_BASE_ICF= diff --git a/5_django_backend/README.md b/5_django_backend/README.md index 0020b96..6c3f13e 100644 --- a/5_django_backend/README.md +++ b/5_django_backend/README.md @@ -100,3 +100,28 @@ curl http://localhost:8001/api/ito/models - 설정이 비어 있어도 서버는 뜨고, `/api/ito/chat/completions` 만 503 으로 뭐가 빠졌는지 알려줌. - ABAP_OPENCODE 의 `apps_ito` 를 통째로 안 가져온 이유: 그쪽은 11k 줄 + DB 테이블 + langgraph 등 의존성 15개인데 여기 필요한 건 통과 중계뿐. 사용자별 키(IP 마스터)는 아직 없음 — 서비스 키 하나로 감. - 개발로 되돌리기: `git checkout opencode/opencode.json`. + +## SAP 조회 MCP 붙이기 (고객사, -12 에 따로 띄움) + +컨테이너끼리(-12↔-13) 통신은 금지라 -13 의 MCP 를 안 빌리고 -12 에 하나 더 띄움. 코드는 ABAP_OPENCODE 의 번들 한 파일(`mcp.bundle.cjs`) 그대로. + +```bash +# PC: -13 에서 번들 꺼내 -12 로 (환경값은 -13 bare/.env 의 SAP_*·MCP_API_KEY 를 손으로 옮김) +scp -P 8916 root@10.196.81.34:/www/abap-ito/web/MCP/code/dist/mcp.bundle.cjs . +scp -P 8912 mcp.bundle.cjs root@10.196.81.34:/www/ + +# -12 +cd /www/ABAP_CODE_ASSISTANT/5_django_backend +vi .env # MCP_PORT=8888, MCP_API_KEY, SAP_HOST_ICF/USERNAME/PASSWORD/CLIENT/VERIFY_SSL/API_BASE 채움 (.env.example 의 SAP 블록) +set -a; . ./.env; set +a +mkdir -p /www/mcp && cp /www/mcp.bundle.cjs /www/mcp/ +(cd /www/mcp && nohup node mcp.bundle.cjs > /www/ABAP_CODE_ASSISTANT/5_django_backend/logs/mcp.log 2>&1 &) +.venv/bin/python opencode/render_opencode.py # MCP_API_KEY 있으면 sap-icf enabled:true 로 렌더 +pkill -f "opencode-bin serve" +(cd opencode && nohup /www/opencode-bin serve --hostname 127.0.0.1 --port 4096 > ../logs/opencode.log 2>&1 &) +# 확인 — 도구 목록에 sap 도구 6개 +curl -s -X POST http://127.0.0.1:8888/mcp -H "Authorization: Bearer $MCP_API_KEY" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | head -c 400 +``` + +- 로컬 개발에선 `MCP_API_KEY` 를 비워두면 `sap-icf` 가 `enabled:false` 로 렌더돼 OpenCode 가 MCP 를 안 찾음. +- MCP 가 zai 모드로 뜨는지는 `logs/mcp.log` 에 `mode=zai` 찍히는 걸로. 고객사 SAP 은 zdict 가 아니라 ZAI_ICF 라 `SAP_API_BASE_ICF` 를 -13 값과 같게. diff --git a/5_django_backend/opencode/opencode.fabrix.json.tmpl b/5_django_backend/opencode/opencode.fabrix.json.tmpl index 6467bc2..41abccb 100644 --- a/5_django_backend/opencode/opencode.fabrix.json.tmpl +++ b/5_django_backend/opencode/opencode.fabrix.json.tmpl @@ -17,9 +17,9 @@ "mcp": { "sap-icf": { "type": "remote", - "url": "{env:SAP_MCP_URL}", - "headers": { "Authorization": "Bearer {env:SAP_MCP_KEY}" }, - "enabled": false + "url": "http://127.0.0.1:${MCP_PORT}/mcp", + "headers": { "Authorization": "Bearer ${MCP_API_KEY}" }, + "enabled": ${SAP_MCP_ENABLED} } } } diff --git a/5_django_backend/opencode/render_opencode.py b/5_django_backend/opencode/render_opencode.py index 2e62b68..17a446b 100644 --- a/5_django_backend/opencode/render_opencode.py +++ b/5_django_backend/opencode/render_opencode.py @@ -34,7 +34,7 @@ def load_env(path: Path) -> dict[str, str]: k, v = line.split("=", 1) v = v.split(" #", 1)[0].strip().strip("\"'") # 줄 끝 주석은 두 칸 띄고 # out[k.strip()] = v - out.update({k: v for k, v in os.environ.items() if k.startswith(("AAF_", "BACKEND_PORT"))}) + out.update({k: v for k, v in os.environ.items() if k.startswith(("AAF_", "BACKEND_PORT", "MCP_"))}) return out @@ -46,6 +46,10 @@ def render(env: dict[str, str]) -> str: values["AAF_FABRIX_MODELS_JSON"] = json.dumps({mid: {"name": name} for mid, name in models.items()}, ensure_ascii=False) values["AAF_FABRIX_DEFAULT_MODEL"] = next(iter(models)) values.setdefault("BACKEND_PORT", "8001") + values.setdefault("MCP_PORT", "8888") + # SAP MCP: MCP_API_KEY 가 있으면 켬. 없으면 끔(로컬 개발) + values["SAP_MCP_ENABLED"] = "true" if values.get("MCP_API_KEY") else "false" + values.setdefault("MCP_API_KEY", "") values["AAF_GATEWAY_KEY"] = values.get("AAF_GATEWAY_KEY") or "x" # SDK 가 빈 키를 거부해서 더미 missing: list[str] = [] diff --git a/z-my-docs/work-log/2026-09/2026-09-21.md b/z-my-docs/work-log/2026-09/2026-09-21.md new file mode 100644 index 0000000..bb76f00 --- /dev/null +++ b/z-my-docs/work-log/2026-09/2026-09-21.md @@ -0,0 +1,8 @@ +# 작업로그 · 2026-09-21 (월) + +| 시간 | 내용 | +|------|------| +| 09:12 | DB 저장 범위 정리 — 채팅 텍스트만 서버, 이미지·클립보드·스니펫은 PC. 이미지 재진입 시 사라지는 건 stage-2 남은 것에 기록 | +| 10:26 | 삼성향 라이트 팔레트 추가·기본으로 — 삼성닷컴 실측 토큰(검정 CTA·흰 바탕·#f7f7f7 면·#ddd 테두리), 알약 radius 20px. 다크는 그대로. 폰트는 라이선스 근거 없어 미적용 | +| 10:40 | PwC 로고·마크 전부 제거(LogoMark 빈 렌더, 파비콘 투명), 기본 모드 라이트로(예전 dark 저장값 한 번 초기화), 삼성 팔레트 포인트를 Samsung Blue #1428A0 로(버튼·링·링크) | +| 10:43 | SAP MCP 를 -12 에 따로 띄우는 준비 — OpenCode 템플릿 sap-icf 를 MCP_API_KEY 유무로 on/off 렌더, .env.example SAP 블록, README 절차(-13 번들 재활용, 컨테이너 간 통신 없이) |