
자작 MCP 서버를 공식 레지스트리와 각 디렉토리에 등록하기 — 전체 절차와 주의할 점
요약
자작 MCP 서버를 공식 레지스트리와 다양한 디렉토리에 등록하는 전체 절차를 설명합니다. 도메인 인증 방법, 버전 관리 시 주의사항, 그리고 API 키 없이도 도구 목록을 응답할 수 있어야 하는 실질적인 요구 사항을 다룹니다.
핵심 포인트
- 공식 레지스트리 등록을 위해 Ed25519 기반 HTTP 도메인 인증이 필요함
- package.json, server.json, 코드 내 상수의 버전을 반드시 동기화해야 함
- 디렉토리 게재를 위해 API 키 없이도 tools/list 응답이 가능해야 함
- 공식 레지스트리 등록 후 Glama, mcp.so 등 하류 디렉토리를 통해 노출됨
TL;DR
- MCP 서버를 만들었다면, 공개되는 장소는 하나가 아니라 계층 구조로 되어 있습니다: 공식 MCP Registry(상류) → Glama / PulseMCP / mcp.so / awesome-mcp-servers 등의 디렉토리(하류)
- 공식 레지스트리 등록은 HTTP 도메인 인증(Ed25519) + server.json + mcp-publisher CLI를 통해 생각보다 간단하게 진행할 수 있었습니다.
- 가장 큰 주의할 점은 의외의 곳에 있었습니다: "API 키 없이도 기동하여 tools/list에 응답할 수 있어야 한다"는 것이 디렉토리 게재의 사실상의 요구 사항이었다는 점을 다룹니다.
- 대상은 Argosvix(아르고스빅스)의 MCP 서버(@argosvix/mcp-server, 87개 도구)이지만, 절차는 자작 MCP 서버 전반에 사용할 수 있을 것입니다.
전제
- MCP 서버를 npm에 공개 완료한 상태 (
npx -y @argosvix/mcp-server로 기동 가능한 상태) - 독자적인 도메인을 보유하고 있음 (공식 레지스트리의 네임스페이스 인증에 사용)
1. 공식 MCP Registry 등록
공식 레지스트리(registry.modelcontextprotocol.io)는 MCP 서버의 "공식 장부"입니다. 여기에 등록해 두면, 후술할 디렉토리 군이 자동 크롤링을 통해 정보를 가져가는 기점이 됩니다.
네임스페이스와 도메인 인증
서버 이름은 역 DNS 형식(예: com.argosvix/server)으로, 해당 도메인의 소유를 증명해야 합니다. 방식은 여러 가지가 있지만, 저는 HTTP 도메인 인증을 사용했습니다.
- Ed25519 키 쌍을 생성한다.
- 공개키를 도메인의
/.well-known/mcp-registry-auth에 배치한다 (정적 파일 1개). mcp-publisher login http --domain yourdomain.com --private-key ...로 로그인한다.
여기서 중요한 운영상의 주의사항이 하나 있습니다: well-known 파일은 등록 후에도 삭제해서는 안 됩니다. 재로그인할 때마다 검증되므로, 영구적으로 계속 배포한다는 전제하에 위치를 결정하십시오 (저는 랜딩 페이지의 정적 파일로서 리포지토리 관리에 포함했습니다).
server.json과 version 동기화의 함정
레지스트리에는 서버의 메타데이터를 server.json으로 등록합니다. 여기서 빠졌던 함정은 version의 삼중 관리입니다.
package.json의 version (npm의 정석)server.json의 version (레지스트리의 정석)- 코드 내의 상수 (initialize 응답 시 밝히는 version)
이 세 가지가 일치하지 않으면, 클라이언트가 handshake에서 보는 version과 레지스트리의 표시가 어긋나게 됩니다. 저는 한 번 이로 인해 불일치가 발생했기 때문에, 이후 "version을 올릴 때는 3곳을 동시에"라는 기계적인 규칙을 세웠습니다. 릴리스 절차서에 한 줄 적어두는 것만으로도 방지할 수 있습니다.
publish
cd your-mcp-server && npm publish
# server.json의 version을 맞춘 후
mcp-publisher publish
npm에 새로운 version을 배포 → server.json을 맞춤 → mcp-publisher publish 순서입니다.
2. 디렉토리의 세계 — 공식 레지스트리만으로는 발견되지 않는다
등록을 통해 알게 된 사실인데, 사용자가 실제로 MCP 서버를 찾는 장소는 공식 레지스트리가 아니라 그 하류의 디렉토리 군입니다.
| 장소 | 성질 |
|---|---|
| Glama | 자동 체크 + 스코어링이 포함된 디렉토리 |
| ... |
awesome-mcp-servers에 PR을 보냈더니, bot으로부터 다음과 같은 답변이 왔습니다: "먼저 Glama에 게재되어 체크를 통과하고, 스코어 배지를 PR에 달아주세요". 즉, 디렉토리 간에도 의존 관계가 있으며, Glama의 체크 통과가 다른 곳으로 가기 위한 입장권이 됩니다.
3. 최대의 주의할 점: "키 없는 기동"이 요구 사항이었다
Glama의 자동 체크는 "서버가 기동하여 introspection (initialize / tools/list)에 응답하는 것"을 확인합니다. 여기서 문제가 발견되었습니다.
제 서버는 API 키(환경 변수)가 설정되어 있지 않으면, 기동 직후 에러를 내며 exit 하는 설계였습니다. 사용자 보호 측면에서는 타당한 설계라고 생각했지만, 체커는 키 없이 기동합니다. 즉, 구조적으로 게재가 불가능했습니다.
대응: introspection-only 모드
"키가 없더라도 기동하여 도구 목록에는 응답하고, 실행하려고 할 때만 설정 절차를 안내하는" 방식으로 변경했습니다.
// 기동 시: exit 하지 않고 경고를 띄우며 계속 진행
if (!API_KEY) {
console.error("[mcp] API key is not set — starting in introspection-only mode.");
...
포인트는 두 가지입니다.
- 프로토콜 에러가 아니라— 이렇게 하면 연결 대상인 LLM이 에러 메시지를 읽고, 사용자에게 설정 절차를 그대로 전달해 줍니다. 에러가 UX가 되는 설계입니다.
- tool 결과에서
isError: true로 반환 -
직접 해보며 깨달은 점인데, 이는 디렉토리 대응을 넘어 일반적으로 좋은 개선이었습니다. 사용자는 키를 발급하기 전에 도구 목록을 보고 "사용할 가치가 있는지"를 판단할 수 있습니다. "키 없이도 기동하여 목록에 응답하는 것"은 MCP 서버의 사실상의 매너라고 생각해도 좋습니다.
4. 리포지토리 공개 문제
또 하나, 많은 디렉토리는 GitHub 리포지토리를 게재 단위로 삼고 있습니다. 개발 리포지토리가 비공개(모노레포)인 경우, npm 패키지만으로는 게재할 수 없는 곳이 있습니다.
저는 "npm에 MIT 라이선스로 공개된 패키지의 소스만 공개 미러 리포지토리로 분리하는" 방식으로 해결했습니다 (argosvix/mcp-server). 이미 전 세계에 배포 중인 코드이므로 새로 공개되는 정보는 늘어나지 않으면서, 디렉토리의 게재 단위, Issue 접수 창구, README의 위치를 확보할 수 있습니다.
미러를 만들 때 주의할 점이 하나 있습니다: 공개하기 전에 포함된 파일을 전부 확인하세요. 저는 CHANGELOG에 내부 문서로의 참조가 남아 있는 것을 공개 후 체크 과정에서 발견하고 급히 삭제했습니다. npm의 files 필드에 포함되지 않은 파일(= npm에서는 공개되지 않았던 파일)을 미러에 포함하면, 의도치 않은 첫 공개가 될 수 있습니다.
마치며
MCP 서버 배포는 "npm에 publish 하고 끝"이 아니라, 공식 레지스트리 → 디렉토리 군이라는 계층을 순차적으로 채워나가는 작업이었습니다. 절차 자체는 모두 어렵지 않지만, "키 없는 기동"과 같은 게재 측의 암묵적인 요구 사항은 직접 해보기 전까지 알 수 없었습니다. 이 글이 앞으로 서버를 올리려는 분들에게 지름길이 된다면 좋겠습니다.
Argosvix는 AI 에이전트의 동작(비용·에러·품질·안전)을 다른 AI가 감시하는 관측 서비스입니다. 이 MCP 서버의 내부 이야기는 공개까지의 개발기에 적어두었습니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기