9 분 소요

Summary

서버는 만들었습니다. 이제 붙일 차례예요.

붙이는 것 자체는 명령 한 줄입니다. 문제는 안 붙었을 때죠. 클라이언트는 대개 “서버에 연결하지 못했습니다” 정도만 말해주고 끝나거든요. 그 한 줄로는 인증이 틀린 건지, URL 이 틀린 건지, 워크플로를 게시 안 한 건지, 프록시가 스트림을 막고 있는 건지 알 수가 없습니다.

그래서 이번 편의 절반은 원인을 가르는 절차입니다. 핵심 도구는 하나예요 — curl 로 직접 찔러보기. 클라이언트를 걷어내고 HTTP 응답 코드를 직접 보면 5분이면 갈립니다.

💡 이 글에서 다루는 것

  • Claude Code 에 붙이기 — claude mcp add 전송 방식과 스코프
  • .mcp.json 형식과 헤더로 토큰 넘기기
  • Claude Desktop — stdio 미지원을 mcp-remote 로 넘기기
  • 인스턴스 레벨 n8n MCP 붙이기 (OAuth / API 키)
  • VS Code·Cursor 설정
  • n8n 에이전트에 남의 MCP 서버 붙이기
  • 🔍 curl 로 tools/list 찍기 — 세대 확인부터 도구 목록까지
  • 증상별 원인 가르기 표 — 401 · 404 · 405 · 406 · 400 · 타임아웃 · 빈 목록
  • 붙인 뒤 반드시 하는 실측 3가지



1. 무엇을 어디에 붙이는가 (복습)

1편의 세 자리를 연결 관점으로 다시 정리하면 이렇습니다.

붙이는 것 어디에 URL
내가 만든 MCP 서버 Claude Code·Desktop 등 노드 패널의 MCP URL
인스턴스 레벨 n8n MCP Claude Code·Desktop 등 /mcp-server/http
남의 MCP 서버 n8n 안의 AI Agent MCP Client Tool 노드

앞의 둘은 n8n 이 서버, 마지막은 n8n 이 클라이언트입니다. 설정 파일을 열기 전에 지금 어느 경우인지부터 확인하세요.


2. Claude Code 에 붙이기

가장 흔한 경우이고 가장 간단합니다.

2-1. HTTP 전송으로 추가

2편에서 만든 서버는 Streamable HTTP 를 지원하니 http 전송을 씁니다.

claude mcp add --transport http <name> <url>

인증을 켰다면 헤더를 같이 넘깁니다.

claude mcp add --transport http <name> <url> \
  --header "Authorization: Bearer your-token"

우리 예제라면 이렇게 됩니다.

claude mcp add --transport http realestate \
  https://n8n.example.com/mcp/realestate \
  --header "Authorization: Bearer $N8N_MCP_TOKEN"

URL 은 반드시 노드 패널에서 복사하세요. 2편에서 본 대로 테스트 URL 과 프로덕션 URL 이 다릅니다. 운영에 붙일 거면 워크플로를 게시한 뒤 Production URL 을 복사해야 해요. n8n 문서가 MCP 트래픽을 /mcp* 로 통칭하는 데서 보듯 두 URL 모두 이 접두 아래에 있습니다.

n8n 이 헤더 인증(Header auth)으로 설정돼 있다면 그 헤더 이름을 그대로 쓰면 됩니다.

claude mcp add --transport sse private-api https://api.company.com/sse \
  --header "X-API-Key: your-key-here"

2-2. 스코프 — 어디에 저장되나

--scope 로 설정이 저장되는 위치를 고릅니다.

스코프 범위 공유
local (기본) 현재 프로젝트만 비공개
project 현재 프로젝트 .mcp.json 으로 공유됨
user 모든 프로젝트 비공개
claude mcp add --transport http shared-server --scope project https://example.com/mcp

🚨 project 스코프에 토큰을 박지 마세요. .mcp.json 은 저장소에 커밋되는 파일입니다. 토큰이 들어가면 그대로 유출돼요. 팀과 공유할 거면 URL 만 project 로 두고 토큰은 각자 local/user 로 넣거나, 환경변수를 참조하게 하세요.

2-3. .mcp.json 형식

project 스코프는 프로젝트 루트의 .mcp.json 에 저장됩니다.

{
  "mcpServers": {
    "shared-server": {
      "type": "http",
      "url": "https://example.com/mcp"
    }
  }
}

헤더를 붙이는 형태는 이렇습니다.

{
  "mcpServers": {
    "secure-api": {
      "type": "http",
      "url": "https://api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer your-token"
      }
    }
  }
}

2-4. 확인·관리 명령

claude mcp list
claude mcp get <name>
claude mcp remove <name>

세션 안에서는 /mcp 로 서버 상태를 봅니다. 여기서 도구 목록이 보이면 연결은 성공한 겁니다.

2-5. 플래그 요약

플래그 짧은 형태
--transport -t http sse stdio
--header -H 반복 사용 가능
--scope -s local project user
--env -e 반복 사용 가능 (stdio 용)


3. Claude Desktop 에 붙이기 — stdio 미지원을 넘기기

1편에서 짚은 제약이 여기서 걸립니다. n8n 의 MCP Server Trigger 는 stdio 를 지원하지 않습니다. 그런데 stdio 로만 말하는 클라이언트가 있어요. 그래서 중간에 게이트웨이를 하나 세웁니다.

n8n 공식 문서가 제시하는 형태가 mcp-remote 입니다.

{
  "mcpServers": {
    "n8n": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "<MCP_URL>",
        "--header",
        "Authorization: Bearer ${AUTH_TOKEN}"
      ],
      "env": {
        "AUTH_TOKEN": "<MCP_BEARER_TOKEN>"
      }
    }
  }
}

구조를 말로 풀면 이렇습니다.

구간 무엇
Claude Desktop ↔ mcp-remote stdio
mcp-remote ↔ n8n SSE / Streamable HTTP

토큰을 args 에 직접 쓰지 않고 env 로 빼둔 것도 그대로 따라 하세요. 설정 파일이 로그나 프로세스 목록에 노출될 여지를 줄여줍니다.

게이트웨이가 하나 더 끼면 끊길 지점도 하나 더 생깁니다. 안 되면 먼저 게이트웨이 없이 curl 로 n8n 을 직접 찔러보세요(6절). 거기서 되면 문제는 게이트웨이 쪽입니다.


4. 인스턴스 레벨 n8n MCP 붙이기

1편의 세 번째 자리, n8n 자체를 다루는 MCP 서버입니다.

4-1. 켜기

Settings > Instance-level MCP 에서 Enable MCP access. 인스턴스 소유자/관리자 권한이 필요합니다.

4-2. 엔드포인트

https://<your-n8n-domain>/mcp-server/http

4-3. Claude Code — OAuth

claude mcp add --transport http n8n https://<your-n8n-domain>/mcp-server/http

설정 파일로 쓰면 이렇습니다.

{
  "mcpServers": {
    "n8n": {
      "type": "http",
      "url": "https://<your-n8n-domain>/mcp-server/http"
    }
  }
}

4-4. Claude Code — API 키

{
  "mcpServers": {
    "n8n-mcp": {
      "type": "http",
      "url": "https://<your-n8n-domain>/mcp-server/http",
      "headers": {
        "Authorization": "Bearer <YOUR_N8N_MCP_TOKEN>"
      }
    }
  }
}

4-5. Claude Desktop — API 키

여기서는 n8n 문서가 supergateway 를 씁니다.

"mcpServers": {
  "n8n-mcp": {
    "command": "npx",
    "args": [
      "-y",
      "supergateway",
      "--streamableHttp",
      "https://<your-n8n-domain>/mcp-server/http",
      "--header",
      "Authorization:Bearer <YOUR_N8N_MCP_TOKEN>"
    ]
  }
}

OAuth 로 붙일 거면 Settings > Connectors 에서 Add custom connector 로 위 URL 을 넣으면 됩니다.

4-6. VS Code · Cursor

VS Code 는 .vscode/mcp.json 입니다.

{
  "servers": {
    "n8n": {
      "type": "http",
      "url": "https://<your-n8n-domain>/mcp-server/http"
    }
  }
}

Cursor 는 ~/.cursor/mcp.json 이고, type 값이 다릅니다.

{
  "mcpServers": {
    "n8n": {
      "type": "streamable-http",
      "url": "https://<your-n8n-domain>/mcp-server/http"
    }
  }
}

type 값이 클라이언트마다 다르다는 걸 꼭 기억하세요. Claude 계열은 http, Cursor 는 streamable-http 입니다. 같은 전송인데 이름이 달라요. 여기서 오타 하나로 몇십 분을 날리는 경우가 흔합니다.

4-7. availableInMCP — 안 보이는 이유의 1순위

붙였는데 워크플로가 안 보인다면 대개 이겁니다. 인스턴스 레벨 MCP 의 도구 대부분은 availableInMCP: true 로 표시된 리소스에만 동작해요. 예외는 search_workflowssearch_agents 뿐이고, 이 둘은 “MCP 에 열어야 할 게 있는지” 사용자가 알 수 있도록 접근 가능한 전체를 돌려줍니다.

search_workflows 에는 뜨는데 다른 도구가 못 만지는 상태라면, 그건 고장이 아니라 아직 MCP 에 열지 않은 것입니다.


5. 반대 방향 — n8n 에이전트에 남의 MCP 붙이기

n8n 워크플로 안의 AI Agent 에 외부 MCP 서버를 물리는 경우입니다. MCP Client Tool 서브노드를 씁니다.

파라미터
SSE Endpoint 접속할 MCP 서버 엔드포인트
Authentication Bearer / 헤더 / 다중 헤더 / OAuth2 / 없음
Tools to Include All Selected All Except

다중 헤더는 API 키와 사용자명처럼 헤더를 여러 개 요구하는 서버용입니다.

Tools to Include 는 3편의 축① 그대로예요 — 기본값 All 을 그대로 두지 마세요. 상대 서버가 도구를 수십 개 내주면 카탈로그만으로 컨텍스트를 먹고 선택 정확도가 떨어집니다. 쓸 것만 Selected 로 고르세요.


6. 🔍 curl 로 직접 찔러보기 — 이게 제일 빠릅니다

클라이언트를 걷어내고 HTTP 만 봅니다. 이 절차가 디버깅의 8할이에요.

6-1. 헤더 규칙부터

1편에서 본 스펙 규칙을 다시 씁니다. Streamable HTTP 로 POST 할 때 클라이언트는 Accept 헤더에 application/jsontext/event-stream 둘 다 넣어야 합니다. 이건 MUST 예요.

이걸 빼먹으면 인증이 맞아도 실패합니다. curl 로 손으로 찌를 때 제일 자주 나는 실수이고, 그 결과를 보고 “토큰이 틀렸나” 하고 엉뚱한 데를 파게 됩니다.

6-2. 1단계 — 살아 있는지, 세대가 어느 쪽인지

curl -i -X POST "$MCP_URL" \
  -H "Authorization: Bearer $N8N_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

응답 헤더에서 볼 것은 하나입니다.

응답 다음 단계
Mcp-Session-Id 헤더가 있다 핸드셰이크 세대 (2025-11-25 이하) 6-3 으로
없이 결과만 온다 무상태 세대 (2026-07-28) 6-4 로
4xx 연결·인증 문제 7절 표로

세션 세대라면 스펙상 클라이언트는 이후 모든 요청에 Mcp-Session-Id 헤더를 실어야 합니다. 서버가 요구하는데 안 보내면 400 이 옵니다.

6-3. 핸드셰이크 세대 — 초기화 완료 후 도구 목록

세션 ID 를 변수에 담았다고 보고, 초기화 완료 알림을 보냅니다. 이건 알림이라 202 Accepted 에 본문 없음이 정상입니다.

curl -i -X POST "$MCP_URL" \
  -H "Authorization: Bearer $N8N_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SID" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

이제 도구 목록입니다.

curl -sN -X POST "$MCP_URL" \
  -H "Authorization: Bearer $N8N_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: $SID" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

-N 은 버퍼링을 끄는 옵션입니다. 응답이 SSE 스트림으로 올 수 있어서 붙였어요.

6-4. 무상태 세대 — 바로 부른다

2026-07-28 세대는 프로토콜 수준 세션이 없습니다. 대신 요청마다 버전을 싣고, Streamable HTTP 에서는 MCP-Protocol-Version 헤더로도 같은 값을 보냅니다.

curl -sN -X POST "$MCP_URL" \
  -H "Authorization: Bearer $N8N_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

지원 버전을 먼저 알고 싶으면 server/discover 를 한 번 부르면 됩니다. 지원 버전·기능·신원을 한 요청으로 돌려주는 필수 RPC예요.

curl -sN -X POST "$MCP_URL" \
  -H "Authorization: Bearer $N8N_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"server/discover"}'

서버가 그 버전을 모르면 UnsupportedProtocolVersionError지원 버전 목록과 함께 돌려줍니다. 그러면 그 목록의 버전으로 다시 부르면 돼요.

여기서 도구 목록이 나오면 서버는 정상입니다. 그 다음에도 클라이언트에서 안 보이면 문제는 100% 클라이언트 설정이에요 — URL 오타, type 값, 헤더 이름, 스코프.

6-5. 도구 하나를 실제로 불러보기

curl -sN -X POST "$MCP_URL" \
  -H "Authorization: Bearer $N8N_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_apartment_trades","arguments":{"lawd_cd":"11680","deal_ymd":"202608"}}}'

3편에서 정한 응답 크기를 여기서 실측하세요. 응답을 파일로 받아 글자 수를 재면 대충 감이 옵니다.

curl -sN -X POST "$MCP_URL" ... -o /tmp/mcp_resp.json
wc -c /tmp/mcp_resp.json

한글 기준 대략 3글자가 3바이트이니, 1만 2천 바이트 근처면 대략 3~4천 토큰입니다. 그보다 크면 3편의 요약 단계를 손보세요.


7. 증상별 원인 가르기

curl 결과를 표에 넣으면 바로 갈립니다.

증상 1순위 원인 확인
401 토큰 없음/오타 헤더 이름과 Bearer 뒤 공백
403 토큰은 맞고 권한 부족 인스턴스 MCP 활성화 여부
404 URL 오타 또는 미게시 워크플로 게시 상태
404 (도중에) 세션 만료 initialize 로 재시작
405 그 메서드를 안 받는 엔드포인트 GET/POST 확인
400 Mcp-Session-Id 누락 6-3 절차
400/406 Accept 헤더 누락 두 타입 모두 넣기
연결은 되는데 응답이 안 옴 프록시 버퍼링 5편의 nginx 설정
간헐적 끊김 웹훅 레플리카 분산 5편의 /mcp* 라우팅
도구 목록이 비어 있음 도구 노드 미연결 캔버스에서 연결선 확인
도구는 뜨는데 인자가 없음 $fromAI() 미사용 2편 4절
테스트만 됨 서브워크플로 미게시 2편 5-3

스펙 근거를 붙여두면 이래요. 세션을 요구하는 서버는 Mcp-Session-Id 없는 요청(초기화 제외)에 400 Bad Request 로 답하도록 돼 있고, 서버가 세션을 종료하면 그 세션 ID 로 오는 요청에 404 Not Found 를 돌려줍니다. 클라이언트는 404 를 받으면 세션 ID 없이 InitializeRequest 로 다시 시작해야 해요. 또 GET 으로 SSE 스트림을 열려 할 때 서버가 그 엔드포인트에서 스트림을 제공하지 않으면 405 Method Not Allowed 가 정상 응답입니다.

405 가 항상 고장은 아닙니다. 이걸 모르면 멀쩡한 서버를 붙잡고 몇 시간을 씁니다.


8. 붙인 뒤 반드시 하는 실측 세 가지

연결됐다고 끝이 아닙니다. 3편에서 만든 도구가 실제로 잘 쓰이는지는 따로 확인해야 해요.

실측 방법 합격 기준
선택 도구를 써야 하는 질문 5개 5개 중 5개에서 도구를 부름
인자 코드가 필요한 질문 5개 코드를 환각하지 않고 룩업 도구를 먼저 부름
크기 실제 호출 응답 바이트 1만 2천 바이트 이하

세 번째가 통과해도 대화를 길게 끌고 가면서 한 번 더 보세요. 3편에서 계산한 대로 대화 기록이 쌓이면 같은 응답도 부담이 커집니다.

그리고 n8n 쪽에서는 Executions 탭을 함께 보세요. 프로덕션 실행은 에디터에 안 뜨지만 여기엔 다 들어옵니다. 도구가 몇 번 불렸는지, 실패가 있었는지, 얼마나 걸렸는지가 전부 남아요. 5편에서 이 데이터가 쌓이는 속도와 그걸 관리하는 방법을 다룹니다.



참고 문서