@mcp-z/mcp-sheets 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +181 -0
  3. package/bin/server.js +5 -0
  4. package/dist/cjs/constants.d.cts +7 -0
  5. package/dist/cjs/constants.d.ts +7 -0
  6. package/dist/cjs/constants.js +18 -0
  7. package/dist/cjs/constants.js.map +1 -0
  8. package/dist/cjs/index.d.cts +8 -0
  9. package/dist/cjs/index.d.ts +8 -0
  10. package/dist/cjs/index.js +314 -0
  11. package/dist/cjs/index.js.map +1 -0
  12. package/dist/cjs/lib/create-store.d.cts +2 -0
  13. package/dist/cjs/lib/create-store.d.ts +2 -0
  14. package/dist/cjs/lib/create-store.js +166 -0
  15. package/dist/cjs/lib/create-store.js.map +1 -0
  16. package/dist/cjs/mcp/index.d.cts +3 -0
  17. package/dist/cjs/mcp/index.d.ts +3 -0
  18. package/dist/cjs/mcp/index.js +66 -0
  19. package/dist/cjs/mcp/index.js.map +1 -0
  20. package/dist/cjs/mcp/prompts/a1-notation.d.cts +19 -0
  21. package/dist/cjs/mcp/prompts/a1-notation.d.ts +19 -0
  22. package/dist/cjs/mcp/prompts/a1-notation.js +169 -0
  23. package/dist/cjs/mcp/prompts/a1-notation.js.map +1 -0
  24. package/dist/cjs/mcp/prompts/index.d.cts +1 -0
  25. package/dist/cjs/mcp/prompts/index.d.ts +1 -0
  26. package/dist/cjs/mcp/prompts/index.js +17 -0
  27. package/dist/cjs/mcp/prompts/index.js.map +1 -0
  28. package/dist/cjs/mcp/resources/index.d.cts +1 -0
  29. package/dist/cjs/mcp/resources/index.d.ts +1 -0
  30. package/dist/cjs/mcp/resources/index.js +17 -0
  31. package/dist/cjs/mcp/resources/index.js.map +1 -0
  32. package/dist/cjs/mcp/resources/spreadsheet.d.cts +2 -0
  33. package/dist/cjs/mcp/resources/spreadsheet.d.ts +2 -0
  34. package/dist/cjs/mcp/resources/spreadsheet.js +258 -0
  35. package/dist/cjs/mcp/resources/spreadsheet.js.map +1 -0
  36. package/dist/cjs/mcp/tools/cells-format.d.cts +144 -0
  37. package/dist/cjs/mcp/tools/cells-format.d.ts +144 -0
  38. package/dist/cjs/mcp/tools/cells-format.js +484 -0
  39. package/dist/cjs/mcp/tools/cells-format.js.map +1 -0
  40. package/dist/cjs/mcp/tools/chart-create.d.cts +94 -0
  41. package/dist/cjs/mcp/tools/chart-create.d.ts +94 -0
  42. package/dist/cjs/mcp/tools/chart-create.js +575 -0
  43. package/dist/cjs/mcp/tools/chart-create.js.map +1 -0
  44. package/dist/cjs/mcp/tools/columns-get.d.cts +55 -0
  45. package/dist/cjs/mcp/tools/columns-get.d.ts +55 -0
  46. package/dist/cjs/mcp/tools/columns-get.js +289 -0
  47. package/dist/cjs/mcp/tools/columns-get.js.map +1 -0
  48. package/dist/cjs/mcp/tools/columns-update.d.cts +86 -0
  49. package/dist/cjs/mcp/tools/columns-update.d.ts +86 -0
  50. package/dist/cjs/mcp/tools/columns-update.js +482 -0
  51. package/dist/cjs/mcp/tools/columns-update.js.map +1 -0
  52. package/dist/cjs/mcp/tools/csv-get-columns.d.cts +43 -0
  53. package/dist/cjs/mcp/tools/csv-get-columns.d.ts +43 -0
  54. package/dist/cjs/mcp/tools/csv-get-columns.js +386 -0
  55. package/dist/cjs/mcp/tools/csv-get-columns.js.map +1 -0
  56. package/dist/cjs/mcp/tools/dimensions-batch-update.d.cts +118 -0
  57. package/dist/cjs/mcp/tools/dimensions-batch-update.d.ts +118 -0
  58. package/dist/cjs/mcp/tools/dimensions-batch-update.js +504 -0
  59. package/dist/cjs/mcp/tools/dimensions-batch-update.js.map +1 -0
  60. package/dist/cjs/mcp/tools/dimensions-move.d.cts +86 -0
  61. package/dist/cjs/mcp/tools/dimensions-move.d.ts +86 -0
  62. package/dist/cjs/mcp/tools/dimensions-move.js +359 -0
  63. package/dist/cjs/mcp/tools/dimensions-move.js.map +1 -0
  64. package/dist/cjs/mcp/tools/index.d.cts +26 -0
  65. package/dist/cjs/mcp/tools/index.d.ts +26 -0
  66. package/dist/cjs/mcp/tools/index.js +122 -0
  67. package/dist/cjs/mcp/tools/index.js.map +1 -0
  68. package/dist/cjs/mcp/tools/lib/dimension-operations.d.cts +48 -0
  69. package/dist/cjs/mcp/tools/lib/dimension-operations.d.ts +48 -0
  70. package/dist/cjs/mcp/tools/lib/dimension-operations.js +177 -0
  71. package/dist/cjs/mcp/tools/lib/dimension-operations.js.map +1 -0
  72. package/dist/cjs/mcp/tools/rows-append.d.cts +58 -0
  73. package/dist/cjs/mcp/tools/rows-append.d.ts +58 -0
  74. package/dist/cjs/mcp/tools/rows-append.js +335 -0
  75. package/dist/cjs/mcp/tools/rows-append.js.map +1 -0
  76. package/dist/cjs/mcp/tools/rows-csv-append.d.cts +67 -0
  77. package/dist/cjs/mcp/tools/rows-csv-append.d.ts +67 -0
  78. package/dist/cjs/mcp/tools/rows-csv-append.js +859 -0
  79. package/dist/cjs/mcp/tools/rows-csv-append.js.map +1 -0
  80. package/dist/cjs/mcp/tools/rows-get.d.cts +56 -0
  81. package/dist/cjs/mcp/tools/rows-get.d.ts +56 -0
  82. package/dist/cjs/mcp/tools/rows-get.js +292 -0
  83. package/dist/cjs/mcp/tools/rows-get.js.map +1 -0
  84. package/dist/cjs/mcp/tools/sheet-copy-to.d.cts +68 -0
  85. package/dist/cjs/mcp/tools/sheet-copy-to.d.ts +68 -0
  86. package/dist/cjs/mcp/tools/sheet-copy-to.js +341 -0
  87. package/dist/cjs/mcp/tools/sheet-copy-to.js.map +1 -0
  88. package/dist/cjs/mcp/tools/sheet-copy.d.cts +80 -0
  89. package/dist/cjs/mcp/tools/sheet-copy.d.ts +80 -0
  90. package/dist/cjs/mcp/tools/sheet-copy.js +394 -0
  91. package/dist/cjs/mcp/tools/sheet-copy.js.map +1 -0
  92. package/dist/cjs/mcp/tools/sheet-create.d.cts +56 -0
  93. package/dist/cjs/mcp/tools/sheet-create.d.ts +56 -0
  94. package/dist/cjs/mcp/tools/sheet-create.js +283 -0
  95. package/dist/cjs/mcp/tools/sheet-create.js.map +1 -0
  96. package/dist/cjs/mcp/tools/sheet-delete.d.cts +62 -0
  97. package/dist/cjs/mcp/tools/sheet-delete.d.ts +62 -0
  98. package/dist/cjs/mcp/tools/sheet-delete.js +341 -0
  99. package/dist/cjs/mcp/tools/sheet-delete.js.map +1 -0
  100. package/dist/cjs/mcp/tools/sheet-find.d.cts +48 -0
  101. package/dist/cjs/mcp/tools/sheet-find.d.ts +48 -0
  102. package/dist/cjs/mcp/tools/sheet-find.js +261 -0
  103. package/dist/cjs/mcp/tools/sheet-find.js.map +1 -0
  104. package/dist/cjs/mcp/tools/sheet-rename.d.cts +60 -0
  105. package/dist/cjs/mcp/tools/sheet-rename.d.ts +60 -0
  106. package/dist/cjs/mcp/tools/sheet-rename.js +305 -0
  107. package/dist/cjs/mcp/tools/sheet-rename.js.map +1 -0
  108. package/dist/cjs/mcp/tools/spreadsheet-copy.d.cts +58 -0
  109. package/dist/cjs/mcp/tools/spreadsheet-copy.d.ts +58 -0
  110. package/dist/cjs/mcp/tools/spreadsheet-copy.js +319 -0
  111. package/dist/cjs/mcp/tools/spreadsheet-copy.js.map +1 -0
  112. package/dist/cjs/mcp/tools/spreadsheet-create.d.cts +52 -0
  113. package/dist/cjs/mcp/tools/spreadsheet-create.d.ts +52 -0
  114. package/dist/cjs/mcp/tools/spreadsheet-create.js +270 -0
  115. package/dist/cjs/mcp/tools/spreadsheet-create.js.map +1 -0
  116. package/dist/cjs/mcp/tools/spreadsheet-find.d.cts +58 -0
  117. package/dist/cjs/mcp/tools/spreadsheet-find.d.ts +58 -0
  118. package/dist/cjs/mcp/tools/spreadsheet-find.js +334 -0
  119. package/dist/cjs/mcp/tools/spreadsheet-find.js.map +1 -0
  120. package/dist/cjs/mcp/tools/spreadsheet-rename.d.cts +56 -0
  121. package/dist/cjs/mcp/tools/spreadsheet-rename.d.ts +56 -0
  122. package/dist/cjs/mcp/tools/spreadsheet-rename.js +289 -0
  123. package/dist/cjs/mcp/tools/spreadsheet-rename.js.map +1 -0
  124. package/dist/cjs/mcp/tools/validation-set.d.cts +144 -0
  125. package/dist/cjs/mcp/tools/validation-set.d.ts +144 -0
  126. package/dist/cjs/mcp/tools/validation-set.js +564 -0
  127. package/dist/cjs/mcp/tools/validation-set.js.map +1 -0
  128. package/dist/cjs/mcp/tools/values-batch-update.d.cts +102 -0
  129. package/dist/cjs/mcp/tools/values-batch-update.d.ts +102 -0
  130. package/dist/cjs/mcp/tools/values-batch-update.js +409 -0
  131. package/dist/cjs/mcp/tools/values-batch-update.js.map +1 -0
  132. package/dist/cjs/mcp/tools/values-clear.d.cts +56 -0
  133. package/dist/cjs/mcp/tools/values-clear.d.ts +56 -0
  134. package/dist/cjs/mcp/tools/values-clear.js +308 -0
  135. package/dist/cjs/mcp/tools/values-clear.js.map +1 -0
  136. package/dist/cjs/mcp/tools/values-csv-update.d.cts +75 -0
  137. package/dist/cjs/mcp/tools/values-csv-update.d.ts +75 -0
  138. package/dist/cjs/mcp/tools/values-csv-update.js +500 -0
  139. package/dist/cjs/mcp/tools/values-csv-update.js.map +1 -0
  140. package/dist/cjs/mcp/tools/values-replace.d.cts +68 -0
  141. package/dist/cjs/mcp/tools/values-replace.d.ts +68 -0
  142. package/dist/cjs/mcp/tools/values-replace.js +378 -0
  143. package/dist/cjs/mcp/tools/values-replace.js.map +1 -0
  144. package/dist/cjs/mcp/tools/values-search.d.cts +74 -0
  145. package/dist/cjs/mcp/tools/values-search.d.ts +74 -0
  146. package/dist/cjs/mcp/tools/values-search.js +470 -0
  147. package/dist/cjs/mcp/tools/values-search.js.map +1 -0
  148. package/dist/cjs/package.json +1 -0
  149. package/dist/cjs/schemas/index.d.cts +14 -0
  150. package/dist/cjs/schemas/index.d.ts +14 -0
  151. package/dist/cjs/schemas/index.js +64 -0
  152. package/dist/cjs/schemas/index.js.map +1 -0
  153. package/dist/cjs/setup/config.d.cts +44 -0
  154. package/dist/cjs/setup/config.d.ts +44 -0
  155. package/dist/cjs/setup/config.js +201 -0
  156. package/dist/cjs/setup/config.js.map +1 -0
  157. package/dist/cjs/setup/http.d.cts +8 -0
  158. package/dist/cjs/setup/http.d.ts +8 -0
  159. package/dist/cjs/setup/http.js +260 -0
  160. package/dist/cjs/setup/http.js.map +1 -0
  161. package/dist/cjs/setup/index.d.cts +5 -0
  162. package/dist/cjs/setup/index.d.ts +5 -0
  163. package/dist/cjs/setup/index.js +46 -0
  164. package/dist/cjs/setup/index.js.map +1 -0
  165. package/dist/cjs/setup/oauth-google.d.cts +54 -0
  166. package/dist/cjs/setup/oauth-google.d.ts +54 -0
  167. package/dist/cjs/setup/oauth-google.js +332 -0
  168. package/dist/cjs/setup/oauth-google.js.map +1 -0
  169. package/dist/cjs/setup/runtime.d.cts +10 -0
  170. package/dist/cjs/setup/runtime.d.ts +10 -0
  171. package/dist/cjs/setup/runtime.js +353 -0
  172. package/dist/cjs/setup/runtime.js.map +1 -0
  173. package/dist/cjs/setup/stdio.d.cts +7 -0
  174. package/dist/cjs/setup/stdio.d.ts +7 -0
  175. package/dist/cjs/setup/stdio.js +239 -0
  176. package/dist/cjs/setup/stdio.js.map +1 -0
  177. package/dist/cjs/spreadsheet/column-utilities.d.cts +1 -0
  178. package/dist/cjs/spreadsheet/column-utilities.d.ts +1 -0
  179. package/dist/cjs/spreadsheet/column-utilities.js +21 -0
  180. package/dist/cjs/spreadsheet/column-utilities.js.map +1 -0
  181. package/dist/cjs/spreadsheet/csv-streaming.d.cts +19 -0
  182. package/dist/cjs/spreadsheet/csv-streaming.d.ts +19 -0
  183. package/dist/cjs/spreadsheet/csv-streaming.js +188 -0
  184. package/dist/cjs/spreadsheet/csv-streaming.js.map +1 -0
  185. package/dist/cjs/spreadsheet/data-operations.d.cts +115 -0
  186. package/dist/cjs/spreadsheet/data-operations.d.ts +115 -0
  187. package/dist/cjs/spreadsheet/data-operations.js +1515 -0
  188. package/dist/cjs/spreadsheet/data-operations.js.map +1 -0
  189. package/dist/cjs/spreadsheet/deduplication-utils.d.cts +31 -0
  190. package/dist/cjs/spreadsheet/deduplication-utils.d.ts +31 -0
  191. package/dist/cjs/spreadsheet/deduplication-utils.js +65 -0
  192. package/dist/cjs/spreadsheet/deduplication-utils.js.map +1 -0
  193. package/dist/cjs/spreadsheet/range-operations.d.cts +184 -0
  194. package/dist/cjs/spreadsheet/range-operations.d.ts +184 -0
  195. package/dist/cjs/spreadsheet/range-operations.js +672 -0
  196. package/dist/cjs/spreadsheet/range-operations.js.map +1 -0
  197. package/dist/cjs/spreadsheet/sheet-operations.d.cts +30 -0
  198. package/dist/cjs/spreadsheet/sheet-operations.d.ts +30 -0
  199. package/dist/cjs/spreadsheet/sheet-operations.js +811 -0
  200. package/dist/cjs/spreadsheet/sheet-operations.js.map +1 -0
  201. package/dist/cjs/spreadsheet/spreadsheet-management.d.cts +21 -0
  202. package/dist/cjs/spreadsheet/spreadsheet-management.d.ts +21 -0
  203. package/dist/cjs/spreadsheet/spreadsheet-management.js +310 -0
  204. package/dist/cjs/spreadsheet/spreadsheet-management.js.map +1 -0
  205. package/dist/cjs/types.d.cts +53 -0
  206. package/dist/cjs/types.d.ts +53 -0
  207. package/dist/cjs/types.js +5 -0
  208. package/dist/cjs/types.js.map +1 -0
  209. package/dist/esm/constants.d.ts +7 -0
  210. package/dist/esm/constants.js +7 -0
  211. package/dist/esm/constants.js.map +1 -0
  212. package/dist/esm/index.d.ts +8 -0
  213. package/dist/esm/index.js +34 -0
  214. package/dist/esm/index.js.map +1 -0
  215. package/dist/esm/lib/create-store.d.ts +2 -0
  216. package/dist/esm/lib/create-store.js +6 -0
  217. package/dist/esm/lib/create-store.js.map +1 -0
  218. package/dist/esm/mcp/index.d.ts +3 -0
  219. package/dist/esm/mcp/index.js +6 -0
  220. package/dist/esm/mcp/index.js.map +1 -0
  221. package/dist/esm/mcp/prompts/a1-notation.d.ts +19 -0
  222. package/dist/esm/mcp/prompts/a1-notation.js +49 -0
  223. package/dist/esm/mcp/prompts/a1-notation.js.map +1 -0
  224. package/dist/esm/mcp/prompts/index.d.ts +1 -0
  225. package/dist/esm/mcp/prompts/index.js +1 -0
  226. package/dist/esm/mcp/prompts/index.js.map +1 -0
  227. package/dist/esm/mcp/resources/index.d.ts +1 -0
  228. package/dist/esm/mcp/resources/index.js +1 -0
  229. package/dist/esm/mcp/resources/index.js.map +1 -0
  230. package/dist/esm/mcp/resources/spreadsheet.d.ts +2 -0
  231. package/dist/esm/mcp/resources/spreadsheet.js +88 -0
  232. package/dist/esm/mcp/resources/spreadsheet.js.map +1 -0
  233. package/dist/esm/mcp/tools/cells-format.d.ts +144 -0
  234. package/dist/esm/mcp/tools/cells-format.js +288 -0
  235. package/dist/esm/mcp/tools/cells-format.js.map +1 -0
  236. package/dist/esm/mcp/tools/chart-create.d.ts +94 -0
  237. package/dist/esm/mcp/tools/chart-create.js +408 -0
  238. package/dist/esm/mcp/tools/chart-create.js.map +1 -0
  239. package/dist/esm/mcp/tools/columns-get.d.ts +55 -0
  240. package/dist/esm/mcp/tools/columns-get.js +113 -0
  241. package/dist/esm/mcp/tools/columns-get.js.map +1 -0
  242. package/dist/esm/mcp/tools/columns-update.d.ts +86 -0
  243. package/dist/esm/mcp/tools/columns-update.js +296 -0
  244. package/dist/esm/mcp/tools/columns-update.js.map +1 -0
  245. package/dist/esm/mcp/tools/csv-get-columns.d.ts +43 -0
  246. package/dist/esm/mcp/tools/csv-get-columns.js +95 -0
  247. package/dist/esm/mcp/tools/csv-get-columns.js.map +1 -0
  248. package/dist/esm/mcp/tools/dimensions-batch-update.d.ts +118 -0
  249. package/dist/esm/mcp/tools/dimensions-batch-update.js +321 -0
  250. package/dist/esm/mcp/tools/dimensions-batch-update.js.map +1 -0
  251. package/dist/esm/mcp/tools/dimensions-move.d.ts +86 -0
  252. package/dist/esm/mcp/tools/dimensions-move.js +183 -0
  253. package/dist/esm/mcp/tools/dimensions-move.js.map +1 -0
  254. package/dist/esm/mcp/tools/index.d.ts +26 -0
  255. package/dist/esm/mcp/tools/index.js +26 -0
  256. package/dist/esm/mcp/tools/index.js.map +1 -0
  257. package/dist/esm/mcp/tools/lib/dimension-operations.d.ts +48 -0
  258. package/dist/esm/mcp/tools/lib/dimension-operations.js +93 -0
  259. package/dist/esm/mcp/tools/lib/dimension-operations.js.map +1 -0
  260. package/dist/esm/mcp/tools/rows-append.d.ts +58 -0
  261. package/dist/esm/mcp/tools/rows-append.js +151 -0
  262. package/dist/esm/mcp/tools/rows-append.js.map +1 -0
  263. package/dist/esm/mcp/tools/rows-csv-append.d.ts +67 -0
  264. package/dist/esm/mcp/tools/rows-csv-append.js +342 -0
  265. package/dist/esm/mcp/tools/rows-csv-append.js.map +1 -0
  266. package/dist/esm/mcp/tools/rows-get.d.ts +56 -0
  267. package/dist/esm/mcp/tools/rows-get.js +116 -0
  268. package/dist/esm/mcp/tools/rows-get.js.map +1 -0
  269. package/dist/esm/mcp/tools/sheet-copy-to.d.ts +68 -0
  270. package/dist/esm/mcp/tools/sheet-copy-to.js +156 -0
  271. package/dist/esm/mcp/tools/sheet-copy-to.js.map +1 -0
  272. package/dist/esm/mcp/tools/sheet-copy.d.ts +80 -0
  273. package/dist/esm/mcp/tools/sheet-copy.js +177 -0
  274. package/dist/esm/mcp/tools/sheet-copy.js.map +1 -0
  275. package/dist/esm/mcp/tools/sheet-create.d.ts +56 -0
  276. package/dist/esm/mcp/tools/sheet-create.js +110 -0
  277. package/dist/esm/mcp/tools/sheet-create.js.map +1 -0
  278. package/dist/esm/mcp/tools/sheet-delete.d.ts +62 -0
  279. package/dist/esm/mcp/tools/sheet-delete.js +125 -0
  280. package/dist/esm/mcp/tools/sheet-delete.js.map +1 -0
  281. package/dist/esm/mcp/tools/sheet-find.d.ts +48 -0
  282. package/dist/esm/mcp/tools/sheet-find.js +90 -0
  283. package/dist/esm/mcp/tools/sheet-find.js.map +1 -0
  284. package/dist/esm/mcp/tools/sheet-rename.d.ts +60 -0
  285. package/dist/esm/mcp/tools/sheet-rename.js +128 -0
  286. package/dist/esm/mcp/tools/sheet-rename.js.map +1 -0
  287. package/dist/esm/mcp/tools/spreadsheet-copy.d.ts +58 -0
  288. package/dist/esm/mcp/tools/spreadsheet-copy.js +117 -0
  289. package/dist/esm/mcp/tools/spreadsheet-copy.js.map +1 -0
  290. package/dist/esm/mcp/tools/spreadsheet-create.d.ts +52 -0
  291. package/dist/esm/mcp/tools/spreadsheet-create.js +97 -0
  292. package/dist/esm/mcp/tools/spreadsheet-create.js.map +1 -0
  293. package/dist/esm/mcp/tools/spreadsheet-find.d.ts +58 -0
  294. package/dist/esm/mcp/tools/spreadsheet-find.js +113 -0
  295. package/dist/esm/mcp/tools/spreadsheet-find.js.map +1 -0
  296. package/dist/esm/mcp/tools/spreadsheet-rename.d.ts +56 -0
  297. package/dist/esm/mcp/tools/spreadsheet-rename.js +112 -0
  298. package/dist/esm/mcp/tools/spreadsheet-rename.js.map +1 -0
  299. package/dist/esm/mcp/tools/validation-set.d.ts +144 -0
  300. package/dist/esm/mcp/tools/validation-set.js +366 -0
  301. package/dist/esm/mcp/tools/validation-set.js.map +1 -0
  302. package/dist/esm/mcp/tools/values-batch-update.d.ts +102 -0
  303. package/dist/esm/mcp/tools/values-batch-update.js +224 -0
  304. package/dist/esm/mcp/tools/values-batch-update.js.map +1 -0
  305. package/dist/esm/mcp/tools/values-clear.d.ts +56 -0
  306. package/dist/esm/mcp/tools/values-clear.js +131 -0
  307. package/dist/esm/mcp/tools/values-clear.js.map +1 -0
  308. package/dist/esm/mcp/tools/values-csv-update.d.ts +75 -0
  309. package/dist/esm/mcp/tools/values-csv-update.js +202 -0
  310. package/dist/esm/mcp/tools/values-csv-update.js.map +1 -0
  311. package/dist/esm/mcp/tools/values-replace.d.ts +68 -0
  312. package/dist/esm/mcp/tools/values-replace.js +171 -0
  313. package/dist/esm/mcp/tools/values-replace.js.map +1 -0
  314. package/dist/esm/mcp/tools/values-search.d.ts +74 -0
  315. package/dist/esm/mcp/tools/values-search.js +229 -0
  316. package/dist/esm/mcp/tools/values-search.js.map +1 -0
  317. package/dist/esm/package.json +1 -0
  318. package/dist/esm/schemas/index.d.ts +14 -0
  319. package/dist/esm/schemas/index.js +35 -0
  320. package/dist/esm/schemas/index.js.map +1 -0
  321. package/dist/esm/setup/config.d.ts +44 -0
  322. package/dist/esm/setup/config.js +151 -0
  323. package/dist/esm/setup/config.js.map +1 -0
  324. package/dist/esm/setup/http.d.ts +8 -0
  325. package/dist/esm/setup/http.js +54 -0
  326. package/dist/esm/setup/http.js.map +1 -0
  327. package/dist/esm/setup/index.d.ts +5 -0
  328. package/dist/esm/setup/index.js +5 -0
  329. package/dist/esm/setup/index.js.map +1 -0
  330. package/dist/esm/setup/oauth-google.d.ts +54 -0
  331. package/dist/esm/setup/oauth-google.js +142 -0
  332. package/dist/esm/setup/oauth-google.js.map +1 -0
  333. package/dist/esm/setup/runtime.d.ts +10 -0
  334. package/dist/esm/setup/runtime.js +84 -0
  335. package/dist/esm/setup/runtime.js.map +1 -0
  336. package/dist/esm/setup/stdio.d.ts +7 -0
  337. package/dist/esm/setup/stdio.js +38 -0
  338. package/dist/esm/setup/stdio.js.map +1 -0
  339. package/dist/esm/spreadsheet/column-utilities.d.ts +1 -0
  340. package/dist/esm/spreadsheet/column-utilities.js +10 -0
  341. package/dist/esm/spreadsheet/column-utilities.js.map +1 -0
  342. package/dist/esm/spreadsheet/csv-streaming.d.ts +19 -0
  343. package/dist/esm/spreadsheet/csv-streaming.js +43 -0
  344. package/dist/esm/spreadsheet/csv-streaming.js.map +1 -0
  345. package/dist/esm/spreadsheet/data-operations.d.ts +115 -0
  346. package/dist/esm/spreadsheet/data-operations.js +712 -0
  347. package/dist/esm/spreadsheet/data-operations.js.map +1 -0
  348. package/dist/esm/spreadsheet/deduplication-utils.d.ts +31 -0
  349. package/dist/esm/spreadsheet/deduplication-utils.js +54 -0
  350. package/dist/esm/spreadsheet/deduplication-utils.js.map +1 -0
  351. package/dist/esm/spreadsheet/range-operations.d.ts +184 -0
  352. package/dist/esm/spreadsheet/range-operations.js +591 -0
  353. package/dist/esm/spreadsheet/range-operations.js.map +1 -0
  354. package/dist/esm/spreadsheet/sheet-operations.d.ts +30 -0
  355. package/dist/esm/spreadsheet/sheet-operations.js +359 -0
  356. package/dist/esm/spreadsheet/sheet-operations.js.map +1 -0
  357. package/dist/esm/spreadsheet/spreadsheet-management.d.ts +21 -0
  358. package/dist/esm/spreadsheet/spreadsheet-management.js +73 -0
  359. package/dist/esm/spreadsheet/spreadsheet-management.js.map +1 -0
  360. package/dist/esm/types.d.ts +53 -0
  361. package/dist/esm/types.js +1 -0
  362. package/dist/esm/types.js.map +1 -0
  363. package/package.json +108 -0
@@ -0,0 +1,151 @@
1
+ import { schemas } from '@mcp-z/oauth-google';
2
+ const { AuthRequiredBranchSchema } = schemas;
3
+ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
4
+ import { google } from 'googleapis';
5
+ import { z } from 'zod';
6
+ import { SheetGidOutput, SheetGidSchema, SpreadsheetIdOutput, SpreadsheetIdSchema } from '../../schemas/index.js';
7
+ import { appendRows, mapRowsToHeader } from '../../spreadsheet/data-operations.js';
8
+ import { ensureTabAndHeaders } from '../../spreadsheet/sheet-operations.js';
9
+ const inputSchema = z.object({
10
+ id: SpreadsheetIdSchema,
11
+ gid: SheetGidSchema,
12
+ rows: z.array(z.array(z.union([
13
+ z.string(),
14
+ z.number(),
15
+ z.boolean(),
16
+ z.null()
17
+ ])).min(1)).min(1).describe('Array of rows, where each row is an array of cell values. Use null to skip a cell (preserve existing value), empty string "" to clear it.'),
18
+ headers: z.array(z.string()).optional().describe('Column order/names - used for blank sheets or column mapping'),
19
+ deduplicateBy: z.array(z.string()).optional().describe('Column names to use as composite key for deduplication')
20
+ });
21
+ const successBranchSchema = z.object({
22
+ type: z.literal('success'),
23
+ id: SpreadsheetIdOutput,
24
+ gid: SheetGidOutput,
25
+ sheetTitle: z.string().describe('Sheet tab name'),
26
+ updatedRows: z.number().describe('Number of rows appended'),
27
+ rowsSkipped: z.number().optional().describe('Number of duplicate rows skipped'),
28
+ sheetUrl: z.string().optional().describe('URL to view the sheet')
29
+ });
30
+ const outputSchema = z.discriminatedUnion('type', [
31
+ successBranchSchema,
32
+ AuthRequiredBranchSchema
33
+ ]);
34
+ const config = {
35
+ description: 'Add new rows to the bottom of an existing sheet with smart header handling and optional deduplication. BEST FOR: Structured database operations where spreadsheet has headers defining schema and rows represent records.',
36
+ inputSchema,
37
+ outputSchema: z.object({
38
+ result: outputSchema
39
+ })
40
+ };
41
+ async function handler({ id, gid, rows, headers, deduplicateBy }, extra) {
42
+ const logger = extra.logger;
43
+ logger.info('sheets.rows.append called', {
44
+ id,
45
+ gid,
46
+ rowCount: rows.length,
47
+ headers,
48
+ deduplicateBy
49
+ });
50
+ try {
51
+ var _ref;
52
+ var _spreadsheetResponse_data_sheets, _sheet_properties;
53
+ const sheets = google.sheets({
54
+ version: 'v4',
55
+ auth: extra.authContext.auth
56
+ });
57
+ // Get sheet details using the gid
58
+ const spreadsheetResponse = await sheets.spreadsheets.get({
59
+ spreadsheetId: id,
60
+ fields: 'sheets.properties.sheetId,sheets.properties.title'
61
+ });
62
+ const sheet = (_spreadsheetResponse_data_sheets = spreadsheetResponse.data.sheets) === null || _spreadsheetResponse_data_sheets === void 0 ? void 0 : _spreadsheetResponse_data_sheets.find((s)=>{
63
+ var _s_properties;
64
+ return String((_s_properties = s.properties) === null || _s_properties === void 0 ? void 0 : _s_properties.sheetId) === gid;
65
+ });
66
+ if (!sheet) {
67
+ throw new McpError(ErrorCode.InvalidParams, 'Sheet not found');
68
+ }
69
+ const sheetTitle = (_ref = sheet === null || sheet === void 0 ? void 0 : (_sheet_properties = sheet.properties) === null || _sheet_properties === void 0 ? void 0 : _sheet_properties.title) !== null && _ref !== void 0 ? _ref : '';
70
+ // Smart header handling and data processing
71
+ let processedRows = rows;
72
+ let currentHeaders = [];
73
+ let rowsSkipped = 0;
74
+ let existingKeySet = new Set();
75
+ if (headers && headers.length > 0) {
76
+ // Use ensureTabAndHeaders to handle header logic
77
+ const headerResult = await ensureTabAndHeaders(sheets, {
78
+ spreadsheetId: id,
79
+ sheetTitle,
80
+ requiredHeader: headers,
81
+ keyColumns: deduplicateBy || [],
82
+ logger
83
+ });
84
+ currentHeaders = headerResult.header;
85
+ existingKeySet = headerResult.keySet;
86
+ // Map data rows to match current header order
87
+ processedRows = mapRowsToHeader({
88
+ rows,
89
+ header: currentHeaders,
90
+ canonical: headers
91
+ });
92
+ }
93
+ // Append rows with optional deduplication
94
+ // If headers are empty but deduplication is requested, skip deduplication for empty spreadsheets
95
+ const effectiveKeyColumns = currentHeaders.length === 0 && deduplicateBy && deduplicateBy.length > 0 ? [] : deduplicateBy || [];
96
+ const appendResult = await appendRows(sheets, {
97
+ spreadsheetId: id,
98
+ sheetTitle,
99
+ rows: processedRows,
100
+ keySet: existingKeySet,
101
+ keyColumns: effectiveKeyColumns,
102
+ header: currentHeaders,
103
+ logger
104
+ });
105
+ rowsSkipped = appendResult.rowsSkipped || 0;
106
+ // Only count data rows, not headers - headers are metadata, not items
107
+ const updatedRows = appendResult.updatedRows || 0;
108
+ const sheetUrl = `https://docs.google.com/spreadsheets/d/${id}/edit#gid=${gid}`;
109
+ logger.info('sheets.rows.append completed', {
110
+ id,
111
+ gid,
112
+ updatedRows,
113
+ rowsSkipped
114
+ });
115
+ const result = {
116
+ type: 'success',
117
+ id,
118
+ gid,
119
+ sheetTitle,
120
+ updatedRows,
121
+ rowsSkipped,
122
+ sheetUrl
123
+ };
124
+ return {
125
+ content: [
126
+ {
127
+ type: 'text',
128
+ text: JSON.stringify(result)
129
+ }
130
+ ],
131
+ structuredContent: {
132
+ result
133
+ }
134
+ };
135
+ } catch (error) {
136
+ const message = error instanceof Error ? error.message : String(error);
137
+ logger.error('sheets.rows.append error', {
138
+ error: message
139
+ });
140
+ throw new McpError(ErrorCode.InternalError, `Error appending rows: ${message}`, {
141
+ stack: error instanceof Error ? error.stack : undefined
142
+ });
143
+ }
144
+ }
145
+ export default function createTool() {
146
+ return {
147
+ name: 'rows-append',
148
+ config,
149
+ handler
150
+ };
151
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-sheets/src/mcp/tools/rows-append.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\nimport { SheetGidOutput, SheetGidSchema, SpreadsheetIdOutput, SpreadsheetIdSchema } from '../../schemas/index.js';\nimport { appendRows, mapRowsToHeader } from '../../spreadsheet/data-operations.js';\nimport { ensureTabAndHeaders } from '../../spreadsheet/sheet-operations.js';\n\nconst inputSchema = z.object({\n id: SpreadsheetIdSchema,\n gid: SheetGidSchema,\n rows: z\n .array(z.array(z.union([z.string(), z.number(), z.boolean(), z.null()])).min(1))\n .min(1)\n .describe('Array of rows, where each row is an array of cell values. Use null to skip a cell (preserve existing value), empty string \"\" to clear it.'),\n headers: z.array(z.string()).optional().describe('Column order/names - used for blank sheets or column mapping'),\n deduplicateBy: z.array(z.string()).optional().describe('Column names to use as composite key for deduplication'),\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n id: SpreadsheetIdOutput,\n gid: SheetGidOutput,\n sheetTitle: z.string().describe('Sheet tab name'),\n updatedRows: z.number().describe('Number of rows appended'),\n rowsSkipped: z.number().optional().describe('Number of duplicate rows skipped'),\n sheetUrl: z.string().optional().describe('URL to view the sheet'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Add new rows to the bottom of an existing sheet with smart header handling and optional deduplication. BEST FOR: Structured database operations where spreadsheet has headers defining schema and rows represent records.',\n inputSchema,\n outputSchema: z.object({\n result: outputSchema,\n }),\n} as const;\n\nexport type Input = z.infer<typeof inputSchema>;\nexport type Output = z.infer<typeof outputSchema>;\n\nasync function handler({ id, gid, rows, headers, deduplicateBy }: Input, extra: EnrichedExtra): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('sheets.rows.append called', { id, gid, rowCount: rows.length, headers, deduplicateBy });\n\n try {\n const sheets = google.sheets({ version: 'v4', auth: extra.authContext.auth });\n\n // Get sheet details using the gid\n const spreadsheetResponse = await sheets.spreadsheets.get({\n spreadsheetId: id,\n fields: 'sheets.properties.sheetId,sheets.properties.title',\n });\n\n const sheet = spreadsheetResponse.data.sheets?.find((s) => String(s.properties?.sheetId) === gid);\n\n if (!sheet) {\n throw new McpError(ErrorCode.InvalidParams, 'Sheet not found');\n }\n\n const sheetTitle = sheet?.properties?.title ?? '';\n\n // Smart header handling and data processing\n let processedRows = rows;\n let currentHeaders: string[] = [];\n let rowsSkipped = 0;\n let existingKeySet: Set<string> = new Set();\n\n if (headers && headers.length > 0) {\n // Use ensureTabAndHeaders to handle header logic\n const headerResult = await ensureTabAndHeaders(sheets, {\n spreadsheetId: id,\n sheetTitle,\n requiredHeader: headers,\n keyColumns: deduplicateBy || [],\n logger,\n });\n\n currentHeaders = headerResult.header;\n existingKeySet = headerResult.keySet;\n\n // Map data rows to match current header order\n processedRows = mapRowsToHeader({ rows, header: currentHeaders, canonical: headers }) as (string | number | boolean | null)[][];\n }\n\n // Append rows with optional deduplication\n // If headers are empty but deduplication is requested, skip deduplication for empty spreadsheets\n const effectiveKeyColumns = currentHeaders.length === 0 && deduplicateBy && deduplicateBy.length > 0 ? [] : deduplicateBy || [];\n\n const appendResult = await appendRows(sheets, {\n spreadsheetId: id,\n sheetTitle,\n rows: processedRows,\n keySet: existingKeySet,\n keyColumns: effectiveKeyColumns,\n header: currentHeaders,\n logger,\n });\n\n rowsSkipped = appendResult.rowsSkipped || 0;\n // Only count data rows, not headers - headers are metadata, not items\n const updatedRows = appendResult.updatedRows || 0;\n\n const sheetUrl = `https://docs.google.com/spreadsheets/d/${id}/edit#gid=${gid}`;\n\n logger.info('sheets.rows.append completed', { id, gid, updatedRows, rowsSkipped });\n\n const result: Output = {\n type: 'success' as const,\n id,\n gid,\n sheetTitle,\n updatedRows,\n rowsSkipped, // Always include rowsSkipped, even when 0\n sheetUrl,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result) }],\n structuredContent: { result },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error('sheets.rows.append error', { error: message });\n\n throw new McpError(ErrorCode.InternalError, `Error appending rows: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'rows-append',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ErrorCode","McpError","google","z","SheetGidOutput","SheetGidSchema","SpreadsheetIdOutput","SpreadsheetIdSchema","appendRows","mapRowsToHeader","ensureTabAndHeaders","inputSchema","object","id","gid","rows","array","union","string","number","boolean","null","min","describe","headers","optional","deduplicateBy","successBranchSchema","type","literal","sheetTitle","updatedRows","rowsSkipped","sheetUrl","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","rowCount","length","spreadsheetResponse","sheet","sheets","version","auth","authContext","spreadsheets","get","spreadsheetId","fields","data","find","s","String","properties","sheetId","InvalidParams","title","processedRows","currentHeaders","existingKeySet","Set","headerResult","requiredHeader","keyColumns","header","keySet","canonical","effectiveKeyColumns","appendResult","content","text","JSON","stringify","structuredContent","error","message","Error","InternalError","stack","undefined","createTool","name"],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /** Import CSV data to Google Sheets with database-style row append and deduplication */
2
+ import type { EnrichedExtra } from '@mcp-z/oauth-google';
3
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
4
+ import { z } from 'zod';
5
+ declare const inputSchema: z.ZodObject<{
6
+ id: z.ZodString;
7
+ gid: z.ZodCoercedString<unknown>;
8
+ sourceUri: z.ZodString;
9
+ sourceHasHeaders: z.ZodDefault<z.ZodBoolean>;
10
+ headerMap: z.ZodArray<z.ZodObject<{
11
+ source: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
12
+ target: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
13
+ }, z.core.$strip>>;
14
+ deduplicateBy: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
15
+ }, z.core.$strip>;
16
+ declare const outputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
17
+ type: z.ZodLiteral<"success">;
18
+ id: z.ZodString;
19
+ gid: z.ZodString;
20
+ sheetTitle: z.ZodString;
21
+ updatedRows: z.ZodNumber;
22
+ rowsSkipped: z.ZodOptional<z.ZodNumber>;
23
+ sheetUrl: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strip>, z.ZodObject<{
25
+ type: z.ZodLiteral<"auth_required">;
26
+ provider: z.ZodString;
27
+ message: z.ZodString;
28
+ url: z.ZodOptional<z.ZodString>;
29
+ }, z.core.$strip>], "type">;
30
+ export type Input = z.infer<typeof inputSchema>;
31
+ export type Output = z.infer<typeof outputSchema>;
32
+ declare function handler({ id, gid, sourceUri, sourceHasHeaders, headerMap, deduplicateBy }: Input, extra: EnrichedExtra): Promise<CallToolResult>;
33
+ export default function createTool(): {
34
+ name: string;
35
+ config: {
36
+ readonly description: "Import CSV to Google Sheets with column mapping and optional deduplication. Streams data for large files.";
37
+ readonly inputSchema: z.ZodObject<{
38
+ id: z.ZodString;
39
+ gid: z.ZodCoercedString<unknown>;
40
+ sourceUri: z.ZodString;
41
+ sourceHasHeaders: z.ZodDefault<z.ZodBoolean>;
42
+ headerMap: z.ZodArray<z.ZodObject<{
43
+ source: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
44
+ target: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
45
+ }, z.core.$strip>>;
46
+ deduplicateBy: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
47
+ }, z.core.$strip>;
48
+ readonly outputSchema: z.ZodObject<{
49
+ result: z.ZodDiscriminatedUnion<[z.ZodObject<{
50
+ type: z.ZodLiteral<"success">;
51
+ id: z.ZodString;
52
+ gid: z.ZodString;
53
+ sheetTitle: z.ZodString;
54
+ updatedRows: z.ZodNumber;
55
+ rowsSkipped: z.ZodOptional<z.ZodNumber>;
56
+ sheetUrl: z.ZodOptional<z.ZodString>;
57
+ }, z.core.$strip>, z.ZodObject<{
58
+ type: z.ZodLiteral<"auth_required">;
59
+ provider: z.ZodString;
60
+ message: z.ZodString;
61
+ url: z.ZodOptional<z.ZodString>;
62
+ }, z.core.$strip>], "type">;
63
+ }, z.core.$strip>;
64
+ };
65
+ handler: typeof handler;
66
+ };
67
+ export {};
@@ -0,0 +1,342 @@
1
+ /** Import CSV data to Google Sheets with database-style row append and deduplication */ import { schemas } from '@mcp-z/oauth-google';
2
+ const { AuthRequiredBranchSchema } = schemas;
3
+ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
4
+ import { parse } from 'csv-parse';
5
+ import { google } from 'googleapis';
6
+ import { z } from 'zod';
7
+ import { SheetGidOutput, SheetGidSchema, SpreadsheetIdOutput, SpreadsheetIdSchema } from '../../schemas/index.js';
8
+ import { getCsvReadStream } from '../../spreadsheet/csv-streaming.js';
9
+ import { buildDeduplicationKey } from '../../spreadsheet/deduplication-utils.js';
10
+ import { ensureTabAndHeaders } from '../../spreadsheet/sheet-operations.js';
11
+ // Header mapping schema: source/target can be string (name) or number (0-based index)
12
+ const HeaderMapItemSchema = z.object({
13
+ source: z.union([
14
+ z.string(),
15
+ z.number().int().min(0)
16
+ ]).describe('CSV column: header name (string) or 0-based index (number)'),
17
+ target: z.union([
18
+ z.string(),
19
+ z.number().int().min(0)
20
+ ]).describe('Sheet column: header name (string) or 0-based index (number)')
21
+ });
22
+ const inputSchema = z.object({
23
+ id: SpreadsheetIdSchema,
24
+ gid: SheetGidSchema,
25
+ sourceUri: z.string().trim().min(1).describe('CSV file URI (file://, http://, https://)'),
26
+ sourceHasHeaders: z.boolean().default(true).describe('Source has header row for column name mapping. Set to false for data-only sources (numeric indices required).'),
27
+ headerMap: z.array(HeaderMapItemSchema).describe('Column mappings from CSV to sheet'),
28
+ deduplicateBy: z.array(z.union([
29
+ z.string(),
30
+ z.number().int().min(0)
31
+ ])).optional().describe('Sheet columns for deduplication (names or indices)')
32
+ });
33
+ const successBranchSchema = z.object({
34
+ type: z.literal('success'),
35
+ id: SpreadsheetIdOutput,
36
+ gid: SheetGidOutput,
37
+ sheetTitle: z.string().describe('Sheet tab name'),
38
+ updatedRows: z.number().describe('Number of rows appended'),
39
+ rowsSkipped: z.number().optional().describe('Number of duplicate rows skipped'),
40
+ sheetUrl: z.string().optional().describe('URL to view the sheet')
41
+ });
42
+ const outputSchema = z.discriminatedUnion('type', [
43
+ successBranchSchema,
44
+ AuthRequiredBranchSchema
45
+ ]);
46
+ const config = {
47
+ description: 'Import CSV to Google Sheets with column mapping and optional deduplication. Streams data for large files.',
48
+ inputSchema,
49
+ outputSchema: z.object({
50
+ result: outputSchema
51
+ })
52
+ };
53
+ /** Batch size for Sheets API calls (1000 rows × 12 cols = 12K cells, well under 40K limit) */ const BATCH_SIZE = 1000;
54
+ /**
55
+ * Resolve column reference to numeric index
56
+ * @param ref Column reference (string name or number index)
57
+ * @param headers Header row (null when sourceHasHeaders=false)
58
+ * @param sourceHasHeaders Whether headers are present
59
+ * @returns 0-based column index
60
+ */ function resolveColumnReference(ref, headers, sourceHasHeaders, context) {
61
+ // If number, use directly as 0-based index
62
+ if (typeof ref === 'number') {
63
+ if (ref < 0) {
64
+ throw new Error(`${context}: Column index must be >= 0, got ${ref}`);
65
+ }
66
+ return ref;
67
+ }
68
+ // If string, must be header name
69
+ if (!sourceHasHeaders || !headers) {
70
+ throw new Error(`${context}: String column reference "${ref}" requires sourceHasHeaders=true. Use numeric index when sourceHasHeaders=false.`);
71
+ }
72
+ const index = headers.indexOf(ref);
73
+ if (index === -1) {
74
+ throw new Error(`${context}: Header "${ref}" not found in [${headers.join(', ')}]`);
75
+ }
76
+ return index;
77
+ }
78
+ async function handler({ id, gid, sourceUri, sourceHasHeaders, headerMap, deduplicateBy }, extra) {
79
+ const logger = extra.logger;
80
+ logger.info('sheets.rows.csv-append called', {
81
+ id,
82
+ gid,
83
+ sourceUri,
84
+ sourceHasHeaders,
85
+ headerMap,
86
+ deduplicateBy
87
+ });
88
+ try {
89
+ var _ref;
90
+ var _spreadsheetResponse_data_sheets, _sheet_properties;
91
+ if (headerMap.length === 0) {
92
+ throw new McpError(ErrorCode.InvalidParams, 'headerMap cannot be empty');
93
+ }
94
+ // Validate: if sourceHasHeaders=false, all references must be numeric
95
+ if (!sourceHasHeaders) {
96
+ for (const { source, target } of headerMap){
97
+ if (typeof source === 'string') {
98
+ throw new McpError(ErrorCode.InvalidParams, `sourceHasHeaders=false requires numeric indices. Got string source: "${source}"`);
99
+ }
100
+ if (typeof target === 'string') {
101
+ throw new McpError(ErrorCode.InvalidParams, `sourceHasHeaders=false requires numeric indices. Got string target: "${target}"`);
102
+ }
103
+ }
104
+ if (deduplicateBy) {
105
+ for (const colRef of deduplicateBy){
106
+ if (typeof colRef === 'string') {
107
+ throw new McpError(ErrorCode.InvalidParams, `sourceHasHeaders=false requires numeric indices in deduplicateBy. Got string: "${colRef}"`);
108
+ }
109
+ }
110
+ }
111
+ }
112
+ const sheets = google.sheets({
113
+ version: 'v4',
114
+ auth: extra.authContext.auth
115
+ });
116
+ // Get sheet details using the gid
117
+ const spreadsheetResponse = await sheets.spreadsheets.get({
118
+ spreadsheetId: id,
119
+ fields: 'sheets.properties.sheetId,sheets.properties.title'
120
+ });
121
+ const sheet = (_spreadsheetResponse_data_sheets = spreadsheetResponse.data.sheets) === null || _spreadsheetResponse_data_sheets === void 0 ? void 0 : _spreadsheetResponse_data_sheets.find((s)=>{
122
+ var _s_properties;
123
+ return String((_s_properties = s.properties) === null || _s_properties === void 0 ? void 0 : _s_properties.sheetId) === gid;
124
+ });
125
+ if (!sheet) {
126
+ throw new McpError(ErrorCode.InvalidParams, 'Sheet not found');
127
+ }
128
+ const sheetTitle = (_ref = sheet === null || sheet === void 0 ? void 0 : (_sheet_properties = sheet.properties) === null || _sheet_properties === void 0 ? void 0 : _sheet_properties.title) !== null && _ref !== void 0 ? _ref : '';
129
+ // Determine target headers (for sourceHasHeaders=true) or column count (for sourceHasHeaders=false)
130
+ let sheetHeaders = null;
131
+ let existingKeySet = new Set();
132
+ const keyColumns = deduplicateBy || [];
133
+ if (sourceHasHeaders) {
134
+ // Extract target header names from headerMap
135
+ const targetHeaderNames = headerMap.map(({ target })=>target).filter((t)=>typeof t === 'string');
136
+ // Use ensureTabAndHeaders to setup headers and fetch existing keys
137
+ const headerResult = await ensureTabAndHeaders(sheets, {
138
+ spreadsheetId: id,
139
+ sheetTitle,
140
+ requiredHeader: targetHeaderNames.length > 0 ? targetHeaderNames : null,
141
+ keyColumns: keyColumns.filter((k)=>typeof k === 'string'),
142
+ logger
143
+ });
144
+ sheetHeaders = headerResult.header;
145
+ existingKeySet = headerResult.keySet;
146
+ } else {
147
+ // sourceHasHeaders=false: Read existing data for deduplication (if needed)
148
+ if (deduplicateBy && deduplicateBy.length > 0) {
149
+ // Read data in chunks for memory efficiency with large sheets
150
+ const CHUNK_SIZE = 1000;
151
+ let startRow = 1;
152
+ let hasMore = true;
153
+ while(hasMore){
154
+ const endRow = startRow + CHUNK_SIZE - 1;
155
+ const chunkRange = `${sheetTitle}!A${startRow}:ZZZ${endRow}`;
156
+ const response = await sheets.spreadsheets.values.get({
157
+ spreadsheetId: id,
158
+ range: chunkRange
159
+ });
160
+ const rows = response.data.values || [];
161
+ for (const row of rows){
162
+ const key = buildDeduplicationKey(row, keyColumns, null, false);
163
+ if (key.replace(/::/g, '') !== '') {
164
+ existingKeySet.add(key);
165
+ }
166
+ }
167
+ // Check if there are more rows to read
168
+ if (rows.length < CHUNK_SIZE) {
169
+ hasMore = false;
170
+ } else {
171
+ startRow += CHUNK_SIZE;
172
+ }
173
+ }
174
+ logger.info('sheets.rows.csv-append existing keys loaded', {
175
+ keyCount: existingKeySet.size
176
+ });
177
+ }
178
+ }
179
+ // Streaming CSV processing state
180
+ let sourceHeaders = null;
181
+ let batch = [];
182
+ let totalRows = 0;
183
+ let rowsSkipped = 0;
184
+ // Get readable stream from CSV URI (no temp files!)
185
+ const readStream = await getCsvReadStream(sourceUri);
186
+ // Create CSV parser
187
+ const parser = readStream.pipe(parse({
188
+ columns: !!sourceHasHeaders,
189
+ skip_empty_lines: true,
190
+ trim: true,
191
+ cast: true,
192
+ relax_column_count: true
193
+ }));
194
+ // Helper to append batch to Sheets
195
+ const appendBatch = async (rows)=>{
196
+ if (rows.length === 0) return;
197
+ await sheets.spreadsheets.values.append({
198
+ spreadsheetId: id,
199
+ range: `${sheetTitle}!A:A`,
200
+ valueInputOption: 'USER_ENTERED',
201
+ requestBody: {
202
+ values: rows,
203
+ majorDimension: 'ROWS'
204
+ }
205
+ });
206
+ logger.info('sheets.rows.csv-append batch appended', {
207
+ batchSize: rows.length,
208
+ totalRows
209
+ });
210
+ };
211
+ // Resolve headerMap to numeric indices (do this after extracting CSV headers)
212
+ let resolvedMap = [];
213
+ // Stream and process records
214
+ for await (const record of parser){
215
+ if (sourceHasHeaders) {
216
+ // Extract source headers from first record
217
+ if (sourceHeaders === null) {
218
+ sourceHeaders = Object.keys(record);
219
+ logger.info('sheets.rows.csv-append source headers', {
220
+ sourceHeaders
221
+ });
222
+ // Resolve headerMap now that we have both source and sheet headers
223
+ resolvedMap = headerMap.map(({ source, target })=>({
224
+ sourceIdx: resolveColumnReference(source, sourceHeaders, sourceHasHeaders, 'headerMap.source'),
225
+ targetIdx: resolveColumnReference(target, sheetHeaders, sourceHasHeaders, 'headerMap.target')
226
+ }));
227
+ }
228
+ // Map source record to sheet row
229
+ const sourceRow = sourceHeaders === null || sourceHeaders === void 0 ? void 0 : sourceHeaders.map((h)=>{
230
+ var _record_h;
231
+ return (_record_h = record[h]) !== null && _record_h !== void 0 ? _record_h : null;
232
+ });
233
+ const maxTargetIdx = Math.max(...resolvedMap.map((m)=>m.targetIdx));
234
+ const sheetRow = new Array(maxTargetIdx + 1).fill(null);
235
+ for (const { sourceIdx, targetIdx } of resolvedMap){
236
+ if (sourceRow) {
237
+ var _sourceRow_sourceIdx;
238
+ sheetRow[targetIdx] = (_sourceRow_sourceIdx = sourceRow[sourceIdx]) !== null && _sourceRow_sourceIdx !== void 0 ? _sourceRow_sourceIdx : null;
239
+ }
240
+ }
241
+ // Check deduplication
242
+ if (deduplicateBy && deduplicateBy.length > 0) {
243
+ const key = buildDeduplicationKey(sheetRow, keyColumns, sheetHeaders, sourceHasHeaders);
244
+ if (existingKeySet.has(key)) {
245
+ rowsSkipped++;
246
+ continue; // Skip duplicate
247
+ }
248
+ existingKeySet.add(key); // Add to set for future deduplication
249
+ }
250
+ // Add to batch
251
+ batch.push(sheetRow);
252
+ totalRows++;
253
+ } else {
254
+ // sourceHasHeaders=false: record is an array (not an object)
255
+ // Resolve map on first row
256
+ if (resolvedMap.length === 0) {
257
+ resolvedMap = headerMap.map(({ source, target })=>({
258
+ sourceIdx: resolveColumnReference(source, null, sourceHasHeaders, 'headerMap.source'),
259
+ targetIdx: resolveColumnReference(target, null, sourceHasHeaders, 'headerMap.target')
260
+ }));
261
+ }
262
+ const sourceRow = record;
263
+ const maxTargetIdx = Math.max(...resolvedMap.map((m)=>m.targetIdx));
264
+ const sheetRow = new Array(maxTargetIdx + 1).fill(null);
265
+ for (const { sourceIdx, targetIdx } of resolvedMap){
266
+ if (sourceIdx < sourceRow.length) {
267
+ var _sourceRow_sourceIdx1;
268
+ sheetRow[targetIdx] = (_sourceRow_sourceIdx1 = sourceRow[sourceIdx]) !== null && _sourceRow_sourceIdx1 !== void 0 ? _sourceRow_sourceIdx1 : null;
269
+ }
270
+ }
271
+ // Check deduplication
272
+ if (deduplicateBy && deduplicateBy.length > 0) {
273
+ const key = buildDeduplicationKey(sheetRow, keyColumns, null, sourceHasHeaders);
274
+ if (existingKeySet.has(key)) {
275
+ rowsSkipped++;
276
+ continue; // Skip duplicate
277
+ }
278
+ existingKeySet.add(key);
279
+ }
280
+ // Add to batch
281
+ batch.push(sheetRow);
282
+ totalRows++;
283
+ }
284
+ // Append batch when full
285
+ if (batch.length >= BATCH_SIZE) {
286
+ await appendBatch(batch);
287
+ batch = []; // Clear batch
288
+ }
289
+ }
290
+ // Flush remaining rows
291
+ if (batch.length > 0) {
292
+ await appendBatch(batch);
293
+ }
294
+ logger.info('sheets.rows.csv-append streaming complete', {
295
+ totalRows,
296
+ rowsSkipped
297
+ });
298
+ const updatedRows = totalRows;
299
+ logger.info('sheets.rows.csv-append completed', {
300
+ id,
301
+ gid,
302
+ updatedRows,
303
+ rowsSkipped,
304
+ sourceUri
305
+ });
306
+ const result = {
307
+ type: 'success',
308
+ id,
309
+ gid,
310
+ sheetTitle,
311
+ updatedRows,
312
+ rowsSkipped,
313
+ sheetUrl: `https://docs.google.com/spreadsheets/d/${id}/edit#gid=${gid}`
314
+ };
315
+ return {
316
+ content: [
317
+ {
318
+ type: 'text',
319
+ text: JSON.stringify(result)
320
+ }
321
+ ],
322
+ structuredContent: {
323
+ result
324
+ }
325
+ };
326
+ } catch (error) {
327
+ const message = error instanceof Error ? error.message : String(error);
328
+ logger.error('sheets.rows.csv-append error', {
329
+ error: message
330
+ });
331
+ throw new McpError(ErrorCode.InternalError, `Error appending CSV rows: ${message}`, {
332
+ stack: error instanceof Error ? error.stack : undefined
333
+ });
334
+ }
335
+ }
336
+ export default function createTool() {
337
+ return {
338
+ name: 'rows-csv-append',
339
+ config,
340
+ handler
341
+ };
342
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/servers/mcp-sheets/src/mcp/tools/rows-csv-append.ts"],"sourcesContent":["/** Import CSV data to Google Sheets with database-style row append and deduplication */\n\nimport type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';\nimport { parse } from 'csv-parse';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\nimport { SheetGidOutput, SheetGidSchema, SpreadsheetIdOutput, SpreadsheetIdSchema } from '../../schemas/index.js';\nimport { getCsvReadStream } from '../../spreadsheet/csv-streaming.js';\nimport { buildDeduplicationKey } from '../../spreadsheet/deduplication-utils.js';\nimport { ensureTabAndHeaders } from '../../spreadsheet/sheet-operations.js';\n\n// Header mapping schema: source/target can be string (name) or number (0-based index)\nconst HeaderMapItemSchema = z.object({\n source: z.union([z.string(), z.number().int().min(0)]).describe('CSV column: header name (string) or 0-based index (number)'),\n target: z.union([z.string(), z.number().int().min(0)]).describe('Sheet column: header name (string) or 0-based index (number)'),\n});\n\nconst inputSchema = z.object({\n id: SpreadsheetIdSchema,\n gid: SheetGidSchema,\n sourceUri: z.string().trim().min(1).describe('CSV file URI (file://, http://, https://)'),\n sourceHasHeaders: z.boolean().default(true).describe('Source has header row for column name mapping. Set to false for data-only sources (numeric indices required).'),\n headerMap: z.array(HeaderMapItemSchema).describe('Column mappings from CSV to sheet'),\n deduplicateBy: z\n .array(z.union([z.string(), z.number().int().min(0)]))\n .optional()\n .describe('Sheet columns for deduplication (names or indices)'),\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n id: SpreadsheetIdOutput,\n gid: SheetGidOutput,\n sheetTitle: z.string().describe('Sheet tab name'),\n updatedRows: z.number().describe('Number of rows appended'),\n rowsSkipped: z.number().optional().describe('Number of duplicate rows skipped'),\n sheetUrl: z.string().optional().describe('URL to view the sheet'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Import CSV to Google Sheets with column mapping and optional deduplication. Streams data for large files.',\n inputSchema,\n outputSchema: z.object({\n result: outputSchema,\n }),\n} as const;\n\nexport type Input = z.infer<typeof inputSchema>;\nexport type Output = z.infer<typeof outputSchema>;\n\n/** Batch size for Sheets API calls (1000 rows × 12 cols = 12K cells, well under 40K limit) */\nconst BATCH_SIZE = 1000;\n\n/**\n * Resolve column reference to numeric index\n * @param ref Column reference (string name or number index)\n * @param headers Header row (null when sourceHasHeaders=false)\n * @param sourceHasHeaders Whether headers are present\n * @returns 0-based column index\n */\nfunction resolveColumnReference(ref: string | number, headers: string[] | null, sourceHasHeaders: boolean, context: string): number {\n // If number, use directly as 0-based index\n if (typeof ref === 'number') {\n if (ref < 0) {\n throw new Error(`${context}: Column index must be >= 0, got ${ref}`);\n }\n return ref;\n }\n\n // If string, must be header name\n if (!sourceHasHeaders || !headers) {\n throw new Error(`${context}: String column reference \"${ref}\" requires sourceHasHeaders=true. Use numeric index when sourceHasHeaders=false.`);\n }\n\n const index = headers.indexOf(ref);\n if (index === -1) {\n throw new Error(`${context}: Header \"${ref}\" not found in [${headers.join(', ')}]`);\n }\n\n return index;\n}\n\nasync function handler({ id, gid, sourceUri, sourceHasHeaders, headerMap, deduplicateBy }: Input, extra: EnrichedExtra): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('sheets.rows.csv-append called', { id, gid, sourceUri, sourceHasHeaders, headerMap, deduplicateBy });\n\n try {\n if (headerMap.length === 0) {\n throw new McpError(ErrorCode.InvalidParams, 'headerMap cannot be empty');\n }\n\n // Validate: if sourceHasHeaders=false, all references must be numeric\n if (!sourceHasHeaders) {\n for (const { source, target } of headerMap) {\n if (typeof source === 'string') {\n throw new McpError(ErrorCode.InvalidParams, `sourceHasHeaders=false requires numeric indices. Got string source: \"${source}\"`);\n }\n if (typeof target === 'string') {\n throw new McpError(ErrorCode.InvalidParams, `sourceHasHeaders=false requires numeric indices. Got string target: \"${target}\"`);\n }\n }\n if (deduplicateBy) {\n for (const colRef of deduplicateBy) {\n if (typeof colRef === 'string') {\n throw new McpError(ErrorCode.InvalidParams, `sourceHasHeaders=false requires numeric indices in deduplicateBy. Got string: \"${colRef}\"`);\n }\n }\n }\n }\n\n const sheets = google.sheets({ version: 'v4', auth: extra.authContext.auth });\n\n // Get sheet details using the gid\n const spreadsheetResponse = await sheets.spreadsheets.get({\n spreadsheetId: id,\n fields: 'sheets.properties.sheetId,sheets.properties.title',\n });\n\n const sheet = spreadsheetResponse.data.sheets?.find((s) => String(s.properties?.sheetId) === gid);\n\n if (!sheet) {\n throw new McpError(ErrorCode.InvalidParams, 'Sheet not found');\n }\n\n const sheetTitle = sheet?.properties?.title ?? '';\n\n // Determine target headers (for sourceHasHeaders=true) or column count (for sourceHasHeaders=false)\n let sheetHeaders: string[] | null = null;\n let existingKeySet: Set<string> = new Set();\n const keyColumns: (string | number)[] = deduplicateBy || [];\n\n if (sourceHasHeaders) {\n // Extract target header names from headerMap\n const targetHeaderNames = headerMap.map(({ target }) => target).filter((t) => typeof t === 'string') as string[];\n\n // Use ensureTabAndHeaders to setup headers and fetch existing keys\n const headerResult = await ensureTabAndHeaders(sheets, {\n spreadsheetId: id,\n sheetTitle,\n requiredHeader: targetHeaderNames.length > 0 ? targetHeaderNames : null,\n keyColumns: keyColumns.filter((k) => typeof k === 'string') as string[],\n logger,\n });\n\n sheetHeaders = headerResult.header;\n existingKeySet = headerResult.keySet;\n } else {\n // sourceHasHeaders=false: Read existing data for deduplication (if needed)\n if (deduplicateBy && deduplicateBy.length > 0) {\n // Read data in chunks for memory efficiency with large sheets\n const CHUNK_SIZE = 1000;\n let startRow = 1;\n let hasMore = true;\n\n while (hasMore) {\n const endRow = startRow + CHUNK_SIZE - 1;\n const chunkRange = `${sheetTitle}!A${startRow}:ZZZ${endRow}`;\n\n const response = await sheets.spreadsheets.values.get({\n spreadsheetId: id,\n range: chunkRange,\n });\n\n const rows = response.data.values || [];\n\n for (const row of rows) {\n const key = buildDeduplicationKey(row, keyColumns, null, false);\n if (key.replace(/::/g, '') !== '') {\n existingKeySet.add(key);\n }\n }\n\n // Check if there are more rows to read\n if (rows.length < CHUNK_SIZE) {\n hasMore = false;\n } else {\n startRow += CHUNK_SIZE;\n }\n }\n\n logger.info('sheets.rows.csv-append existing keys loaded', { keyCount: existingKeySet.size });\n }\n }\n\n // Streaming CSV processing state\n let sourceHeaders: string[] | null = null;\n let batch: (string | number | boolean | null)[][] = [];\n let totalRows = 0;\n let rowsSkipped = 0;\n\n // Get readable stream from CSV URI (no temp files!)\n const readStream = await getCsvReadStream(sourceUri);\n\n // Create CSV parser\n const parser = readStream.pipe(\n parse({\n columns: !!sourceHasHeaders, // Parse first row as column names if source has headers\n skip_empty_lines: true,\n trim: true,\n cast: true, // Auto-convert numbers/booleans\n relax_column_count: true,\n })\n );\n\n // Helper to append batch to Sheets\n const appendBatch = async (rows: (string | number | boolean | null)[][]): Promise<void> => {\n if (rows.length === 0) return;\n\n await sheets.spreadsheets.values.append({\n spreadsheetId: id,\n range: `${sheetTitle}!A:A`,\n valueInputOption: 'USER_ENTERED',\n requestBody: { values: rows, majorDimension: 'ROWS' },\n });\n\n logger.info('sheets.rows.csv-append batch appended', { batchSize: rows.length, totalRows });\n };\n\n // Resolve headerMap to numeric indices (do this after extracting CSV headers)\n let resolvedMap: Array<{ sourceIdx: number; targetIdx: number }> = [];\n\n // Stream and process records\n for await (const record of parser) {\n if (sourceHasHeaders) {\n // Extract source headers from first record\n if (sourceHeaders === null) {\n sourceHeaders = Object.keys(record as Record<string, unknown>);\n logger.info('sheets.rows.csv-append source headers', { sourceHeaders });\n\n // Resolve headerMap now that we have both source and sheet headers\n resolvedMap = headerMap.map(({ source, target }) => ({\n sourceIdx: resolveColumnReference(source, sourceHeaders, sourceHasHeaders, 'headerMap.source'),\n targetIdx: resolveColumnReference(target, sheetHeaders, sourceHasHeaders, 'headerMap.target'),\n }));\n }\n\n // Map source record to sheet row\n const sourceRow = sourceHeaders?.map((h) => (record as Record<string, unknown>)[h] ?? null);\n const maxTargetIdx = Math.max(...resolvedMap.map((m) => m.targetIdx));\n const sheetRow = new Array(maxTargetIdx + 1).fill(null);\n\n for (const { sourceIdx, targetIdx } of resolvedMap) {\n if (sourceRow) {\n sheetRow[targetIdx] = sourceRow[sourceIdx] ?? null;\n }\n }\n\n // Check deduplication\n if (deduplicateBy && deduplicateBy.length > 0) {\n const key = buildDeduplicationKey(sheetRow, keyColumns, sheetHeaders, sourceHasHeaders);\n if (existingKeySet.has(key)) {\n rowsSkipped++;\n continue; // Skip duplicate\n }\n existingKeySet.add(key); // Add to set for future deduplication\n }\n\n // Add to batch\n batch.push(sheetRow);\n totalRows++;\n } else {\n // sourceHasHeaders=false: record is an array (not an object)\n // Resolve map on first row\n if (resolvedMap.length === 0) {\n resolvedMap = headerMap.map(({ source, target }) => ({\n sourceIdx: resolveColumnReference(source, null, sourceHasHeaders, 'headerMap.source'),\n targetIdx: resolveColumnReference(target, null, sourceHasHeaders, 'headerMap.target'),\n }));\n }\n\n const sourceRow = record as unknown[];\n const maxTargetIdx = Math.max(...resolvedMap.map((m) => m.targetIdx));\n const sheetRow = new Array(maxTargetIdx + 1).fill(null);\n\n for (const { sourceIdx, targetIdx } of resolvedMap) {\n if (sourceIdx < sourceRow.length) {\n sheetRow[targetIdx] = sourceRow[sourceIdx] ?? null;\n }\n }\n\n // Check deduplication\n if (deduplicateBy && deduplicateBy.length > 0) {\n const key = buildDeduplicationKey(sheetRow, keyColumns, null, sourceHasHeaders);\n if (existingKeySet.has(key)) {\n rowsSkipped++;\n continue; // Skip duplicate\n }\n existingKeySet.add(key);\n }\n\n // Add to batch\n batch.push(sheetRow);\n totalRows++;\n }\n\n // Append batch when full\n if (batch.length >= BATCH_SIZE) {\n await appendBatch(batch);\n batch = []; // Clear batch\n }\n }\n\n // Flush remaining rows\n if (batch.length > 0) {\n await appendBatch(batch);\n }\n\n logger.info('sheets.rows.csv-append streaming complete', { totalRows, rowsSkipped });\n\n const updatedRows = totalRows;\n\n logger.info('sheets.rows.csv-append completed', { id, gid, updatedRows, rowsSkipped, sourceUri });\n\n const result: Output = {\n type: 'success' as const,\n id,\n gid,\n sheetTitle,\n updatedRows,\n rowsSkipped,\n sheetUrl: `https://docs.google.com/spreadsheets/d/${id}/edit#gid=${gid}`,\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(result) }],\n structuredContent: { result },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error('sheets.rows.csv-append error', { error: message });\n\n throw new McpError(ErrorCode.InternalError, `Error appending CSV rows: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'rows-csv-append',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ErrorCode","McpError","parse","google","z","SheetGidOutput","SheetGidSchema","SpreadsheetIdOutput","SpreadsheetIdSchema","getCsvReadStream","buildDeduplicationKey","ensureTabAndHeaders","HeaderMapItemSchema","object","source","union","string","number","int","min","describe","target","inputSchema","id","gid","sourceUri","trim","sourceHasHeaders","boolean","default","headerMap","array","deduplicateBy","optional","successBranchSchema","type","literal","sheetTitle","updatedRows","rowsSkipped","sheetUrl","outputSchema","discriminatedUnion","config","description","result","BATCH_SIZE","resolveColumnReference","ref","headers","context","Error","index","indexOf","join","handler","extra","logger","info","spreadsheetResponse","sheet","length","InvalidParams","colRef","sheets","version","auth","authContext","spreadsheets","get","spreadsheetId","fields","data","find","s","String","properties","sheetId","title","sheetHeaders","existingKeySet","Set","keyColumns","targetHeaderNames","map","filter","t","headerResult","requiredHeader","k","header","keySet","CHUNK_SIZE","startRow","hasMore","endRow","chunkRange","response","values","range","rows","row","key","replace","add","keyCount","size","sourceHeaders","batch","totalRows","readStream","parser","pipe","columns","skip_empty_lines","cast","relax_column_count","appendBatch","append","valueInputOption","requestBody","majorDimension","batchSize","resolvedMap","record","Object","keys","sourceIdx","targetIdx","sourceRow","h","maxTargetIdx","Math","max","m","sheetRow","Array","fill","has","push","content","text","JSON","stringify","structuredContent","error","message","InternalError","stack","undefined","createTool","name"],"mappings":"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"}