Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

mcp_redact_secrets() throws "subscript out of bounds" on schemas containing a null field

オープン 初心者向け
#135 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
88/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
r
領域
api

調査の方向性

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

  • mcptools 1.0.3.9000 (installed from GitHub)
  • Confirmed the same unpatched loop is present in R/client.R on the main branch 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 を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

posit-dev/mcptools のほかの issue

posit-dev/mcptools の issue をすべて見る

似ている issue

R の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。