Fix: handle string-encoded number parameters from MCP clients #93

Merged
dmikushin merged 0 commits from refs/pull/93/head into main 2026-03-20 06:45:59 +00:00
dmikushin commented 2026-03-19 18:07:17 +00:00 (Migrated from codeberg.org)

Problem

MCP clients (notably Claude Code) may serialize number-typed tool parameters as JSON strings instead of JSON numbers. For example, a parameter declared as mcp.WithNumber("index", ...) arrives as "17" (string) rather than 17 (float64) in req.GetArguments().

The current code extracts all number parameters via bare Go type assertions:

index, _ := req.GetArguments()["index"].(float64)

When the value is a string, this assertion silently returns 0 (the _ discards the ok=false). This causes cryptic errors like:

list issue comments err: issue does not exist [id: 0, repo_id: 350, index: 0]

...even though the caller passed index: 17. The bug affects all 62 number parameter extractions across 9 operation files — every tool that accepts index, page, limit, comment_id, run_id, etc.

Fix

  1. New helper to.Float64() (pkg/to/number.go) that handles multiple incoming types:

    • float64 — standard JSON number (pass-through)
    • int, int64 — alternative integer representations
    • string — string-encoded number (parsed via strconv.ParseFloat)
    • Returns a descriptive error for nil or unexpected types
  2. Replaced all 62 bare .(float64) assertions with to.Float64() calls across:

    • operation/issue/issue.go (17 occurrences)
    • operation/pull/pull.go (16 occurrences)
    • operation/pull/review.go (9 occurrences)
    • operation/user/notification.go (6 occurrences)
    • operation/actions/workflow_runs.go (4 occurrences)
    • operation/repo/repo.go, branch.go, commit.go (6 occurrences)
    • operation/search/search.go (2 occurrences)
  3. Adjusted ok-based default patterns (e.g., page/limit defaults) to use zero-value checks (if page == 0 { page = 1 }) since to.Float64 returns (float64, error) instead of (float64, bool).

How to reproduce

Using Claude Code (or any MCP client that serializes numbers as strings):

# Before fix — fails silently:
list_issue_comments(owner="myorg", repo="myrepo", index=42)
→ "issue does not exist [id: 0, repo_id: 350, index: 0]"

# After fix — works:
→ [list of comments for issue #42]

Testing

  • go build ./... passes with zero errors
  • Verified end-to-end with Claude Code calling list_issue_comments, get_pull_request_by_index, and merge_pull_request — all number parameters now work correctly
## Problem MCP clients (notably Claude Code) may serialize `number`-typed tool parameters as JSON strings instead of JSON numbers. For example, a parameter declared as `mcp.WithNumber("index", ...)` arrives as `"17"` (string) rather than `17` (float64) in `req.GetArguments()`. The current code extracts all number parameters via bare Go type assertions: ```go index, _ := req.GetArguments()["index"].(float64) ``` When the value is a string, this assertion **silently returns 0** (the `_` discards the `ok=false`). This causes cryptic errors like: ``` list issue comments err: issue does not exist [id: 0, repo_id: 350, index: 0] ``` ...even though the caller passed `index: 17`. The bug affects **all 62** number parameter extractions across 9 operation files — every tool that accepts `index`, `page`, `limit`, `comment_id`, `run_id`, etc. ## Fix 1. **New helper `to.Float64()`** (`pkg/to/number.go`) that handles multiple incoming types: - `float64` — standard JSON number (pass-through) - `int`, `int64` — alternative integer representations - `string` — string-encoded number (parsed via `strconv.ParseFloat`) - Returns a descriptive error for `nil` or unexpected types 2. **Replaced all 62 bare `.(float64)` assertions** with `to.Float64()` calls across: - `operation/issue/issue.go` (17 occurrences) - `operation/pull/pull.go` (16 occurrences) - `operation/pull/review.go` (9 occurrences) - `operation/user/notification.go` (6 occurrences) - `operation/actions/workflow_runs.go` (4 occurrences) - `operation/repo/repo.go`, `branch.go`, `commit.go` (6 occurrences) - `operation/search/search.go` (2 occurrences) 3. **Adjusted `ok`-based default patterns** (e.g., `page`/`limit` defaults) to use zero-value checks (`if page == 0 { page = 1 }`) since `to.Float64` returns `(float64, error)` instead of `(float64, bool)`. ## How to reproduce Using Claude Code (or any MCP client that serializes numbers as strings): ``` # Before fix — fails silently: list_issue_comments(owner="myorg", repo="myrepo", index=42) → "issue does not exist [id: 0, repo_id: 350, index: 0]" # After fix — works: → [list of comments for issue #42] ``` ## Testing - `go build ./...` passes with zero errors - Verified end-to-end with Claude Code calling `list_issue_comments`, `get_pull_request_by_index`, and `merge_pull_request` — all number parameters now work correctly
goern commented 2026-03-20 06:46:20 +00:00 (Migrated from codeberg.org)

Hey @dmikushin thanks for fixing this!!

Hey @dmikushin thanks for fixing this!!
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
agentic-forges/forgejo-mcp!93
No description provided.