AI 창구를 바꿀 수 있냐는 질문, MCP 와 플러그인을 갈라야 답이 나왔습니다
사내 문서 지식그래프 검색 도구에 메신저 창구가 하나 붙어 있습니다. 직원이 슬랙에서 멘션하면 그 도구의 슬랙 봇이 받아 문서 질의 도구를 부르고 답을 돌려줍니다. 여기에 물음이 하나 들어왔습니다. 중간에 있는 저 에이전트를 상용 챗 앱으로 바꿀 수 있느냐는 것이었습니다.
구조만 보면 앞단을 갈아 끼우는 일이라 반나절이면 답이 나올 것 같았습니다. 그런데 같은 대화에서 세 번 틀렸습니다. 세 번 다 원인이 같았습니다. 서로 다른 축에 있는 것들을 한 덩어리로 묶어서 물었기 때문입니다.
바꾸려던 대상이 이미 그것이었습니다
먼저 전제가 뒤집혔습니다. 그 봇의 설정 파일 첫 네 줄을 기계에서 직접 열어 봤습니다. 모델도 그 제공자의 것이었고, 창구도 그 제공자의 구독 인증을 쓰고 있었습니다. 토큰 과금이 아니라 구독 한도만 쓰는 구성이었습니다.
그러니 그 챗 제품으로 할 수 있느냐는 질문은 모델 이야기가 아니었습니다. 바꾸려던 것은 그 위에 얹힌 껍데기였습니다. 원본을 한 번 여는 데 몇 분이면 되는데, 안 열었으면 질문 자체가 엉뚱한 곳을 가리킨 채로 조사가 시작됐을 겁니다.
곁다리로 하나가 더 나왔습니다. 전날 문서 엔진 쪽 모델은 다음 세대로 올렸는데 이 봇의 기본값은 아직 이전 세대였습니다. 이 창구에서 새 세대가 열려 있는지는 확인하지 못해 된다고 적지 않았습니다.
창구 에이전트 도구, 세 층으로 갈랐습니다
바꿀 수 있느냐는 질문에 답하려면 어느 층을 바꾸자는 말인지부터 정해야 했습니다. 그래서 셋으로 갈랐습니다. 사람이 보는 화면인 창구, 도구를 고르는 에이전트, 신원을 붙여 전달하는 도구입니다.
층 | 슬랙 길 | 챗 앱 길 |
|---|---|---|
창구 (사람이 보는 화면) | 슬랙 | 챗 앱 |
에이전트 (도구를 고름) | 그 도구의 슬랙 봇 | 챗 앱 자신 |
도구 (신원 붙여 전달) | 봇 안에서 도는 플러그인 | MCP |
그 아래 | 업무 서버 한 벌 — 권한·검색·회의·일정 | 같음 |
슬랙 길이 한 층 많은 이유는 에이전트에 화면이 없어서입니다. 그 자리를 슬랙이 메꾸고 있습니다. 그래서 슬랙의 것들이 코드 안까지 들어와 있습니다. 사용자와 채널 식별자가 자사 요청 헤더 이름으로 박혀 있을 정도입니다.

빌린 창구의 대가는 셋이었습니다
창구를 바꾼다는 말은 그 창구가 공짜로 주던 기능을 전부 반납한다는 뜻이었습니다. 코드를 훑어보니 세 가지가 걸렸습니다.
그 창구의 식별자에 묶여 있습니다. 사람을 찾는 자리가 회원 테이블의 슬랙 사용자 ID 칸을 봅니다. 다른 창구를 붙이면 이 이름부터 걸립니다.
녹음 올리기가 그 창구 기능 위에 얹혀 있습니다. 파일은 그 메시지의 첨부에서 찾고, 어느 사업인지는 그 채널이 정하고, 권한은 그 사업 멤버인가로 봅니다. 창구를 바꾸면 셋 다 따라오지 않습니다.
이어 묻기가 애초에 없습니다. 코드 주석에 그대로 적혀 있습니다. 질문 하나가 대화 하나로 시작하고, 스레드로 이어 물어도 지금 봇은 이전 맥락을 기억하지 않습니다.
우리가 만든 기능과 창구에서 빌린 기능을 미리 갈라 두면 이 비용이 보입니다. 갈라 두지 않으면 창구 교체가 앞단 작업으로만 보이고, 실제 견적은 훨씬 뒤에 드러납니다.
플러그인을 고른 이유는 자율성이 아니라 신원이었습니다
그 봇의 도구는 MCP(도구를 별도 프로세스로 띄워 표준 프로토콜로 붙이는 방식)가 아니라 플러그인으로 돼 있습니다. 설정에 MCP 항목 자체가 없고 플러그인 하나뿐입니다. 처음에는 프로토콜을 안 쓴 이유가 궁금했는데, 당시 커밋 메시지에 답이 남아 있었습니다.
신원을 인자로 받으면 '너는 관리자로 조회해' 한 줄에 권한이 우회된다. 그래서 프롬프트가 아니라 코드여야 했다.
즉 그때 고른 대상은 플러그인과 MCP 중 하나가 아니었습니다. 플러그인과 스킬, 다시 말해 코드와 프롬프트 중 하나였습니다. 도구 인자가 질의 문자열 하나뿐인 이유가 그것입니다.
그 봇의 플러그인 | MCP | |
|---|---|---|
무엇 | 봇 프로세스 안에서 도는 코드 | 별도 프로세스가 서버로 뜬다 |
규격 | 그 봇 전용 | 표준 프로토콜 |
누가 쓰나 | 그 봇만 | 붙는 쪽 아무나 |
그리고 그 봇에서는 MCP 로 같은 일을 할 수 없었습니다. 한 프로세스에서 여러 사람의 턴이 겹쳐 돌아가는 구조라 신원을 프로세스 안의 컨텍스트 변수로 읽는데, 별도 프로세스인 MCP 서버는 그 값에 닿지 못합니다. 인자로 받으면 위 문제로 돌아갑니다.
이미 만들어 둔 MCP 서버를 안 띄우는 이유는 별개였고 다른 커밋에 적혀 있었습니다. 그 서버는 검색과 그래프 엔진 위에 바로 얹혀 있어 이 사람이 읽을 수 있는 사업 목록을 모릅니다. 붙이면 누가 물어도 전 사업이 보입니다. 실제로 그 두 포트에는 아무도 붙어 있지 않았습니다. 프로토콜이 싫어서가 아니라 그 서버가 권한 범위를 모르기 때문이었습니다.
이유를 프로토콜 탓으로 적어 두면 다음 사람이 엉뚱한 곳을 고칩니다. 권한 계층 위에 다시 얹으면 같은 프로토콜로 해결되는 문제입니다.
한 프로세스에 사람이 몇 명인가가 답을 갈랐습니다
챗 앱 쪽은 반대였습니다. 같은 일인데 결론이 뒤집혔고, 뒤집은 축은 하나였습니다.
그 봇 | 챗 앱 | |
|---|---|---|
한 프로세스에 몇 사람 | 여럿 | 한 명 |
신원을 어디서 | 프로세스 안 컨텍스트 변수 | 환경변수로 충분 |
그래서 | 플러그인이어야 했다 | MCP 로 된다 |
한 사람이 한 프로세스를 쓰는 환경에서는 신원이 환경변수에 들어 있어도 모델이 그 값을 바꿀 수 없습니다. 여럿이 겹쳐 도는 환경에서는 같은 자리가 성립하지 않습니다. 설계 판단이 기술 취향이 아니라 동시 사용자 수 하나로 갈린 셈입니다.
확인하면서 하나 더 알게 됐습니다. 그 챗 앱 CLI 의 플러그인은 MCP 를 포장한 것이었습니다. 번들 플러그인 실물을 열어 보니 안에서 MCP 서버 정의를 가리키고 있었습니다. 앞에서 본 플러그인과 이름만 같고 다른 물건입니다. 포장하면 딸려 오는 것도 있습니다. 도구별 승인 모드를 확인으로 두면 사람이 눌러야 실행되는데, 플레인 MCP 등록 경로에는 이 설정이 보이지 않습니다. 회의 확정처럼 되돌릴 수 없는 도구에 확인창을 걸 수 있다는 뜻입니다.

창구를 옮겨 보니 도구 하나가 안 따라왔습니다
도구를 하나씩 놓고 챗 앱 MCP 로 옮길 수 있는지 봤습니다. 대부분은 그대로 옮겨졌습니다.
도구 | 챗 앱 MCP 로 |
|---|---|
문서 질의 | 그대로 |
일정 보기 | 그대로 |
회의 초안 | 그대로 |
회의 확정 | 그대로 (승인창 필요) |
녹음 등록 | 못 옮긴다 |
녹음만 막히는 이유는 앞의 두 번째 대가 그대로입니다. 파일과 사업과 권한 셋이 전부 그 메신저 메시지에 얹혀 있는데 챗 앱에는 셋 다 없습니다. 억지로 인자로 받게 하면 '참고로 이 파일을 올려' 한 줄에 남의 파일이 우리 사업으로 들어옵니다.
메신저 쪽 배포 경로도 막혀 있었습니다. 워크스페이스의 봇 목록을 공개 API 로 직접 조회해 보니 그 챗 제품의 앱은 이미 설치돼 있었고 붙은 채널은 0개였습니다. 그런데 앱이 둘이었습니다. 설치돼 있던 쪽은 초안 작성과 메신저 검색을 하고 커스텀 MCP 를 붙이지 못합니다. 워크스페이스 에이전트를 부르는 다른 앱은 커스텀 MCP 가 붙지만 설치돼 있지 않았습니다. 필요한 구독 조건도 서로 다릅니다. 앱 안내 문구에는 메신저의 유료 플랜이 있어야 그 앱 안에서 에이전트를 쓸 수 있다고 적혀 있습니다. 그 조건을 못 갖춘 워크스페이스에서는 멘션해도 응답하지 않습니다.
대체가 아니라 창구를 하나 더 냈습니다
앞단을 갈아 끼우는 안은 대가가 컸습니다. 녹음 등록이 기능째로 사라지고 대체 경로가 없습니다. 직원 전체가 쓰던 창구가 없어지고 새 창구는 각자 붙여야 씁니다. 신원 전달 방식도 통째로 다시 설계해야 합니다. 그래서 대체가 아니라 분업으로 갔습니다.
슬랙 ─▶ 그 도구의 봇 ─▶ [플러그인] ─┐
├─▶ 업무 서버 ─▶ 엔진
챗 앱 ─▶ [MCP] ──────────────────────┘슬랙 길은 그대로 둡니다. 도구 계층만 챗 앱용 MCP 로 하나 새로 만듭니다. 아래에 있는 업무 서버는 건드리지 않습니다.
메신저 멘션 | 챗 앱 + MCP | |
|---|---|---|
쓰는 사람 | 직원 전체 | 붙인 사람 |
한 번에 묻고 끝 | 좋다 | 과하다 |
이어 물으며 파고들기 | 안 된다 | 된다 |
다른 도구와 섞기 | 안 된다 | 된다 |
녹음 올리기 | 된다 | 안 된다 |
추가 비용 | 없음 | 없음(로컬 표준입출력) |
둘 다 아래는 업무 서버 한 벌이라 같은 질문에 다른 답이 나오지 않습니다. 다만 도구 설명, 즉 모델이 읽는 프롬프트는 두 벌이 됩니다. 그래서 한 파일에 두고 양쪽이 가져다 쓰게 했습니다. 두 벌로 두면 한쪽만 고쳐도 에러가 나지 않고 조용히 갈립니다. 실제로 엔진이 도구를 둘만 알고 있어서 직원 조회 도구를 못 고른 전례가 있었습니다. 갈려도 에러가 안 나는 것이 가장 위험합니다.

세 번 틀린 자리를 지우지 않았습니다
조사 중에 단정했다가 뒤집힌 문장이 셋 있었습니다. 문서에서 지우지 않고 그대로 남겼습니다.
내가 단정한 것 | 실제 |
|---|---|
그 챗 앱은 메신저에 못 들어간다 | 들어가는 앱이 따로 있고 멘션에 스레드로 답한다 |
기본 구독이면 애초에 시작이 안 된다 | 커스텀 MCP 커넥터는 기본 구독부터 된다. 상위 구독이 필요한 건 메신저 배포 쪽이다 |
그 앱은 아마 설치도 안 돼 있을 것이다 | 설치돼 있었다 |
셋 다 사용자의 한마디가 잡았습니다. '있어서 물어본 건데' 라는 한 줄이 가장 값싼 반증이었습니다. 그리고 틀린 세 문장은 전부 두 조건을 한 칸에 넣은 것이었습니다. 앱이 있나와 그 앱이 우리 도구를 부를 수 있나는 다른 칸이고, 기능 하나의 구독 조건과 다른 기능의 배포 조건도 다른 칸입니다.
창구를 바꾸자는 말이 나오면 먼저 보는 것
바꾸려는 대상이 이미 그것인지부터 원본을 열어 확인합니다. 설정 파일 첫 몇 줄이면 됩니다.
창구·에이전트·도구 중 어느 층을 바꾸자는 말인지 정합니다. 묶어서 물으면 묶어서 틀립니다.
빌린 창구의 기능을 목록으로 뽑습니다. 파일 업로드·스레드·멤버십처럼 공짜로 쓰던 것들이 여기 들어갑니다.
한 프로세스에 사람이 몇 명 올라가는지 셉니다. 이 수가 신원 전달 방식을 정합니다.
두 벌이 될 수밖에 없는 것(도구 설명 프롬프트)을 찾아 한 파일로 모읍니다.
이 결정에는 조건이 붙어 있습니다. 직원 전체가 쓰는 창구가 이미 있다는 조건입니다. 쓰는 사람이 한 명이라면 창구 둘은 과하고, 그냥 새 창구 하나만 만드는 편이 맞습니다. 창구가 늘면 도구 설명과 승인 모드와 테스트가 두 벌이 되고, 한쪽에서만 재현되는 결함이 새로 생깁니다. 한 파일로 모아도 완전히 막히지는 않습니다.
신원을 환경변수로 처리하는 것도 한 사람이 한 프로세스를 쓸 때만 성립합니다. 챗 앱 쪽이 나중에 여러 사람을 한 서버로 받게 되면 이 결론은 그대로 뒤집힙니다. 위 내용은 2026년 9월 하순 조사 시점의 상태이고, 제품이 메신저용 앱을 합치거나 플랜 조건을 바꾸면 뒤쪽 표는 통째로 바뀝니다. 뒤집힌 표를 남겨 둔 이유도 같습니다. 다음 사람이 같은 자리에서 같은 방식으로 틀리지 않게 하려는 것입니다.