MCP 서버 개발 가이드라인
GitLab v19.3요약
이 페이지에는 GitLab MCP 서버를 개발하고 사용하는 방법에 대한 정보가 포함되어 있습니다. 개발 환경을 설정하려면 다음을 수행합니다: GDK에서 HTTPS를 활성화하고 구성합니다. node를 설치하고 mcp-remote를 전역으로 설치합니다.
이 페이지에는 GitLab MCP 서버를 개발하고 사용하는 방법에 대한 정보가 포함되어 있습니다.
개발 환경 설정#
개발 환경을 설정하려면 다음을 수행합니다:
-
node를 설치하고mcp-remote를 전역으로 설치합니다. GDK에는 Node.js가 포함되어 있지만, 설치된 AI 어시스턴트는 GDK 버전을 사용할 수 없습니다.
디버깅 및 문제 해결#
Cursor 디버깅#
더 자세한 로깅을 위해 mcp-remote 명령에 --debug를 추가합니다. Output을 열고 MCP:SERVERNAME을 선택하여 MCP 서버 로그를 확인합니다. 아래 예시의 경우 MCP:user-GitLab-GDK가 됩니다.
{
"mcpServers": {
"GitLab-GDK": {
"command": "npx",
"args": [
"mcp-remote",
"https://gdk.test:3443/api/v4/mcp",
"--debug"
],
"env": {
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
}
}
}
Claude Desktop 디버깅#
Node.js 버전 확인#
Claude Desktop은 지원되지 않는 버전의 Node.js를 사용합니다. 특정 버전을 사용하는 사용자 지정 래퍼 스크립트를 생성합니다:
#!/bin/bash
# Force use of your Node.js version
NODE_BIN="/PATH_TO_NODE_INSTALL/node/22.17.0/bin/node"
MCP_REMOTE_BIN="/PATH_TO_NODE_INSTALL/node/22.17.0/bin/mcp-remote"
# Run mcp-remote with your Node.js
exec "$NODE_BIN" "$MCP_REMOTE_BIN" "$@"
Claude Desktop 구성에서 래퍼 스크립트를 사용합니다.
{
"mcpServers": {
"GitLab-GDK": {
"command": "/PATH_TO_REMOTE_WRAPPER_SCRIPT/mcp-remote-wrapper",
"args": [
"https://gdk.test:3443/api/v4/mcp",
"--debug"
],
"env": {
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
}
}
}
mcp-remote 디버깅#
AI 어시스턴트 외부에서 mcp-remote에서 GDK로의 인증을 테스트합니다:
NODE_TLS_REJECT_UNAUTHORIZED=0 npx mcp-remote https://gdk.test:3443/api/v4/mcp --debug
브랜치를 전환하면 인증 문제가 발생할 수 있으며, 여기에는 로그에 나타나는 UNABLE_TO_VERIFY_LEAF_SIGNATURE 오류가 포함될 수 있습니다. 체인 내 신뢰할 수 없는 인증서 오류는 TLS를 사용하는 GDK 인스턴스에 특유한 것입니다. 이 오류는 Node.js에서 사용되는 https 클라이언트와 npx를 통한 mcp-remote 라이브러리로 인해 발생합니다. https 클라이언트는 번들로 제공되는 인증 기관 목록 외부에서 서명된 인증서를 신뢰하지 않습니다.
인증 문제가 발생하는 경우, 최후의 수단으로 ~/.mcp-auth 디렉터리를 삭제하면 mcp-remote에 저장된 자격 증명이 재설정됩니다. AI 어시스턴트가 MCP 서버에 다시 연결되면 인증을 요청하는 브라우저 창이 열립니다.
rm -rf ~/.mcp-auth
MCP Inspector로 디버깅#
MCP Inspector는 MCP 서버를 테스트하고 디버깅하기 위한 대화형 개발자 도구입니다.
다음 명령은 서버에 연결하고 MCP 도구를 나열하고 실행할 수 있는 직관적인 웹 UI를 엽니다:
npx -y @modelcontextprotocol/inspector npx
개발 워크플로#
유용한 링크#
새 도구 추가#
도구 제안 프로세스#
현재의 개발 가이드라인은 아직 초기 개발 단계에 있습니다. 특히 사용자 지정 도구와 집계 도구에 대한 도구 개발 표준을 계속 확립해 나가면서, 제안된 도구를 구현 전에 평가하고 새로운 MCP 도구를 계획하는 팀을 안내하기 위해 임시 mcp-tool-review-board 위원회를 만들었습니다.
새 도구를 추가하려면 MCP 도구 제안 이슈를 생성하고 템플릿 지침을 따르십시오.
도구 구현 위치는 GitLab 리소스와의 상호 작용 방식에 따라 달라집니다:
-
GitLab 리소스와 상호 작용하는 도구는 궁극적으로 MCP 서버에 있어야 하지만, 단기적이거나 긴급한 필요에 따라 Agent Platform에서 구현될 수 있습니다.
-
GitLab 리소스와 상호 작용하지 않는 도구는 Agent Platform에서 구현되어야 합니다.
MCP 서버 기능을 Agent Platform에 통합하기 위해 작업하고 있습니다. 이 이슈를 통해 진행 상황을 추적할 수 있습니다.
모든 엔지니어가 도구 제안 프로세스를 따르고 사용 사례에 대한 명확한 설명을 제공할 것을 강력히 권장합니다.
도구 이름 지정 및 통합 규칙#
도구를 추가하거나 통합할 때는 도구 표면을 작고 예측 가능하게 유지하기 위해 다음 규칙을 따릅니다. 이 규칙은 기능을 잃지 않으면서 도구 수와 토큰 오버헤드를 줄입니다.
동사 클래스: 모든 도구 이름은 verb_object 형태를 사용하며, 동사는 작업의 종류를 나타냅니다:
-
단일 객체에는
get_, 컬렉션에는list_를 사용합니다. -
생성 및 필드 업데이트 변경에는
save_를 사용합니다.id의 존재 여부가 해당 작업이 생성 작업인지 업데이트 작업인지를 결정합니다. 생성 시 필수인 매개변수는 도구 정의에 그렇게 표시해야 합니다. 의도적 예외:save_도구는 필드 변경이 아닌 라이프사이클 액션(예:retry,cancel)을action매개변수 뒤로 묶을 수도 있습니다. 단, 해당 액션이 그 도구가 생성하는 것과 동일한 리소스에 대해 동작하고 별도의 전용 도구를 둘 만큼 중요하지 않은 경우에 한합니다. 상위 식별자가 아니라 리소스 자체의 ID 존재 여부로 분기합니다. 예를 들어,save_pipeline은pipeline_id가 없으면 생성으로 처리하고,pipeline_id가 있고action이 함께 오면 해당 파이프라인에 대한 라이프사이클 전환으로 처리합니다. 이를 도구 설명에 문서화하고 의도적 예외로 기록합니다(아래 참조). -
실제 삭제 작업에는
delete_를 사용합니다. 더 나은 거버넌스 처리를 위해 이를save_에 절대 묶어서는 안 됩니다. -
add_또는 이 패턴에서 벗어난 다른 형태는 커밋, 브랜치, 세션과 같이 일반적인 CRUD 형태를 갖지 않는 객체를 위해 예약되어 있습니다(예:add_commit,add_branch).
리소스 식별: 모든 프로젝트 범위 도구는 동일한 방식으로 대상을 식별합니다. 각 도구는 자체 입력 스키마에 url, project_id, 그리고 리소스의 내부 ID를 선언합니다. 이러한 매개변수를 확인하려면 Mcp::Tools::Concerns::UrlParser와 Mcp::Tools::Concerns::ResourceFinder concern을 포함합니다. 호출자는 다음 중 하나를 제공합니다:
-
url- 전체 경로를 인코딩하는 완전한 GitLab URL(예:https://gitlab.com/group/project/-/merge_requests/1), 또는 -
ID 그룹 -
project_id(숫자 ID 또는gitlab-org%2Fgitlab과 같은 URL 인코딩된 경로)와 리소스의 내부 ID(merge_request_iid,work_item_iid,commit_sha등).
프로젝트 식별자와 내부 ID는 별도의 매개변수로 유지합니다. 이 둘을 하나의 id로 묶지 마십시오. 이들은 서로 다른 값이며(iid/sha는 프로젝트 범위로 한정되어 project_id 없이는 의미가 없습니다), url은 이미 이 둘을 하나로 합쳐주는 단일 값 편의 수단입니다. url과 ID가 모두 제공되면 서로 교차 검증되며, 불일치하면 오류가 발생합니다. 작업 항목 도구는 동일한 그룹에서 group_id 또는 project_id를 허용합니다.
선택적 매개변수: Base::BaseService는 선택적 매개변수에 대한 명시적 null 또는 "" 값을 키가 생략된 것과 동일하게 처리하므로, 스키마의 모든 속성을 채워 보내는 호출자도 선택적 enum 매개변수에 대한 유효성 검사를 통과합니다.
읽기(단일 대 컬렉션):
-
하나의 상위 객체에 범위가 한정된 패싯은 별도의
list_*도구가 아니라include매개변수를 통해 해당 객체의get_도구에 통합됩니다(예:include: ["diffs"]를 사용하는get_merge_request). 유효한 값은diffs,commits,notes,pipelines,discussions입니다. 호출당 하나의 패싯만 지원되더라도include를 열거형 값의 배열로 선언하고maxItems로 제한합니다. 나중에 그 상한을 올리는 것은 추가적인 변경이지만, 매개변수를 문자열에서 배열로 바꾸면 기존 호출자가 깨집니다. 단일 패싯에 범위가 한정된 필터(job_status)를 포함하여 이 패턴을 구현한 예시는get_pipeline(include: ["jobs"]/["downstream_pipelines"]/["bridge_jobs"])을 참조하십시오. -
자체적으로 쿼리할 수 있는 독립적인 컬렉션은 자체
list_도구를 갖습니다(예:list_merge_requests,list_pipelines). -
패싯 범위 페이지네이션은
get_리더에 위치하며 관련include값에만 적용됩니다. 이를 매개변수 설명에 문서화합니다. -
diff가 페이로드의 대부분을 차지하는 diff 포함 읽기에는
detail열거형(none/stats/full_patch)을 추가합니다(예:get_commit의diff패싯과get_merge_request의diffs패싯). 더 적합한 조절 수단이 이미 있는 곳에detail을 나중에 덧붙이지 마십시오. 파일 콘텐츠는 줄 페이지네이션(offset/limit)을, 작업 로그는 바이트 페이지네이션(byte_offset/byte_limit)을 사용하는데, 이러한 API에는 diff 방식의 상세 수준 개념이 없기 때문입니다. -
한 패싯이 다른 패싯의 부분집합인 경우, 새 패싯이나 새 도구보다 필터 매개변수를 사용하는 것이 좋습니다(예: 별도의
failing_jobs패싯 대신job_status: failed필터).
페이지네이션: 도구의 페이지네이션 방식은 서버 전체에 단일 규칙을 강제하기보다, 그 도구가 감싸는 엔드포인트의 방식을 그대로 따릅니다. 방식 간 변환을 하지 마십시오(예: 페이지 번호를 불투명한 커서로 감싸지 마십시오). 오프셋 페이지네이션 위에 만든 인위적인 커서는 커서의 안정성을 얻지 못한 채 메커니즘만 감추고, 엔드포인트가 제공하는 보장에 대해 호출자를 오해하게 만듭니다.
-
REST 기반 도구는
page(1부터 시작, 기본값1)와per_page(기본값20, 최대100)를 사용하는 오프셋 페이지네이션을 사용하며,page,per_page,has_more를 포함하는metadata객체를 반환합니다.list_repository_tree,list_branches,list_commits,list_pipelines,search와 같은 도구에 적용됩니다. -
GraphQL 기반 도구는
first(기본값20, 최대100)와after(불투명 커서)를 사용하는 네이티브 커서 페이지네이션을 사용하며,endCursor와hasNextPage를 포함하는pageInfo객체를 반환합니다.list_work_items,list_merge_requests와 같은 도구에 적용됩니다. -
콘텐츠 리더는 항목 페이지네이션 대신 페이로드에 맞는 범위 윈도우를 사용합니다. 파일 콘텐츠는 줄 페이지네이션(
offset/limit)을, 작업 로그는 바이트 페이지네이션(byte_offset/byte_limit)을 사용합니다. 다음 윈도우를 가져오는 방법을 호출자에게 알려주는system_instruction을 반환합니다. -
get_리더의 패싯 범위 페이지네이션에는 패싯 이름을 접두사로 붙이며(예:get_merge_request의notes_page/notes_per_page,get_commit의comments_page/comments_per_page), 해당 패싯을 지원하는 엔드포인트의 방식을 따릅니다.
확산보다 통합:
- 리소스별 검색 도구를 추가하는 대신, 범위가 한정된 검색 변형들을
scope매개변수를 사용하는 통합search도구로 병합합니다.
의도적 예외를 문서화합니다. 도구가 의도적으로 규칙을 위반하는 경우(일회성 액션 동사, 하나의 리소스에 대한 두 번째 write_ 도구), 실수로 오해되지 않도록 제안서에 의도적인 것으로 기록합니다.
REST API 라우트에서 도구 구현#
이 병합 요청은 API 라우트에서 MCP 도구를 생성하는 프로세스를 정의합니다.
API 라우트 정의에 다음 route_setting을 추가합니다:
route_setting :mcp, tool_name: :get_issue, params: [:id, :issue_iid], resource_name: "issue"
-
get_issue도구를 도구 목록에 추가하고 그 실행을 활성화합니다 -
도구 및 매개변수 설명은 OpenAPI 라우트 정의에서 가져옵니다
-
허용되는 매개변수는
params인수로 필터링됩니다. 예를 들어,id와issue_iid만 노출되고 허용됩니다 -
도구가 호출되면 전달된 매개변수로 라우트 코드가 직접 실행됩니다
-
선택적
resource_name필드는 리소스별 404 오류 메시지를 제공합니다(예: 일반적인"404 Not Found"대신"404 Issue Not Found")."issue"또는"merge request"와 같은 소문자 문자열을 사용합니다. 렌더링된 메시지에서 첫 글자는 대문자로 표시됩니다.
이 병합 요청은 더 많은 예시를 제공합니다.
집계 REST API 도구 구현#
집계 API 도구는 여러 관련 API 도구를 하나의 통합 인터페이스로 결합하여 도구 수를 줄이고 사용자 경험을 개선합니다. 검색 도구는 전역, 그룹, 프로젝트 검색을 하나의 도구로 통합하여 이 패턴을 보여줍니다.
집계 도구를 사용해야 하는 경우:
유사한 목적을 수행하지만 서로 다른 범위(전역, 그룹, 프로젝트)에서 작동하는 여러 API 엔드포인트가 있는 경우 집계 도구를 사용합니다. 이렇게 하면 세 개 대신 하나의 도구를 제시하여 LLM의 인지 부하를 줄입니다.
구현 단계:
Mcp::Tools::Base::AggregatedService를 상속하는 집계 서비스 클래스를 생성합니다:
module Mcp
module Tools
class ExampleAggregatedService < Base::AggregatedService
include Gitlab::Utils::StrongMemoize
extend ::Gitlab::Utils::Override
register_version '0.1.0', {
description: 'My example aggregated tool',
input_schema: {
type: 'object',
properties: {},
required: []
}
}
override :tool_name
def self.tool_name
'new_tool'
end
override :select_tool
def select_tool(args)
tool_name = if args[:group_id]
:example_tool_for_group
elsif args[:project_id]
:example_tool_for_project
end
tools.find { |tool| tool.name.to_sym == tool_name }
end
override :transform_arguments
def transform_arguments(args)
if args[:group_id]
args.merge(id: args[:group_id])
elsif args[:project_id]
args.merge(id: args[:project_id])
else
args
end
end
end
end
end
- 라우트 정의에서 기본 API 도구를 집계기에 등록합니다:
route_setting :mcp, tool_name: :example_tool_for_group, params: [:id], aggregators: [::Mcp::Tools::ExampleAggregatedService]
route_setting :mcp, tool_name: :example_tool_for_project, params: [:id], aggregators: [::Mcp::Tools::ExampleAggregatedService]
Mcp::Tools::Manager는aggregators가 지정된 라우트를 스캔하여 집계 도구를 자동으로 검색하고, 수집된 도구로 집계기 클래스를 인스턴스화합니다.
GraphQL 기반 도구 구현#
GitLab GraphQL API를 사용하는 MCP 도구의 경우 GraphQL 통합 가이드라인을 참조하십시오.
AI 코딩 어시스턴트로 GraphQL 기반 도구를 스캐폴딩하려면 gitlab-mcp-tool-builder 스킬을 사용하십시오. 이 스킬은 이 페이지와 GraphQL 통합 가이드라인의 지침을 요약하고, 흔히 겪는 함정을 추가하며, 도구 클래스, 서비스 클래스, .graphql 작업 파일, 매니저 등록, 스펙까지 차례로 안내합니다. 이 저장소에는 .claude/skills/gitlab-mcp-tool-builder/에 해당 스킬이 포함되어 있으므로 별도로 설치할 것이 없습니다:
-
Claude Code와 GitLab Duo CLI는 세션 시작 시 이 스킬을 검색합니다. 어시스턴트에게 GraphQL MCP 도구를 만들거나 스캐폴딩해 달라고 요청하거나, 스킬을 이름으로 호출하십시오. GitLab Duo CLI가 스킬을 검색하고 실행하는 방법은 에이전트 스킬을 참조하십시오.
-
AGENTS.md규칙을 따르는 어시스턴트는.agents/skills심볼릭 링크를 통해 동일한 스킬을 로드합니다.
가이드라인이 정본입니다. 스킬과 가이드라인이 서로 다르면 가이드라인을 따르고 스킬을 업데이트하십시오.
사용자 지정 도구 구현#
API 노출과 분리되어야 하는 고유한 기능을 가진 도구의 경우, 독립형 클래스를 정의할 수 있습니다(참고로 이 예시를 참조하십시오).
AI 에이전트 아키텍처에서 도구 확산의 위험#
너무 많은 도구를 추가할 때의 주요 문제#
-
성능 저하
-
컨텍스트 팽창: 모든 도구 정의(이름, 설명, JSON 스키마)가 모델의 프롬프트 컨텍스트에 추가되어 입력 토큰 수가 증가합니다
-
지연 시간 증가: 프롬프트가 커질수록 응답 시간이 느려집니다
-
비용 증가: 토큰이 많을수록 요청당 API 비용이 높아집니다
-
정확도 저하: 연구에 따르면 컨텍스트가 많아지고 도구가 많아질수록 에이전트 성능이 저하됩니다
-
궤적 저하: 더 긴 추론 경로가 필요한 에이전트는 도구 확산에 따라 더 빠르게 저하됩니다
-
도구 선택 혼란
-
의사 결정 복잡성: 도구가 많을수록 모델이 올바른 도구를 선택하기가 더 어려워집니다
-
매개변수 설계 문제: LLM이 학습한 공개용 형식(프로젝트 경로, IID) 대신 내부 ID(예: GitLab 전역 ID)를 사용하면 도구 사용 효율성이 떨어집니다
-
유사한 도구 간의 모호성: 모델은 유사한 목적을 가진 도구(예: 로컬 파일 작업 대 원격 파일 작업)를 구별하는 데 어려움을 겪습니다
-
사용자 경험에 미치는 영향
-
도구 체이닝 노이즈: 도구가 많을수록 단일 요청에서 더 많은 도구 호출이 발생하여 노이즈와 산만함을 만듭니다
-
응답 속도 저하: 처리 시간이 증가하면 사용자 만족도에 영향을 미칩니다
-
잘못된 도구 선택: 잘못된 도구 선택은 부정확하거나 관련 없는 응답으로 이어집니다
도구를 추가하기 전에 개발자가 답해야 할 질문#
-
필요성: 이것이 정말로 새로운 기능인가, 아니면 매개변수 조정을 통해 기존 도구로 처리할 수 있는가?
-
통합 가능성: 이 기능을 열거형(enum)이나 매개변수를 사용하여 기존 도구와 병합할 수 있는가?
-
매개변수 설계: 모델의 학습 데이터와 일치하는 공개적으로 인식 가능한 식별자를 사용하고 있는가?
-
평가 전략: 이 도구가 전체 에이전트 성능을 개선하는지 아니면 저하시키는지 어떻게 측정하는가?
-
컨텍스트 관리: 이 도구의 정의가 실제 추론에 사용 가능한 컨텍스트 윈도우에 어떤 영향을 미치는가?
-
도구 라우팅: 이 도구가 메인 에이전트의 도구 세트가 아니라 전문화된 하위 에이전트의 일부가 되어야 하는가?
-
권한 모델: 이 도구가 권한/가격 모델과 어떻게 상호 작용하는가? 복잡성을 만들지는 않는가?
-
의미적 구별성: 이 도구가 도구 세트의 다른 도구와 명확하게 구별되는가?
더 많은 도구가 항상 더 나은 것은 아닙니다. 연구에 따르면 컨텍스트 크기와 도구 수 모두 수확 체감이 있으며 결국 성능 저하로 이어집니다. 도구 세트를 계속 확장하는 대신 도구 통합, 전문화된 하위 에이전트, 또는 동적 도구 라우팅을 고려하십시오.
기존 도구 수정#
MCP 도구는 소비자에게 호환성이 깨지는 변경을 방지하기 위해 시맨틱 버전 관리를 사용합니다. 도구를 수정할 때는 이 병합 요청에서 도입된 버전 관리 시스템을 사용합니다.
버전 관리가 중요한 이유:
LLM과 AI 에이전트는 도구 스키마를 캐시하고 특정 도구 동작을 중심으로 워크플로를 구축합니다. 도구 매개변수, 설명 또는 출력 형식의 변경은 기존 통합을 깨뜨릴 수 있습니다. 버전 관리를 통해 하위 호환성을 유지하면서 안전하게 발전시킬 수 있습니다.
버전 등록 패턴:
집계 API, 사용자 지정, GraphQL 도구의 경우 register_version을 사용하여 버전을 등록합니다:
module Mcp
module Tools
class GetServerVersionService < Base::CustomService
register_version '0.1.0', {
description: 'Get the current version of MCP server.',
input_schema: {
type: 'object',
properties: {},
required: []
}
}
def perform_v0_1_0(_arguments = {})
data = { version: Gitlab::VERSION, revision: Gitlab.revision }
formatted_content = [{ type: 'text', text: data[:version] }]
::Mcp::Tools::Base::Response.success(formatted_content, data)
end
override :perform_default
def perform_default(arguments = {})
perform_v0_1_0(arguments)
end
end
end
end
새 버전 추가:
도구의 동작을 수정해야 하는 경우:
- 업데이트된 메타데이터로 새 버전을 등록합니다:
register_version '0.2.0', {
description: 'Get version with additional metadata.',
input_schema: {
type: 'object',
properties: {
include_metadata: {
type: 'boolean',
description: 'Include additional metadata'
}
},
required: []
}
}
- 버전별 메서드를 구현합니다:
def perform_v0_2_0(arguments = {})
data = {
version: Gitlab::VERSION,
revision: Gitlab.revision
}
if arguments[:include_metadata]
data[:metadata] = { build_date: Time.current }
end
formatted_content = [{ type: 'text', text: data[:version] }]
::Mcp::Tools::Base::Response.success(formatted_content, data)
end
- 최신 버전을 사용하도록
perform_default를 업데이트합니다:
override :perform_default
def perform_default(arguments = {})
perform_v0_2_0(arguments)
end
API 도구의 경우:
API 도구는 자동으로 버전 0.1.0으로 기본 설정됩니다. 필요한 경우 라우트 설정에서 버전을 지정할 수 있습니다:
route_setting :mcp, tool_name: :get_issue,
params: [:id, :issue_iid],
version: '1.0.0'
라우트에서 가져온 API 도구는 도구당 단일 버전을 사용합니다. 여러 버전이 필요한 도구의 경우 대신 사용자 지정 도구로 구현하는 것을 고려하십시오.
버전 지원 정책:
프레임워크는 버전이 지정되지 않은 경우 자동으로 최신 버전을 사용합니다. 소비자는 도구 호출 중에 특정 버전을 요청할 수 있습니다. 버전을 사용 중단할 때는 다중 버전 호환성 가이드라인을 따르십시오.
도구 이름 변경#
도구 이름을 변경하려면 하위 호환성을 유지하기 위해 도구 별칭을 사용해야 합니다. 연결된 클라이언트는 도구 이름을 캐시하며 도구 이름이 변경되어도 자동으로 새로 고치지 않습니다. 이 병합 요청에서 도입된 별칭 시스템을 사용하면 기존 통합을 깨뜨리지 않고 원활하게 이름을 변경할 수 있습니다.
별칭이 필요한 이유:
MCP 클라이언트는 tools/list에서 도구 목록을 캐시하며 도구가 변경되어도 자동으로 다시 가져오지 않습니다. 도구 이름을 변경하면 클라이언트가 존재하지 않는 도구 이름을 호출하게 되어 오류가 발생하거나 무한정 멈추게 됩니다. MCP 사양은 클라이언트에 변경 사항을 알리기 위한 notifications/tools/list_changed를 지원하지만, GitLab MCP 서버는 이를 구현하지 않습니다(이 이슈에서 추적됨).
구현 단계:
- 도구 클래스에서
tool_aliases를 재정의하여 이전 이름을 포함합니다:
module Mcp
module Tools
class RenamedService < Base::AggregatedService
override :tool_name
def self.tool_name
'new_name'
end
override :tool_aliases
def self.tool_aliases
['old_name']
end
end
end
end
route_setting :mcp를 통해 정의된 API 도구의 경우, 클래스 메서드를 재정의하는 대신 tool_aliases: 설정으로 별칭을 선언합니다. ApiTool은 모든 라우트가 공유하는 단일 클래스이므로 별칭은 라우트별로 선언해야 합니다:
route_setting :mcp, tool_name: :new_name,
params: [:id],
tool_aliases: [:old_name]
-
모든 참조를 새 도구 이름을 사용하도록 업데이트합니다:
tool_name:이 포함된 라우트 설정 -
테스트 파일
-
문서
-
하드코딩된 모든 도구 이름 참조
-
Mcp::Tools::Manager는get_tool호출 중에 별칭을 자동으로 확인하므로, 이전 이름을 사용하는 클라이언트는 계속 작동합니다.
중요 참고 사항:
-
list_tools는 별칭이 아닌 정식 도구 이름만 반환합니다 -
별칭은 모든 도구 유형에 대해 작동합니다. 사용자 지정, GraphQL, 집계 도구는 도구 클래스에서
self.tool_aliases를 재정의합니다. API 도구는tool_aliases:라우트 설정을 통해 별칭을 선언합니다 -
aggregators:도 함께 설정된 라우트에서는tool_aliases:가 아무런 효과가 없습니다. 집계 도구의 별칭은 집계기 클래스의self.tool_aliases에서 가져옵니다 -
별칭 확인은 모든 도구 레지스트리를 확인하는
Manager#resolve_alias에서 발생합니다 -
클라이언트가 업데이트할 충분한 시간이 지난 후 향후 릴리스에서 별칭을 제거할 계획을 세웁니다
사용 중단 타임라인:
릴리스 M: 별칭 추가 및 도구 이름 변경 릴리스 M+1: 별칭 제거(클라이언트가 도구 목록을 새로 고칠 시간이 지난 후)
이 접근 방식은 도구 이름 변경 중에 연결된 클라이언트의 다운타임을 제로로 보장합니다.
집계 도구에서 액션 분리#
여러 작업을 하나의 매개변수(예: action 또는 불리언 플래그) 뒤로 묶는 집계 도구는 list/save 분리 규칙에 따라 컬렉션 읽기 액션을 위한 전용 list_ 도구를 별도로 가질 수 있습니다. 이름 변경과 달리 호출 형태가 바뀌므로(호출자가 더 이상 선택자 매개변수를 전달하지 않음) 도구 별칭으로는 동작을 보존할 수 없습니다. 이전 액션을 사용하던 호출자는 명시적으로 새 도구로 마이그레이션해야 합니다.
이 변경 사항은 MCP 서버 도구에서 이전 도구의 블록에 [Removed] 항목으로 문서화하고, 어떤 액션이 어느 도구로 이동했는지 명시하며, 새 도구에 대한 일반적인 [Introduced] 항목도 함께 기록합니다. 예시는 해당 페이지의 list_pipelines와 manage_pipeline 항목을 참조하십시오.