mcp_redact_secrets() throws "subscript out of bounds" on schemas containing a null field
まだ誰も着手していません。
評価
調査の方向性
R/client.R の mcp_redact_secrets() から開始し、提供されているスキーマ再現を実行して subscript エラーを確認します。null 値のスキーマフィールドを含むレスポンスが失敗しなくなり、秘密のフィールドが引き続きクライアントのデバッグロギング前に redact されることを検証します。
索引モデルが issue の本文から書いたものです。
説明
Bug
mcp_tools() fails with subscript out of bounds while loading tools from a remote MCP server, inside add_mcp_server() / mcp_redact_secrets().
Root cause
mcp_redact_secrets() (R/client.R) is called unconditionally on every MCP server response, purely to redact secrets before writing to the client debug log (MCPTOOLS_CLIENT_LOG). It iterates for (i in seq_along(x)) while mutating x in place. When a field's JSON value is null (parsed by jsonlite::parse_json() as R NULL), the assignment x[[i]] <- NULL deletes that list element and shrinks x, so later iterations of the same loop index past the new, shorter length.
Trigger
Any MCP server that returns a tool schema containing a null-valued field anywhere in the response will hit this. Concretely, I hit it against the Google Analytics MCP server: its run_report, run_realtime_report, and run_conversions_report tools each expose a dimension_filter / metric_filter parameter whose JSON Schema legitimately includes "default": null - a completely valid, spec-compliant schema.
Repro
schema <- list(
additionalProperties = TRUE,
default = NULL,
title = "Dimension Filter",
type = "object"
)
# Reproduces the mutate-while-iterating bug directly:
mcptools:::mcp_redact_secrets(list(params = list(dimension_filter = schema)))
# Error in x[[i]] : subscript out of bounds
More generally, calling mcp_tools(config = ...) against any remote server whose tools/list response includes such a schema fails the same way.
Suggested fix
Build the redacted list into a fresh vector("list", length(x)) instead of mutating x in place, so a NULL assignment can't change the list's length mid-loop:
mcp_redact_secrets <- function(x) {
if (!is.list(x)) return(x)
nms <- names(x)
if (is.null(nms)) {
return(lapply(x, mcp_redact_secrets))
}
secret_fields <- mcp_secret_fields()
out <- vector("list", length(x))
for (i in seq_along(x)) {
name <- tolower(nms[[i]])
if (nzchar(name) && name %in% secret_fields) {
out[[i]] <- "<redacted>"
} else {
out[[i]] <- mcp_redact_secrets(x[[i]])
}
}
names(out) <- nms
out
}
Environment
mcptools1.0.3.9000 (installed from GitHub)- Confirmed the same unpatched loop is present in
R/client.Ron themainbranch as of 2026-09-29, so this isn't fixed in a newer release yet. - R 4.4.3, Windows
Workaround in use
We're currently monkey-patching mcp_redact_secrets in-process at app startup (via assignInNamespace-style unlockBinding()/assign()/lockBinding()) with the fixed implementation above, as a stopgap until this is fixed upstream.
- 主要言語
- R
- スター
- 196
- フォーク
- 21
- 平均マージ
- 10日 21時間
- マージ済み PR(30日)
- 1
環境構築
このプロジェクトの環境構築ファイルはまだ確認していません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
posit-dev/mcptools のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
posit-dev/mcptools の issue をすべて見る
似ている issue
-
Elevation orderオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
inbo/erl-butterflies-2025#19 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
The-Strategy-Unit/nhp_output_reports#116 · コメント 1 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 92/100
Open-Systems-Pharmacology/OSPSuite.ParameterIdentification#322 ·