ping emits result:[] not result:{} (json.lua empty-table gotcha) #19
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
pingcurrently emits{"result":[],"id":1,"jsonrpc":"2.0"}—resultis[](empty array) but the MCP spec sayspingreturnsresult: {}(empty object). Spec-strict clients may reject the response.Root cause
jsonrpc_result(id, {})atlmcp.lua:97passes an empty Lua table tojson.encode.json.lua'sis_arrayreturns true for any table wherenext(t) == niland emits[]. This is the project-memorialised gotcha (project_json_empty_table_gotcha.md) — present since v0.1.0, latent on HTTP transport, surfaced during the stdio work (issue #15) where every byte goes through a single pipe.Fix
Two options at
lmcp.lua:97:resultentirely (cleanest): JSON-RPC 2.0 allows the absence ofresultonly for errors, so this is technically wrong. NOT recommended.json.empty_object = setmetatable({}, {__jsontype = "object"})(or similar) injson.lua; teachjson.encodeto honour the metatable; usejson.empty_objectat the call site. Cleanest, also fixes any future case where an empty object must be emitted.{jsonrpc:2.0,id: .. id .. ,result:{}}from a smallping-specific helper. Surgical but loses uniformity.Recommendation
Option 2 — add
json.empty_objectsentinel. Future-proofs any field that must serialise as{}. The pattern would also benefitnotifications/*.paramsif we ever need to emit it (currently omitted per the same memory entry).Scope
json.lua: addempty_objectsentinel + encoder branch (5-10 lines).lmcp.lua:97: changejsonrpc_result(id, {})→jsonrpc_result(id, json.empty_object).jsonrpc_result(id, {})andparams = {}— none currently active besides ping.Priority
Low — has been broken since v0.1.0 with no client complaints. Worth fixing as defensive correctness, especially before issue #16 (Streamable HTTP) lands which may attract spec-strict clients. Surfaced during issue #15 Phase 7 verification.
Implemented in this session — added
json.empty_objectsentinel (Option 2 from the issue body) and switchedpingto use it. Verified live over stdio:pingnow emits{"jsonrpc":"2.0","result":{},"id":1}(wasresult:[]).Other empty-array emissions (
resources/list,tools/list,prompts/listetc.) correctly stay as[]per spec — those are arrays, not objects.