
RPR로 MCP Tool Call을 통제하기 —— 성공 응답만으로 외부 변경을 완료하지 않는다
요약
AI 에이전트의 외부 조작을 안전하게 관리하기 위한 Python Runtime인 RPR(Responsibility Pathway Runtime)의 MCP(Model Context Protocol) 대응 방안을 다룹니다. MCP Tool Call 과정에서 발생할 수 있는 결과 불명 상태를 처리하고, 권한 및 실행 이력을 통제하는 메커니즘을 설명합니다.
핵심 포인트
- RPR은 AI 에이전트의 외부 조작을 책임 경로(Responsibility Pathway)로 통과시키는 Runtime임
- MCP Tool Call 시 결과 불명 상태를 처리하여 외부 변경의 안정성을 확보함
- Human Gate, 실행 이력, 복구, 재개 등 에이전트의 안전한 실행을 위한 메커니즘 포함
- RPR 상태 확인을 위한 read-only MCP Server 기능 제공
MCP Tool Call에도 「결과 불명」은 있다
Responsibility Pathway Runtime (RPR)은 AI 에이전트나 자동 처리의 외부 조작을 권한, Human Gate, 실행 이력, 증거, 결과 불명, 대조, 복구, 재개까지 포함하는 책임 경로(Responsibility Pathway)로 통과시키는 Python Runtime입니다.
지금까지의 기사에서는 RPR을 제작하여 PyPI에 공개하게 된 경위와, Runtime 내부에서 무엇을 하고 있는지에 대해 작성했습니다.
이번에는 RPR 0.1.0a4 시점의 MCP 대응에 대해 다룹니다.
전반부, 후반부, 그리고 그 이면에서 MCP도 진행하고 있었다
첫 번째 기사에서는 RPR이라는 Runtime을 처음 만들고, GitHub와 PyPI에 배포하는 과정까지를 작성했습니다.
다음 기사에서는 Human Gate, write_status_unknown, readback, repair, resume 등 Runtime 내부에서 무엇을 보호하려고 하는지를 작성했습니다.
표로 보면, 우선 본체를 만들고, 다음에 메커니즘을 설명한 뒤, 그 후에 MCP 대응으로 나아간 것처럼 보일 수도 있습니다.
실제로는 MCP 대응도 이면에서 조금씩 진행하고 있었습니다.
외부로 향하는 MCP Tool Call을 책임 경로로 통과시키는 처리, Local subprocess와 stdio Transport, Server와 Tool의 Binding, 결과 불명의 처리, Restart 후의 지속.
나아가 RPR 자신의 상태를 읽기 위한 read-only MCP Server도 만들고 있었습니다.
다만, 전반부 기사와 후반부 기사를 작성했을 시점에는, 거기까지를 Public Package의 설명으로서 내놓을 수 있는 상태가 아니었습니다.
만들고 있는 것과, 공개 Package로서 설명해도 되는 것은 별개입니다.
그래서 MCP 관련 기사만 조금 늦게 등장하게 되었습니다.
전반부 기사
RPR을 만들어 공개했다
↓
...
순조로워 보이는 마지막 두 단계에 작은 사건이 있습니다.
0.1.0a3를 배포했더니, 설명문이 오래되었다
RPR 0.1.0a3에서는 Local stdio의 read-only MCP inspection server와 rpr-mcp 커맨드를 Package에 포함했습니다.
GitHub Release도 성공했고, PyPI로의 Publish Workflow도 성공했습니다.
"좋아, 나왔다"라고 생각하며 PyPI 페이지를 확인해보니, 설명문에는 다음과 같은 내용이 남아 있었습니다.
Public Alpha — 0.1.0a2
Published PyPI 0.1.0a2
Unreleased read-only server preview
Package 본체는 0.1.0a3입니다.
rpr-mcp도 실제로 포함되어 있습니다.
그런데 설명문만은 "아직 미공개 상태입니다"라고 말하고 있었습니다.
……공개한 본인이, 공개 페이지에서 미공개라고 말하고 있는 상태입니다 (웃음).
원인은 PyPI의 Long Description에 사용하는 README가 옛날 상태 그대로 남아 있었기 때문이었습니다.
twine check는 통과했습니다. Package의 Build도 Install도 CLI도 통과했습니다.
하지만 "설명문이 현재의 Version과 내용이 일치하는가"는 확인하지 않았습니다.
구문으로서 올바른 것과, 적혀 있는 내용이 올바른 것은 별개입니다.
이것은 RPR이 외부 작용에 대해 말하고 있는 것과 묘하게 닮아 있습니다.
Publish Workflow가 성공했다
≠
공개 페이지의 설명이 올바르다는 것을 확인했다
자신의 Release를 통해, 자신의 설계 사상을 실지 확인하게 되었습니다.
0.1.0a4는 Correction Release가 되었다
PyPI에서는 이미 공개한 동일한 Version의 Distribution을 교체할 수 없습니다.
따라서 0.1.0a3를 덮어쓰는 대신, 설명과 Release Metadata를 수정한 0.1.0a4를 Correction Release로서 공개했습니다.
수정한 내용은 주로 다음과 같습니다.
- Public Alpha의 Version 표기
- PyPI의 Install 예시
rpr-mcp를 공개된 기능으로 설명하는 부분- stable MCP Protocol
2025-11-25기재 - Article 50 profile의 경계
- GitHub Release와 PyPI로의 Link
- Browser demo가 참조하는 wheel Version
또한, 동일한 실수를 반복하지 않기 위해 빌드(Build)한 wheel 내부의 METADATA를 직접 읽는 검사를 Publish Workflow에 추가했습니다.
현재는 다음 내용이 일치하지 않으면 PyPI Publish로 진행되지 않습니다.
- Package Metadata의 Version
- README 내의 Public Alpha Version
pip install예시의 Version - 공개된 read-only MCP Server의 설명- stable Protocol:
2025-11-25 - 오래된
0.1.0a2나unreleased preview표현이 남아있지 않을 것
- stable Protocol:
즉, 이번 기사에서 다루는 MCP 대응은 구현뿐만 아니라, 공개 설명을 잘못하여 Correction Release를 내보낸 과정까지 포함하는 개발 기록입니다.
멋지게 "MCP를 대응했습니다"로 끝내지 못한 것은 조금 아쉽지만, 실패한 Release를 통해 검사가 하나 늘었습니다.
이런 부분 또한 Public Alpha다운 기록이라고 생각합니다.
자, 이제부터가 MCP Tool Call 그 자체에 대한 이야기입니다.
MCP Server로 tools/call을 보내고, 성공 응답이 돌아왔습니다.
그렇다면, 그 Tool이 수행하려 했던 외부 변경도 성공했을까요?
반드시 그렇다고 할 수는 없습니다.
MCP tools/call이 성공했다
≠
외부의 변경이 성립되었음을 확인했다
반대로, 호출 중에 통신이 끊긴 경우도 단순히 실패라고 말할 수 없습니다. MCP Server 측에서는 이미 Tool이 실행되고 있을지도 모르기 때문입니다.
음, API와 마찬가지로 곤란하네요 (웃음)
RPR에는 두 가지 MCP 경계가 있다
RPR 0.1.0a4에는 MCP에 관한 두 가지 서로 다른 경로가 있습니다.
- Host Application에서 MCP Server로 보내는 외향적(Outbound) Tool Call을 책임 경로(Responsibility Path) 내에서 통제하는 경로
- RPR의 저장 상태를 신뢰할 수 있는 Local Client로부터 read-only로 관측하는
rpr-mcpServer
이 두 가지는 역할과 권한이 다릅니다.
외향적 Tool Call의 통제
Host Application / Agent
↓
...
RPR 상태의 read-only 관측
Trusted Local MCP Client
↓ stdio
...
전자는 외부 작용을 동반하는 Tool Call의 책임 경로입니다. 후자는 RPR 자신의 상태, Pathway, Evidence, 미결 Record를 읽기 위한 관측면입니다.
rpr-mcp에는 승인, 실행, 상태 전이, 대조, 복구, 재개를 수행하는 Tool은 없습니다.
Server와 Tool을 실행 전에 결합하기
"MCP Tool을 호출한다"고 해도, Tool 이름만 보고 실행하는 것으로는 충분하지 않습니다.
이름이 같더라도 연결 대상인 Server나 Schema가 바뀌면 의미와 영향 범위가 달라질 가능성이 있습니다.
RPR의 외향적 MCP 경로에서는 실행 전에 다음 정보를 바인딩(binding)합니다.
- Protocol Version
- Server Identity
- Server Capability
- Tool Name
- Tool Schema
Capability와 Tool Schema는 Digest로서 유지하며, Admission 시에 상정했던 Server·Tool과 실행 시의 대상이 어긋나지 않았는지 확인합니다.
이것은 "해당 MCP Server가 안전하다고 RPR이 인증한다"는 의미는 아닙니다.
Server의 선정, 인증, Credential, 권한, Network, Filesystem, Tool Permission은 통합 측의 책임입니다.
RPR이 수행하는 것은 통합 측이 허가한 대상과 실제로 호출하려는 대상을 책임 경로 내에서 결합하는 것입니다.
전송 전의 실패와, 전송 후일지도 모르는 실패를 구분하기
Tool Call이 실패했을 때 가장 중요한 것은 "외부 작용이 시작되었을 가능성이 있는가"입니다.
RPR은 적어도 다음과 같이 취급을 구분합니다.
| 관측된 내용 | RPR에서의 취급 |
|---|---|
| Call이 전송되기 전에 거부되었음을 확인할 수 있음 | dispatch_state: not_sent를 동반하는 실패 |
| 전송되었을 가능성이 있으나, 확실한 결과가 없음 | write_status_unknown |
| Dispatch 후일 수도 있는 Transport Error | write_status_unknown |
| MCP Server가 명시적인 Tool Error를 반환함 | Tool Result를 보유한 실패 |
| ... |
중요한 것은, Timeout이나 Connection Error를 본 것만으로 "전송되지 않았다"라고 단정 짓지 않는 것입니다.
전송되었을지도 모른다면, 미결 상태(unresolved)로 멈춥니다.
Client Process가 재시작되었다고 해서, 동일한 tools/call을 묵묵히 재전송하지 않습니다.
이 경계는 이중 등록, 이중 전송, 이중 업데이트를 피하기 위해 필요합니다.
MCP의 성공 응답은 외부 작용의 증거가 아니다
MCP Server로부터 정상적인 JSON-RPC 응답이 반환된 경우, 그것은 Server가 결과를 반환했다는 증거입니다.
하지만, Tool이 변경하려고 했던 외부 상태가 기대한 대로 성립되었다는 증거와는 반드시 일치하지 않습니다.
예를 들어, MCP Tool이 다음과 같은 조작을 수행하는 경우입니다.
- 파일을 업데이트한다
- Issue나 Pull Request를 생성한다
- 메시지를 전송한다
- 업무 데이터를 다시 쓴다
- 외부 API에 등록한다
RPR에서는 중요한 변경을 수반하는 Tool에 대해, 독립적이고 권위 있는 readback을 요구할 수 있습니다.
tools/call의 응답
↓
외부 상태를 별도 경로로 다시 읽음 (readback)
...
Tool 스스로가 반환한 "성공했습니다"라는 문자열만으로 완료 처리하지 않는 것입니다.
"자기가 성공이라고 말했으니 오케이!"는 증거로서 다소 편파적입니다 (웃음).
Restart는 Retry가 아니다
MCP Client나 Host Application이 재시작되었을 때, 미결 Call을 자동으로 재전송해서는 안 됩니다.
외부 측에서 첫 번째 Call이 성립되었을 경우, 이중 작용이 될 가능성이 있습니다.
RPR은 Operation, Execution Attempt, Binding, Evidence, 미결 State를 저장하고, Restart 후에 다시 읽어옵니다.
그 후에 외부 상태의 readback, repair, reconciliation, 인간에게의 반환 단계로 진행합니다.
write_status_unknown을 저장
↓
Process Restart
...
프로세스를 재시작할 수 있다는 것과, 조작을 안전하게 재실행할 수 있다는 것은 별개의 문제입니다.
공개된 read-only MCP inspection server
RPR 0.1.0a4에는 Local stdio에서 동작하는 rpr-mcp가 포함되어 있습니다.
python -m pip install responsibility-pathway-runtime==0.1.0a4
rpr-mcp --database ./rpr.sqlite3
대상 Protocol은 stable 2025-11-25입니다. 다른 Version 요구는 fail-closed 방식으로 거부합니다.
공개된 Tool은 다음 다섯 가지입니다.
rpr.get_status
rpr.list_pathways
rpr.get_pathway
...
Database는 read-only로 열리며, Tool Surface에도 변경 조작은 없습니다.
단, read-only라고 해서 무조건 안전하다는 뜻은 아닙니다. Pathway 정의나 Evidence에는 운용상의 정보가 포함될 수 있으므로, OS상에서 이미 Database를 읽을 권한을 가진 신뢰할 수 있는 Local Client만을 전제로 합니다.
rpr-mcp는 인증 기반(authentication infrastructure), 테넌트 분리(Tenant isolation), Secret 관리, Redaction Gateway가 아닙니다.
현재의 검증 범위
RPR Public Alpha에서는 확인 환경 내에서 다음을 검증하고 있습니다.
외향적(Outbound) MCP Tool Call
- 로컬 (Local) MCP 서브프로세스 (subprocess)
- stdio 전송 (Transport)
- JSON-RPC 세션 (Session) 및 프레이밍 (Framing)
- 프로토콜 버전 (Protocol Version), 서버 식별 (Server Identity), 기능 (Capability), 도구 스키마 (Tool Schema)의 바인딩 (Binding)
tools/call
이전의 승인 확인 (Admission Check) - 결함 주입 (Fault Injection)
- 결과 불명 상태의 유지
- 재시작 (Restart) 후의 지속
- 중복 디스패치 (Duplicate Dispatch) 방지
rpr-mcp
읽기 전용 (read-only) - 안정적인 (stable) 프로토콜 2025-11-25의 초기화 (initialize) - 도구 (Tool) 목록과 5개의 관측 도구
- 잘못된 요청 (malformed request) 및 프로토콜 남용 (Protocol abuse)에 대한 페일 클로즈 (fail-closed) 응답
- 알림 (Notification)에 대한 불필요한 응답 (Response) 억제
- 데이터베이스 바이트 불변성 (Database byte invariance)
- 경로 누락 (missing pathway), 데이터베이스 누락 (missing database), 비-RPR 데이터베이스 (non-RPR database) 거부
rpr-mcp --help를 포함한 배포 패키지 (Package) 검증
한편, 다음으로는 환경별 평가가 필요합니다.
- 원격 (Remote) MCP 전송 (Transport)
- 호스팅된 (Hosted) MCP 서비스 (Service)
- 기업 프록시 (Proxy), TLS, 식별 (Identity), 자격 증명 (Credential) 구성
- 독립적인 MCP 클라이언트 (Client) 구현과의 상호 운용성
- 서비스 고유의 도구 의미론 (Tool Semantics)
- 권위 있는 리드백 소스 (readback source)
- Windows, macOS, 컨테이너 (Container), 별도 Python 환경
- 운영 환경 (Production)에서의 우회 (Bypass) 방지, 모니터링, 인시던트 소유자 (Incident Owner)
로컬 서브프로세스 (Local subprocess)에서 작동했다는 것이 모든 MCP 서버 (Server)나 원격 서비스 (Remote Service)와의 호환성을 보장하지는 않습니다.
통합 측에 남는 책임
RPR은 MCP 서버의 신뢰성이나 업무 판단을 자동으로 결정하는 제품이 아닙니다.
통합 측은 최소한 다음을 설계해야 합니다.
- 어떤 MCP 서버에 접속할 것인가
- 서버를 어떻게 인증할 것인가
- 자격 증명 (Credential)과 환경 변수를 어떻게 보호할 것인가
- 프로세스 (Process), 네트워크 (Network), 파일 시스템 (Filesystem), 도구 권한 (Tool Permission)을 어떻게 제한할 것인가
- 어떤 도구에 휴먼 게이트 (Human Gate)를 요구할 것인가
- 외부 작용을 무엇으로 리드백 (readback)할 것인가
- 결과 불명 상태를 누가 대조 및 복구 (reconciliation/repair)할 것인가
- RPR을 통하지 않는 우회 경로를 어떻게 방지할 것인가
rpr-mcp에서 참조 가능한 데이터베이스와 클라이언트를 어떻게 제한할 것인가
RPR은 그 책임을 대신 떠맡는 것이 아니라, 실행 도중에 목적을 잃지 않도록 돕는 런타임 (Runtime)입니다.
다음에 필요한 것은 '쓸 수 있는 MCP 서버'가 아니라 경계의 검증
RPR 자체의 읽기 전용 (read-only) MCP 서버는 공개할 수 있었습니다.
다음에 변이 도구 (mutating Tool)를 추가할지 여부는 단순히 인터페이스 (Interface)를 늘리는 문제와는 다릅니다.
승인, 실행, 대조, 복구, 재개를 MCP 도구로 공개하려면 최소한 다음과 같은 경계가 필요합니다.
- 누가 어떤 도구를 호출할 수 있는가
- 권한 (Authority)과 휴먼 게이트 (Human Gate)를 어떻게 증명할 것인가
- 도구 호출 (Tool Call)과 실행 시도 (Execution Attempt)를 어떻게 고유하게 연결할 것인가
- 결과 불명 상태를 어떻게 유지할 것인가
- 원격 전송 (Remote Transport)이나 자격 증명 (Credential)을 어떻게 분리할 것인가
- 우회 (Bypass)와 재전송을 어떻게 방지할 것인가
그 증거가 갖춰지기 전까지 rpr-mcp는 관측 전용으로 유지됩니다.
요약
MCP 도구 호출 (Tool Call)에서도 성공 응답과 외부 작용의 성립은 동일하지 않습니다.
통신이 끊겼을 때, 전송되지 않았다고도, 성공했다고도 단정할 수 없는 경우가 있습니다.
RPR은 외향적 (Outbound) MCP 도구 호출을 액터 (Actor), 권한 (Authority), 휴먼 게이트 (Human Gate), 실행 시도 (Execution Attempt), 바인딩 (Binding), 리드백 (Readback), 복구 (Repair), 대조 (Reconciliation)로 연결합니다.
동시에 RPR 0.1.0a4는 저장된 경로 (Pathway)와 증거 (Evidence)를 읽기 위한 로컬 stdio 읽기 전용 (read-only) MCP 검사 서버 (inspection server)도 제공합니다.
모르는 결과를 아는 것으로 치부하지 않는다.
재시작을 무조건적인 재전송으로 만들지 않는다.
관측용 인터페이스를 변경 권한으로 함부로 확장하지 않는다.
MCP의 편리함을 유지하면서, 외부 작용의 책임 경로를 끊지 않는다.
그것이 현재 RPR에서의 MCP 대응입니다.
Discussion

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