@@ -156,6 +156,13 @@ func (jcu *JSONConfigUpdater) Remove(serverName string) error {
156
156
// This is necessary because the MCP client config file is a JSON object,
157
157
// and we need to ensure that the path exists before we can add a new key to it.
158
158
func ensurePathExists (content []byte , path string ) []byte {
159
+ // Special case: if path is root ("/"), just return everything (formatted)
160
+ if path == "/" {
161
+ v , _ := hujson .Parse (content )
162
+ formatted , _ := hujson .Format (v .Pack ())
163
+ return formatted
164
+ }
165
+
159
166
segments := strings .Split (path , "/" )
160
167
161
168
// Navigate through the JSON structure
@@ -172,12 +179,18 @@ func ensurePathExists(content []byte, path string) []byte {
172
179
// The "/" is added to the path for the patch operation because the path
173
180
// is a JSON pointer, and JSON pointers are prefixed with "/".
174
181
// The "." is added to the path for the retrieval operation.
182
+ // - gjson (used for retrieval) treats `.` as a special (traversal) character,
183
+ // so any json keys which contain `.` must have the `.` "escaped" with a single
184
+ // '\'. In it, key `a.b` would be matched by `a\.b` but not `a.b`.
185
+ // - hujson (used for the patch) treats "." and "\" as ordinary characters in a
186
+ // json key. In it, key `a.b` would be matched by `a.b` but not `a\.b`.
187
+ // So we need to "escape" json keys this way for retrieval, but not for patch.
175
188
if len (pathSoFarForPatch ) == 0 {
176
189
pathSoFarForPatch = "/" + segment
177
- pathSoFarForRetrieval = segment
190
+ pathSoFarForRetrieval = strings . ReplaceAll ( segment , "." , `\.` )
178
191
} else {
179
192
pathSoFarForPatch = pathSoFarForPatch + "/" + segment
180
- pathSoFarForRetrieval = pathSoFarForRetrieval + "." + segment
193
+ pathSoFarForRetrieval = pathSoFarForRetrieval + "." + strings . ReplaceAll ( segment , "." , `\.` )
181
194
}
182
195
183
196
// We retrieve the segment from the content so that we can check if it exists
0 commit comments