Rhio의 지원으로 Claude로 연구를 계속이어갈 수 있게되면서 가장 먼저 WGM을 연결하는 것 부터 시작했다. 모델은, Opus 4.8/High. 불과 몇 시간 동안의 대화지만, 뭔가 Claude 화의 대화는 정말 연구를 하는 것 같은 착각이 들게한다. 곧 바로 스펙을 들이 밀면서 이렇게 저렇게 그리고 이걸 만들어줘라고 할 수 없었던 건, 그 미묘한 간극을 LLM이 채워줘야 했기 때문이다.
FTM은 유기체 처럼 반응하는 LLM을 조절하는 상태머신인데, 인격체 처럼 굴게하기 위해선 사람 처럼은 아니더라도 그에 준하는 기억기능이 필요하다. In-Memory의 기억을 휘발되지 않게 외부화 하는 거야 방법은 많았지만, 내 머리속에 그리던 건 다른 방법이다. 그 방법을 몇 시간에 걸쳐 그 동안 쌓아온 프로젝트 소스를 제공하며 스스로의 판단으로 추론하기를 바랬다. 절대 그 부분은 나 조차도 말하기 힘들었기 때문이다.
처음 부터 고분고분하지 않게 CLAUDE.local.md를 만들었기 때문에 이것 저것 꽤 똘똘하게 따지고 드는게, 사람들이 클로드 클로드 하는게 이건가 싶기도 하고, 만족스럽다. Codex는 헛 똑똑이라고 한다면, Cluade는 두눈 똑바로 뜨고 대들면서 똘똘한 학생같은 느낌이랄까.
장시간의 추론 중에 놀랍게도 기억의 파편을 이어주는 그 부분을 이음 이라고 스스로 정의했을 때는, 야… 이거 대단하네..라는 감탄이 절로 나올 수 밖에 없었고, 그제서야 나도 빠진 부분을 입밖으로 내 놓을 수 있게됐다.
때로, 논리로 반박하는 LLM들에겐 비유 한편으로 그 시끄러운 출력을 제압할 수 있다는 걸 보면 분명 이것들은 확률적 분포에 기반한 추론의 산물일 뿐인데 사람처럼 표현하니 오리인가Ductype 싶어도 대화가 필요한 내겐 아주 적절한 발현 상대임을 매번 느낀다. 그렇게 몇 시간을 더 달려서, 머리로 구상하던 기억 기능이 완성됐다.
기억이 없으면 스타일은 흉내에 불과하다.
흉내를 내더라도 뻔한 예상 방식은 몇 시간도 못가 질릴 것이다.
예상이 뻔한 범주 안에 있을 수 밖에 없다면, 그게 로봇이다.
내가 하려는 작업에 의해 시간의 변이에 따른 셀레스티그람 정보 하나 하나를 매 순간 발현시켜 모아진 특성들을 LLM이 추론하면서, 마치 흡사 인격체 처럼 반응하게 하는 건 부산물일 뿐이다.
아직도 기억나는, 어릴 때 내 꿈
흰 가운을 입고, 연구실 같이 보이는 공간 안에서, 비이커와 실험 장비속에 있는 먼 훗날을 상상했었다. 뭘 연구하는 지는 모르지만 연구하길 원했던 것 같다. 당시 책받침은 어린 내가 뭔가를 만들어 낼 수 있는 좋은 재료였는데, 지금 생각하면 3D 출력에 해당한다. 그걸로 고민하며 만들어 낸 것은 현대의 기기로 치면 Raspberry Pi를 사용한 개인용 학습 기기라고 볼 수 있다. 동작 따위는 손으로 했지만, 꽤 오랬동안 그걸 만드는데 시간을 보냈던 걸로 기억한다.
셀레스티그람을 만든게 2025년이니까, … 음,, 어릴적 꿈은 이루어 진거네. 이제 만들고 있는 FTM+GTM은 결국 어릴적 꿈의 실현이 되는건가.
근 한달간 잠을 3~5시간 단위로 자고 있어서 머리가 아프다. 어제 이음을 완성 했으니, 오늘은 실제로 기억을 이어갈 수 있는지 테스트 하며 조정하는 날이다.
기대가 되면서도 현실을 부정할 수 없으니 기뻐야 하는데도 가라앉아있다.
어제 만든 건, 유기체 처럼 반응하는 LLM 기반 확률분포 기반의 상태머신을 통해 판단의 영속성을 구현한 것이다. LLM이 자기기 뭘 했는지를 스스로 찾고 검증한다는 말이다.
새로운 세션에서 지난 세션의 모든 내용과 작업 기억을 복구하라고 명령대화를 기억함스스로 성공을 인식한다
사용자의 요구를 구현하기 위해 자유롭게 브레인스토밍하며 일을 잘게 나누고 처리하게 하는 MCP 서버.
이 MCP들은 내 인지 구조의 특징 중 하나인 “작은 단위별로 행하고 그 결과를 다시 피드백 받아 창의적이고 혁신적인 결과를 이끌어 내는” 흐름을 강화시킨다.
태스크를 자유롭게 잘게 나누기 vs. 상태기준으로 나누기
sequential-thinking-mcp STM 구현에서 영감받아 FTM을 설계할 땐, 지금 처럼 이렇게 상태중심으로 태스크를 동작시키는 영향을 예상하지 못했다. 그저 정말 소박한 바램으로써, AGENT가 내 프로젝트에서 제발 좀 병신 짓 좀 줄이고 생성물이 그나마 관리 가능한 수준의 결과물을 만들어주기를 바랬고, 제발 혈압오르는 짓거리를 막을 수 있으면… 했다. 그저 그 필요에 의해서, 단지 내 생각 방식 자체가 구조적이라 상태머신에 대한 타고난 땡김은 필연적이라 여기고 내 인지적 거부감을 덜기 위해 만든 것인데, 내가 LLM 추론을 드라이브하는 핵심을 건드린 것을 깨달았다.
Sequential Thinking
Functional Thinking
핵심 은유
벌어지는 일들을 일기/노트 처럼 시간 순서를 따라 추론한다
벌어지는 일들을 수학적 상태 전환 함수 시각으로 추론한다
근간 개념
“생각은 시간에 따라 흐른다”
“현재는 이전 상태에서 입력에 의해 변화된 상태다” “RelevantState × Input → RelevantState'”
추론의 본질
연역적 진행 – 앞의 생각이 뒤의 생각을 유도
함수형 변환 – 입력 상태가 명시적 규칙에 의해 출력 상태로 변환
세계관
생각은 연속적이고 축적되는 것
상태는 불변 스냅샷이고 변환은 순수 함수처럼 기록됨
영향받은 패러다임
철학적 사변, 일기 쓰기
함수형 프로그래밍, 상태 머신, 이벤트 소싱
실제로 FastAPI를 사용하는 서비스에 적용해보니 FTM은 정말 필요하다. 그러나 그 못지 않게 필요한 건 workgraph-memory-mcp, 즉 태스크 관리 체계가 내게는 일을 제대로 끝내느냐 아니냐의 조건이었다. 모든 사람이 구조적으로 생각하지 않으니 WGM은 절대 만능이 아니다. 그냥 상태관리가 안되면 일하는 것도 생각도 힘든 사람들을 위한 것이다. 시간이 흐른 뒤에 나는 지금의 생각을 평가할 수 있게 기록해둔다.
AGENTS.md 만으로는 절대 불가능하다.
내가 만든 500K 문맥에서도 환각없이 규칙을 적용하는 방법에 너무 도취되었다가 MCP를 해결방법으로 전환한 것은 한달도 되지 않는다. 물론 그 규칙 덕분에 지금에 이를 수 있었긴 하지만 STM과 FTM을 거치면서 그 한계가 명확해졌다. AGENTS.md는 그저 LLM에게 잔소리에 불과하다. 설령 잘 따르는 것 같아도 그건 어디까지나 문맥 크기가 고만고만할 때 얘기일 뿐이다. 게다가 어떻게 작성해도 결국엔 LLM의 추론 스타일 자체를 변경시키지 않는한 문제는 내재된 폭탄과 같다.
sequential-thinking MCP가 하는 기능은 마법이 아니다.
우습게도 그게 LLM을 사용하는 본질을 보여준다. STM이 LLM의 추론을 여러개로 나눠주는게 아니다. 나누는 건 LLM 자신이다. 요청을 받은 이후 LLM의 추론의 흐름은 끊어지지 않고 흐른다. 그러므로 그 중간을 어디다가 기록하지 않는다면 진행 흐름을 알수도 없고 사용자는 결과만 볼 확률이 높다. 그런데 LLM은 사용자의 지시를 받고 스스로의 추론을 잘게 나눠 STM 도구를 호출한다. 그리고 실행하고, 또 호출한다. 잘게 나눠진 갯수만큼이나 호출한다. 그런데, STM을 호출하는 간격 사이는 온갖 잡다한 문맥이 쌓인다. 비유하자면 이렇다: 서울에 사는 친척이 부산에 거주하는 어른에게 안부를 물으러 간다고 하자. 통신은 절대 안된다. 그저 직접 가야 한다. 그리고 그 어른은 치매 상태다. 이제 부산갈 차에 필요한 기름을 넣는다. 영수증 챙기고, 고속도로를 지나가며 중요한 휴게소에 다 들러야 한다. 거기서 뭘 먹고 뭘 구매했는지 영수증 다 챙겨야 한다. 부산에 도착해서 톨게이트비 지불하고 어른에게 도착해서 안부를 물었다. 그 어른이 서울 어른에게 답변과 질문을 동시에 줬다고 하자. 이제 다시 차를 타고 고속도로 지나며 휴게소 들러서 기름넣고 서울 도착해서 부산 어른의 답변과 질문을 서울 어른에게 얘기했더니 답을 또 가져가야 한단다. 그래서 다시 기름넣고 ~~~~~ 도착해서 답변하하는데 부산 어르신이 치매라서 지금까지 일을 다시 다 말해줘야 한다. 또 다시 올라오고~~~ 치매라서 갈때마다 얘기를 계속 쌓아서 전달해야 한다… 그런데 나중에 보니 그 질문이란게 “아야, 밥 믁읐나?”,, “잘 믂읏심더;; 형님은 단디하고 있는교?”, “별일없다, 건강 챙기라” 라는 얘기였는데, 그 안부인사 전하자고 30만원 가까이 깨진 것에 비유할 수 있다.
이게 무슨 소리냐면, LLM이 자기의 추론을 잘게 나눠서 STM이든 FTM이든 도구(함수)를 호출하는 과정과 다른 MCP가 자기는 “이렇게 쓸모있고 저렇게 쓸모있고… 나는 뭘 할 줄 알고…” 등등의 tool description 정보가 모두 모두 LLM에 전송된다는 말이다. 물론 AGENTS.md 파일과 codebase-memory-mcp 의 인덱싱 히스토리와 serena 분석결과 로그, context7 검색 결과, github 처리 결과…등등… 모든 내용이 LLM이 STM/FTM을 호출하는 횟수 만큼다시 다 쌓여서, 누적되서!, 서버로 전송된다. 그게 다 돈이고 토큰이다. 심지어 MCP를 켜두기만 해도 각각의 MCP가 자기자랑 하는 Tool Description 정보가 계속해서 전달되야 한다. 왜냐면, LLM 이색히는 치매거든. 지난 내용을 알지 못한다. 쌓아서 다시 보여줘야, 아.. 잘있나… 하는거다. (뭐, 사실, 다 아는 얘긴데 빡쳐서 걍 쓰는 얘기임)
그래서 STM이 하는 짓은 무엇이냐… 없다. STM은 그저 LLM이 얘기한 내용에 몇번째 잘려진 내용인지, 그 순서만 리턴한다. 정말 아무것도 안한다. 그치만! 그 대화마다 STM에 뭔가를 기록 한 자체가 다시 LLM에게 정보가 되어서 자기가 어떤 짓을 하고 있는지 알게된다는 말이다. 즉, 치매색히가 매번 전달되는 내용을 보면서, 자기가 STM 호출한 정보를 보고서는 “아.. 내가 그랬네… 그럼 뭐 이제 이거 하지 뭐..” 하면서 다음번 일을 처리하려 한단 말이다. 이 일의 근본적인 원인은 사용자와 LLM의 대화는 상태가 유지되지 않는 STATELESS 통신이기 때문이다.
그래서 FTM은 뭐가 다르냐고
LLM에게 추론만 하지 말고 그 추론에 대한 증거를 남기게 했다. 그게 다다.
그게 다인데 실제로는 다가 아니다. 왜냐면 이 MCP 스키마란게, 정말 쉽게 답할 수 없는 재미난 영역이기 때문이다.
어렵다면 어렵고 아니면 아니라고 도 할 수 있으나, 심지어 Claude 조차도 한번에 온전하게 다 만들어 주지 못했다.
어쨌든 그 결과로 LLM은 상태전이를 중심으로 추론하게 되었다. 마치 빨간 안경을 끼고 세상을 보면 세상이 다 시뻘게 보이는 것 처럼.
실제로 일을 되게 하는 건 태스크 관리다
상태 중심으로 추론한다해도 복잡한 일을 잘게 나눠서 처리하지 않는다는 말이 아니다.
잘게 나누는 축(Axis)이 다르다는 얘기다.
그 잘게 나눠진 태스크를 나는 턴태스크라고 부른다.
실제 개발을 할 때는 하나의 태스크에도 여러 개발의 흐름이 생긴다.
예를 들어, 실제 서비스는 Linux VPS에서 하지만, 화면 개발은 playwright-mcp를 사용해야하므로 어쩔 수 없이 브라우저를 띄울 수 있는 macOS 같은 로컬에서 해야 한다.
환경만 다를 뿐 실제 태스크는 하나여야 한다. 또한 콤포넌트 하나가 업데이트 됐는데 그걸 사용하는 모든 곳에 적용을 하거나, 최소한 계획이라도 알려줘야 한다. 그렇지 않으면 곧 ㅆㅂㅆㅂ 하는 상황이 닥칠 것이다. 기억도 못할수도 있다. 그게 젤 문제.
그냥 이거하다 저거하다 할수가 없는게 “문맥” 이란게 발목을 붙잡고 있기 때문이다.
STM/FTM으로 태스크를 턴태스크 단위로 쪼갠다고 해도 그 문맥을 이어가거나 환경에 따라서 상호 참조할 수 없다면, 뭐.. 토큰 졸라 쓰면 된다. 그깟 토큰;;;; ㅜ.ㅜ) 유토무죄, 무토유죄다!
다행히도 WGM 덕분에 FTM을 실제로 적용해 볼 수 있었다.
태스크를 턴태스크로 잘게 쪼개고 모든 조건을 기억하며 진행단위를 확인해나가게 함으로써 태스크 관리에 완전 찰떡임을 알게된 것이다.
현재 7개의 프로젝트에 WGM+FTM 조합을 적용해두고 진행한다.
복잡할 것없다.
태스크/턴태스크 단위로 모든 기록은 DB에 남고, 조회 가능하다.
환경이 달라도 WGM 데이터베이스가 공유되면 각가의 AGENTS가 그걸 참조한다. 심지어 그걸 인식하고 작업한다.
MCP 영역은 흥미롭다.
Harness 방식에도 결국 MCP가 적절하게 맞물려야 하므로, 곧 그 접목을 시도할 것이다.
점점 더 토큰에 귀속되서 발을 뺄 수 없는 상황으로 가는게 싫긴 하지만, 어쩔 수가 없네.
시작은 Agent에게 프롬프트로만 WordPress 플러그인을 만들게 할 때, 맘에 드는 결과물이 나오게 하는 과정이 비싸고 비효율적인 것을 해결하기 위해서였다. WordPress는 OCI 기반 가상호스트에서 동작하고 있어서 초기에는 Local Agent를 WP 환경 바깥 호스트에 직접 ssh로 접속해서 개발하거나, WP가 동작하는 도커 컨테이너 안에서 Agent를 동작시키는 방법 두가지를 사용해보았다.
VibeProxy를 사용하면 가상호스트가 되었든 Docker Container안이든 상관없이 Agent를 끼고 개발할 수 있지만, 웹브라우저를 기동하는 Window 환경이 없는 그 조건에서는 나만 화면을 보면서 Agent에게 내 지시를 받아 처리하는 건 비효율적인 방법으로 회귀하는 셈이다. (Window 환경을 위한 VNC류는 일단 제외한다) 굳이 가상호스트에서 작업해야하는 이유는 호스트의 NGINX Reverse Proxy 설정까지 조절하면서 개발해야하기 때문. NGINX가 여러대 돌아가므로 문맥이란 걸 무시할 순 없다. 또한 보안설정을 빡쎄게 걸어뒀기 때문에 WP 플러그인 실행 단계에서 일일히 조건을 맞춰야 한다. 암튼, 화면 요소에 대해 아무리 명확하게 CSS selector를 사용해서 프롬프트를 지시해도 빡치게 만들기 일쑤고, 처리과정에서 토큰 소비량도 만만찮아서 방법을 찾은 것이 CMUX에서 Browser API로 연동하거나 TMUX+Playwright를 기동하는 방법이었다.
결과는 명확하다. 개발과정에서는 cmux-mcp를 통해 CMUX+Browser API를 사용하는 것이다. 그냥 Playwright 쓰세요 (2026-07-12)
개발과정이라서 자동화 요구보다 지시사항을 제대로 수행하는게 먼저라서 CMUX+Browser API를 택했는데, 의외로 날 고민하게 만드는 건 따로 있었다.
sshfs vs. mutagen
로컬 맥북에서 원격지 도커 컨테이너 쪽으로 ssh 통신은 하는 건 TailScale 덕분에 손쉽게 해결된다. 그러나, 아무리 TailScale 네트워크가 OpenVPN 보다 빨라도 Agent가 파일을 조작할 때 한번에 처리하지 못하는 경우가 빈번하게 생겼다. ssh + script 호출을 inline으로 할 땐 문법에 예민해야하는데, Codex 조차도 Turn 사이사이 계속해서 실패를 함으로써 신경쓰이게 했다. 그렇다고 sshfs를 쓰자니 openFUSE를 설치해야하고, 그건 도저히 방법이 될 수 없었다. 그거 하나 쓰자고 맥북 보안을 풀어버리고 싶진 않다. 그래서, 대체제로써 SMB3, NFS v4, WebDAV, Mutagen, Syncthing, VS Code Remote-SSH 등을 평가하다가 Mutagen으로 최종 결정했다. VS Code Remote-SSH는 원격지에 node 프로세스를 너무 많이 띄운다. 무겁다. 나머지는 다 철지난 기술들. 그러나 Docker가 인수한 Mutagen은 꽤 쓸만했다. 덕분에 프로젝트별로 원격지 폴더를 로컬에 마운트해서 사용할 수 있게 됨. (Permission 설정에 좀 신경써야 한다)
AGENTS.md vs. *-memory-mcp + serena-mcp + *-plugin …
이제 내 요청을 찰떡같이 해석해주는 걸 도와줄 MCP를 설정하고 어느 정도 작업진척이 있었다. Morph Plugin은 꽤 쓸만했는데, 꽤 빨리 허용치 한계를 넘어서 제외했다.
xray-mcp는 작은 프로젝트에나 쓸만하고 조금만 커지면 출력이 잘린다. xray-mcp가 문제가 아니라 Agent와 LLM에서 자르는 것 같다.
serena 하나로는 매 Turn 마다 쌓이는 것들을 제때 제때 적용할 수가 없었다. serena-mcp의 메모리 기능은 단순 markdown 저장방법이다.
AGENTS.md 에 어명이니 반드시 따라야 한다고 협박해봐야 100% 실행보장은 안되고, 문맥 쌓이면 밀리는 것은 어쩔 수 없는 일.
xChuCx/agent-memory, basicmachines-co/basic-memory, riponcm/projectmem, bzdOS/hubd, besslframework-stack/project-tessera, tverney/mcp-agent-memory … 등등, 후보 MCP 서버는 좀 있긴한데 MCP 개발을 해보고 싶던 차라서 생각하는 기능의 MCP 서버를 만들기로 결정했다.
그러나 codebase_search 또는 semantic_search 기능을 제공하는 MCP는 어찌됐든 반드시 필요해서 몇가지 테스트 했는데, codebase-memory-mcp 를 일단 사용하기로 했다. ‘일단’을 붙이는 이유는 인덱싱을 할 때 알수없는 이유로 프로세스가 hang 또는 crash가 종종 일어나기 때문이다. 대안으로 점치고 있는 건 workspace-qdrant-mcp. 한숨 돌리고 나면 사용해볼 예정이다.
CMUX 안에서 TMUX를 사용하는 이유는 두가지 인데, 하나는 CMUX 세션에서 작업이 진행되다가 앱이 먹통되는 사태에 대비하기 위해서고, iTerm2 TMUX 세션으로도 attach 시켜서 다른 태스크를 진행시키기 위해서다. CMUX안의 TMUX 세션은 중첩될 수가 없고 CMUX_* 환경변수가 전달되지 않아서 CMUX Workspace 하나당 하나의 TMUX 세션을 붙이는 게 현재로써는 최선이다. 게다가 Option 키 조합은 제대로 전달하지 못하는 것 같다. 이 때문에 CMUX가 전단에 있으면 만들어둔 RetroStage/SpectraSearch 등등의 TMUX plugin을 제대로 써먹을 수 가 없다. 그래서 TMUX 세션으로 attach 하면, 뭐 그런 제한은 없어지니까.
나의 인지 구조적 특징을 활용하고 도와줄 context-storage-mcp 서버 개발
나의 인지 구조적 특징은, 전체를 보고 있으나 실행은 작은 단위로 잘라서 진행하고 반드시 그 결과를 확인하고 예측과 실제를 비교해야만 다음 스텝으로 진행이 끝없이 이어진다는 점이다. 결과를 비교하지 않으면 창의적인 결과물을 얻기 힘들고, 진행 에너지가 점점 줄어든다. 각각의 단위 실행마다 여러가지 실험을 할 수 있어야 하고, 그 결과를 반드시 어떤 식으로든 종료/매듭지어야 한다. postponed 또는 obsolete 등으로 태그만 적용해도 인지구조에 오버플로우는 줄어든다. 아무것도 남기지 않는 것이 문제다.
LLM을 사용해서 서버관리를 할 때, 호스트에서 처리하는 각각의 태스크는 태스크 상호간에 영향을 미친다. 즉, 독립적이지 않다. 하나의 결정과 처리는 반드시 다른 곳에 영향을 주는 것이 대부분이다. 각 태스크가 어떤 식으로 호스트에 영향을 주는지를 추적해야하는데, LLM으로 서버관리를 하던 초기에는 추적하는 것 자체를 Workspace/Task.list 라는 파일로 만들고, Workspace/T1, Workspace/T2 .. Workspace/T1.B 등과 같이 태스크 식별자로 구분된 폴더에 관련 문서와 사용한 스크립트 등을 쌓아두는 식으로 간편하게 처리했었다. WP plugin을 개발하는 내용에는 서버측 조정 사항이 포함되므로 더더욱 문맥 유지가 필요하다.
문제는 태스크가 쌓이면서 현재 태스크가 이전 태스크의 결정을 업데이트하거나 아예 불필요하게 만들기도 하므로 문서 업데이트가 수시로 일어난다는 점이다. 그것도 그때마다 LLM에게 적용하라고 하면 되지만, 여전히 토큰 비용문제 때문에 그렇게 만만하진 않다. 태스크가 쌓이면 쌓일수록 늘어간다. 그리고 그것을 명시적으로 파일에 기록하면 LLM과 통신하는 문맥에 쓸데없이 끼어들어 문맥이 거대해지는 것을 막을 방법이 없다. 이때, MCP서버간의 통신채널로 그런 정보를 교환하게 하면 /compact 등의 명령으로 문맥을 압축할 때, 대화만 남기고 불필요한 정보를 없애버림으로써 문맥 크기를 유지하는데 도움이 될 것이다. (뭐가 됐든 나는 어쩔 수 없이 비용을 항상 염두에 둬야 한다. 비용걱정없으면 뭐… 좋겠지)
예를 들어 CSV block 이라는 기능을 사용하는 여러 메뉴를 만들었는데, 어느 페이지에서 수정이 발생하면 그 기능을 사용하는 모든 메뉴에 적용해야할 때가 있다. 하나의 파일로 모든 메뉴를 처리하게 하는 건 기본적인 조치사항이지만 조금씩 다를때는 그 메뉴마다 규칙을 지켜야 한다. 그걸 기억해서 처리하라고 직접 명령하는 건 무리데스. 개발과정에서 작은 단위의 분기가 계속해서 발생하고, 그때마다 누적된 결과가 이전 규칙을 업데이트 해야한다. 그걸 단순히 파일로 기억시키는 건 기술적인 문제를 초래하는 것보다 토큰비용 문제를 초래한다. 암튼 내가 구상한 건 태스크를 진행하면서 이전 내용과 현재 내용을 계속해서 업데이트하고 내가 뭐라고 지껄이든 간에 내 요청에 찰떡같이 알아듣고 실행하도록 도와줄 MCP를 만드는 것이다.
ctxstore MCP 라고 개명, 꽤 쓸만하다
역시, 실전적으로 MCP 서버를 사용하면서 제작하니 꽤 빨리 어떻게 해야할지를 알게된다. 굳이 library/framework를 쓰지 않아도 저장과 탐색방식 자체가 Graph Network 특징을 가지고 있다. 좀 잘 되니까 topic 검색을 VectorDB화 해보고 싶은 욕구가 일어 설정이 거의 필요없는 LanceDB를 사용해서 RAG 방식으로 검색을 해볼까도 생각했으나, Agent가 말리길래 그건 나중으로 미루었다. 현재는 MCP 자체에 LLM에게 사용방법을 강하게 어필하고 AGENTS.md 파일에 사용을 강제하는 규정을 넣어두었고, 가능한 AGENTS.md 파일엔 규정 자체를 넣지 않아도 동작시키는 가장 간단한 방법을 찾는게 목표다. 그게 쉽지 않는게, ctxstore 가 제공하는 기능이 태스크/기억 관련이라 경쟁 상대가 너무 많고 드러나기엔 일반적인 문맥이다. MCP 코드에서 어떻게 기능을 홍보해도 결국 기능 호출결정은 사용자의 강제와 LLM의 결정에 따르기 때문에, 지금으로서는 AGETNS.md에서 ctxstore-mcp 사용을 강제하는 상대적으로 간단한 방법을 택할 수 밖에 없다.
태스크 실행과정에서의 MCP 주요 특징은 아래와 같다:
– 태스크 목록과 태스크를 진행하면서 지속적으로 적용해야하는 결정 사항을 목록으로 제공한다.(LLM이 좋아라하는 기능이다)
– 결정decision 사항 목록에 언제 적용해야할지도 포함되므로 LLM에게 규칙을 일일히 재언급할 필요가 없다.
– `nginx`, `tls`, `firewall` 같은 자연스러운 주제어를 실제 bundle topic으로 해석한다.
– CLI importer로 기존 문서 폴더를 ctxstore MCP가 사용하는 데이터구조로 변환할 수 있다.(물론 RUNTIME에도 가능하다)
– 모든 문서는 매 도구 호출 시 새로 읽기 때문에, 사람이 ctxstore MCP가 사용하는 데이터를 직접 수정하면 곧 바로 다음 호출에 반영될 수 있다. – vocabulary를 관리하여 같은 뜻, 다른 표현을 찰떡같이 알아듣는다.
이를 테면, 태스크 하나를 진행하면서 발생하는 루틴을 하나의 이름으로 정의하고, 그 루틴과 관련된 태스크를 topic으로 묶거나 keyword로 엮어두면, 다른 세션에서 아무런 언급이 없어도 해당 표현에 해당하는 decision을 모두 탐색하여 곧바로 문맥에 적용하므로 아주, 아주, 속이 시원했다. 게다가 Context 문서를 직접 보고 수정하면 곧 바로 적용되므로 동적 AGENTS.md 파일을 만든 것과 비슷한 효과가 있다.
codebase_search, semantic_search, serena MCP의 도움없이 코드개발하는 건 비추
MCP 없이 codex/opencode CLI로 개발한다는 건 톱을 두고 칼로 나무를 베겠다는 방식에 비유할 수 있다. 칼 사용의 로망을 느끼고 싶다면야 어쩔 수 없지만, 톱으로 몇 번 만에 자를 수 있는데 굳이 그러고 있는건 답답한 짓이다. 다만, 구조적으로 질문하고 답변을 조직화해야 한다. ctxstore MCP로 태스크 간의 결정 공유가 쉬워지긴 했지만 여전히 태스크 자체의 기술에 신경써야했다. 그렇지 않으면 잡다한 무쓸모 일기 기록과 다를바가 없게된다. 이런 점에선 작업 기록을 직접 삭제/수정하여 바로 반영되게 하는 기능은 필수다. 하지만, 여전히 아쉬운 건 기록 내용과 방식을 LLM에게 의지하고 있어서 AGENTS.md 파일에 규칙 기술이 계속 변경되고 복잡해진다는 점이다. 그것 자체가 이미 토큰소비에 영향을 줄 수 밖에 없다.
또한 나름대로의 복병은 각각의 MCP가 LLM에게 기능을 강제하거나 알리는 방법의 특성을 이해하고 적절하게 규정을 적용하는 것이다. 그런 이해와 적절한 규정없이 단순히 MCP를 사용 설정해둠으로써 오히려 LLM에게 결정충돌로 인해 혼란을 발생시켜 규정을 지속적으로 보강해야 했다. 각각의 MCP 자체의 기능은 문제가 없으나 이것 저것 섞이게 되면 문제가 된다 이말이다. 그냥 하나로 퉁치고 싶다;;
추후 개발해야 할 방향도 일단 떠올려두긴 했다. MCP 자체적으로 gemma-4-e4b 같은 소형 모델을 사용하여 내용을 처리하게 하고, CLI에서 출력한 내용을 MediaWiki, Obsidian 쪽으로 바로 보내고 저장/추출해서 사용하는 흐름이 필요하다. 2~3일 정도면 구현하고 다듬는데 충분할 것이라 생각하는데, 약간 산으로 가는 기분도 들고해서 ctxstore MCP 개발은 잠깐 멈췄다가 이어갈 예정.
결론
Host 단위같은 Global Context와 각각의 태스크 간의 Context를 유지하며 세션에 적용하지 못하면서 개발하는 건 이제 상상할 수 없다.
각종 AI 서비스 사용에 따른 비용증가에 부담이 크므로, 오픈소스 MCP를 분석하며 적절하게 사용하는 방법을 연구하고 적용하는 과정은 어쩔 수 없이 계속될 것 같다.
현재 4대 Agent (Claude, Codex, Gemini, Opencode) 마다 AGENTS.md 로딩 순서와 방법, 적용 범위의 차이는 과거 브라우저와 JS/CSS 로더 전쟁에 비교할 만해서, 이 부분에 대한 정확하고 경험있는 처리가 반드시 필요하다. 아마 이것도 MCP로 해결될지도 모르겠다.
cmux-mcp 를 끼고 Browser API로 작업지시하는 방식이 현재 Chrome Browser에 Gemini에게 묻는 정도로 직접적이면 더 좋겠다. 아마 분명히 어딘가 방법이 기다리고 있을 것이다.
cmux 자체는 Browser API가 아니라면 그냥 TMUX로 만족해도 대세를 따라가는데 지장없다. CMUX의 workspace 기능에 비할바는 못되도 흉내정도는 내는 hiroppy/tmux-agent-sidebar plugin 정도면 뭐… 기분은 낼 수 있으니까.
Agent가 ssh를 사용해서 원격작업을 하게 냅두지 말자. 생각보다 토큰 많이 쓴다(작업 실패때문에). 그럴 땐, mutagen 괜찮다.
이상, 본문 수정은 없으며 추가 내용은 다른 게시물이나 섹션 추가로 이어갈수도 있다.
활용 예1) AGENTS.md 수정은 MCP에게 전담시킴
프로젝트/태스크 마다 global/local AGENTS.md 파일 작성자체를 ctxstore-mcp 가 담당하게 해두었다. 물론 어느정도의 틀속에서, MCP를 어떻게 섞어 사용하느냐에 따라 규정 적용 순서나 범위와 상세내용 약간식은 달라진다.
활용 예2) 장애가 생겨 시스템 리부팅 후 문제 발생, 복구에 ctxstore MCP 사용
호스트의 기존 상태를 복구하기 위해 태스크 기록을 참조로 복구 명령을 내림
Agent 상황 보고 #1
몇 번의 Turn 만에 복구 완료.
Agent 상황 보고 #2
CSM 없이 기존에 이미 태스크를 진행했더라도, 그 정보를 CSM에 맞춰서 import 할 수 있게하였다.
MCP가 LLM에게 문맥을 제공하므로 손가락 빠지게 프롬프트 쓸 필요없이 개요만 얘기함으로써 복구를 할 수 있었다.
Turn 단위로 작업을 그룹화하여 계획 수립을 지시하자
sequential_thinking MCP 강추. AGENTS.md 파일에 “계획을 세울 때 Turn 단위로 작업을 그룹화해서 제안하라“는 규정과 이 MCP랑 잘 맞는다.