db-mcp 2.0.0 → 3.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 (553) hide show
  1. package/README.md +96 -91
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/adapters/database-adapter.d.ts +173 -0
  4. package/dist/adapters/database-adapter.d.ts.map +1 -0
  5. package/dist/adapters/query-validation.d.ts +20 -0
  6. package/dist/adapters/query-validation.d.ts.map +1 -0
  7. package/dist/adapters/registration/index.d.ts +4 -0
  8. package/dist/adapters/registration/index.d.ts.map +1 -0
  9. package/dist/adapters/registration/prompts.d.ts +7 -0
  10. package/dist/adapters/registration/prompts.d.ts.map +1 -0
  11. package/dist/adapters/registration/resources.d.ts +7 -0
  12. package/dist/adapters/registration/resources.d.ts.map +1 -0
  13. package/dist/adapters/registration/tools.d.ts +9 -0
  14. package/dist/adapters/registration/tools.d.ts.map +1 -0
  15. package/dist/adapters/sqlite/index.d.ts +9 -0
  16. package/dist/adapters/sqlite/index.d.ts.map +1 -0
  17. package/dist/adapters/sqlite/json-utils.d.ts +100 -0
  18. package/dist/adapters/sqlite/json-utils.d.ts.map +1 -0
  19. package/dist/adapters/sqlite/prompts/analysis.d.ts +23 -0
  20. package/dist/adapters/sqlite/prompts/analysis.d.ts.map +1 -0
  21. package/dist/adapters/sqlite/prompts/index.d.ts +16 -0
  22. package/dist/adapters/sqlite/prompts/index.d.ts.map +1 -0
  23. package/dist/adapters/sqlite/prompts/query.d.ts +19 -0
  24. package/dist/adapters/sqlite/prompts/query.d.ts.map +1 -0
  25. package/dist/adapters/sqlite/prompts/schema.d.ts +20 -0
  26. package/dist/adapters/sqlite/prompts/schema.d.ts.map +1 -0
  27. package/dist/adapters/sqlite/query-executor.d.ts +38 -0
  28. package/dist/adapters/sqlite/query-executor.d.ts.map +1 -0
  29. package/dist/adapters/sqlite/resources.d.ts +13 -0
  30. package/dist/adapters/sqlite/resources.d.ts.map +1 -0
  31. package/dist/adapters/sqlite/schema-manager.d.ts +69 -0
  32. package/dist/adapters/sqlite/schema-manager.d.ts.map +1 -0
  33. package/dist/adapters/sqlite/schemas/admin.d.ts +459 -0
  34. package/dist/adapters/sqlite/schemas/admin.d.ts.map +1 -0
  35. package/dist/adapters/sqlite/schemas/codemode.d.ts +30 -0
  36. package/dist/adapters/sqlite/schemas/codemode.d.ts.map +1 -0
  37. package/dist/adapters/sqlite/schemas/common.d.ts +9 -0
  38. package/dist/adapters/sqlite/schemas/common.d.ts.map +1 -0
  39. package/dist/adapters/sqlite/schemas/core.d.ts +530 -0
  40. package/dist/adapters/sqlite/schemas/core.d.ts.map +1 -0
  41. package/dist/adapters/sqlite/schemas/error-mixin.d.ts +10 -0
  42. package/dist/adapters/sqlite/schemas/error-mixin.d.ts.map +1 -0
  43. package/dist/adapters/sqlite/schemas/fts.d.ts +106 -0
  44. package/dist/adapters/sqlite/schemas/fts.d.ts.map +1 -0
  45. package/dist/adapters/sqlite/schemas/geo.d.ts +135 -0
  46. package/dist/adapters/sqlite/schemas/geo.d.ts.map +1 -0
  47. package/dist/adapters/sqlite/schemas/index.d.ts +23 -0
  48. package/dist/adapters/sqlite/schemas/index.d.ts.map +1 -0
  49. package/dist/adapters/sqlite/schemas/introspection.d.ts +583 -0
  50. package/dist/adapters/sqlite/schemas/introspection.d.ts.map +1 -0
  51. package/dist/adapters/sqlite/schemas/json.d.ts +849 -0
  52. package/dist/adapters/sqlite/schemas/json.d.ts.map +1 -0
  53. package/dist/adapters/sqlite/schemas/migration.d.ts +220 -0
  54. package/dist/adapters/sqlite/schemas/migration.d.ts.map +1 -0
  55. package/dist/adapters/sqlite/schemas/native.d.ts +235 -0
  56. package/dist/adapters/sqlite/schemas/native.d.ts.map +1 -0
  57. package/dist/adapters/sqlite/schemas/server.d.ts +13 -0
  58. package/dist/adapters/sqlite/schemas/server.d.ts.map +1 -0
  59. package/dist/adapters/sqlite/schemas/spatialite.d.ts +114 -0
  60. package/dist/adapters/sqlite/schemas/spatialite.d.ts.map +1 -0
  61. package/dist/adapters/sqlite/schemas/stats.d.ts +780 -0
  62. package/dist/adapters/sqlite/schemas/stats.d.ts.map +1 -0
  63. package/dist/adapters/sqlite/schemas/text.d.ts +570 -0
  64. package/dist/adapters/sqlite/schemas/text.d.ts.map +1 -0
  65. package/dist/adapters/sqlite/schemas/vector.d.ts +252 -0
  66. package/dist/adapters/sqlite/schemas/vector.d.ts.map +1 -0
  67. package/dist/adapters/sqlite/schemas/virtual.d.ts +257 -0
  68. package/dist/adapters/sqlite/schemas/virtual.d.ts.map +1 -0
  69. package/dist/adapters/sqlite/schemas/where.d.ts +20 -0
  70. package/dist/adapters/sqlite/schemas/where.d.ts.map +1 -0
  71. package/dist/adapters/sqlite/sqlite-adapter/lifecycle.d.ts +13 -0
  72. package/dist/adapters/sqlite/sqlite-adapter/lifecycle.d.ts.map +1 -0
  73. package/dist/adapters/sqlite/sqlite-adapter/schema.d.ts +7 -0
  74. package/dist/adapters/sqlite/sqlite-adapter/schema.d.ts.map +1 -0
  75. package/dist/adapters/sqlite/sqlite-adapter.d.ts +138 -0
  76. package/dist/adapters/sqlite/sqlite-adapter.d.ts.map +1 -0
  77. package/dist/adapters/sqlite/tools/admin/backup/analyze.d.ts +7 -0
  78. package/dist/adapters/sqlite/tools/admin/backup/analyze.d.ts.map +1 -0
  79. package/dist/adapters/sqlite/tools/admin/backup/create.d.ts +11 -0
  80. package/dist/adapters/sqlite/tools/admin/backup/create.d.ts.map +1 -0
  81. package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts +7 -0
  82. package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts.map +1 -0
  83. package/dist/adapters/sqlite/tools/admin/backup/index.d.ts +7 -0
  84. package/dist/adapters/sqlite/tools/admin/backup/index.d.ts.map +1 -0
  85. package/dist/adapters/sqlite/tools/admin/backup/integrity.d.ts +7 -0
  86. package/dist/adapters/sqlite/tools/admin/backup/integrity.d.ts.map +1 -0
  87. package/dist/adapters/sqlite/tools/admin/backup/optimize.d.ts +7 -0
  88. package/dist/adapters/sqlite/tools/admin/backup/optimize.d.ts.map +1 -0
  89. package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts +7 -0
  90. package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts.map +1 -0
  91. package/dist/adapters/sqlite/tools/admin/helpers.d.ts +18 -0
  92. package/dist/adapters/sqlite/tools/admin/helpers.d.ts.map +1 -0
  93. package/dist/adapters/sqlite/tools/admin/index.d.ts +10 -0
  94. package/dist/adapters/sqlite/tools/admin/index.d.ts.map +1 -0
  95. package/dist/adapters/sqlite/tools/admin/pragma.d.ts +37 -0
  96. package/dist/adapters/sqlite/tools/admin/pragma.d.ts.map +1 -0
  97. package/dist/adapters/sqlite/tools/admin/reindex.d.ts +10 -0
  98. package/dist/adapters/sqlite/tools/admin/reindex.d.ts.map +1 -0
  99. package/dist/adapters/sqlite/tools/admin/verify.d.ts +13 -0
  100. package/dist/adapters/sqlite/tools/admin/verify.d.ts.map +1 -0
  101. package/dist/adapters/sqlite/tools/admin/wal.d.ts +10 -0
  102. package/dist/adapters/sqlite/tools/admin/wal.d.ts.map +1 -0
  103. package/dist/adapters/sqlite/tools/codemode.d.ts +22 -0
  104. package/dist/adapters/sqlite/tools/codemode.d.ts.map +1 -0
  105. package/dist/adapters/sqlite/tools/column-validation.d.ts +26 -0
  106. package/dist/adapters/sqlite/tools/column-validation.d.ts.map +1 -0
  107. package/dist/adapters/sqlite/tools/core/alter-table.d.ts +11 -0
  108. package/dist/adapters/sqlite/tools/core/alter-table.d.ts.map +1 -0
  109. package/dist/adapters/sqlite/tools/core/constraints.d.ts +10 -0
  110. package/dist/adapters/sqlite/tools/core/constraints.d.ts.map +1 -0
  111. package/dist/adapters/sqlite/tools/core/convenience-helpers.d.ts +20 -0
  112. package/dist/adapters/sqlite/tools/core/convenience-helpers.d.ts.map +1 -0
  113. package/dist/adapters/sqlite/tools/core/convenience-schemas.d.ts +20 -0
  114. package/dist/adapters/sqlite/tools/core/convenience-schemas.d.ts.map +1 -0
  115. package/dist/adapters/sqlite/tools/core/convenience.d.ts +29 -0
  116. package/dist/adapters/sqlite/tools/core/convenience.d.ts.map +1 -0
  117. package/dist/adapters/sqlite/tools/core/datetime.d.ts +11 -0
  118. package/dist/adapters/sqlite/tools/core/datetime.d.ts.map +1 -0
  119. package/dist/adapters/sqlite/tools/core/index.d.ts +14 -0
  120. package/dist/adapters/sqlite/tools/core/index.d.ts.map +1 -0
  121. package/dist/adapters/sqlite/tools/core/indexes.d.ts +20 -0
  122. package/dist/adapters/sqlite/tools/core/indexes.d.ts.map +1 -0
  123. package/dist/adapters/sqlite/tools/core/queries.d.ts +16 -0
  124. package/dist/adapters/sqlite/tools/core/queries.d.ts.map +1 -0
  125. package/dist/adapters/sqlite/tools/core/tables.d.ts +37 -0
  126. package/dist/adapters/sqlite/tools/core/tables.d.ts.map +1 -0
  127. package/dist/adapters/sqlite/tools/core/triggers.d.ts +18 -0
  128. package/dist/adapters/sqlite/tools/core/triggers.d.ts.map +1 -0
  129. package/dist/adapters/sqlite/tools/fts.d.ts +13 -0
  130. package/dist/adapters/sqlite/tools/fts.d.ts.map +1 -0
  131. package/dist/adapters/sqlite/tools/geo.d.ts +14 -0
  132. package/dist/adapters/sqlite/tools/geo.d.ts.map +1 -0
  133. package/dist/adapters/sqlite/tools/index.d.ts +33 -0
  134. package/dist/adapters/sqlite/tools/index.d.ts.map +1 -0
  135. package/dist/adapters/sqlite/tools/introspection/analysis/constraints.d.ts +10 -0
  136. package/dist/adapters/sqlite/tools/introspection/analysis/constraints.d.ts.map +1 -0
  137. package/dist/adapters/sqlite/tools/introspection/analysis/diff.d.ts +11 -0
  138. package/dist/adapters/sqlite/tools/introspection/analysis/diff.d.ts.map +1 -0
  139. package/dist/adapters/sqlite/tools/introspection/analysis/index.d.ts +10 -0
  140. package/dist/adapters/sqlite/tools/introspection/analysis/index.d.ts.map +1 -0
  141. package/dist/adapters/sqlite/tools/introspection/analysis/risks.d.ts +9 -0
  142. package/dist/adapters/sqlite/tools/introspection/analysis/risks.d.ts.map +1 -0
  143. package/dist/adapters/sqlite/tools/introspection/analysis/snapshot.d.ts +40 -0
  144. package/dist/adapters/sqlite/tools/introspection/analysis/snapshot.d.ts.map +1 -0
  145. package/dist/adapters/sqlite/tools/introspection/diagnostics/index.d.ts +9 -0
  146. package/dist/adapters/sqlite/tools/introspection/diagnostics/index.d.ts.map +1 -0
  147. package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts +10 -0
  148. package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts.map +1 -0
  149. package/dist/adapters/sqlite/tools/introspection/diagnostics/query-plan.d.ts +10 -0
  150. package/dist/adapters/sqlite/tools/introspection/diagnostics/query-plan.d.ts.map +1 -0
  151. package/dist/adapters/sqlite/tools/introspection/diagnostics/storage.d.ts +10 -0
  152. package/dist/adapters/sqlite/tools/introspection/diagnostics/storage.d.ts.map +1 -0
  153. package/dist/adapters/sqlite/tools/introspection/graph/helpers.d.ts +44 -0
  154. package/dist/adapters/sqlite/tools/introspection/graph/helpers.d.ts.map +1 -0
  155. package/dist/adapters/sqlite/tools/introspection/graph/index.d.ts +9 -0
  156. package/dist/adapters/sqlite/tools/introspection/graph/index.d.ts.map +1 -0
  157. package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts +12 -0
  158. package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts.map +1 -0
  159. package/dist/adapters/sqlite/tools/introspection/index.d.ts +17 -0
  160. package/dist/adapters/sqlite/tools/introspection/index.d.ts.map +1 -0
  161. package/dist/adapters/sqlite/tools/json-helpers/helpers.d.ts +21 -0
  162. package/dist/adapters/sqlite/tools/json-helpers/helpers.d.ts.map +1 -0
  163. package/dist/adapters/sqlite/tools/json-helpers/index.d.ts +17 -0
  164. package/dist/adapters/sqlite/tools/json-helpers/index.d.ts.map +1 -0
  165. package/dist/adapters/sqlite/tools/json-helpers/read.d.ts +24 -0
  166. package/dist/adapters/sqlite/tools/json-helpers/read.d.ts.map +1 -0
  167. package/dist/adapters/sqlite/tools/json-helpers/write.d.ts +24 -0
  168. package/dist/adapters/sqlite/tools/json-helpers/write.d.ts.map +1 -0
  169. package/dist/adapters/sqlite/tools/json-operations/crud.d.ts +39 -0
  170. package/dist/adapters/sqlite/tools/json-operations/crud.d.ts.map +1 -0
  171. package/dist/adapters/sqlite/tools/json-operations/diff.d.ts +11 -0
  172. package/dist/adapters/sqlite/tools/json-operations/diff.d.ts.map +1 -0
  173. package/dist/adapters/sqlite/tools/json-operations/helpers.d.ts +18 -0
  174. package/dist/adapters/sqlite/tools/json-operations/helpers.d.ts.map +1 -0
  175. package/dist/adapters/sqlite/tools/json-operations/index.d.ts +10 -0
  176. package/dist/adapters/sqlite/tools/json-operations/index.d.ts.map +1 -0
  177. package/dist/adapters/sqlite/tools/json-operations/query.d.ts +24 -0
  178. package/dist/adapters/sqlite/tools/json-operations/query.d.ts.map +1 -0
  179. package/dist/adapters/sqlite/tools/json-operations/security.d.ts +19 -0
  180. package/dist/adapters/sqlite/tools/json-operations/security.d.ts.map +1 -0
  181. package/dist/adapters/sqlite/tools/json-operations/transform.d.ts +24 -0
  182. package/dist/adapters/sqlite/tools/json-operations/transform.d.ts.map +1 -0
  183. package/dist/adapters/sqlite/tools/migration/helpers.d.ts +34 -0
  184. package/dist/adapters/sqlite/tools/migration/helpers.d.ts.map +1 -0
  185. package/dist/adapters/sqlite/tools/migration/index.d.ts +15 -0
  186. package/dist/adapters/sqlite/tools/migration/index.d.ts.map +1 -0
  187. package/dist/adapters/sqlite/tools/migration/tracking/apply.d.ts +4 -0
  188. package/dist/adapters/sqlite/tools/migration/tracking/apply.d.ts.map +1 -0
  189. package/dist/adapters/sqlite/tools/migration/tracking/history.d.ts +4 -0
  190. package/dist/adapters/sqlite/tools/migration/tracking/history.d.ts.map +1 -0
  191. package/dist/adapters/sqlite/tools/migration/tracking/index.d.ts +7 -0
  192. package/dist/adapters/sqlite/tools/migration/tracking/index.d.ts.map +1 -0
  193. package/dist/adapters/sqlite/tools/migration/tracking/init.d.ts +4 -0
  194. package/dist/adapters/sqlite/tools/migration/tracking/init.d.ts.map +1 -0
  195. package/dist/adapters/sqlite/tools/migration/tracking/record.d.ts +4 -0
  196. package/dist/adapters/sqlite/tools/migration/tracking/record.d.ts.map +1 -0
  197. package/dist/adapters/sqlite/tools/migration/tracking/rollback.d.ts +4 -0
  198. package/dist/adapters/sqlite/tools/migration/tracking/rollback.d.ts.map +1 -0
  199. package/dist/adapters/sqlite/tools/migration/tracking/status.d.ts +4 -0
  200. package/dist/adapters/sqlite/tools/migration/tracking/status.d.ts.map +1 -0
  201. package/dist/adapters/sqlite/tools/stats/advanced.d.ts +28 -0
  202. package/dist/adapters/sqlite/tools/stats/advanced.d.ts.map +1 -0
  203. package/dist/adapters/sqlite/tools/stats/anomaly-detection.d.ts +22 -0
  204. package/dist/adapters/sqlite/tools/stats/anomaly-detection.d.ts.map +1 -0
  205. package/dist/adapters/sqlite/tools/stats/basic.d.ts +32 -0
  206. package/dist/adapters/sqlite/tools/stats/basic.d.ts.map +1 -0
  207. package/dist/adapters/sqlite/tools/stats/helpers.d.ts +27 -0
  208. package/dist/adapters/sqlite/tools/stats/helpers.d.ts.map +1 -0
  209. package/dist/adapters/sqlite/tools/stats/index.d.ts +12 -0
  210. package/dist/adapters/sqlite/tools/stats/index.d.ts.map +1 -0
  211. package/dist/adapters/sqlite/tools/stats/inference/hypothesis.d.ts +7 -0
  212. package/dist/adapters/sqlite/tools/stats/inference/hypothesis.d.ts.map +1 -0
  213. package/dist/adapters/sqlite/tools/stats/inference/index.d.ts +4 -0
  214. package/dist/adapters/sqlite/tools/stats/inference/index.d.ts.map +1 -0
  215. package/dist/adapters/sqlite/tools/stats/inference/outlier.d.ts +7 -0
  216. package/dist/adapters/sqlite/tools/stats/inference/outlier.d.ts.map +1 -0
  217. package/dist/adapters/sqlite/tools/stats/inference/regression.d.ts +7 -0
  218. package/dist/adapters/sqlite/tools/stats/inference/regression.d.ts.map +1 -0
  219. package/dist/adapters/sqlite/tools/stats/math-helpers.d.ts +17 -0
  220. package/dist/adapters/sqlite/tools/stats/math-helpers.d.ts.map +1 -0
  221. package/dist/adapters/sqlite/tools/stats/schema-risks.d.ts +15 -0
  222. package/dist/adapters/sqlite/tools/stats/schema-risks.d.ts.map +1 -0
  223. package/dist/adapters/sqlite/tools/text/formatting.d.ts +48 -0
  224. package/dist/adapters/sqlite/tools/text/formatting.d.ts.map +1 -0
  225. package/dist/adapters/sqlite/tools/text/helpers.d.ts +22 -0
  226. package/dist/adapters/sqlite/tools/text/helpers.d.ts.map +1 -0
  227. package/dist/adapters/sqlite/tools/text/index.d.ts +10 -0
  228. package/dist/adapters/sqlite/tools/text/index.d.ts.map +1 -0
  229. package/dist/adapters/sqlite/tools/text/regex.d.ts +21 -0
  230. package/dist/adapters/sqlite/tools/text/regex.d.ts.map +1 -0
  231. package/dist/adapters/sqlite/tools/text/search.d.ts +17 -0
  232. package/dist/adapters/sqlite/tools/text/search.d.ts.map +1 -0
  233. package/dist/adapters/sqlite/tools/text/sentiment.d.ts +13 -0
  234. package/dist/adapters/sqlite/tools/text/sentiment.d.ts.map +1 -0
  235. package/dist/adapters/sqlite/tools/text/validate.d.ts +11 -0
  236. package/dist/adapters/sqlite/tools/text/validate.d.ts.map +1 -0
  237. package/dist/adapters/sqlite/tools/vector/helpers.d.ts +11 -0
  238. package/dist/adapters/sqlite/tools/vector/helpers.d.ts.map +1 -0
  239. package/dist/adapters/sqlite/tools/vector/index.d.ts +14 -0
  240. package/dist/adapters/sqlite/tools/vector/index.d.ts.map +1 -0
  241. package/dist/adapters/sqlite/tools/vector/metadata.d.ts +28 -0
  242. package/dist/adapters/sqlite/tools/vector/metadata.d.ts.map +1 -0
  243. package/dist/adapters/sqlite/tools/vector/search.d.ts +16 -0
  244. package/dist/adapters/sqlite/tools/vector/search.d.ts.map +1 -0
  245. package/dist/adapters/sqlite/tools/vector/storage.d.ts +24 -0
  246. package/dist/adapters/sqlite/tools/vector/storage.d.ts.map +1 -0
  247. package/dist/adapters/sqlite/tools/vector/tools.d.ts +9 -0
  248. package/dist/adapters/sqlite/tools/vector/tools.d.ts.map +1 -0
  249. package/dist/adapters/sqlite/tools/virtual/analysis.d.ts +24 -0
  250. package/dist/adapters/sqlite/tools/virtual/analysis.d.ts.map +1 -0
  251. package/dist/adapters/sqlite/tools/virtual/extensions.d.ts +13 -0
  252. package/dist/adapters/sqlite/tools/virtual/extensions.d.ts.map +1 -0
  253. package/dist/adapters/sqlite/tools/virtual/helpers.d.ts +18 -0
  254. package/dist/adapters/sqlite/tools/virtual/helpers.d.ts.map +1 -0
  255. package/dist/adapters/sqlite/tools/virtual/index.d.ts +10 -0
  256. package/dist/adapters/sqlite/tools/virtual/index.d.ts.map +1 -0
  257. package/dist/adapters/sqlite/tools/virtual/views.d.ts +21 -0
  258. package/dist/adapters/sqlite/tools/virtual/views.d.ts.map +1 -0
  259. package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts +4 -0
  260. package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts.map +1 -0
  261. package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts +4 -0
  262. package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts.map +1 -0
  263. package/dist/adapters/sqlite/tools/virtual/vtable/drop.d.ts +4 -0
  264. package/dist/adapters/sqlite/tools/virtual/vtable/drop.d.ts.map +1 -0
  265. package/dist/adapters/sqlite/tools/virtual/vtable/index.d.ts +6 -0
  266. package/dist/adapters/sqlite/tools/virtual/vtable/index.d.ts.map +1 -0
  267. package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts +4 -0
  268. package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts.map +1 -0
  269. package/dist/adapters/sqlite/tools/virtual/vtable/list.d.ts +4 -0
  270. package/dist/adapters/sqlite/tools/virtual/vtable/list.d.ts.map +1 -0
  271. package/dist/adapters/sqlite/types.d.ts +89 -0
  272. package/dist/adapters/sqlite/types.d.ts.map +1 -0
  273. package/dist/adapters/sqlite-helpers.d.ts +51 -0
  274. package/dist/adapters/sqlite-helpers.d.ts.map +1 -0
  275. package/dist/adapters/sqlite-native/extensions.d.ts +17 -0
  276. package/dist/adapters/sqlite-native/extensions.d.ts.map +1 -0
  277. package/dist/adapters/sqlite-native/index.d.ts +11 -0
  278. package/dist/adapters/sqlite-native/index.d.ts.map +1 -0
  279. package/dist/adapters/sqlite-native/native-query-executor.d.ts +24 -0
  280. package/dist/adapters/sqlite-native/native-query-executor.d.ts.map +1 -0
  281. package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts +160 -0
  282. package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts.map +1 -0
  283. package/dist/adapters/sqlite-native/registration/index.d.ts +12 -0
  284. package/dist/adapters/sqlite-native/registration/index.d.ts.map +1 -0
  285. package/dist/adapters/sqlite-native/tools/spatialite/analysis.d.ts +23 -0
  286. package/dist/adapters/sqlite-native/tools/spatialite/analysis.d.ts.map +1 -0
  287. package/dist/adapters/sqlite-native/tools/spatialite/index.d.ts +15 -0
  288. package/dist/adapters/sqlite-native/tools/spatialite/index.d.ts.map +1 -0
  289. package/dist/adapters/sqlite-native/tools/spatialite/loader.d.ts +22 -0
  290. package/dist/adapters/sqlite-native/tools/spatialite/loader.d.ts.map +1 -0
  291. package/dist/adapters/sqlite-native/tools/spatialite/schemas.d.ts +78 -0
  292. package/dist/adapters/sqlite-native/tools/spatialite/schemas.d.ts.map +1 -0
  293. package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts +30 -0
  294. package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts.map +1 -0
  295. package/dist/adapters/sqlite-native/tools/transactions.d.ts +12 -0
  296. package/dist/adapters/sqlite-native/tools/transactions.d.ts.map +1 -0
  297. package/dist/adapters/sqlite-native/tools/window.d.ts +7 -0
  298. package/dist/adapters/sqlite-native/tools/window.d.ts.map +1 -0
  299. package/dist/adapters/sqlite-native/transaction-methods.d.ts +36 -0
  300. package/dist/adapters/sqlite-native/transaction-methods.d.ts.map +1 -0
  301. package/dist/audit/backup-manager.d.ts +90 -0
  302. package/dist/audit/backup-manager.d.ts.map +1 -0
  303. package/dist/audit/index.d.ts +11 -0
  304. package/dist/audit/index.d.ts.map +1 -0
  305. package/dist/audit/interceptor.d.ts +54 -0
  306. package/dist/audit/interceptor.d.ts.map +1 -0
  307. package/dist/audit/logger.d.ts +62 -0
  308. package/dist/audit/logger.d.ts.map +1 -0
  309. package/dist/audit/types.d.ts +112 -0
  310. package/dist/audit/types.d.ts.map +1 -0
  311. package/dist/auth/auth-context.d.ts +28 -0
  312. package/dist/auth/auth-context.d.ts.map +1 -0
  313. package/dist/auth/authorization-server-discovery.d.ts +90 -0
  314. package/dist/auth/authorization-server-discovery.d.ts.map +1 -0
  315. package/dist/auth/errors.d.ts +74 -0
  316. package/dist/auth/errors.d.ts.map +1 -0
  317. package/dist/auth/middleware/core.d.ts +22 -0
  318. package/dist/auth/middleware/core.d.ts.map +1 -0
  319. package/dist/auth/middleware/express-auth.d.ts +13 -0
  320. package/dist/auth/middleware/express-auth.d.ts.map +1 -0
  321. package/dist/auth/middleware/express-scopes.d.ts +6 -0
  322. package/dist/auth/middleware/express-scopes.d.ts.map +1 -0
  323. package/dist/auth/middleware/extraction.d.ts +2 -0
  324. package/dist/auth/middleware/extraction.d.ts.map +1 -0
  325. package/dist/auth/middleware/index.d.ts +5 -0
  326. package/dist/auth/middleware/index.d.ts.map +1 -0
  327. package/dist/auth/oauth-resource-server.d.ts +74 -0
  328. package/dist/auth/oauth-resource-server.d.ts.map +1 -0
  329. package/dist/auth/scope-map.d.ts +24 -0
  330. package/dist/auth/scope-map.d.ts.map +1 -0
  331. package/dist/auth/scopes/constants.d.ts +40 -0
  332. package/dist/auth/scopes/constants.d.ts.map +1 -0
  333. package/dist/auth/scopes/display.d.ts +5 -0
  334. package/dist/auth/scopes/display.d.ts.map +1 -0
  335. package/dist/auth/scopes/enforcement.d.ts +27 -0
  336. package/dist/auth/scopes/enforcement.d.ts.map +1 -0
  337. package/dist/auth/scopes/index.d.ts +6 -0
  338. package/dist/auth/scopes/index.d.ts.map +1 -0
  339. package/dist/auth/scopes/mapping.d.ts +39 -0
  340. package/dist/auth/scopes/mapping.d.ts.map +1 -0
  341. package/dist/auth/scopes/validation.d.ts +27 -0
  342. package/dist/auth/scopes/validation.d.ts.map +1 -0
  343. package/dist/auth/token-validator.d.ts +63 -0
  344. package/dist/auth/token-validator.d.ts.map +1 -0
  345. package/dist/auth/transport-agnostic.d.ts +11 -0
  346. package/dist/auth/transport-agnostic.d.ts.map +1 -0
  347. package/dist/auth/types.d.ts +257 -0
  348. package/dist/auth/types.d.ts.map +1 -0
  349. package/dist/chunk-E5IESRTK.js +489 -0
  350. package/dist/{chunk-5Y42NPBP.js → chunk-FR65YPAH.js} +4657 -1830
  351. package/dist/{chunk-645ZEFLA.js → chunk-L552U3QS.js} +887 -309
  352. package/dist/{chunk-WBER5YY4.js → chunk-THATOQRT.js} +1026 -455
  353. package/dist/{chunk-Z7C2TM4L.js → chunk-W5WQVNVX.js} +169 -57
  354. package/dist/cli.d.ts +7 -0
  355. package/dist/cli.d.ts.map +1 -0
  356. package/dist/cli.js +47 -26
  357. package/dist/codemode/api-constants.d.ts +40 -0
  358. package/dist/codemode/api-constants.d.ts.map +1 -0
  359. package/dist/codemode/api.d.ts +70 -0
  360. package/dist/codemode/api.d.ts.map +1 -0
  361. package/dist/codemode/auto-return.d.ts +25 -0
  362. package/dist/codemode/auto-return.d.ts.map +1 -0
  363. package/dist/codemode/index.d.ts +12 -0
  364. package/dist/codemode/index.d.ts.map +1 -0
  365. package/dist/codemode/sandbox-factory.d.ts +72 -0
  366. package/dist/codemode/sandbox-factory.d.ts.map +1 -0
  367. package/dist/codemode/sandbox.d.ts +54 -0
  368. package/dist/codemode/sandbox.d.ts.map +1 -0
  369. package/dist/codemode/security.d.ts +45 -0
  370. package/dist/codemode/security.d.ts.map +1 -0
  371. package/dist/codemode/types.d.ts +167 -0
  372. package/dist/codemode/types.d.ts.map +1 -0
  373. package/dist/constants/server-instructions.d.ts +22 -0
  374. package/dist/constants/server-instructions.d.ts.map +1 -0
  375. package/dist/filtering/tool-constants.d.ts +45 -0
  376. package/dist/filtering/tool-constants.d.ts.map +1 -0
  377. package/dist/filtering/tool-filter.d.ts +82 -0
  378. package/dist/filtering/tool-filter.d.ts.map +1 -0
  379. package/dist/{http-6KF4ULDI.js → http-HWTUVFIA.js} +498 -391
  380. package/dist/index.d.ts +9 -1065
  381. package/dist/index.d.ts.map +1 -0
  382. package/dist/index.js +4 -6
  383. package/dist/server/mcp-server.d.ts +66 -0
  384. package/dist/server/mcp-server.d.ts.map +1 -0
  385. package/dist/server/registration/audit-tools.d.ts +13 -0
  386. package/dist/server/registration/audit-tools.d.ts.map +1 -0
  387. package/dist/server/registration/built-in-tools.d.ts +8 -0
  388. package/dist/server/registration/built-in-tools.d.ts.map +1 -0
  389. package/dist/server/registration/help-resources.d.ts +7 -0
  390. package/dist/server/registration/help-resources.d.ts.map +1 -0
  391. package/dist/server/registration/index.d.ts +4 -0
  392. package/dist/server/registration/index.d.ts.map +1 -0
  393. package/dist/{sqlite-U5KSYQXK.js → sqlite-6C3AJI4I.js} +61 -17
  394. package/dist/{sqlite-native-JXMCFQBA.js → sqlite-native-ZSSWCTYC.js} +459 -254
  395. package/dist/transports/http/index.d.ts +8 -0
  396. package/dist/transports/http/index.d.ts.map +1 -0
  397. package/dist/transports/http/middleware.d.ts +25 -0
  398. package/dist/transports/http/middleware.d.ts.map +1 -0
  399. package/dist/transports/http/oauth.d.ts +24 -0
  400. package/dist/transports/http/oauth.d.ts.map +1 -0
  401. package/dist/transports/http/session.d.ts +2 -0
  402. package/dist/transports/http/session.d.ts.map +1 -0
  403. package/dist/transports/http/sessions/index.d.ts +4 -0
  404. package/dist/transports/http/sessions/index.d.ts.map +1 -0
  405. package/dist/transports/http/sessions/legacy-sse.d.ts +6 -0
  406. package/dist/transports/http/sessions/legacy-sse.d.ts.map +1 -0
  407. package/dist/transports/http/sessions/mutex.d.ts +6 -0
  408. package/dist/transports/http/sessions/mutex.d.ts.map +1 -0
  409. package/dist/transports/http/sessions/stateful.d.ts +12 -0
  410. package/dist/transports/http/sessions/stateful.d.ts.map +1 -0
  411. package/dist/transports/http/sessions/stateless.d.ts +6 -0
  412. package/dist/transports/http/sessions/stateless.d.ts.map +1 -0
  413. package/dist/transports/http/transport.d.ts +65 -0
  414. package/dist/transports/http/transport.d.ts.map +1 -0
  415. package/dist/transports/http/type-adapters.d.ts +20 -0
  416. package/dist/transports/http/type-adapters.d.ts.map +1 -0
  417. package/dist/transports/http/types.d.ts +120 -0
  418. package/dist/transports/http/types.d.ts.map +1 -0
  419. package/dist/types/adapter.d.ts +138 -0
  420. package/dist/types/adapter.d.ts.map +1 -0
  421. package/dist/types/auth.d.ts +79 -0
  422. package/dist/types/auth.d.ts.map +1 -0
  423. package/dist/types/database.d.ts +100 -0
  424. package/dist/types/database.d.ts.map +1 -0
  425. package/dist/types/filtering.d.ts +41 -0
  426. package/dist/types/filtering.d.ts.map +1 -0
  427. package/dist/types/index.d.ts +13 -0
  428. package/dist/types/index.d.ts.map +1 -0
  429. package/dist/types/server.d.ts +48 -0
  430. package/dist/types/server.d.ts.map +1 -0
  431. package/dist/utils/annotations.d.ts +62 -0
  432. package/dist/utils/annotations.d.ts.map +1 -0
  433. package/dist/utils/errors/base.d.ts +33 -0
  434. package/dist/utils/errors/base.d.ts.map +1 -0
  435. package/dist/utils/errors/categories.d.ts +41 -0
  436. package/dist/utils/errors/categories.d.ts.map +1 -0
  437. package/dist/utils/errors/classes.d.ts +124 -0
  438. package/dist/utils/errors/classes.d.ts.map +1 -0
  439. package/dist/utils/errors/error-response-fields.d.ts +24 -0
  440. package/dist/utils/errors/error-response-fields.d.ts.map +1 -0
  441. package/dist/utils/errors/format.d.ts +74 -0
  442. package/dist/utils/errors/format.d.ts.map +1 -0
  443. package/dist/utils/errors/index.d.ts +11 -0
  444. package/dist/utils/errors/index.d.ts.map +1 -0
  445. package/dist/utils/errors/suggestions.d.ts +16 -0
  446. package/dist/utils/errors/suggestions.d.ts.map +1 -0
  447. package/dist/utils/icons.d.ts +19 -0
  448. package/dist/utils/icons.d.ts.map +1 -0
  449. package/dist/utils/identifiers.d.ts +121 -0
  450. package/dist/utils/identifiers.d.ts.map +1 -0
  451. package/dist/utils/index.d.ts +9 -0
  452. package/dist/utils/index.d.ts.map +1 -0
  453. package/dist/utils/insights-manager.d.ts +39 -0
  454. package/dist/utils/insights-manager.d.ts.map +1 -0
  455. package/dist/utils/logger/error-codes.d.ts +48 -0
  456. package/dist/utils/logger/error-codes.d.ts.map +1 -0
  457. package/dist/utils/logger/index.d.ts +22 -0
  458. package/dist/utils/logger/index.d.ts.map +1 -0
  459. package/dist/utils/logger/logger.d.ts +94 -0
  460. package/dist/utils/logger/logger.d.ts.map +1 -0
  461. package/dist/utils/logger/module-logger.d.ts +28 -0
  462. package/dist/utils/logger/module-logger.d.ts.map +1 -0
  463. package/dist/utils/logger/types.d.ts +36 -0
  464. package/dist/utils/logger/types.d.ts.map +1 -0
  465. package/dist/utils/progress-utils.d.ts +54 -0
  466. package/dist/utils/progress-utils.d.ts.map +1 -0
  467. package/dist/utils/redaction.d.ts +4 -0
  468. package/dist/utils/redaction.d.ts.map +1 -0
  469. package/dist/utils/resource-annotations.d.ts +36 -0
  470. package/dist/utils/resource-annotations.d.ts.map +1 -0
  471. package/dist/utils/validate-json-path.d.ts +43 -0
  472. package/dist/utils/validate-json-path.d.ts.map +1 -0
  473. package/dist/utils/validate-path.d.ts +37 -0
  474. package/dist/utils/validate-path.d.ts.map +1 -0
  475. package/dist/utils/where-clause.d.ts +42 -0
  476. package/dist/utils/where-clause.d.ts.map +1 -0
  477. package/dist/version.d.ts +10 -0
  478. package/dist/version.d.ts.map +1 -0
  479. package/package.json +25 -13
  480. package/.gitattributes +0 -2
  481. package/.gitleaks.toml +0 -9
  482. package/.trivyignore +0 -8
  483. package/dist/chunk-OKOVZ5QE.js +0 -28
  484. package/dist/chunk-SFJQCNG7.js +0 -131
  485. package/dist/chunk-VIDSICEL.js +0 -85
  486. package/dist/chunk-X3MUUOWM.js +0 -152
  487. package/dist/worker-script.d.ts +0 -2
  488. package/dist/worker-script.js +0 -150
  489. package/logs/.gitkeep +0 -1
  490. package/mcp-config-example.json +0 -83
  491. package/playwright.config.ts +0 -101
  492. package/scripts/generate-server-instructions.ts +0 -111
  493. package/scripts/update-badges.ts +0 -99
  494. package/server.json +0 -54
  495. package/test-server/README.md +0 -115
  496. package/test-server/code-map.md +0 -421
  497. package/test-server/fixtures/sample.csv +0 -6
  498. package/test-server/reset-database.ps1 +0 -415
  499. package/test-server/sample.csv +0 -11
  500. package/test-server/scripts/README.md +0 -27
  501. package/test-server/scripts/test-help-resources.mjs +0 -245
  502. package/test-server/scripts/test-prompts.mjs +0 -251
  503. package/test-server/scripts/test-tool-annotations.mjs +0 -162
  504. package/test-server/test-advanced/README.md +0 -70
  505. package/test-server/test-advanced/test-codemode-advanced-admin.md +0 -174
  506. package/test-server/test-advanced/test-codemode-advanced-core.md +0 -193
  507. package/test-server/test-advanced/test-codemode-advanced-geo.md +0 -157
  508. package/test-server/test-advanced/test-codemode-advanced-introspection.md +0 -171
  509. package/test-server/test-advanced/test-codemode-advanced-json.md +0 -169
  510. package/test-server/test-advanced/test-codemode-advanced-migration.md +0 -160
  511. package/test-server/test-advanced/test-codemode-advanced-stats.md +0 -185
  512. package/test-server/test-advanced/test-codemode-advanced-text.md +0 -183
  513. package/test-server/test-advanced/test-codemode-advanced-transactions.md +0 -136
  514. package/test-server/test-advanced/test-codemode-advanced-vector.md +0 -141
  515. package/test-server/test-codemode/README.md +0 -121
  516. package/test-server/test-codemode/test-codemode-admin.md +0 -223
  517. package/test-server/test-codemode/test-codemode-core.md +0 -286
  518. package/test-server/test-codemode/test-codemode-geo.md +0 -177
  519. package/test-server/test-codemode/test-codemode-introspection.md +0 -190
  520. package/test-server/test-codemode/test-codemode-json.md +0 -237
  521. package/test-server/test-codemode/test-codemode-migration.md +0 -278
  522. package/test-server/test-codemode/test-codemode-sandbox.md +0 -413
  523. package/test-server/test-codemode/test-codemode-stats.md +0 -232
  524. package/test-server/test-codemode/test-codemode-text.md +0 -237
  525. package/test-server/test-codemode/test-codemode-transactions.md +0 -236
  526. package/test-server/test-codemode/test-codemode-vector.md +0 -244
  527. package/test-server/test-codemode/test-codemode-wasm-degradation.md +0 -394
  528. package/test-server/test-database.sql +0 -424
  529. package/test-server/test-preflight.md +0 -53
  530. package/test-server/test-prompts.md +0 -354
  531. package/test-server/test-resources.md +0 -272
  532. package/test-server/test-tool-groups/README.md +0 -100
  533. package/test-server/test-tool-groups/test-admin-core.md +0 -165
  534. package/test-server/test-tool-groups/test-admin-extensions.md +0 -133
  535. package/test-server/test-tool-groups/test-core-data.md +0 -262
  536. package/test-server/test-tool-groups/test-core-schema.md +0 -240
  537. package/test-server/test-tool-groups/test-geo-haversine.md +0 -130
  538. package/test-server/test-tool-groups/test-geo-spatialite.md +0 -110
  539. package/test-server/test-tool-groups/test-introspection-diagnostics.md +0 -123
  540. package/test-server/test-tool-groups/test-introspection-schema.md +0 -133
  541. package/test-server/test-tool-groups/test-json-read.md +0 -219
  542. package/test-server/test-tool-groups/test-json-write.md +0 -157
  543. package/test-server/test-tool-groups/test-migration.md +0 -193
  544. package/test-server/test-tool-groups/test-stats-advanced.md +0 -118
  545. package/test-server/test-tool-groups/test-stats-basic.md +0 -156
  546. package/test-server/test-tool-groups/test-text-advanced.md +0 -169
  547. package/test-server/test-tool-groups/test-text-basic.md +0 -177
  548. package/test-server/test-tool-groups/test-transactions.md +0 -179
  549. package/test-server/test-tool-groups/test-vector-read.md +0 -130
  550. package/test-server/test-tool-groups/test-vector-write.md +0 -115
  551. package/test-server/tool-reference.md +0 -257
  552. package/tsconfig.build.json +0 -6
  553. package/tsconfig.test.json +0 -9
@@ -1,13 +1,14 @@
1
- import { runWithAuthContext, SUPPORTED_SCOPES, scopesGrantToolAccess, BASE_SCOPES, SCOPE_PATTERNS, parseScopes } from './chunk-SFJQCNG7.js';
2
- import './chunk-X3MUUOWM.js';
3
- import { createModuleLogger, DbMcpError, ERROR_CODES } from './chunk-645ZEFLA.js';
1
+ import { createModuleLogger, DbMcpError, runWithAuthContext, ERROR_CODES, logger, SUPPORTED_SCOPES, scopesGrantToolAccess, InsufficientScopeError, hasAdminScope, hasReadScope, isOAuthError, BASE_SCOPES, AuthServerDiscoveryError, JwksFetchError, parseScopes, TokenExpiredError, InvalidSignatureError, InvalidTokenError, TokenMissingError } from './chunk-L552U3QS.js';
4
2
  import express from 'express';
5
3
  import { localhostHostValidation } from '@modelcontextprotocol/sdk/server/middleware/hostHeaderValidation.js';
6
4
  import cors from 'cors';
7
- import { randomUUID } from 'crypto';
5
+ import rateLimit from 'express-rate-limit';
6
+ import RedisStore from 'rate-limit-redis';
7
+ import { createClient } from 'redis';
8
8
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
9
- import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
9
+ import { randomUUID } from 'crypto';
10
10
  import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
11
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
11
12
  import * as jose from 'jose';
12
13
 
13
14
  // src/auth/middleware/extraction.ts
@@ -28,115 +29,8 @@ function extractBearerToken(authHeader) {
28
29
  return token.length > 0 ? token : null;
29
30
  }
30
31
 
31
- // src/auth/errors.ts
32
- var OAuthError = class extends DbMcpError {
33
- /** HTTP status code for this error */
34
- httpStatus;
35
- /** WWW-Authenticate header value */
36
- wwwAuthenticate;
37
- constructor(message, code, httpStatus, details, wwwAuthenticate) {
38
- super(message, code, "authentication" /* AUTHENTICATION */, { details });
39
- this.name = "OAuthError";
40
- this.httpStatus = httpStatus;
41
- this.wwwAuthenticate = wwwAuthenticate;
42
- }
43
- };
44
- var TokenMissingError = class extends OAuthError {
45
- constructor(realm = "db-mcp") {
46
- super(
47
- "No access token provided",
48
- ERROR_CODES.AUTH.TOKEN_MISSING.full,
49
- 401,
50
- void 0,
51
- `Bearer realm="${realm}"`
52
- );
53
- this.name = "TokenMissingError";
54
- }
55
- };
56
- var InvalidTokenError = class extends OAuthError {
57
- constructor(message = "Invalid access token", details) {
58
- super(
59
- message,
60
- ERROR_CODES.AUTH.TOKEN_INVALID.full,
61
- 401,
62
- details,
63
- 'Bearer error="invalid_token"'
64
- );
65
- this.name = "InvalidTokenError";
66
- }
67
- };
68
- var TokenExpiredError = class extends OAuthError {
69
- constructor(expiredAt) {
70
- super(
71
- "Access token has expired",
72
- ERROR_CODES.AUTH.TOKEN_EXPIRED.full,
73
- 401,
74
- expiredAt ? { expiredAt: expiredAt.toISOString() } : void 0,
75
- 'Bearer error="invalid_token", error_description="Token has expired"'
76
- );
77
- this.name = "TokenExpiredError";
78
- }
79
- };
80
- var InvalidSignatureError = class extends OAuthError {
81
- constructor(message = "Token signature verification failed") {
82
- super(
83
- message,
84
- ERROR_CODES.AUTH.SIGNATURE_INVALID.full,
85
- 401,
86
- void 0,
87
- 'Bearer error="invalid_token", error_description="Signature verification failed"'
88
- );
89
- this.name = "InvalidSignatureError";
90
- }
91
- };
92
- var InsufficientScopeError = class extends OAuthError {
93
- constructor(requiredScope, providedScopes) {
94
- const required = Array.isArray(requiredScope) ? requiredScope : [requiredScope];
95
- const scopeValue = required.join(" ");
96
- super(
97
- `Insufficient scope. Required: ${scopeValue}`,
98
- ERROR_CODES.AUTH.SCOPE_DENIED.full,
99
- 403,
100
- { requiredScope: required, providedScopes },
101
- `Bearer error="insufficient_scope", scope="${scopeValue}"`
102
- );
103
- this.name = "InsufficientScopeError";
104
- }
105
- };
106
- var AuthServerDiscoveryError = class extends OAuthError {
107
- constructor(serverUrl, cause) {
108
- super(
109
- `Failed to discover authorization server metadata: ${serverUrl}`,
110
- ERROR_CODES.AUTH.DISCOVERY_FAILED.full,
111
- 500,
112
- {
113
- serverUrl,
114
- cause: cause?.message
115
- }
116
- );
117
- this.name = "AuthServerDiscoveryError";
118
- }
119
- };
120
- var JwksFetchError = class extends OAuthError {
121
- constructor(jwksUri, cause) {
122
- super(
123
- `Failed to fetch JWKS: ${jwksUri}`,
124
- ERROR_CODES.AUTH.JWKS_FETCH_FAILED.full,
125
- 500,
126
- {
127
- jwksUri,
128
- cause: cause?.message
129
- }
130
- );
131
- this.name = "JwksFetchError";
132
- }
133
- };
134
- function isOAuthError(error) {
135
- return error instanceof OAuthError;
136
- }
137
-
138
32
  // src/auth/middleware/express-auth.ts
139
- var logger = createModuleLogger("AUTH");
33
+ var logger2 = createModuleLogger("AUTH");
140
34
  function isPublicPath(path, publicPaths) {
141
35
  if (path.startsWith("/.well-known/")) {
142
36
  return true;
@@ -159,8 +53,9 @@ function createAuthMiddleware(config) {
159
53
  return async (req, res, next) => {
160
54
  const requestId = crypto.randomUUID();
161
55
  req.requestId = requestId;
56
+ res.setHeader("X-Request-ID", requestId);
162
57
  if (isPublicPath(req.path, publicPaths)) {
163
- logger.info(`Public path accessed: ${req.path}`, {
58
+ logger2.info(`Public path accessed: ${req.path}`, {
164
59
  code: "AUTH_PUBLIC_PATH",
165
60
  requestId,
166
61
  path: req.path
@@ -171,7 +66,7 @@ function createAuthMiddleware(config) {
171
66
  const token = extractBearerToken(req.headers.authorization);
172
67
  if (!token) {
173
68
  const error = new TokenMissingError(resourceServer.getResourceUri());
174
- logger.warning("No access token provided", {
69
+ logger2.warning("No access token provided", {
175
70
  code: ERROR_CODES.AUTH.TOKEN_MISSING.full,
176
71
  requestId,
177
72
  path: req.path
@@ -186,7 +81,7 @@ function createAuthMiddleware(config) {
186
81
  }
187
82
  const result = await tokenValidator.validate(token);
188
83
  if (!result.valid) {
189
- logger.warning(
84
+ logger2.warning(
190
85
  `Token validation failed: ${result.error ?? "Unknown error"}`,
191
86
  {
192
87
  code: result.errorCode ?? ERROR_CODES.AUTH.TOKEN_INVALID.full,
@@ -197,11 +92,14 @@ function createAuthMiddleware(config) {
197
92
  res.status(401);
198
93
  res.setHeader(
199
94
  "WWW-Authenticate",
200
- resourceServer.getWWWAuthenticateHeader("invalid_token", result.error)
95
+ resourceServer.getWWWAuthenticateHeader(
96
+ "invalid_token",
97
+ "Token validation failed"
98
+ )
201
99
  );
202
100
  res.json({
203
101
  error: "invalid_token",
204
- error_description: result.error
102
+ error_description: "Token validation failed"
205
103
  });
206
104
  return;
207
105
  }
@@ -212,7 +110,7 @@ function createAuthMiddleware(config) {
212
110
  }
213
111
  req.auth = claims;
214
112
  req.accessToken = token;
215
- logger.info(`Request authenticated: ${claims.sub}`, {
113
+ logger2.info(`Request authenticated: ${claims.sub}`, {
216
114
  code: "AUTH_SUCCESS",
217
115
  requestId,
218
116
  sub: claims.sub,
@@ -250,18 +148,9 @@ var JSONRPC_INTERNAL_ERROR = -32603;
250
148
  var HTTP_REQUEST_TIMEOUT_MS = 12e4;
251
149
  var HTTP_KEEP_ALIVE_TIMEOUT_MS = 65e3;
252
150
  var HTTP_HEADERS_TIMEOUT_MS = 66e3;
253
- function getClientIp(req, trustProxy) {
254
- if (trustProxy) {
255
- const forwarded = req.headers["x-forwarded-for"];
256
- if (typeof forwarded === "string") {
257
- const firstIp = forwarded.split(",")[0]?.trim();
258
- if (firstIp) return firstIp;
259
- }
260
- }
261
- return req.ip ?? req.socket.remoteAddress ?? "unknown";
262
- }
263
151
  function setupSecurityHeaders(state) {
264
152
  if (!state.app) return;
153
+ state.app.disable("x-powered-by");
265
154
  state.app.use((_req, res, next) => {
266
155
  res.setHeader("X-Content-Type-Options", "nosniff");
267
156
  res.setHeader("X-Frame-Options", "DENY");
@@ -275,8 +164,12 @@ function setupSecurityHeaders(state) {
275
164
  "camera=(), microphone=(), geolocation=()"
276
165
  );
277
166
  res.setHeader("Referrer-Policy", "no-referrer");
167
+ res.setHeader("X-Permitted-Cross-Domain-Policies", "none");
278
168
  if (state.config.enableHSTS) {
279
- const maxAge = state.config.hstsMaxAge ?? DEFAULT_HSTS_MAX_AGE;
169
+ const maxAge = Math.max(
170
+ state.config.hstsMaxAge ?? DEFAULT_HSTS_MAX_AGE,
171
+ 31536e3
172
+ );
280
173
  res.setHeader(
281
174
  "Strict-Transport-Security",
282
175
  `max-age=${String(maxAge)}; includeSubDomains`
@@ -289,13 +182,15 @@ function matchesCorsOrigin(origin, pattern) {
289
182
  if (pattern === "*") return true;
290
183
  if (pattern.startsWith("*.")) {
291
184
  const domain = pattern.slice(1);
185
+ const isLocalDev = origin === "http://localhost" || origin.startsWith("http://localhost:") || origin === "http://127.0.0.1" || origin.startsWith("http://127.0.0.1:") || origin === "http://[::1]" || origin.startsWith("http://[::1]:");
186
+ if (!isLocalDev && !origin.startsWith("https://")) return false;
292
187
  return origin.endsWith(domain) && origin.length > domain.length;
293
188
  }
294
189
  return origin === pattern;
295
190
  }
296
191
  function setupCors(state) {
297
192
  if (!state.app) return;
298
- const corsOrigins = state.config.corsOrigins ?? ["*"];
193
+ const corsOrigins = state.config.corsOrigins ?? [];
299
194
  const isWildcard = corsOrigins.includes("*");
300
195
  state.app.use((req, res, next) => {
301
196
  const origin = req.headers.origin;
@@ -326,41 +221,41 @@ function setupCors(state) {
326
221
  function setupRateLimiting(state) {
327
222
  if (!state.app) return;
328
223
  const windowMs = DEFAULT_RATE_LIMIT_WINDOW_MS;
329
- const maxRequests = process.env["MCP_RATE_LIMIT_MAX"] ? parseInt(process.env["MCP_RATE_LIMIT_MAX"], 10) : DEFAULT_RATE_LIMIT_MAX;
330
- const trustProxy = state.config.trustProxy ?? false;
331
- state.rateLimitCleanupTimer = setInterval(() => {
332
- const now = Date.now();
333
- for (const [ip, entry] of state.rateLimitMap) {
334
- if (now >= entry.resetAt) {
335
- state.rateLimitMap.delete(ip);
336
- }
337
- }
338
- }, windowMs);
339
- state.rateLimitCleanupTimer.unref();
340
- state.app.use((req, res, next) => {
341
- if (req.path === "/health") {
342
- next();
343
- return;
344
- }
345
- const ip = getClientIp(req, trustProxy);
346
- const now = Date.now();
347
- let entry = state.rateLimitMap.get(ip);
348
- if (!entry || now >= entry.resetAt) {
349
- entry = { count: 0, resetAt: now + windowMs };
350
- state.rateLimitMap.set(ip, entry);
351
- }
352
- entry.count++;
353
- if (entry.count > maxRequests) {
354
- const retryAfter = Math.ceil((entry.resetAt - now) / 1e3);
355
- res.setHeader("Retry-After", String(retryAfter));
356
- res.status(429).json({
357
- error: "Too Many Requests",
358
- retryAfter
224
+ const parsedMax = process.env["MCP_RATE_LIMIT_MAX"] ? parseInt(process.env["MCP_RATE_LIMIT_MAX"], 10) : DEFAULT_RATE_LIMIT_MAX;
225
+ const safeParsedMax = Number.isNaN(parsedMax) ? DEFAULT_RATE_LIMIT_MAX : parsedMax;
226
+ const maxRequests = Math.max(1, Math.min(safeParsedMax, 1e4));
227
+ let store;
228
+ if (process.env["REDIS_URL"]) {
229
+ const redisClient = createClient({ url: process.env["REDIS_URL"] });
230
+ redisClient.connect().catch((err) => {
231
+ logger.error("Redis connection failed", {
232
+ error: err instanceof Error ? err : new Error(String(err))
233
+ });
234
+ });
235
+ store = new RedisStore({
236
+ sendCommand: (...args) => redisClient.sendCommand(args)
237
+ });
238
+ logger.info("Configured RedisStore for rate limiting", { module: "HTTP" });
239
+ } else if (process.env["NODE_ENV"] === "production") {
240
+ logger.error(
241
+ "CRITICAL SECURITY WARNING: Using default in-memory rate limit store in production. In multi-instance deployments, rate limits will not be synchronized across instances (leading to amplification attacks). Configure REDIS_URL for production clusters or ensure your proxy handles rate limiting.",
242
+ { module: "HTTP" }
243
+ );
244
+ }
245
+ const limiter = rateLimit({
246
+ windowMs,
247
+ max: maxRequests,
248
+ standardHeaders: true,
249
+ legacyHeaders: false,
250
+ ...store ? { store } : {},
251
+ skip: (req) => req.path === "/health",
252
+ handler: (_req, res, _next, options) => {
253
+ res.status(options.statusCode).json({
254
+ error: "Too Many Requests"
359
255
  });
360
- return;
361
256
  }
362
- next();
363
257
  });
258
+ state.app.use(limiter);
364
259
  }
365
260
 
366
261
  // src/transports/http/type-adapters.ts
@@ -371,32 +266,8 @@ function asServerResponse(res) {
371
266
  return res;
372
267
  }
373
268
 
374
- // src/transports/http/session.ts
375
- var logger3 = createModuleLogger("HTTP");
376
- var Mutex = class {
377
- queue = [];
378
- locked = false;
379
- async acquire() {
380
- return new Promise((resolve) => {
381
- const lock = () => {
382
- this.locked = true;
383
- resolve(() => {
384
- this.locked = false;
385
- if (this.queue.length > 0) {
386
- const next = this.queue.shift();
387
- next?.();
388
- }
389
- });
390
- };
391
- if (this.locked) {
392
- this.queue.push(lock);
393
- } else {
394
- lock();
395
- }
396
- });
397
- }
398
- };
399
- var connectionMutex = new Mutex();
269
+ // src/transports/http/sessions/stateless.ts
270
+ var logger4 = createModuleLogger("HTTP");
400
271
  async function setupStatelessEndpoints(state) {
401
272
  if (!state.app || !state.mcpServer) {
402
273
  throw new DbMcpError(
@@ -409,14 +280,14 @@ async function setupStatelessEndpoints(state) {
409
280
  enableJsonResponse: true
410
281
  });
411
282
  state.statelessTransport.onclose ??= () => {
412
- logger3.debug("Stateless transport closed", {
283
+ logger4.debug("Stateless transport closed", {
413
284
  code: "HTTP_STATELESS_CLOSE"
414
285
  });
415
286
  };
416
287
  await state.mcpServer.connect(
417
288
  state.statelessTransport
418
289
  );
419
- logger3.info("Stateless transport connected", { code: "HTTP_STATELESS" });
290
+ logger4.info("Stateless transport connected", { code: "HTTP_STATELESS" });
420
291
  state.app.post("/mcp", (req, res) => {
421
292
  if (!state.statelessTransport) {
422
293
  res.status(500).json({ error: "Transport not initialized" });
@@ -442,6 +313,47 @@ async function setupStatelessEndpoints(state) {
442
313
  res.status(204).end();
443
314
  });
444
315
  }
316
+
317
+ // src/transports/http/sessions/mutex.ts
318
+ var Mutex = class {
319
+ queue = [];
320
+ locked = false;
321
+ async acquire() {
322
+ return new Promise((resolve) => {
323
+ const lock = () => {
324
+ this.locked = true;
325
+ resolve(() => {
326
+ this.locked = false;
327
+ if (this.queue.length > 0) {
328
+ const next = this.queue.shift();
329
+ next?.();
330
+ }
331
+ });
332
+ };
333
+ if (this.locked) {
334
+ this.queue.push(lock);
335
+ } else {
336
+ lock();
337
+ }
338
+ });
339
+ }
340
+ };
341
+
342
+ // src/transports/http/sessions/stateful.ts
343
+ var logger5 = createModuleLogger("HTTP");
344
+ var connectionMutex = new Mutex();
345
+ function verifySessionOwner(state, sessionId, reqAuthSub) {
346
+ const owner = state.sessionOwners.get(sessionId);
347
+ if (owner !== void 0 && owner !== reqAuthSub) {
348
+ return false;
349
+ }
350
+ return true;
351
+ }
352
+ function isValidSessionId(id) {
353
+ if (!id) return false;
354
+ if (id.length !== 36) return false;
355
+ return /^[0-9a-fA-F-]{36}$/.test(id);
356
+ }
445
357
  function setupStatefulEndpoints(state) {
446
358
  if (!state.app || !state.mcpServer) {
447
359
  throw new DbMcpError(
@@ -453,6 +365,17 @@ function setupStatefulEndpoints(state) {
453
365
  const server = state.mcpServer;
454
366
  state.app.post("/mcp", (req, res) => {
455
367
  const sessionId = req.headers["mcp-session-id"];
368
+ if (sessionId !== void 0 && !isValidSessionId(sessionId)) {
369
+ res.status(400).json({
370
+ jsonrpc: "2.0",
371
+ error: {
372
+ code: JSONRPC_SERVER_ERROR,
373
+ message: "Bad Request: Invalid session ID format"
374
+ },
375
+ id: null
376
+ });
377
+ return;
378
+ }
456
379
  if (sessionId && state.sseTransports.has(sessionId)) {
457
380
  res.status(400).json({
458
381
  jsonrpc: "2.0",
@@ -476,34 +399,60 @@ function setupStatefulEndpoints(state) {
476
399
  void (async () => {
477
400
  try {
478
401
  let httpTransport;
479
- if (sessionId && state.transports.has(sessionId)) {
480
- httpTransport = state.transports.get(sessionId);
402
+ const existingTransport = sessionId ? state.transports.get(sessionId) : void 0;
403
+ if (typeof sessionId === "string" && existingTransport !== void 0) {
404
+ if (!verifySessionOwner(state, sessionId, req.auth?.sub)) {
405
+ res.status(403).json({
406
+ jsonrpc: "2.0",
407
+ error: {
408
+ code: JSONRPC_SERVER_ERROR,
409
+ message: "Forbidden: session belongs to a different client"
410
+ },
411
+ id: null
412
+ });
413
+ return;
414
+ }
415
+ httpTransport = existingTransport;
481
416
  } else if (sessionId === void 0 && isNewSessionRequest(req.body)) {
417
+ const maxSessions = state.config.maxSessions ?? 1e3;
418
+ if (state.transports.size >= maxSessions) {
419
+ res.status(429).json({
420
+ jsonrpc: "2.0",
421
+ error: {
422
+ code: JSONRPC_SERVER_ERROR,
423
+ message: "Too Many Requests: Maximum number of concurrent sessions reached"
424
+ },
425
+ id: null
426
+ });
427
+ return;
428
+ }
482
429
  const newTransport = new StreamableHTTPServerTransport({
483
430
  sessionIdGenerator: () => randomUUID(),
484
431
  onsessioninitialized: (sid) => {
485
- logger3.info("HTTP session initialized", {
432
+ logger5.info("HTTP session initialized", {
486
433
  code: "HTTP_SESSION_INIT",
487
434
  sessionId: sid
488
435
  });
489
436
  state.transports.set(sid, newTransport);
437
+ state.sessionOwners.set(sid, req.auth?.sub);
490
438
  }
491
439
  });
492
440
  newTransport.onclose = () => {
493
441
  const sid = newTransport.sessionId;
494
442
  if (sid !== void 0 && state.transports.has(sid)) {
495
- logger3.info("HTTP transport closed", {
443
+ logger5.info("HTTP transport closed", {
496
444
  code: "HTTP_SESSION_CLOSE",
497
445
  sessionId: sid
498
446
  });
499
447
  state.transports.delete(sid);
448
+ state.sessionOwners.delete(sid);
500
449
  }
501
450
  };
502
451
  await connectionMutex.acquire().then(async (release) => {
503
452
  try {
504
453
  if (server.server.transport) {
505
454
  const oldTransport = server.server.transport;
506
- logger3.info("Captured oldTransport in /mcp", {
455
+ logger5.info("Captured oldTransport in /mcp", {
507
456
  hasOldTransport: oldTransport !== void 0,
508
457
  hasOnclose: oldTransport.onclose !== void 0
509
458
  });
@@ -517,25 +466,25 @@ function setupStatefulEndpoints(state) {
517
466
  )
518
467
  )
519
468
  ]);
520
- logger3.info("server.close() succeeded in /mcp");
469
+ logger5.info("server.close() succeeded in /mcp");
521
470
  } catch (closeErr) {
522
- logger3.error("server.close() failed or timed out in /mcp", {
471
+ logger5.error("server.close() failed or timed out in /mcp", {
523
472
  error: closeErr instanceof Error ? closeErr : new Error(String(closeErr))
524
473
  });
525
474
  }
526
475
  if (server.server.transport === oldTransport && oldTransport.onclose !== void 0) {
527
- logger3.info(
476
+ logger5.info(
528
477
  "Manually invoking oldTransport.onclose() to clear Protocol state in /mcp"
529
478
  );
530
479
  oldTransport.onclose();
531
480
  }
532
481
  delete oldTransport.onclose;
533
482
  }
534
- logger3.info("Attempting server.connect(newTransport)");
483
+ logger5.info("Attempting server.connect(newTransport)");
535
484
  await server.connect(
536
485
  newTransport
537
486
  );
538
- logger3.info("server.connect succeeded in /mcp");
487
+ logger5.info("server.connect succeeded in /mcp");
539
488
  } finally {
540
489
  release();
541
490
  }
@@ -565,7 +514,7 @@ function setupStatefulEndpoints(state) {
565
514
  );
566
515
  }
567
516
  } catch (error) {
568
- logger3.error("Error handling MCP request", {
517
+ logger5.error("Error handling MCP request", {
569
518
  code: ERROR_CODES.SERVER.TRANSPORT_ERROR.full,
570
519
  error: error instanceof Error ? error : void 0
571
520
  });
@@ -584,44 +533,62 @@ function setupStatefulEndpoints(state) {
584
533
  });
585
534
  state.app.get("/mcp", (req, res) => {
586
535
  const sessionId = req.headers["mcp-session-id"];
587
- if (sessionId === void 0 || !state.transports.has(sessionId)) {
536
+ if (sessionId === void 0 || !isValidSessionId(sessionId)) {
537
+ res.status(400).send("Invalid or missing session ID");
538
+ return;
539
+ }
540
+ const httpTransport = state.transports.get(sessionId);
541
+ if (httpTransport === void 0) {
588
542
  res.status(400).send("Invalid or missing session ID");
589
543
  return;
590
544
  }
545
+ if (!verifySessionOwner(state, sessionId, req.auth?.sub)) {
546
+ res.status(403).send("Forbidden: session belongs to a different client");
547
+ return;
548
+ }
591
549
  const lastEventId = req.headers["last-event-id"];
592
550
  if (lastEventId !== void 0) {
593
- logger3.debug("Client reconnecting with Last-Event-ID", {
551
+ logger5.debug("Client reconnecting with Last-Event-ID", {
594
552
  code: "HTTP_SSE_RECONNECT",
595
553
  sessionId,
596
554
  lastEventId
597
555
  });
598
556
  }
599
- const httpTransport = state.transports.get(sessionId);
600
557
  if (httpTransport !== void 0) {
601
558
  void httpTransport.handleRequest(asIncoming(req), asServerResponse(res));
602
559
  }
603
560
  });
604
561
  state.app.delete("/mcp", (req, res) => {
605
562
  const sessionId = req.headers["mcp-session-id"];
606
- if (sessionId === void 0 || !state.transports.has(sessionId)) {
563
+ if (sessionId === void 0 || !isValidSessionId(sessionId)) {
564
+ res.status(400).send("Invalid or missing session ID");
565
+ return;
566
+ }
567
+ const httpTransport = state.transports.get(sessionId);
568
+ if (httpTransport === void 0) {
607
569
  res.status(400).send("Invalid or missing session ID");
608
570
  return;
609
571
  }
610
- logger3.info("Session termination requested", {
572
+ if (!verifySessionOwner(state, sessionId, req.auth?.sub)) {
573
+ res.status(403).send("Forbidden: session belongs to a different client");
574
+ return;
575
+ }
576
+ logger5.info("Session termination requested", {
611
577
  code: "HTTP_SESSION_DELETE",
612
578
  sessionId
613
579
  });
614
- const httpTransport = state.transports.get(sessionId);
615
580
  if (httpTransport !== void 0) {
616
581
  void httpTransport.handleRequest(asIncoming(req), asServerResponse(res));
617
582
  }
618
583
  });
619
584
  }
585
+ var logger6 = createModuleLogger("HTTP");
586
+ var connectionMutex2 = new Mutex();
620
587
  function setupLegacySSEEndpoints(state) {
621
588
  if (!state.app || !state.mcpServer) return;
622
589
  const server = state.mcpServer;
623
590
  state.app.get("/sse", (req, res) => {
624
- logger3.info("Legacy SSE connection requested", {
591
+ logger6.info("Legacy SSE connection requested", {
625
592
  code: "SSE_CONNECT"
626
593
  });
627
594
  const sseTransport = new SSEServerTransport(
@@ -631,32 +598,27 @@ function setupLegacySSEEndpoints(state) {
631
598
  void (async () => {
632
599
  try {
633
600
  state.sseTransports.set(sseTransport.sessionId, sseTransport);
601
+ state.sessionOwners.set(sseTransport.sessionId, req.auth?.sub);
634
602
  sseTransport.onclose = () => {
635
- logger3.info("Legacy SSE transport closed", {
603
+ logger6.info("Legacy SSE transport closed", {
636
604
  code: "SSE_CLOSE",
637
605
  sessionId: sseTransport.sessionId
638
606
  });
639
607
  state.sseTransports.delete(sseTransport.sessionId);
608
+ state.sessionOwners.delete(sseTransport.sessionId);
640
609
  };
641
610
  const origSend = sseTransport.send.bind(sseTransport);
642
611
  sseTransport.send = async (message) => {
643
- try {
644
- logger3.info("SSE SEND", {
645
- sessionId: sseTransport.sessionId,
646
- msg: JSON.stringify(message).substring(0, 1e3)
647
- });
648
- } catch (e) {
649
- logger3.error("SSE SEND Stringify Error", {
650
- error: e instanceof Error ? e : new Error(String(e))
651
- });
652
- }
612
+ logger6.debug("SSE SEND", {
613
+ sessionId: sseTransport.sessionId
614
+ });
653
615
  return origSend(message);
654
616
  };
655
- await connectionMutex.acquire().then(async (release) => {
617
+ await connectionMutex2.acquire().then(async (release) => {
656
618
  try {
657
619
  if (server.server.transport) {
658
620
  const oldTransport = server.server.transport;
659
- logger3.info("Captured oldTransport", {
621
+ logger6.info("Captured oldTransport", {
660
622
  hasOldTransport: oldTransport !== void 0,
661
623
  hasOnclose: oldTransport.onclose !== void 0
662
624
  });
@@ -670,29 +632,29 @@ function setupLegacySSEEndpoints(state) {
670
632
  )
671
633
  )
672
634
  ]);
673
- logger3.info("server.close() succeeded");
635
+ logger6.info("server.close() succeeded");
674
636
  } catch (closeErr) {
675
- logger3.error("server.close() failed or timed out", {
637
+ logger6.error("server.close() failed or timed out", {
676
638
  error: closeErr instanceof Error ? closeErr : new Error(String(closeErr))
677
639
  });
678
640
  }
679
641
  if (server.server.transport === oldTransport && oldTransport.onclose !== void 0) {
680
- logger3.info(
642
+ logger6.info(
681
643
  "Manually invoking oldTransport.onclose() to clear Protocol state"
682
644
  );
683
645
  oldTransport.onclose();
684
646
  }
685
647
  delete oldTransport.onclose;
686
648
  }
687
- logger3.info("Attempting server.connect(sseTransport)");
649
+ logger6.info("Attempting server.connect(sseTransport)");
688
650
  await server.connect(sseTransport);
689
- logger3.info("server.connect succeeded");
651
+ logger6.info("server.connect succeeded");
690
652
  } finally {
691
653
  release();
692
654
  }
693
655
  });
694
656
  } catch (error) {
695
- logger3.error("Error starting SSE transport", {
657
+ logger6.error("Error starting SSE transport", {
696
658
  code: ERROR_CODES.SERVER.TRANSPORT_ERROR.full,
697
659
  error: error instanceof Error ? error : void 0
698
660
  });
@@ -703,6 +665,7 @@ function setupLegacySSEEndpoints(state) {
703
665
  })();
704
666
  req.on("close", () => {
705
667
  state.sseTransports.delete(sseTransport.sessionId);
668
+ state.sessionOwners.delete(sseTransport.sessionId);
706
669
  });
707
670
  });
708
671
  state.app.post("/messages", (req, res) => {
@@ -730,14 +693,25 @@ function setupLegacySSEEndpoints(state) {
730
693
  });
731
694
  return;
732
695
  }
696
+ if (!verifySessionOwner(state, sessionId, req.auth?.sub)) {
697
+ res.status(403).json({
698
+ jsonrpc: "2.0",
699
+ error: {
700
+ code: JSONRPC_SERVER_ERROR,
701
+ message: "Forbidden: session belongs to a different client"
702
+ },
703
+ id: null
704
+ });
705
+ return;
706
+ }
733
707
  void sseTransport.handlePostMessage(
734
708
  asIncoming(req),
735
709
  asServerResponse(res),
736
710
  req.body
737
711
  ).then(() => {
738
- logger3.info("handlePostMessage completed", { sessionId });
712
+ logger6.info("handlePostMessage completed", { sessionId });
739
713
  }).catch((e) => {
740
- logger3.error("handlePostMessage error", {
714
+ logger6.error("handlePostMessage error", {
741
715
  error: e instanceof Error ? e : new Error(String(e))
742
716
  });
743
717
  });
@@ -745,7 +719,7 @@ function setupLegacySSEEndpoints(state) {
745
719
  }
746
720
 
747
721
  // src/auth/oauth-resource-server.ts
748
- var logger4 = createModuleLogger("AUTH");
722
+ var logger7 = createModuleLogger("AUTH");
749
723
  var OAuthResourceServer = class {
750
724
  config;
751
725
  metadata = null;
@@ -756,7 +730,7 @@ var OAuthResourceServer = class {
756
730
  scopesSupported: config.scopesSupported.length > 0 ? config.scopesSupported : [...SUPPORTED_SCOPES],
757
731
  bearerMethodsSupported: config.bearerMethodsSupported ?? ["header"]
758
732
  };
759
- logger4.info(
733
+ logger7.info(
760
734
  `OAuth Resource Server initialized for: ${this.config.resource}`,
761
735
  { code: "AUTH_INIT" }
762
736
  );
@@ -794,7 +768,7 @@ var OAuthResourceServer = class {
794
768
  res.setHeader("Content-Type", "application/json");
795
769
  res.setHeader("Cache-Control", "public, max-age=3600");
796
770
  res.json(metadata);
797
- logger4.info("Protected Resource Metadata served", {
771
+ logger7.info("Protected Resource Metadata served", {
798
772
  code: "AUTH_METADATA_SERVED"
799
773
  });
800
774
  };
@@ -812,7 +786,8 @@ var OAuthResourceServer = class {
812
786
  parts.push(`error="${error}"`);
813
787
  }
814
788
  if (errorDescription) {
815
- parts.push(`error_description="${errorDescription}"`);
789
+ const safe = errorDescription.replace(/"/g, "'").substring(0, 200);
790
+ parts.push(`error_description="${safe}"`);
816
791
  }
817
792
  return parts.join(", ");
818
793
  }
@@ -845,12 +820,6 @@ var OAuthResourceServer = class {
845
820
  if (this.config.scopesSupported.includes(scope)) {
846
821
  return true;
847
822
  }
848
- if (SCOPE_PATTERNS.DATABASE.test(scope)) {
849
- return true;
850
- }
851
- if (SCOPE_PATTERNS.TABLE.test(scope)) {
852
- return true;
853
- }
854
823
  return false;
855
824
  }
856
825
  /**
@@ -868,7 +837,7 @@ var OAuthResourceServer = class {
868
837
  };
869
838
 
870
839
  // src/auth/authorization-server-discovery.ts
871
- var logger5 = createModuleLogger("AUTH");
840
+ var logger8 = createModuleLogger("AUTH");
872
841
  var AuthorizationServerDiscovery = class {
873
842
  authServerUrl;
874
843
  cacheTtl;
@@ -879,7 +848,16 @@ var AuthorizationServerDiscovery = class {
879
848
  this.authServerUrl = config.authServerUrl.replace(/\/+$/, "");
880
849
  this.cacheTtl = config.cacheTtl ?? 3600;
881
850
  this.timeout = config.timeout ?? 5e3;
882
- logger5.info(
851
+ if (!this.authServerUrl.startsWith("https://") && process.env["NODE_ENV"] !== "development" && process.env["NODE_ENV"] !== "test") {
852
+ const url = new URL(this.authServerUrl);
853
+ const isLocalDev = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
854
+ if (!isLocalDev) {
855
+ throw new Error(
856
+ `Security: Authorization server URL must use HTTPS in production. Got: ${this.authServerUrl}. Set NODE_ENV=development to allow HTTP for local testing.`
857
+ );
858
+ }
859
+ }
860
+ logger8.info(
883
861
  `Authorization Server Discovery initialized for: ${this.authServerUrl}`,
884
862
  { code: "AUTH_INIT" }
885
863
  );
@@ -895,13 +873,13 @@ var AuthorizationServerDiscovery = class {
895
873
  */
896
874
  async discover() {
897
875
  if (this.cachedMetadata && Date.now() < this.cacheExpiry) {
898
- logger5.info("Using cached authorization server metadata", {
876
+ logger8.info("Using cached authorization server metadata", {
899
877
  code: "AUTH_CACHE_HIT"
900
878
  });
901
879
  return this.cachedMetadata;
902
880
  }
903
881
  const metadataUrl = `${this.authServerUrl}/.well-known/oauth-authorization-server`;
904
- logger5.info(`Fetching authorization server metadata from: ${metadataUrl}`, {
882
+ logger8.info(`Fetching authorization server metadata from: ${metadataUrl}`, {
905
883
  code: "AUTH_DISCOVERY"
906
884
  });
907
885
  try {
@@ -926,14 +904,14 @@ var AuthorizationServerDiscovery = class {
926
904
  this.validateMetadata(metadata);
927
905
  this.cachedMetadata = metadata;
928
906
  this.cacheExpiry = Date.now() + this.cacheTtl * 1e3;
929
- logger5.info(
907
+ logger8.info(
930
908
  `Authorization server metadata cached for ${String(this.cacheTtl)}s`,
931
909
  { code: "AUTH_DISCOVERY_SUCCESS" }
932
910
  );
933
911
  return metadata;
934
912
  } catch (error) {
935
913
  const cause = error instanceof Error ? error : new Error(String(error));
936
- logger5.error(
914
+ logger8.error(
937
915
  `Failed to discover authorization server: ${this.authServerUrl}`,
938
916
  {
939
917
  code: ERROR_CODES.AUTH.DISCOVERY_FAILED.full,
@@ -963,11 +941,22 @@ var AuthorizationServerDiscovery = class {
963
941
  "validation" /* VALIDATION */
964
942
  );
965
943
  }
944
+ try {
945
+ new URL(metadata.issuer);
946
+ new URL(metadata.token_endpoint);
947
+ } catch {
948
+ throw new DbMcpError(
949
+ "Invalid URL format in metadata fields",
950
+ "AUTH_DISCOVERY_INVALID",
951
+ "validation" /* VALIDATION */
952
+ );
953
+ }
966
954
  const expectedIssuer = this.authServerUrl;
967
955
  if (metadata.issuer !== expectedIssuer) {
968
- logger5.warning(
969
- `Issuer mismatch: expected ${expectedIssuer}, got ${metadata.issuer}`,
970
- { code: "AUTH_ISSUER_MISMATCH" }
956
+ throw new DbMcpError(
957
+ `Issuer validation failed. Per RFC 8414 \xA73.3, the issuer MUST be identical to the authorization server URL.`,
958
+ "AUTH_ISSUER_MISMATCH",
959
+ "validation" /* VALIDATION */
971
960
  );
972
961
  }
973
962
  }
@@ -1045,7 +1034,7 @@ var AuthorizationServerDiscovery = class {
1045
1034
  clearCache() {
1046
1035
  this.cachedMetadata = null;
1047
1036
  this.cacheExpiry = 0;
1048
- logger5.info("Authorization server metadata cache cleared", {
1037
+ logger8.info("Authorization server metadata cache cleared", {
1049
1038
  code: "AUTH_CACHE_CLEARED"
1050
1039
  });
1051
1040
  }
@@ -1062,23 +1051,43 @@ var AuthorizationServerDiscovery = class {
1062
1051
  return this.authServerUrl;
1063
1052
  }
1064
1053
  };
1065
- var logger6 = createModuleLogger("AUTH");
1066
- var TokenValidator = class {
1054
+ var logger9 = createModuleLogger("AUTH");
1055
+ var TokenValidator = class _TokenValidator {
1056
+ /** Default algorithms accepted when none are explicitly configured */
1057
+ static DEFAULT_ALGORITHMS = [
1058
+ "RS256",
1059
+ "RS384",
1060
+ "RS512",
1061
+ "ES256",
1062
+ "ES384",
1063
+ "ES512"
1064
+ ];
1067
1065
  /** Resolved configuration with all defaults applied */
1068
1066
  jwksUri;
1069
1067
  issuer;
1070
1068
  audience;
1071
1069
  clockTolerance;
1072
1070
  jwksCacheTtl;
1071
+ algorithms;
1073
1072
  jwks = null;
1074
1073
  jwksExpiry = 0;
1075
1074
  constructor(config) {
1075
+ if (config.jwksUri && !config.jwksUri.startsWith("https://") && process.env["ALLOW_HTTP_JWKS"] !== "true") {
1076
+ const url = new URL(config.jwksUri);
1077
+ const isLocalDev = url.hostname === "localhost" || url.hostname === "127.0.0.1";
1078
+ if (!isLocalDev) {
1079
+ throw new Error(
1080
+ `Security: JWKS URI must use HTTPS in production. Got: ${config.jwksUri}. Set ALLOW_HTTP_JWKS=true to allow HTTP for local testing.`
1081
+ );
1082
+ }
1083
+ }
1076
1084
  this.jwksUri = config.jwksUri;
1077
1085
  this.issuer = config.issuer;
1078
1086
  this.audience = config.audience;
1079
- this.clockTolerance = config.clockTolerance ?? 60;
1087
+ this.clockTolerance = config.clockTolerance ?? 30;
1080
1088
  this.jwksCacheTtl = config.jwksCacheTtl ?? 3600;
1081
- logger6.info(`Token Validator initialized for issuer: ${this.issuer}`, {
1089
+ this.algorithms = config.algorithms ?? _TokenValidator.DEFAULT_ALGORITHMS;
1090
+ logger9.info(`Token Validator initialized for issuer: ${this.issuer}`, {
1082
1091
  code: "AUTH_INIT"
1083
1092
  });
1084
1093
  }
@@ -1094,10 +1103,11 @@ var TokenValidator = class {
1094
1103
  const { payload } = await jose.jwtVerify(token, jwks, {
1095
1104
  issuer: this.issuer,
1096
1105
  audience: this.audience,
1097
- clockTolerance: this.clockTolerance
1106
+ clockTolerance: this.clockTolerance,
1107
+ algorithms: this.algorithms
1098
1108
  });
1099
1109
  const claims = this.extractClaims(payload);
1100
- logger6.info(`Token validated for subject: ${claims.sub}`, {
1110
+ logger9.info(`Token validated for subject: ${claims.sub}`, {
1101
1111
  code: "AUTH_TOKEN_VALID",
1102
1112
  sub: claims.sub,
1103
1113
  scopes: claims.scopes.length,
@@ -1118,7 +1128,7 @@ var TokenValidator = class {
1118
1128
  if (this.jwks && Date.now() < this.jwksExpiry) {
1119
1129
  return this.jwks;
1120
1130
  }
1121
- logger6.info(`Fetching JWKS from: ${this.jwksUri}`, {
1131
+ logger9.debug(`Fetching JWKS from: ${this.jwksUri}`, {
1122
1132
  code: "AUTH_JWKS_FETCH"
1123
1133
  });
1124
1134
  try {
@@ -1128,13 +1138,13 @@ var TokenValidator = class {
1128
1138
  cacheMaxAge: this.jwksCacheTtl * 1e3
1129
1139
  });
1130
1140
  this.jwksExpiry = Date.now() + this.jwksCacheTtl * 1e3;
1131
- logger6.info(`JWKS cached for ${String(this.jwksCacheTtl)}s`, {
1141
+ logger9.info(`JWKS cached for ${String(this.jwksCacheTtl)}s`, {
1132
1142
  code: "AUTH_JWKS_CACHED"
1133
1143
  });
1134
1144
  return this.jwks;
1135
1145
  } catch (error) {
1136
1146
  const cause = error instanceof Error ? error : new Error(String(error));
1137
- logger6.error(`Failed to fetch JWKS: ${this.jwksUri}`, {
1147
+ logger9.error(`Failed to fetch JWKS: ${this.jwksUri}`, {
1138
1148
  code: ERROR_CODES.AUTH.JWKS_FETCH_FAILED.full,
1139
1149
  error: cause
1140
1150
  });
@@ -1157,18 +1167,25 @@ var TokenValidator = class {
1157
1167
  (s) => typeof s === "string"
1158
1168
  );
1159
1169
  }
1170
+ const safePayload = {};
1171
+ for (const key of Object.keys(payload)) {
1172
+ if (key !== "__proto__" && key !== "constructor" && key !== "prototype" && key !== "valueOf" && key !== "toString" && key !== "hasOwnProperty") {
1173
+ safePayload[key] = payload[key];
1174
+ }
1175
+ }
1160
1176
  return {
1161
- sub: payload.sub ?? "unknown",
1177
+ // Include all other claims (prototype-polluting keys filtered above)
1178
+ ...safePayload,
1179
+ // Explicitly set authoritative fields last to prevent override via safePayload
1180
+ sub: safePayload.sub ?? "unknown",
1162
1181
  scopes,
1163
- exp: payload.exp ?? 0,
1164
- iat: payload.iat ?? 0,
1165
- iss: payload.iss,
1166
- aud: payload.aud,
1167
- nbf: payload.nbf ?? void 0,
1168
- jti: payload.jti,
1169
- client_id: payload["client_id"],
1170
- // Include all other claims
1171
- ...payload
1182
+ exp: safePayload.exp ?? 0,
1183
+ iat: safePayload.iat ?? 0,
1184
+ iss: safePayload.iss,
1185
+ aud: safePayload.aud,
1186
+ nbf: safePayload.nbf ?? void 0,
1187
+ jti: safePayload.jti,
1188
+ client_id: safePayload["client_id"]
1172
1189
  };
1173
1190
  }
1174
1191
  /**
@@ -1176,7 +1193,7 @@ var TokenValidator = class {
1176
1193
  */
1177
1194
  handleValidationError(error) {
1178
1195
  if (error instanceof jose.errors.JWTExpired) {
1179
- logger6.warning("Token has expired", {
1196
+ logger9.warning("Token has expired", {
1180
1197
  code: ERROR_CODES.AUTH.TOKEN_EXPIRED.full,
1181
1198
  error
1182
1199
  });
@@ -1187,18 +1204,18 @@ var TokenValidator = class {
1187
1204
  };
1188
1205
  }
1189
1206
  if (error instanceof jose.errors.JWTClaimValidationFailed) {
1190
- logger6.warning(`Token claim validation failed: ${error.message}`, {
1207
+ logger9.warning(`Token claim validation failed: ${error.message}`, {
1191
1208
  code: ERROR_CODES.AUTH.TOKEN_INVALID.full,
1192
1209
  error
1193
1210
  });
1194
1211
  return {
1195
1212
  valid: false,
1196
- error: `Token claim validation failed: ${error.message}`,
1213
+ error: "Token claim validation failed",
1197
1214
  errorCode: ERROR_CODES.AUTH.TOKEN_INVALID.full
1198
1215
  };
1199
1216
  }
1200
1217
  if (error instanceof jose.errors.JWSSignatureVerificationFailed) {
1201
- logger6.warning("Token signature verification failed", {
1218
+ logger9.warning("Token signature verification failed", {
1202
1219
  code: ERROR_CODES.AUTH.SIGNATURE_INVALID.full,
1203
1220
  error
1204
1221
  });
@@ -1209,7 +1226,7 @@ var TokenValidator = class {
1209
1226
  };
1210
1227
  }
1211
1228
  if (error instanceof jose.errors.JWKSNoMatchingKey) {
1212
- logger6.warning("No matching key found in JWKS", {
1229
+ logger9.warning("No matching key found in JWKS", {
1213
1230
  code: ERROR_CODES.AUTH.TOKEN_INVALID.full,
1214
1231
  error
1215
1232
  });
@@ -1220,13 +1237,13 @@ var TokenValidator = class {
1220
1237
  };
1221
1238
  }
1222
1239
  const message = error instanceof Error ? error.message : String(error);
1223
- logger6.error(`Token validation failed: ${message}`, {
1240
+ logger9.error(`Token validation failed: ${message}`, {
1224
1241
  code: ERROR_CODES.AUTH.TOKEN_INVALID.full,
1225
1242
  error: error instanceof Error ? error : void 0
1226
1243
  });
1227
1244
  return {
1228
1245
  valid: false,
1229
- error: `Token validation failed: ${message}`,
1246
+ error: "Token validation failed",
1230
1247
  errorCode: ERROR_CODES.AUTH.TOKEN_INVALID.full
1231
1248
  };
1232
1249
  }
@@ -1237,7 +1254,7 @@ var TokenValidator = class {
1237
1254
  this.jwks = null;
1238
1255
  this.jwksExpiry = 0;
1239
1256
  this.getJwks();
1240
- logger6.info("JWKS cache refreshed", { code: "AUTH_JWKS_REFRESHED" });
1257
+ logger9.info("JWKS cache refreshed", { code: "AUTH_JWKS_REFRESHED" });
1241
1258
  }
1242
1259
  /**
1243
1260
  * Clear the JWKS cache
@@ -1245,7 +1262,7 @@ var TokenValidator = class {
1245
1262
  clearCache() {
1246
1263
  this.jwks = null;
1247
1264
  this.jwksExpiry = 0;
1248
- logger6.info("Token validator cache cleared", {
1265
+ logger9.info("Token validator cache cleared", {
1249
1266
  code: "AUTH_CACHE_CLEARED"
1250
1267
  });
1251
1268
  }
@@ -1264,8 +1281,15 @@ var TokenValidator = class {
1264
1281
  };
1265
1282
 
1266
1283
  // src/transports/http/oauth.ts
1267
- var logger7 = createModuleLogger("HTTP");
1284
+ var logger10 = createModuleLogger("HTTP");
1268
1285
  function applyAuthMiddleware(state) {
1286
+ const corsOrigins = state.config.corsOrigins ?? [];
1287
+ const isPubliclyExposed = state.config.oauth.enabled || state.config.noAuthEnforcement;
1288
+ if (corsOrigins.includes("*") && isPubliclyExposed) {
1289
+ throw new Error(
1290
+ "Security: CORS wildcard origin ('*') is forbidden when authentication is enabled or enforcement is explicitly disabled. Configure explicit origins via --cors-origins for production deployments."
1291
+ );
1292
+ }
1269
1293
  if (state.config.oauth.enabled && state.tokenValidator && state.resourceServer && state.app) {
1270
1294
  const authMiddleware = createAuthMiddleware({
1271
1295
  tokenValidator: state.tokenValidator,
@@ -1273,98 +1297,148 @@ function applyAuthMiddleware(state) {
1273
1297
  publicPaths: ["/health", ...state.config.oauth.publicPaths ?? []]
1274
1298
  });
1275
1299
  state.app.use(authMiddleware);
1276
- } else if (state.config.authToken && state.app) {
1277
- state.app.use(createSimpleBearerAuth(state.config.authToken));
1278
- logger7.info("Simple bearer token authentication enabled", {
1279
- code: "AUTH_BEARER_ENABLED"
1280
- });
1281
1300
  } else if (state.app) {
1282
- logger7.warning(
1283
- "No authentication configured for HTTP transport. Set --auth-token or --oauth-enabled for production deployments.",
1301
+ logger10.warning(
1302
+ "No authentication configured for HTTP transport. Set --oauth-enabled for production deployments.",
1284
1303
  { code: "AUTH_NONE" }
1285
1304
  );
1286
1305
  }
1287
1306
  }
1288
- function createSimpleBearerAuth(expectedToken) {
1289
- const publicPaths = ["/health", "/", "/.well-known"];
1290
- return (req, res, next) => {
1291
- if (publicPaths.some((p) => req.path === p || req.path.startsWith(`${p}/`))) {
1307
+ function applyScopeEnforcementMiddleware(state) {
1308
+ if (!state.app) return;
1309
+ state.app.use((req, res, next) => {
1310
+ const body = req.body;
1311
+ if (req.method !== "POST") {
1292
1312
  next();
1293
1313
  return;
1294
1314
  }
1295
- const authHeader = req.headers.authorization;
1296
- if (!authHeader?.startsWith("Bearer ")) {
1297
- res.status(401);
1298
- res.setHeader("WWW-Authenticate", 'Bearer realm="db-mcp"');
1299
- res.json({
1300
- error: "unauthorized",
1301
- error_description: "Bearer token required"
1315
+ const contentType = req.headers["content-type"]?.split(";")[0]?.trim();
1316
+ if (contentType !== "application/json") {
1317
+ res.status(400).json({
1318
+ error: "invalid_request",
1319
+ error_description: "Content-Type must be exactly application/json"
1302
1320
  });
1303
1321
  return;
1304
1322
  }
1305
- const token = authHeader.slice(7);
1306
- if (token !== expectedToken) {
1307
- logger7.warning("Invalid bearer token rejected", {
1308
- code: "AUTH_BEARER_REJECTED"
1309
- });
1310
- res.status(401);
1311
- res.setHeader(
1312
- "WWW-Authenticate",
1313
- 'Bearer realm="db-mcp", error="invalid_token"'
1314
- );
1315
- res.json({
1316
- error: "unauthorized",
1317
- error_description: "Invalid bearer token"
1323
+ if (Array.isArray(body)) {
1324
+ res.status(400).json({
1325
+ error: "invalid_request",
1326
+ error_description: "Batch JSON-RPC requests are not supported"
1318
1327
  });
1319
1328
  return;
1320
1329
  }
1321
- next();
1322
- };
1323
- }
1324
- function applyScopeEnforcementMiddleware(state) {
1325
- if (!state.app) return;
1326
- state.app.use((req, res, next) => {
1327
- const body = req.body;
1328
- if (req.method !== "POST" || body?.method !== "tools/call") {
1329
- next();
1330
- return;
1331
- }
1332
- const toolName = body.params?.name;
1333
- if (!toolName) {
1330
+ if (!req.auth) {
1334
1331
  next();
1335
1332
  return;
1336
1333
  }
1337
- if (!req.auth) {
1334
+ const rpcMethod = body?.method;
1335
+ if (rpcMethod === "tools/list") {
1336
+ const originalJson = res.json;
1337
+ const scopes = req.auth.scopes;
1338
+ const isRecord = (val) => typeof val === "object" && val !== null && !Array.isArray(val);
1339
+ res.json = function(data) {
1340
+ if (isRecord(data) && isRecord(data["result"]) && Array.isArray(data["result"]["tools"])) {
1341
+ data["result"]["tools"] = data["result"]["tools"].filter(
1342
+ (tool) => {
1343
+ if (isRecord(tool) && typeof tool["name"] === "string") {
1344
+ return scopesGrantToolAccess(scopes, tool["name"]);
1345
+ }
1346
+ return false;
1347
+ }
1348
+ );
1349
+ }
1350
+ return originalJson.call(this, data);
1351
+ };
1338
1352
  next();
1339
1353
  return;
1340
1354
  }
1341
- const hasAccess = scopesGrantToolAccess(req.auth.scopes, toolName);
1342
- if (!hasAccess) {
1343
- const error = new InsufficientScopeError(
1344
- `Tool access: ${toolName}`,
1345
- req.auth.scopes
1346
- );
1347
- logger7.warning(`Insufficient scope for tool: ${toolName}`, {
1348
- code: ERROR_CODES.AUTH.SCOPE_DENIED.full,
1349
- toolName,
1350
- providedScopes: req.auth.scopes
1351
- });
1352
- res.status(error.httpStatus);
1353
- if (error.wwwAuthenticate) {
1354
- res.setHeader("WWW-Authenticate", error.wwwAuthenticate);
1355
+ if (rpcMethod === "tools/call") {
1356
+ const toolName = body?.params?.name;
1357
+ if (!toolName) {
1358
+ next();
1359
+ return;
1360
+ }
1361
+ const hasAccess = scopesGrantToolAccess(req.auth.scopes, toolName);
1362
+ if (!hasAccess) {
1363
+ const error = new InsufficientScopeError(
1364
+ `Tool access: ${toolName}`,
1365
+ req.auth.scopes
1366
+ );
1367
+ logger10.warning(`Insufficient scope for tool: ${toolName}`, {
1368
+ code: ERROR_CODES.AUTH.SCOPE_DENIED.full,
1369
+ toolName,
1370
+ providedScopes: req.auth.scopes
1371
+ });
1372
+ res.status(error.httpStatus);
1373
+ if (error.wwwAuthenticate) {
1374
+ res.setHeader("WWW-Authenticate", error.wwwAuthenticate);
1375
+ }
1376
+ res.json({
1377
+ error: "insufficient_scope",
1378
+ error_description: `Access to tool '${toolName}' denied`,
1379
+ tool: toolName
1380
+ });
1381
+ return;
1382
+ }
1383
+ } else if (rpcMethod === "resources/read") {
1384
+ const resourceUri = body?.params?.uri ?? "";
1385
+ const requiredScope = resourceUri.startsWith("sqlite://audit") ? "admin" : "read";
1386
+ const hasAccess = requiredScope === "admin" ? hasAdminScope(req.auth.scopes) : hasReadScope(req.auth.scopes);
1387
+ if (!hasAccess) {
1388
+ const error = new InsufficientScopeError(
1389
+ `Resource access: ${resourceUri}`,
1390
+ req.auth.scopes
1391
+ );
1392
+ logger10.warning(`Insufficient scope for resource: ${resourceUri}`, {
1393
+ code: ERROR_CODES.AUTH.SCOPE_DENIED.full,
1394
+ resourceUri,
1395
+ requiredScope,
1396
+ providedScopes: req.auth.scopes
1397
+ });
1398
+ res.status(error.httpStatus);
1399
+ if (error.wwwAuthenticate) {
1400
+ res.setHeader("WWW-Authenticate", error.wwwAuthenticate);
1401
+ }
1402
+ res.json({
1403
+ error: "insufficient_scope",
1404
+ error_description: `Access to resource '${resourceUri}' requires '${requiredScope}' scope`
1405
+ });
1406
+ return;
1407
+ }
1408
+ } else if (rpcMethod === "prompts/get") {
1409
+ const hasAccess = hasReadScope(req.auth.scopes);
1410
+ if (!hasAccess) {
1411
+ const promptName = body?.params?.name ?? "unknown";
1412
+ const error = new InsufficientScopeError(
1413
+ `Prompt access: ${promptName}`,
1414
+ req.auth.scopes
1415
+ );
1416
+ logger10.warning(`Insufficient scope for prompt: ${promptName}`, {
1417
+ code: ERROR_CODES.AUTH.SCOPE_DENIED.full,
1418
+ promptName,
1419
+ providedScopes: req.auth.scopes
1420
+ });
1421
+ res.status(error.httpStatus);
1422
+ if (error.wwwAuthenticate) {
1423
+ res.setHeader("WWW-Authenticate", error.wwwAuthenticate);
1424
+ }
1425
+ res.json({
1426
+ error: "insufficient_scope",
1427
+ error_description: `Access to prompt '${promptName}' requires 'read' scope`
1428
+ });
1429
+ return;
1355
1430
  }
1356
- res.json({
1357
- error: "insufficient_scope",
1358
- error_description: `Access to tool '${toolName}' denied`,
1359
- tool: toolName
1360
- });
1361
- return;
1362
1431
  }
1363
1432
  next();
1364
1433
  });
1365
1434
  }
1366
1435
  async function setupOAuth(state, resourceUri) {
1367
- logger7.info("Setting up OAuth 2.1...", { code: "HTTP_OAUTH_SETUP" });
1436
+ logger10.info("Setting up OAuth 2.1...", { code: "HTTP_OAUTH_SETUP" });
1437
+ if (state.config.oauth.enabled && !state.config.oauth.audience) {
1438
+ throw new Error(
1439
+ "Security: OAuth audience must be explicitly configured when OAuth is enabled."
1440
+ );
1441
+ }
1368
1442
  state.resourceServer = new OAuthResourceServer({
1369
1443
  resource: resourceUri,
1370
1444
  authorizationServers: [state.config.oauth.authorizationServerUrl],
@@ -1385,25 +1459,25 @@ async function setupOAuth(state, resourceUri) {
1385
1459
  audience: state.config.oauth.audience,
1386
1460
  clockTolerance: state.config.oauth.clockTolerance
1387
1461
  });
1388
- logger7.info("OAuth 2.1 setup complete", { code: "HTTP_OAUTH_READY" });
1462
+ logger10.info("OAuth 2.1 setup complete", { code: "HTTP_OAUTH_READY" });
1389
1463
  } catch (error) {
1390
- logger7.warning(
1464
+ logger10.warning(
1391
1465
  "Authorization server discovery failed. OAuth validation disabled.",
1392
1466
  {
1393
1467
  code: ERROR_CODES.AUTH.DISCOVERY_FAILED.full,
1394
1468
  error: error instanceof Error ? error : void 0
1395
1469
  }
1396
1470
  );
1397
- if (!state.config.oauth.jwksUri) {
1398
- logger7.error(
1399
- "No JWKS URI available. Please provide oauth.jwksUri in config.",
1471
+ if (!state.config.oauth.jwksUri || !state.config.oauth.issuer) {
1472
+ logger10.error(
1473
+ "OAuth discovery failed and explicit jwksUri/issuer were not provided. Hard failing to prevent spoofed token acceptance.",
1400
1474
  { code: ERROR_CODES.AUTH.DISCOVERY_FAILED.full }
1401
1475
  );
1402
1476
  throw error;
1403
1477
  }
1404
1478
  state.tokenValidator = new TokenValidator({
1405
1479
  jwksUri: state.config.oauth.jwksUri,
1406
- issuer: state.config.oauth.issuer ?? state.config.oauth.authorizationServerUrl,
1480
+ issuer: state.config.oauth.issuer,
1407
1481
  audience: state.config.oauth.audience,
1408
1482
  clockTolerance: state.config.oauth.clockTolerance
1409
1483
  });
@@ -1411,7 +1485,7 @@ async function setupOAuth(state, resourceUri) {
1411
1485
  }
1412
1486
 
1413
1487
  // src/transports/http/transport.ts
1414
- var logger8 = createModuleLogger("HTTP");
1488
+ var logger11 = createModuleLogger("HTTP");
1415
1489
  var HttpTransport = class {
1416
1490
  /** Internal state shared with session/middleware/oauth modules */
1417
1491
  state;
@@ -1419,7 +1493,7 @@ var HttpTransport = class {
1419
1493
  this.state = {
1420
1494
  config: {
1421
1495
  ...config,
1422
- host: config.host ?? "0.0.0.0",
1496
+ host: config.host ?? "127.0.0.1",
1423
1497
  stateless: config.stateless ?? false,
1424
1498
  enableHSTS: config.enableHSTS ?? process.env["MCP_ENABLE_HSTS"] === "true"
1425
1499
  },
@@ -1427,13 +1501,12 @@ var HttpTransport = class {
1427
1501
  httpServer: null,
1428
1502
  transports: /* @__PURE__ */ new Map(),
1429
1503
  sseTransports: /* @__PURE__ */ new Map(),
1504
+ sessionOwners: /* @__PURE__ */ new Map(),
1430
1505
  statelessTransport: null,
1431
1506
  resourceServer: null,
1432
1507
  authServerDiscovery: null,
1433
1508
  tokenValidator: null,
1434
- mcpServer: null,
1435
- rateLimitMap: /* @__PURE__ */ new Map(),
1436
- rateLimitCleanupTimer: null
1509
+ mcpServer: null
1437
1510
  };
1438
1511
  }
1439
1512
  /**
@@ -1445,13 +1518,25 @@ var HttpTransport = class {
1445
1518
  * @param server - The MCP server instance
1446
1519
  */
1447
1520
  async initialize(server) {
1448
- logger8.info("Initializing HTTP transport...", {
1521
+ logger11.info("Initializing HTTP transport...", {
1449
1522
  code: "HTTP_INIT",
1450
1523
  stateless: this.state.config.stateless
1451
1524
  });
1452
1525
  this.state.mcpServer = server;
1453
1526
  this.state.app = express();
1454
1527
  this.state.app.use(localhostHostValidation());
1528
+ if (this.state.config.trustedProxyIps !== void 0) {
1529
+ if (Array.isArray(this.state.config.trustedProxyIps) && this.state.config.trustedProxyIps.length === 0) {
1530
+ throw new DbMcpError(
1531
+ "trustedProxyIps cannot be an empty array if specified",
1532
+ "CONFIG_ERROR",
1533
+ "config" /* CONFIGURATION */
1534
+ );
1535
+ }
1536
+ this.state.app.set("trust proxy", this.state.config.trustedProxyIps);
1537
+ } else {
1538
+ this.state.app.set("trust proxy", false);
1539
+ }
1455
1540
  setupSecurityHeaders(this.state);
1456
1541
  setupCors(this.state);
1457
1542
  setupRateLimiting(this.state);
@@ -1460,17 +1545,32 @@ var HttpTransport = class {
1460
1545
  express.json({ limit: maxBodyBytes })
1461
1546
  );
1462
1547
  const resourceUri = this.state.config.resourceUri ?? `http://localhost:${String(this.state.config.port)}`;
1548
+ if (!this.state.config.oauth.enabled && !this.state.config.noAuthEnforcement) {
1549
+ throw new DbMcpError(
1550
+ "HTTP transport is enabled without authentication. You must configure OAuth (--oauth-enabled) or explicitly bypass this check with --no-auth-enforcement.",
1551
+ "AUTH_REQUIRED",
1552
+ "config" /* CONFIGURATION */
1553
+ );
1554
+ }
1463
1555
  if (this.state.config.oauth.enabled) {
1556
+ if (resourceUri.startsWith("http://") && !resourceUri.includes("localhost") && !resourceUri.includes("127.0.0.1")) {
1557
+ logger11.warning(
1558
+ "Security Warning (F09): OAuth is enabled but resource URI is not using HTTPS. A TLS-terminating reverse proxy is required in production."
1559
+ );
1560
+ }
1464
1561
  await setupOAuth(this.state, resourceUri);
1465
1562
  }
1466
- this.state.app.get("/health", (_req, res) => {
1467
- res.json({
1563
+ this.state.app.get("/health", (req, res) => {
1564
+ const response = {
1468
1565
  status: "healthy",
1469
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1470
- oauth: this.state.config.oauth.enabled,
1471
- mode: this.state.config.stateless ? "stateless" : "stateful",
1472
- activeSessions: this.state.transports.size
1473
- });
1566
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1567
+ };
1568
+ if (req.auth) {
1569
+ response["oauth"] = this.state.config.oauth.enabled;
1570
+ response["mode"] = this.state.config.stateless ? "stateless" : "stateful";
1571
+ response["activeSessions"] = this.state.transports.size;
1572
+ }
1573
+ res.json(response);
1474
1574
  });
1475
1575
  this.state.app.get("/", (_req, res) => {
1476
1576
  res.json({
@@ -1490,19 +1590,29 @@ var HttpTransport = class {
1490
1590
  });
1491
1591
  applyAuthMiddleware(this.state);
1492
1592
  applyScopeEnforcementMiddleware(this.state);
1593
+ const oauthEnabled = this.state.config.oauth?.enabled ?? false;
1594
+ let lastNoAuthWarning = 0;
1493
1595
  this.state.app.use((req, _res, next) => {
1494
- if (req.auth) {
1495
- const authCtx = {
1496
- authenticated: true,
1497
- claims: req.auth,
1498
- scopes: req.auth.scopes
1499
- };
1500
- runWithAuthContext(authCtx, () => {
1501
- next();
1502
- });
1503
- } else {
1504
- next();
1596
+ const implicitAdmin = !req.auth && !oauthEnabled;
1597
+ if (implicitAdmin) {
1598
+ const now = Date.now();
1599
+ if (now - lastNoAuthWarning > 6e4) {
1600
+ logger11.warning(
1601
+ "No-auth mode is granting implicit 'admin' scope. This is expected for local dev but dangerous in production.",
1602
+ { module: "HTTP", ip: req.ip }
1603
+ );
1604
+ lastNoAuthWarning = now;
1605
+ }
1505
1606
  }
1607
+ const authCtx = {
1608
+ authenticated: !!req.auth || !oauthEnabled,
1609
+ claims: req.auth,
1610
+ scopes: req.auth?.scopes ?? (implicitAdmin ? ["admin"] : []),
1611
+ clientIp: req.ip
1612
+ };
1613
+ runWithAuthContext(authCtx, () => {
1614
+ next();
1615
+ });
1506
1616
  });
1507
1617
  if (this.state.config.stateless) {
1508
1618
  await setupStatelessEndpoints(this.state);
@@ -1516,7 +1626,7 @@ var HttpTransport = class {
1516
1626
  this.state.app.use((_req, res) => {
1517
1627
  res.status(404).json({ error: "Not found" });
1518
1628
  });
1519
- logger8.info("HTTP transport initialized", {
1629
+ logger11.info("HTTP transport initialized", {
1520
1630
  code: "HTTP_INIT_COMPLETE",
1521
1631
  port: this.state.config.port,
1522
1632
  oauth: this.state.config.oauth.enabled,
@@ -1539,15 +1649,15 @@ var HttpTransport = class {
1539
1649
  try {
1540
1650
  this.state.httpServer = this.state.app?.listen(
1541
1651
  this.state.config.port,
1542
- this.state.config.host ?? "0.0.0.0",
1652
+ this.state.config.host ?? "127.0.0.1",
1543
1653
  () => {
1544
1654
  if (this.state.httpServer) {
1545
1655
  this.state.httpServer.setTimeout(HTTP_REQUEST_TIMEOUT_MS);
1546
1656
  this.state.httpServer.keepAliveTimeout = HTTP_KEEP_ALIVE_TIMEOUT_MS;
1547
1657
  this.state.httpServer.headersTimeout = HTTP_HEADERS_TIMEOUT_MS;
1548
1658
  }
1549
- logger8.info(
1550
- `HTTP server listening on ${this.state.config.host ?? "0.0.0.0"}:${String(this.state.config.port)}`,
1659
+ logger11.info(
1660
+ `HTTP server listening on ${this.state.config.host ?? "127.0.0.1"}:${String(this.state.config.port)}`,
1551
1661
  {
1552
1662
  code: "HTTP_SERVER_STARTED",
1553
1663
  mode: this.state.config.stateless ? "stateless" : "stateful"
@@ -1557,7 +1667,7 @@ var HttpTransport = class {
1557
1667
  }
1558
1668
  ) ?? null;
1559
1669
  this.state.httpServer?.on("error", (error) => {
1560
- logger8.error("Failed to start HTTP server", {
1670
+ logger11.error("Failed to start HTTP server", {
1561
1671
  code: ERROR_CODES.SERVER.START_FAILED.full,
1562
1672
  error
1563
1673
  });
@@ -1572,19 +1682,15 @@ var HttpTransport = class {
1572
1682
  * Stop the server and close all active sessions
1573
1683
  */
1574
1684
  async stop() {
1575
- if (this.state.rateLimitCleanupTimer) {
1576
- clearInterval(this.state.rateLimitCleanupTimer);
1577
- this.state.rateLimitCleanupTimer = null;
1578
- }
1579
1685
  for (const [sessionId, transport] of this.state.transports) {
1580
1686
  try {
1581
- logger8.debug("Closing transport", {
1687
+ logger11.debug("Closing transport", {
1582
1688
  code: "HTTP_SESSION_CLEANUP",
1583
1689
  sessionId
1584
1690
  });
1585
1691
  await transport.close();
1586
1692
  } catch (error) {
1587
- logger8.error("Error closing transport", {
1693
+ logger11.error("Error closing transport", {
1588
1694
  code: ERROR_CODES.SERVER.SHUTDOWN_FAILED.full,
1589
1695
  sessionId,
1590
1696
  error: error instanceof Error ? error : void 0
@@ -1592,15 +1698,16 @@ var HttpTransport = class {
1592
1698
  }
1593
1699
  }
1594
1700
  this.state.transports.clear();
1701
+ this.state.sessionOwners.clear();
1595
1702
  for (const [sessionId, transport] of this.state.sseTransports) {
1596
1703
  try {
1597
- logger8.debug("Closing SSE transport", {
1704
+ logger11.debug("Closing SSE transport", {
1598
1705
  code: "SSE_SESSION_CLEANUP",
1599
1706
  sessionId
1600
1707
  });
1601
1708
  await transport.close();
1602
1709
  } catch (error) {
1603
- logger8.error("Error closing SSE transport", {
1710
+ logger11.error("Error closing SSE transport", {
1604
1711
  code: ERROR_CODES.SERVER.SHUTDOWN_FAILED.full,
1605
1712
  sessionId,
1606
1713
  error: error instanceof Error ? error : void 0
@@ -1612,7 +1719,7 @@ var HttpTransport = class {
1612
1719
  try {
1613
1720
  await this.state.statelessTransport.close();
1614
1721
  } catch (error) {
1615
- logger8.error("Error closing stateless transport", {
1722
+ logger11.error("Error closing stateless transport", {
1616
1723
  code: ERROR_CODES.SERVER.SHUTDOWN_FAILED.full,
1617
1724
  error: error instanceof Error ? error : void 0
1618
1725
  });
@@ -1625,13 +1732,13 @@ var HttpTransport = class {
1625
1732
  }
1626
1733
  this.state.httpServer.close((error) => {
1627
1734
  if (error) {
1628
- logger8.error("Error stopping HTTP server", {
1735
+ logger11.error("Error stopping HTTP server", {
1629
1736
  code: ERROR_CODES.SERVER.SHUTDOWN_FAILED.full,
1630
1737
  error
1631
1738
  });
1632
1739
  reject(error);
1633
1740
  } else {
1634
- logger8.info("HTTP server stopped", { code: "HTTP_SERVER_STOPPED" });
1741
+ logger11.info("HTTP server stopped", { code: "HTTP_SERVER_STOPPED" });
1635
1742
  resolve();
1636
1743
  }
1637
1744
  });