원격 MCP 커넥터 생성하기
stateless Streamable-HTTP MCP 서버(TypeScript, @modelcontextprotocol/sdk)를 구축하여 Claude.ai 커스텀 커넥터로 작동하도록 합니다. 선택적으로 인라인 시각 카드(MCP 앱)를 포함하며, Vercel에 배포합니다. 30개 이상의 도구가 있는 실제 프로젝트에서 검증되었습니다.
템플릿은 이 파일 옆에 있는 templates/ 디렉토리에 있습니다. 자세한 노트는 references/에 있으며, 단계에서 필요할 때만 읽으십시오:
references/mcp-apps-cards.md— 인라인 카드:ui://리소스, postMessage 프로토콜, CSP, 클릭 가능한 목록references/deploy-vercel.md— Vercel 설정, 배포, Claude.ai에서 커넥터 재추가references/gotchas.md— 실제 시간을 소모하는 함정들 (디버깅 전에 읽으십시오)
워크플로우
- 명확히 하기 (추론할 수 없는 것만 질문): 어떤 데이터/API인지, 읽기 전용인지 쓰기 가능인지, 인증이 필요한지, 카드 또는 텍스트만 원하는지. 기본값: 공개 데이터, 읽기 전용, 인증 없음, 텍스트 + 카드.
- 코드를 작성하기 전에 모든 상위 API를 조사하십시오. 각 엔드포인트에
curl을 사용하십시오: 상태, 응답 형태, 날짜 형식, 속도 제한, 타임아웃, 리디렉션 (301은 URL이 변경되었음을 의미합니다, 예:api.frankfurter.dev가 아닌.app). 공개 SPARQL/검색 엔드포인트는 느릴 수 있습니다: 시간을 측정하고, 쿼리를 단순하게 유지하며, 코드에서 필터링하십시오. - 템플릿에서 스캐폴딩 (
templates/에서package.json,tsconfig.json,vercel.json,api/,src/,scripts/복사),my-connector이름 변경,npm install실행. src/server.ts에 도구 작성 (각 도구마다registerTool하나씩). 아래 규칙 참조.- 모든 도구를
scripts/test-client.ts에 추가하십시오. 실행 프로그램은 테스트되지 않은 도구, 빈 출력 및isError에서 실패합니다. - 로컬에서 검증:
npm run typecheck,PORT=<fresh port> npm run dev실행, 로그에 "listening"이 표시되는지 확인(EADDRINUSE가 아님), 그런 다음npm test -- http://localhost:<port>/mcp실행. 목표:Untested tools: none. Problems: 0. - 문서화: README 도구 표(도구당 한 행), CONTRIBUTING, LICENSE.
- 사용자의 승인을 받은 후에만 커밋, 푸시, 배포 (
references/deploy-vercel.md참조), 그런 다음 라이브 URL에 대해 테스트를 실행하십시오. - 사용자에게 Claude.ai에서 커넥터를 제거하고 다시 추가하라고 알리십시오 (도구 목록을 캐시합니다). 3-5개의 짧은 테스트 프롬프트를 제공하십시오.
도구 설계 규칙
- 적고, 실제로 작동하는 도구. 이름은
snake_case동사:search_x,get_x,list_x. - 모든 입력에 제한이 있는 Zod 스키마 (
min/max,default); 각 필드를 예시와 함께 설명하십시오. - 설명은 반환하는 내용과 언제 사용해야 하는지를 한두 문장으로 나타냅니다. 모델이 도구를 선택하기 위해 읽습니다.
- 어노테이션:
readOnlyHint: true, idempotentHint: true, destructiveHint: false, 외부 API의 경우openWorldHint: true. - 모든 핸들러를
safe(...)로 감싸십시오: 상위 실패는 읽기 쉬운 메시지와 함께isError결과가 되며, 절대 충돌하지 않습니다. - 모든 결과에 데이터 소스 이름을 명시하십시오. 데이터가 커뮤니티 편집 또는 임시 정보인 경우 알리십시오.
- 누락된 필드에서 절대 충돌하지 말고, "unknown"으로 대체하십시오.
- 오타 허용: 일치하는 항목이 없으면 빈 결과 대신 "did you mean" 제안을 반환하십시오.
- 상위 호출을 캐시하십시오 (템플릿
getJson/getText에는 TTL, 인플라이트 중복 제거, 짧은 실패 캐시, 타임아웃이 있습니다). 실시간 데이터에는 짧은 TTL(분), 정적 데이터에는 긴 TTL을 사용하십시오. 무료 API에 친절하게 대하십시오. card(text, data)와 같은 헬퍼를 통해 텍스트(모델용)와structuredContent(카드용)를 모두 반환하십시오.- 저장소에 비밀 정보를 넣지 마십시오. 키가 필요한 경우
process.env에서 읽고 문서화하십시오. - 상위 쿼리가 느린 경우, 코드에서 무거운 작업을 필터링하십시오.
Stateless 서버 (Vercel 친화적)
요청마다 새로운 McpServer와 전송이 생성됩니다 (src/handler.ts); 세션이 없고, 요청 간 메모리가 유지되지 않습니다. 유일한 상태는 인메모리 캐시이며, 최선의 노력으로 제공됩니다. CORS와 본문 크기 제한이 핸들러에 있습니다. api/mcp.ts는 { fetch }와 maxDuration: 30을 내보냅니다. vercel.json은 /mcp를 /api/mcp로 재작성합니다.
카드 (MCP 앱), 간략 버전
하나의 ui://… HTML 리소스(mimeType: text/html;profile=mcp-app)를 등록한 다음, 각 도구에 _meta: { ui: { resourceUri }, "ui/resourceUri": resourceUri }를 제공하고 kind 필드가 있는 structuredContent를 반환하십시오. HTML은 kind에 따라 렌더링되는 독립 실행형 파일입니다. references/mcp-apps-cards.md 및 templates/src/view.ts를 참조하십시오.
사용자에게 출력
간결하게 작성하십시오. 보고할 내용: 구축된 내용(도구 목록), 테스트 결과, URL, 커넥터를 새로 고치는 정확한 단계. 한계를 정직하게 명시하십시오(확인되지 않은 UI 경로, 느린 상위 API, 커뮤니티 데이터).