@rekog/mcp-nest 1.9.10 → 2.0.0-alpha.1

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 (364) hide show
  1. package/README.md +76 -29
  2. package/dist/index.d.ts +0 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +0 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/mcp/decorators/constants.d.ts +1 -0
  7. package/dist/mcp/decorators/constants.d.ts.map +1 -1
  8. package/dist/mcp/decorators/constants.js +2 -1
  9. package/dist/mcp/decorators/constants.js.map +1 -1
  10. package/dist/mcp/decorators/index.d.ts +3 -1
  11. package/dist/mcp/decorators/index.d.ts.map +1 -1
  12. package/dist/mcp/decorators/index.js +3 -1
  13. package/dist/mcp/decorators/index.js.map +1 -1
  14. package/dist/mcp/decorators/mcp-controller.decorator.d.ts +6 -0
  15. package/dist/mcp/decorators/mcp-controller.decorator.d.ts.map +1 -0
  16. package/dist/mcp/decorators/mcp-controller.decorator.js +43 -0
  17. package/dist/mcp/decorators/mcp-controller.decorator.js.map +1 -0
  18. package/dist/mcp/decorators/mcp-message-pattern.d.ts +3 -0
  19. package/dist/mcp/decorators/mcp-message-pattern.d.ts.map +1 -0
  20. package/dist/mcp/decorators/mcp-message-pattern.js +13 -0
  21. package/dist/mcp/decorators/mcp-message-pattern.js.map +1 -0
  22. package/dist/mcp/decorators/prompt.decorator.d.ts +4 -1
  23. package/dist/mcp/decorators/prompt.decorator.d.ts.map +1 -1
  24. package/dist/mcp/decorators/prompt.decorator.js +2 -1
  25. package/dist/mcp/decorators/prompt.decorator.js.map +1 -1
  26. package/dist/mcp/decorators/public.decorator.js.map +1 -1
  27. package/dist/mcp/decorators/raw-request.decorator.d.ts +2 -0
  28. package/dist/mcp/decorators/raw-request.decorator.d.ts.map +1 -0
  29. package/dist/mcp/decorators/raw-request.decorator.js +6 -0
  30. package/dist/mcp/decorators/raw-request.decorator.js.map +1 -0
  31. package/dist/mcp/decorators/resource-template.decorator.d.ts +1 -1
  32. package/dist/mcp/decorators/resource-template.decorator.d.ts.map +1 -1
  33. package/dist/mcp/decorators/resource-template.decorator.js +2 -1
  34. package/dist/mcp/decorators/resource-template.decorator.js.map +1 -1
  35. package/dist/mcp/decorators/resource.decorator.d.ts +1 -1
  36. package/dist/mcp/decorators/resource.decorator.d.ts.map +1 -1
  37. package/dist/mcp/decorators/resource.decorator.js +2 -1
  38. package/dist/mcp/decorators/resource.decorator.js.map +1 -1
  39. package/dist/mcp/decorators/tool.decorator.d.ts +1 -3
  40. package/dist/mcp/decorators/tool.decorator.d.ts.map +1 -1
  41. package/dist/mcp/decorators/tool.decorator.js +2 -1
  42. package/dist/mcp/decorators/tool.decorator.js.map +1 -1
  43. package/dist/mcp/filters/mcp-exception.filter.d.ts +6 -0
  44. package/dist/mcp/filters/mcp-exception.filter.d.ts.map +1 -0
  45. package/dist/mcp/filters/mcp-exception.filter.js +26 -0
  46. package/dist/mcp/filters/mcp-exception.filter.js.map +1 -0
  47. package/dist/mcp/index.d.ts +11 -7
  48. package/dist/mcp/index.d.ts.map +1 -1
  49. package/dist/mcp/index.js +11 -7
  50. package/dist/mcp/index.js.map +1 -1
  51. package/dist/mcp/interfaces/authenticated-user.interface.d.ts +9 -0
  52. package/dist/mcp/interfaces/authenticated-user.interface.d.ts.map +1 -0
  53. package/dist/{authz/interfaces/request-with-user.js → mcp/interfaces/authenticated-user.interface.js} +1 -1
  54. package/dist/mcp/interfaces/authenticated-user.interface.js.map +1 -0
  55. package/dist/mcp/interfaces/dynamic-prompt.interface.d.ts +1 -1
  56. package/dist/mcp/interfaces/dynamic-prompt.interface.d.ts.map +1 -1
  57. package/dist/mcp/interfaces/dynamic-prompt.interface.js.map +1 -1
  58. package/dist/mcp/interfaces/dynamic-resource.interface.d.ts +1 -1
  59. package/dist/mcp/interfaces/dynamic-resource.interface.d.ts.map +1 -1
  60. package/dist/mcp/interfaces/dynamic-resource.interface.js.map +1 -1
  61. package/dist/mcp/interfaces/dynamic-tool.interface.d.ts +1 -1
  62. package/dist/mcp/interfaces/dynamic-tool.interface.d.ts.map +1 -1
  63. package/dist/mcp/interfaces/dynamic-tool.interface.js.map +1 -1
  64. package/dist/mcp/interfaces/index.d.ts +2 -2
  65. package/dist/mcp/interfaces/index.d.ts.map +1 -1
  66. package/dist/mcp/interfaces/index.js +0 -3
  67. package/dist/mcp/interfaces/index.js.map +1 -1
  68. package/dist/mcp/services/tool-authorization.service.d.ts +7 -5
  69. package/dist/mcp/services/tool-authorization.service.d.ts.map +1 -1
  70. package/dist/mcp/services/tool-authorization.service.js +9 -6
  71. package/dist/mcp/services/tool-authorization.service.js.map +1 -1
  72. package/dist/mcp/transport/mcp-context.d.ts +34 -0
  73. package/dist/mcp/transport/mcp-context.d.ts.map +1 -0
  74. package/dist/mcp/transport/mcp-context.js +74 -0
  75. package/dist/mcp/transport/mcp-context.js.map +1 -0
  76. package/dist/mcp/transport/mcp-http-handler.d.ts +7 -0
  77. package/dist/mcp/transport/mcp-http-handler.d.ts.map +1 -0
  78. package/dist/mcp/transport/mcp-http-handler.js +5 -0
  79. package/dist/mcp/transport/mcp-http-handler.js.map +1 -0
  80. package/dist/mcp/transport/mcp-server-options.interface.d.ts +23 -0
  81. package/dist/mcp/transport/mcp-server-options.interface.d.ts.map +1 -0
  82. package/dist/{authz/providers/oauth-provider.interface.js → mcp/transport/mcp-server-options.interface.js} +1 -1
  83. package/dist/mcp/transport/mcp-server-options.interface.js.map +1 -0
  84. package/dist/mcp/transport/mcp-transport.constants.d.ts +19 -0
  85. package/dist/mcp/transport/mcp-transport.constants.d.ts.map +1 -0
  86. package/dist/mcp/transport/mcp-transport.constants.js +21 -0
  87. package/dist/mcp/transport/mcp-transport.constants.js.map +1 -0
  88. package/dist/mcp/transport/mcp-transport.interface.d.ts +17 -0
  89. package/dist/mcp/transport/mcp-transport.interface.d.ts.map +1 -0
  90. package/dist/{authz/interfaces/oauth-common.interface.js → mcp/transport/mcp-transport.interface.js} +1 -1
  91. package/dist/mcp/transport/mcp-transport.interface.js.map +1 -0
  92. package/dist/mcp/transport/mcp.strategy.d.ts +56 -0
  93. package/dist/mcp/transport/mcp.strategy.d.ts.map +1 -0
  94. package/dist/mcp/transport/mcp.strategy.js +446 -0
  95. package/dist/mcp/transport/mcp.strategy.js.map +1 -0
  96. package/dist/mcp/transport/resource-matcher.d.ts +13 -0
  97. package/dist/mcp/transport/resource-matcher.d.ts.map +1 -0
  98. package/dist/mcp/transport/resource-matcher.js +83 -0
  99. package/dist/mcp/transport/resource-matcher.js.map +1 -0
  100. package/dist/mcp/transport/streamable-http.controller.d.ts +16 -0
  101. package/dist/mcp/transport/streamable-http.controller.d.ts.map +1 -0
  102. package/dist/mcp/transport/streamable-http.controller.js +98 -0
  103. package/dist/mcp/transport/streamable-http.controller.js.map +1 -0
  104. package/dist/mcp/transport/transports/index.d.ts +3 -0
  105. package/dist/mcp/transport/transports/index.d.ts.map +1 -0
  106. package/dist/{authz → mcp/transport/transports}/index.js +2 -10
  107. package/dist/mcp/transport/transports/index.js.map +1 -0
  108. package/dist/mcp/transport/transports/read-body.d.ts +3 -0
  109. package/dist/mcp/transport/transports/read-body.d.ts.map +1 -0
  110. package/dist/mcp/transport/transports/read-body.js +32 -0
  111. package/dist/mcp/transport/transports/read-body.js.map +1 -0
  112. package/dist/mcp/transport/transports/stdio.transport.d.ts +9 -0
  113. package/dist/mcp/transport/transports/stdio.transport.d.ts.map +1 -0
  114. package/dist/mcp/transport/transports/stdio.transport.js +27 -0
  115. package/dist/mcp/transport/transports/stdio.transport.js.map +1 -0
  116. package/dist/mcp/transport/transports/streamable-http.transport.d.ts +33 -0
  117. package/dist/mcp/transport/transports/streamable-http.transport.d.ts.map +1 -0
  118. package/dist/mcp/transport/transports/streamable-http.transport.js +216 -0
  119. package/dist/mcp/transport/transports/streamable-http.transport.js.map +1 -0
  120. package/dist/mcp/utils/mcp-logger.factory.d.ts +6 -2
  121. package/dist/mcp/utils/mcp-logger.factory.d.ts.map +1 -1
  122. package/dist/mcp/utils/mcp-logger.factory.js.map +1 -1
  123. package/package.json +3 -66
  124. package/src/index.ts +0 -1
  125. package/src/mcp/decorators/constants.ts +1 -0
  126. package/src/mcp/decorators/index.ts +3 -1
  127. package/src/mcp/decorators/mcp-controller.decorator.ts +126 -0
  128. package/src/mcp/decorators/mcp-message-pattern.ts +38 -0
  129. package/src/mcp/decorators/prompt.decorator.ts +32 -2
  130. package/src/mcp/decorators/public.decorator.ts +3 -3
  131. package/src/mcp/decorators/raw-request.decorator.ts +32 -0
  132. package/src/mcp/decorators/resource-template.decorator.ts +6 -2
  133. package/src/mcp/decorators/resource.decorator.ts +6 -2
  134. package/src/mcp/decorators/tool.decorator.ts +6 -3
  135. package/src/mcp/filters/mcp-exception.filter.ts +47 -0
  136. package/src/mcp/index.ts +13 -7
  137. package/src/mcp/interfaces/authenticated-user.interface.ts +22 -0
  138. package/src/mcp/interfaces/dynamic-prompt.interface.ts +1 -1
  139. package/src/mcp/interfaces/dynamic-resource.interface.ts +1 -1
  140. package/src/mcp/interfaces/dynamic-tool.interface.ts +2 -2
  141. package/src/mcp/interfaces/index.ts +3 -7
  142. package/src/mcp/services/tool-authorization.service.ts +52 -72
  143. package/src/mcp/transport/mcp-context.ts +138 -0
  144. package/src/mcp/transport/mcp-http-handler.ts +32 -0
  145. package/src/mcp/transport/mcp-server-options.interface.ts +75 -0
  146. package/src/mcp/transport/mcp-transport.constants.ts +99 -0
  147. package/src/mcp/transport/mcp-transport.interface.ts +50 -0
  148. package/src/mcp/transport/mcp.strategy.ts +752 -0
  149. package/src/mcp/transport/resource-matcher.ts +107 -0
  150. package/src/mcp/transport/streamable-http.controller.ts +114 -0
  151. package/src/mcp/transport/transports/index.ts +2 -0
  152. package/src/mcp/transport/transports/read-body.ts +39 -0
  153. package/src/mcp/transport/transports/stdio.transport.ts +35 -0
  154. package/src/mcp/transport/transports/streamable-http.transport.ts +384 -0
  155. package/src/mcp/utils/mcp-logger.factory.spec.ts +8 -22
  156. package/src/mcp/utils/mcp-logger.factory.ts +13 -2
  157. package/dist/authz/guards/jwt-auth.guard.d.ts +0 -19
  158. package/dist/authz/guards/jwt-auth.guard.d.ts.map +0 -1
  159. package/dist/authz/guards/jwt-auth.guard.js +0 -108
  160. package/dist/authz/guards/jwt-auth.guard.js.map +0 -1
  161. package/dist/authz/index.d.ts +0 -11
  162. package/dist/authz/index.d.ts.map +0 -1
  163. package/dist/authz/index.js.map +0 -1
  164. package/dist/authz/interfaces/oauth-common.interface.d.ts +0 -21
  165. package/dist/authz/interfaces/oauth-common.interface.d.ts.map +0 -1
  166. package/dist/authz/interfaces/oauth-common.interface.js.map +0 -1
  167. package/dist/authz/interfaces/request-with-user.d.ts +0 -13
  168. package/dist/authz/interfaces/request-with-user.d.ts.map +0 -1
  169. package/dist/authz/interfaces/request-with-user.js.map +0 -1
  170. package/dist/authz/mcp-oauth.controller.d.ts +0 -81
  171. package/dist/authz/mcp-oauth.controller.d.ts.map +0 -1
  172. package/dist/authz/mcp-oauth.controller.js +0 -540
  173. package/dist/authz/mcp-oauth.controller.js.map +0 -1
  174. package/dist/authz/mcp-oauth.module.d.ts +0 -12
  175. package/dist/authz/mcp-oauth.module.d.ts.map +0 -1
  176. package/dist/authz/mcp-oauth.module.js +0 -271
  177. package/dist/authz/mcp-oauth.module.js.map +0 -1
  178. package/dist/authz/providers/azure-ad.provider.d.ts +0 -3
  179. package/dist/authz/providers/azure-ad.provider.d.ts.map +0 -1
  180. package/dist/authz/providers/azure-ad.provider.js +0 -37
  181. package/dist/authz/providers/azure-ad.provider.js.map +0 -1
  182. package/dist/authz/providers/github.provider.d.ts +0 -3
  183. package/dist/authz/providers/github.provider.d.ts.map +0 -1
  184. package/dist/authz/providers/github.provider.js +0 -24
  185. package/dist/authz/providers/github.provider.js.map +0 -1
  186. package/dist/authz/providers/google.provider.d.ts +0 -3
  187. package/dist/authz/providers/google.provider.d.ts.map +0 -1
  188. package/dist/authz/providers/google.provider.js +0 -25
  189. package/dist/authz/providers/google.provider.js.map +0 -1
  190. package/dist/authz/providers/oauth-provider.interface.d.ts +0 -107
  191. package/dist/authz/providers/oauth-provider.interface.d.ts.map +0 -1
  192. package/dist/authz/providers/oauth-provider.interface.js.map +0 -1
  193. package/dist/authz/services/client.service.d.ts +0 -12
  194. package/dist/authz/services/client.service.d.ts.map +0 -1
  195. package/dist/authz/services/client.service.js +0 -81
  196. package/dist/authz/services/client.service.js.map +0 -1
  197. package/dist/authz/services/jwt-token.service.d.ts +0 -37
  198. package/dist/authz/services/jwt-token.service.d.ts.map +0 -1
  199. package/dist/authz/services/jwt-token.service.js +0 -182
  200. package/dist/authz/services/jwt-token.service.js.map +0 -1
  201. package/dist/authz/services/oauth-strategy.service.d.ts +0 -13
  202. package/dist/authz/services/oauth-strategy.service.d.ts.map +0 -1
  203. package/dist/authz/services/oauth-strategy.service.js +0 -71
  204. package/dist/authz/services/oauth-strategy.service.js.map +0 -1
  205. package/dist/authz/stores/memory-store.service.d.ts +0 -27
  206. package/dist/authz/stores/memory-store.service.d.ts.map +0 -1
  207. package/dist/authz/stores/memory-store.service.js +0 -107
  208. package/dist/authz/stores/memory-store.service.js.map +0 -1
  209. package/dist/authz/stores/oauth-store.interface.d.ts +0 -61
  210. package/dist/authz/stores/oauth-store.interface.d.ts.map +0 -1
  211. package/dist/authz/stores/oauth-store.interface.js +0 -5
  212. package/dist/authz/stores/oauth-store.interface.js.map +0 -1
  213. package/dist/authz/stores/typeorm/constants.d.ts +0 -3
  214. package/dist/authz/stores/typeorm/constants.d.ts.map +0 -1
  215. package/dist/authz/stores/typeorm/constants.js +0 -6
  216. package/dist/authz/stores/typeorm/constants.js.map +0 -1
  217. package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts +0 -15
  218. package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts.map +0 -1
  219. package/dist/authz/stores/typeorm/entities/authorization-code.entity.js +0 -69
  220. package/dist/authz/stores/typeorm/entities/authorization-code.entity.js.map +0 -1
  221. package/dist/authz/stores/typeorm/entities/index.d.ts +0 -5
  222. package/dist/authz/stores/typeorm/entities/index.d.ts.map +0 -1
  223. package/dist/authz/stores/typeorm/entities/index.js +0 -12
  224. package/dist/authz/stores/typeorm/entities/index.js.map +0 -1
  225. package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts +0 -17
  226. package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts.map +0 -1
  227. package/dist/authz/stores/typeorm/entities/oauth-client.entity.js +0 -77
  228. package/dist/authz/stores/typeorm/entities/oauth-client.entity.js.map +0 -1
  229. package/dist/authz/stores/typeorm/entities/oauth-session.entity.d.ts +0 -14
  230. package/dist/authz/stores/typeorm/entities/oauth-session.entity.d.ts.map +0 -1
  231. package/dist/authz/stores/typeorm/entities/oauth-session.entity.js +0 -65
  232. package/dist/authz/stores/typeorm/entities/oauth-session.entity.js.map +0 -1
  233. package/dist/authz/stores/typeorm/entities/user-profile.entity.d.ts +0 -13
  234. package/dist/authz/stores/typeorm/entities/user-profile.entity.d.ts.map +0 -1
  235. package/dist/authz/stores/typeorm/entities/user-profile.entity.js +0 -62
  236. package/dist/authz/stores/typeorm/entities/user-profile.entity.js.map +0 -1
  237. package/dist/authz/stores/typeorm/typeorm-store.service.d.ts +0 -28
  238. package/dist/authz/stores/typeorm/typeorm-store.service.d.ts.map +0 -1
  239. package/dist/authz/stores/typeorm/typeorm-store.service.js +0 -138
  240. package/dist/authz/stores/typeorm/typeorm-store.service.js.map +0 -1
  241. package/dist/mcp/constants/feature-registration.constants.d.ts +0 -7
  242. package/dist/mcp/constants/feature-registration.constants.d.ts.map +0 -1
  243. package/dist/mcp/constants/feature-registration.constants.js +0 -5
  244. package/dist/mcp/constants/feature-registration.constants.js.map +0 -1
  245. package/dist/mcp/decorators/tool-guards.decorator.d.ts +0 -12
  246. package/dist/mcp/decorators/tool-guards.decorator.d.ts.map +0 -1
  247. package/dist/mcp/decorators/tool-guards.decorator.js +0 -13
  248. package/dist/mcp/decorators/tool-guards.decorator.js.map +0 -1
  249. package/dist/mcp/interfaces/mcp-options.interface.d.ts +0 -53
  250. package/dist/mcp/interfaces/mcp-options.interface.d.ts.map +0 -1
  251. package/dist/mcp/interfaces/mcp-options.interface.js +0 -10
  252. package/dist/mcp/interfaces/mcp-options.interface.js.map +0 -1
  253. package/dist/mcp/mcp.module.d.ts +0 -15
  254. package/dist/mcp/mcp.module.d.ts.map +0 -1
  255. package/dist/mcp/mcp.module.js +0 -248
  256. package/dist/mcp/mcp.module.js.map +0 -1
  257. package/dist/mcp/services/handlers/mcp-handler.base.d.ts +0 -117
  258. package/dist/mcp/services/handlers/mcp-handler.base.d.ts.map +0 -1
  259. package/dist/mcp/services/handlers/mcp-handler.base.js +0 -125
  260. package/dist/mcp/services/handlers/mcp-handler.base.js.map +0 -1
  261. package/dist/mcp/services/handlers/mcp-prompts.handler.d.ts +0 -12
  262. package/dist/mcp/services/handlers/mcp-prompts.handler.d.ts.map +0 -1
  263. package/dist/mcp/services/handlers/mcp-prompts.handler.js +0 -98
  264. package/dist/mcp/services/handlers/mcp-prompts.handler.js.map +0 -1
  265. package/dist/mcp/services/handlers/mcp-resources.handler.d.ts +0 -13
  266. package/dist/mcp/services/handlers/mcp-resources.handler.d.ts.map +0 -1
  267. package/dist/mcp/services/handlers/mcp-resources.handler.js +0 -117
  268. package/dist/mcp/services/handlers/mcp-resources.handler.js.map +0 -1
  269. package/dist/mcp/services/handlers/mcp-tools.handler.d.ts +0 -22
  270. package/dist/mcp/services/handlers/mcp-tools.handler.d.ts.map +0 -1
  271. package/dist/mcp/services/handlers/mcp-tools.handler.js +0 -258
  272. package/dist/mcp/services/handlers/mcp-tools.handler.js.map +0 -1
  273. package/dist/mcp/services/mcp-dynamic-registry.service.d.ts +0 -26
  274. package/dist/mcp/services/mcp-dynamic-registry.service.d.ts.map +0 -1
  275. package/dist/mcp/services/mcp-dynamic-registry.service.js +0 -133
  276. package/dist/mcp/services/mcp-dynamic-registry.service.js.map +0 -1
  277. package/dist/mcp/services/mcp-executor.service.d.ts +0 -15
  278. package/dist/mcp/services/mcp-executor.service.d.ts.map +0 -1
  279. package/dist/mcp/services/mcp-executor.service.js +0 -47
  280. package/dist/mcp/services/mcp-executor.service.js.map +0 -1
  281. package/dist/mcp/services/mcp-registry-discovery.service.d.ts +0 -63
  282. package/dist/mcp/services/mcp-registry-discovery.service.d.ts.map +0 -1
  283. package/dist/mcp/services/mcp-registry-discovery.service.js +0 -397
  284. package/dist/mcp/services/mcp-registry-discovery.service.js.map +0 -1
  285. package/dist/mcp/services/mcp-sse.service.d.ts +0 -20
  286. package/dist/mcp/services/mcp-sse.service.d.ts.map +0 -1
  287. package/dist/mcp/services/mcp-sse.service.js +0 -91
  288. package/dist/mcp/services/mcp-sse.service.js.map +0 -1
  289. package/dist/mcp/services/mcp-streamable-http.service.d.ts +0 -32
  290. package/dist/mcp/services/mcp-streamable-http.service.d.ts.map +0 -1
  291. package/dist/mcp/services/mcp-streamable-http.service.js +0 -327
  292. package/dist/mcp/services/mcp-streamable-http.service.js.map +0 -1
  293. package/dist/mcp/services/sse-ping.service.d.ts +0 -23
  294. package/dist/mcp/services/sse-ping.service.d.ts.map +0 -1
  295. package/dist/mcp/services/sse-ping.service.js +0 -99
  296. package/dist/mcp/services/sse-ping.service.js.map +0 -1
  297. package/dist/mcp/transport/sse.controller.factory.d.ts +0 -14
  298. package/dist/mcp/transport/sse.controller.factory.d.ts.map +0 -1
  299. package/dist/mcp/transport/sse.controller.factory.js +0 -67
  300. package/dist/mcp/transport/sse.controller.factory.js.map +0 -1
  301. package/dist/mcp/transport/stdio.service.d.ts +0 -14
  302. package/dist/mcp/transport/stdio.service.d.ts.map +0 -1
  303. package/dist/mcp/transport/stdio.service.js +0 -66
  304. package/dist/mcp/transport/stdio.service.js.map +0 -1
  305. package/dist/mcp/transport/streamable-http.controller.factory.d.ts +0 -14
  306. package/dist/mcp/transport/streamable-http.controller.factory.d.ts.map +0 -1
  307. package/dist/mcp/transport/streamable-http.controller.factory.js +0 -74
  308. package/dist/mcp/transport/streamable-http.controller.factory.js.map +0 -1
  309. package/dist/mcp/utils/capabilities-builder.d.ts +0 -5
  310. package/dist/mcp/utils/capabilities-builder.d.ts.map +0 -1
  311. package/dist/mcp/utils/capabilities-builder.js +0 -25
  312. package/dist/mcp/utils/capabilities-builder.js.map +0 -1
  313. package/dist/mcp/utils/mcp-server.factory.d.ts +0 -6
  314. package/dist/mcp/utils/mcp-server.factory.d.ts.map +0 -1
  315. package/dist/mcp/utils/mcp-server.factory.js +0 -22
  316. package/dist/mcp/utils/mcp-server.factory.js.map +0 -1
  317. package/src/authz/guards/jwt-auth.guard.ts +0 -127
  318. package/src/authz/index.ts +0 -10
  319. package/src/authz/interfaces/oauth-common.interface.ts +0 -21
  320. package/src/authz/interfaces/request-with-user.ts +0 -16
  321. package/src/authz/mcp-oauth.controller.ts +0 -860
  322. package/src/authz/mcp-oauth.module.ts +0 -384
  323. package/src/authz/providers/azure-ad.provider.ts +0 -40
  324. package/src/authz/providers/github.provider.ts +0 -22
  325. package/src/authz/providers/google.provider.ts +0 -23
  326. package/src/authz/providers/oauth-provider.interface.ts +0 -147
  327. package/src/authz/services/client.service.ts +0 -125
  328. package/src/authz/services/jwt-token.service.spec.ts +0 -67
  329. package/src/authz/services/jwt-token.service.ts +0 -188
  330. package/src/authz/services/oauth-strategy.service.ts +0 -64
  331. package/src/authz/stores/memory-store.service.spec.ts +0 -475
  332. package/src/authz/stores/memory-store.service.ts +0 -141
  333. package/src/authz/stores/oauth-store.interface.ts +0 -131
  334. package/src/authz/stores/typeorm/README.md +0 -140
  335. package/src/authz/stores/typeorm/constants.ts +0 -6
  336. package/src/authz/stores/typeorm/entities/authorization-code.entity.ts +0 -41
  337. package/src/authz/stores/typeorm/entities/index.ts +0 -4
  338. package/src/authz/stores/typeorm/entities/oauth-client.entity.ts +0 -53
  339. package/src/authz/stores/typeorm/entities/oauth-session.entity.ts +0 -38
  340. package/src/authz/stores/typeorm/entities/user-profile.entity.ts +0 -46
  341. package/src/authz/stores/typeorm/typeorm-store.service.spec.ts +0 -494
  342. package/src/authz/stores/typeorm/typeorm-store.service.ts +0 -165
  343. package/src/mcp/constants/feature-registration.constants.ts +0 -24
  344. package/src/mcp/decorators/tool-guards.decorator.ts +0 -82
  345. package/src/mcp/interfaces/mcp-options.interface.ts +0 -95
  346. package/src/mcp/mcp.module.ts +0 -349
  347. package/src/mcp/services/handlers/mcp-handler.base.ts +0 -203
  348. package/src/mcp/services/handlers/mcp-prompts.handler.ts +0 -143
  349. package/src/mcp/services/handlers/mcp-resources.handler.ts +0 -183
  350. package/src/mcp/services/handlers/mcp-tools.handler.spec.ts +0 -41
  351. package/src/mcp/services/handlers/mcp-tools.handler.ts +0 -436
  352. package/src/mcp/services/mcp-dynamic-registry.service.ts +0 -236
  353. package/src/mcp/services/mcp-executor.service.ts +0 -64
  354. package/src/mcp/services/mcp-registry-discovery.service.spec.ts +0 -306
  355. package/src/mcp/services/mcp-registry-discovery.service.ts +0 -849
  356. package/src/mcp/services/mcp-sse.service.ts +0 -124
  357. package/src/mcp/services/mcp-streamable-http.service.ts +0 -472
  358. package/src/mcp/services/sse-ping.service.ts +0 -144
  359. package/src/mcp/transport/custom-decorator.spec.ts +0 -75
  360. package/src/mcp/transport/sse.controller.factory.ts +0 -84
  361. package/src/mcp/transport/stdio.service.ts +0 -75
  362. package/src/mcp/transport/streamable-http.controller.factory.ts +0 -80
  363. package/src/mcp/utils/capabilities-builder.ts +0 -43
  364. package/src/mcp/utils/mcp-server.factory.ts +0 -33
@@ -9,10 +9,10 @@ export const MCP_PUBLIC_METADATA_KEY = 'mcp:public-tool';
9
9
  * Decorator to mark a tool as publicly accessible, bypassing authentication requirements.
10
10
  *
11
11
  * Use this when you want a tool to be available even to unauthenticated users
12
- * when `allowUnauthenticatedAccess` is enabled in McpModule options.
12
+ * when `allowUnauthenticatedAccess` is enabled on the {@link McpStrategy}.
13
13
  *
14
- * When applied to a tool method, it allows the tool to be called without authentication,
15
- * even if the module has guards configured.
14
+ * When applied to a tool method, it allows the tool to be listed and called
15
+ * without authentication, even when other tools on the server require it.
16
16
  *
17
17
  * @example
18
18
  * ```typescript
@@ -0,0 +1,32 @@
1
+ import { createParamDecorator, ExecutionContext } from '@nestjs/common';
2
+ import type { McpContext } from '../transport/mcp-context';
3
+
4
+ /**
5
+ * Injects the raw transport request into an MCP capability handler — the MCP
6
+ * analog of NestJS's `@Req()`.
7
+ *
8
+ * Returns the underlying HTTP request object (Express `Request` / Fastify
9
+ * `FastifyRequest`) for HTTP-based transports, or `undefined` for STDIO, which
10
+ * is stream-oriented and has no per-call request object. Annotate the parameter
11
+ * with your framework's request type — the decorator itself does not type it,
12
+ * exactly like `@Req()`:
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import type { Request } from 'express';
17
+ *
18
+ * @Tool({ name: 'whoami', description: 'Echo the caller' })
19
+ * whoami(@McpRawRequest() req?: Request) {
20
+ * return { content: [{ type: 'text', text: req?.ip ?? 'stdio' }] };
21
+ * }
22
+ * ```
23
+ *
24
+ * This is sugar for `ctx.getRawRequest()` on the `@Ctx()` context; reach for it
25
+ * when the request is all you need from the context. Note that, like every
26
+ * NestJS param decorator, using this means the data parameter must also be
27
+ * annotated (with `@Payload()`).
28
+ */
29
+ export const McpRawRequest = createParamDecorator(
30
+ (_data: unknown, ctx: ExecutionContext) =>
31
+ ctx.switchToRpc().getContext<McpContext>()?.getRawRequest(),
32
+ );
@@ -1,5 +1,6 @@
1
- import { SetMetadata } from '@nestjs/common';
1
+ import { applyDecorators, SetMetadata } from '@nestjs/common';
2
2
  import { MCP_RESOURCE_TEMPLATE_METADATA_KEY } from './constants';
3
+ import { mcpMessagePattern } from './mcp-message-pattern';
3
4
 
4
5
  export type ResourceTemplateOptions =
5
6
  // https://modelcontextprotocol.io/docs/concepts/resources#resource-templates
@@ -27,5 +28,8 @@ export interface ResourceTemplateMetadata {
27
28
  * @returns {MethodDecorator} - The decorator
28
29
  */
29
30
  export const ResourceTemplate = (options: ResourceTemplateOptions) => {
30
- return SetMetadata(MCP_RESOURCE_TEMPLATE_METADATA_KEY, options);
31
+ return applyDecorators(
32
+ SetMetadata(MCP_RESOURCE_TEMPLATE_METADATA_KEY, options),
33
+ mcpMessagePattern('resource-template', options.uriTemplate),
34
+ );
31
35
  };
@@ -1,5 +1,6 @@
1
- import { SetMetadata } from '@nestjs/common';
1
+ import { applyDecorators, SetMetadata } from '@nestjs/common';
2
2
  import { MCP_RESOURCE_METADATA_KEY } from './constants';
3
+ import { mcpMessagePattern } from './mcp-message-pattern';
3
4
 
4
5
  export type ResourceOptions =
5
6
  // https://modelcontextprotocol.io/docs/concepts/resources#direct-resources
@@ -27,5 +28,8 @@ export interface ResourceMetadata {
27
28
  * @returns {MethodDecorator} - The decorator
28
29
  */
29
30
  export const Resource = (options: ResourceOptions) => {
30
- return SetMetadata(MCP_RESOURCE_METADATA_KEY, options);
31
+ return applyDecorators(
32
+ SetMetadata(MCP_RESOURCE_METADATA_KEY, options),
33
+ mcpMessagePattern('resource', options.uri),
34
+ );
31
35
  };
@@ -1,7 +1,8 @@
1
- import { CanActivate, SetMetadata, Type } from '@nestjs/common';
1
+ import { applyDecorators, SetMetadata } from '@nestjs/common';
2
2
  import { z } from 'zod';
3
3
  import { ToolAnnotations as SdkToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
4
4
  import { MCP_TOOL_METADATA_KEY } from './constants';
5
+ import { mcpMessagePattern } from './mcp-message-pattern';
5
6
 
6
7
  /**
7
8
  * Security scheme type for MCP tools
@@ -22,7 +23,6 @@ export interface ToolMetadata {
22
23
  isPublic?: boolean;
23
24
  requiredScopes?: string[];
24
25
  requiredRoles?: string[];
25
- guards?: Type<CanActivate>[];
26
26
  }
27
27
 
28
28
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -51,5 +51,8 @@ export const Tool = (options: ToolOptions) => {
51
51
  options.parameters = z.object({});
52
52
  }
53
53
 
54
- return SetMetadata(MCP_TOOL_METADATA_KEY, options);
54
+ return applyDecorators(
55
+ SetMetadata(MCP_TOOL_METADATA_KEY, options),
56
+ mcpMessagePattern('tool', options.name),
57
+ );
55
58
  };
@@ -0,0 +1,47 @@
1
+ import { ArgumentsHost, Catch, RpcExceptionFilter } from '@nestjs/common';
2
+ import { RpcException } from '@nestjs/microservices';
3
+ import { Observable, throwError } from 'rxjs';
4
+
5
+ /**
6
+ * Surfaces the real error message of any exception thrown by an MCP
7
+ * tool/resource/prompt handler, instead of NestJS's default "Internal server
8
+ * error" masking.
9
+ *
10
+ * By default NestJS's RPC pipeline masks any non-`RpcException` to a generic
11
+ * "Internal server error" before the strategy can read it, so a plain
12
+ * `throw new Error('Order #42 not found')` reaches the agent as an opaque
13
+ * failure. That is a safe default (it avoids leaking internals), but it is poor
14
+ * DX when the message is meant for the caller. Register this filter to opt into
15
+ * passing the original message through:
16
+ *
17
+ * ```typescript
18
+ * // Globally (recommended) — applies to every MCP handler, but never overrides
19
+ * // a more specific `@UseFilters()` you put on a controller/method.
20
+ * providers: [{ provide: APP_FILTER, useClass: McpExceptionFilter }]
21
+ * ```
22
+ *
23
+ * ```typescript
24
+ * // Or per controller/method:
25
+ * @UseFilters(McpExceptionFilter)
26
+ * @McpController()
27
+ * class MyTools { ... }
28
+ * ```
29
+ *
30
+ * The surfaced message becomes an `isError: true` tool result (or a JSON-RPC
31
+ * error for resources/prompts), so the agent can tell a real failure from a
32
+ * successful call. For input problems, prefer the built-in Zod validation
33
+ * (a clear "Invalid parameters: …" result) or `throw new RpcException(...)` /
34
+ * a NestJS exception — those are already surfaced without this filter.
35
+ */
36
+ @Catch()
37
+ export class McpExceptionFilter implements RpcExceptionFilter {
38
+ catch(exception: unknown, _host: ArgumentsHost): Observable<never> {
39
+ // RpcException already carries an explicit, client-facing payload.
40
+ if (exception instanceof RpcException) {
41
+ return throwError(() => exception.getError());
42
+ }
43
+ const message =
44
+ exception instanceof Error ? exception.message : 'Internal server error';
45
+ return throwError(() => ({ status: 'error', message }));
46
+ }
47
+ }
package/src/mcp/index.ts CHANGED
@@ -1,9 +1,15 @@
1
1
  export * from './decorators';
2
2
  export * from './interfaces';
3
- export * from './mcp.module';
4
- export * from './services/mcp-registry-discovery.service';
5
- export * from './services/mcp-executor.service';
6
- export * from './services/mcp-sse.service';
7
- export * from './services/mcp-streamable-http.service';
8
- export * from './services/mcp-dynamic-registry.service';
9
- export * from './constants/feature-registration.constants';
3
+ export * from './services/tool-authorization.service';
4
+ export * from './filters/mcp-exception.filter';
5
+ export * from './utils/normalize-endpoint';
6
+
7
+ // Microservice transport strategy API
8
+ export * from './transport/mcp-transport.constants';
9
+ export * from './transport/mcp-context';
10
+ export * from './transport/mcp-server-options.interface';
11
+ export * from './transport/mcp-transport.interface';
12
+ export * from './transport/mcp-http-handler';
13
+ export * from './transport/mcp.strategy';
14
+ export * from './transport/streamable-http.controller';
15
+ export * from './transport/transports';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Minimal shape of an authenticated principal as far as the core per-tool
3
+ * authorization logic is concerned.
4
+ *
5
+ * The core module never authenticates anyone itself — a guard or transport-level
6
+ * auth middleware resolves the user and places it on `req.user`. Per-tool checks
7
+ * (`@ToolScopes()`, `@ToolRoles()`) only read scopes and roles off that object, so
8
+ * core depends on this structural type rather than on any concrete token payload.
9
+ *
10
+ * The auth package's richer `JwtPayload` is structurally compatible with this
11
+ * interface, so no coupling back to `@rekog/mcp-nest-auth` is required.
12
+ */
13
+ export interface AuthenticatedUser {
14
+ /** OAuth 2.0 space-delimited scope string. */
15
+ scope?: string;
16
+ /** Roles carried directly on the principal. */
17
+ roles?: string[];
18
+ /** Provider-specific user data; may carry roles. */
19
+ user_data?: { roles?: string[] } & Record<string, any>;
20
+ /** Allow additional, provider-specific claims without widening the read surface. */
21
+ [key: string]: any;
22
+ }
@@ -6,7 +6,7 @@ export type DynamicPromptHandler = (
6
6
  args: Record<string, string> | undefined,
7
7
  context: Context,
8
8
  request: any,
9
- ) => Promise<any> | any;
9
+ ) => any;
10
10
 
11
11
  export interface DynamicPromptDefinition {
12
12
  /** Unique name for the prompt */
@@ -4,7 +4,7 @@ export type DynamicResourceHandler = (
4
4
  params: Record<string, unknown>,
5
5
  context: Context,
6
6
  request: any,
7
- ) => Promise<any> | any;
7
+ ) => any;
8
8
 
9
9
  export interface DynamicResourceDefinition {
10
10
  /** URI that uniquely identifies this resource */
@@ -10,11 +10,11 @@ export type DynamicToolHandler = (
10
10
  args: Record<string, unknown>,
11
11
  context: Context,
12
12
  request: any,
13
- ) => Promise<any> | any;
13
+ ) => any;
14
14
 
15
15
  /**
16
16
  * Definition for a dynamically registered tool.
17
- * Use this with McpRegistryService.registerTool() to register tools at runtime.
17
+ * Use this with `McpStrategy.registerTool()` to register tools at runtime.
18
18
  *
19
19
  * @example
20
20
  * ```typescript
@@ -1,10 +1,4 @@
1
- export { McpTransportType } from './mcp-options.interface';
2
- export type {
3
- McpOptions,
4
- McpAsyncOptions,
5
- McpOptionsFactory,
6
- McpModuleAsyncOptions,
7
- } from './mcp-options.interface';
1
+ export type { Icon } from '@modelcontextprotocol/sdk/types.js';
8
2
 
9
3
  export type {
10
4
  Literal,
@@ -16,6 +10,8 @@ export type {
16
10
 
17
11
  export type { HttpRequest } from './http-adapter.interface';
18
12
 
13
+ export type { AuthenticatedUser } from './authenticated-user.interface';
14
+
19
15
  export type {
20
16
  DynamicToolDefinition,
21
17
  DynamicToolHandler,
@@ -1,24 +1,42 @@
1
1
  import { Injectable } from '@nestjs/common';
2
2
  import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
3
- import { DiscoveredCapability } from './mcp-registry-discovery.service';
4
3
  import { ToolMetadata, SecurityScheme } from '../decorators/tool.decorator';
5
- import { JwtPayload } from '../../authz/services/jwt-token.service';
4
+ import { AuthenticatedUser } from '../interfaces/authenticated-user.interface';
5
+
6
+ /** Minimal shape the authorization logic needs: a capability carrying tool metadata. */
7
+ export interface AuthorizableTool {
8
+ metadata: ToolMetadata;
9
+ }
6
10
 
7
11
  /**
8
- * Service responsible for tool-level authorization logic
12
+ * Per-tool authorization.
13
+ *
14
+ * This service powers `tools/list` filtering and the `tools/call` access check
15
+ * based purely on the per-tool decorators (`@PublicTool()`, `@ToolScopes()`,
16
+ * `@ToolRoles()`) and the user resolved off the raw request (`req.user`, set by
17
+ * a guard or by transport-level auth middleware).
18
+ *
19
+ * It is intentionally NOT an authentication mechanism: real enforcement is the
20
+ * job of standard NestJS `@UseGuards()` (which run inside the RPC pipeline at
21
+ * call time) and/or auth middleware on the HTTP routes. This service only
22
+ * decides which tools a *known* principal may see and invoke.
9
23
  */
10
24
  @Injectable()
11
25
  export class ToolAuthorizationService {
12
26
  /**
13
- * Generate security schemes for a tool based on its metadata and module configuration
27
+ * Generate security schemes for a tool, advertised to clients (e.g. ChatGPT)
28
+ * via the OpenAI `securitySchemes` spec so they know which tools need auth.
14
29
  *
15
30
  * @param tool - The discovered tool
16
- * @param moduleHasGuards - Whether the module has guards configured
31
+ * @param freemiumMode - Whether the server runs in freemium mode
32
+ * (`allowUnauthenticatedAccess`). In freemium mode an undecorated,
33
+ * non-public tool still requires authentication, so it is advertised as
34
+ * `oauth2`.
17
35
  * @returns Array of security schemes for the tool
18
36
  */
19
37
  generateSecuritySchemes(
20
- tool: DiscoveredCapability<ToolMetadata>,
21
- moduleHasGuards: boolean,
38
+ tool: AuthorizableTool,
39
+ freemiumMode: boolean,
22
40
  ): SecurityScheme[] {
23
41
  const metadata = tool.metadata;
24
42
  const schemes: SecurityScheme[] = [];
@@ -32,8 +50,12 @@ export class ToolAuthorizationService {
32
50
  if (metadata.requiredScopes && metadata.requiredScopes.length > 0) {
33
51
  schemes.push({ type: 'oauth2', scopes: metadata.requiredScopes });
34
52
  }
35
- // Else if module has guards and tool is not public, require oauth2
36
- else if (moduleHasGuards && !metadata.isPublic) {
53
+ // Else if tool requires specific roles, advertise that auth is needed
54
+ else if (metadata.requiredRoles && metadata.requiredRoles.length > 0) {
55
+ schemes.push({ type: 'oauth2' });
56
+ }
57
+ // Else, in freemium mode a non-public tool still requires authentication
58
+ else if (freemiumMode && !metadata.isPublic) {
37
59
  schemes.push({ type: 'oauth2' });
38
60
  }
39
61
 
@@ -46,18 +68,16 @@ export class ToolAuthorizationService {
46
68
  }
47
69
 
48
70
  /**
49
- * Check if a user can access a tool based on security requirements
71
+ * Check if a user can access a tool based on its per-tool requirements.
50
72
  *
51
73
  * @param user - The authenticated user (may be undefined)
52
74
  * @param tool - The discovered tool
53
- * @param moduleHasGuards - Whether the module has guards configured
54
75
  * @param allowUnauthenticatedAccess - Whether unauthenticated access is allowed (freemium mode)
55
- * @returns true if user can access the tool, false otherwise
76
+ * @returns true if the user can access the tool, false otherwise
56
77
  */
57
78
  canAccessTool(
58
- user: JwtPayload | undefined,
59
- tool: DiscoveredCapability<ToolMetadata>,
60
- moduleHasGuards: boolean,
79
+ user: AuthenticatedUser | undefined,
80
+ tool: AuthorizableTool,
61
81
  allowUnauthenticatedAccess: boolean = false,
62
82
  ): boolean {
63
83
  const metadata = tool.metadata;
@@ -90,50 +110,33 @@ export class ToolAuthorizationService {
90
110
  }
91
111
  }
92
112
 
93
- // At this point:
94
- // - Tool is not public
95
- // - Tool has no specific scope/role requirements (or they passed)
96
- //
97
- // Decision logic based on allowUnauthenticatedAccess:
98
- //
99
- // allowUnauthenticatedAccess = false (default, standard auth mode):
100
- // - Guards are expected to fully authorize requests (via JWT, API keys, etc)
101
- // - If guard let request through AND there's no user object:
102
- // * Guard used non-JWT auth mechanism (API key, IP whitelist, etc)
103
- // * Trust the guard's decision to authorize
104
- // - If no guards configured, allow access (no auth required)
113
+ // At this point the tool is not public and has no (or satisfied) scope/role
114
+ // requirements. The only remaining question is the undecorated tool:
105
115
  //
106
- // allowUnauthenticatedAccess = true (freemium mode):
107
- // - Guards may let unauthenticated requests through for per-tool auth
108
- // - Only @PublicTool or tools with specific scopes/roles accessible
109
- // - Tools without decorators require authentication (user must be present)
110
- //
111
- if (allowUnauthenticatedAccess && moduleHasGuards && !user) {
112
- // Freemium mode: unauthenticated access only for @PublicTool or specific scopes
113
- // This tool has no decorators, so it requires authentication
116
+ // - Freemium mode (allowUnauthenticatedAccess = true): anonymous callers may
117
+ // only reach @PublicTool() (or specifically-scoped) tools, so an
118
+ // undecorated tool requires a user.
119
+ // - Standard mode (default): real enforcement is delegated to @UseGuards /
120
+ // auth middleware, so we trust that decision and allow access. (On stdio
121
+ // there is no request and no user — all undecorated tools are reachable.)
122
+ if (allowUnauthenticatedAccess && !user) {
114
123
  return false;
115
124
  }
116
125
 
117
- // Standard mode: If we're here, either:
118
- // - No guards (open access)
119
- // - Guards authorized it (trust guard decision, even without user object)
120
- // - User is present and passed all checks
121
126
  return true;
122
127
  }
123
128
 
124
129
  /**
125
- * Validate that a user can access a tool, throwing an error if not authorized
130
+ * Validate that a user can access a tool, throwing an error if not authorized.
126
131
  *
127
132
  * @param user - The authenticated user (may be undefined)
128
133
  * @param tool - The discovered tool
129
- * @param moduleHasGuards - Whether the module has guards configured
130
134
  * @param allowUnauthenticatedAccess - Whether unauthenticated access is allowed (freemium mode)
131
135
  * @throws McpError if user is not authorized to access the tool
132
136
  */
133
137
  validateToolAccess(
134
- user: JwtPayload | undefined,
135
- tool: DiscoveredCapability<ToolMetadata>,
136
- moduleHasGuards: boolean,
138
+ user: AuthenticatedUser | undefined,
139
+ tool: AuthorizableTool,
137
140
  allowUnauthenticatedAccess: boolean = false,
138
141
  ): void {
139
142
  const metadata = tool.metadata;
@@ -176,37 +179,14 @@ export class ToolAuthorizationService {
176
179
  }
177
180
  }
178
181
 
179
- // At this point:
180
- // - Tool is not public
181
- // - Tool has no specific scope/role requirements (or they passed)
182
- //
183
- // Decision logic based on allowUnauthenticatedAccess:
184
- //
185
- // allowUnauthenticatedAccess = false (default, standard auth mode):
186
- // - Guards are expected to fully authorize requests (via JWT, API keys, etc)
187
- // - If guard let request through AND there's no user object:
188
- // * Guard used non-JWT auth mechanism (API key, IP whitelist, etc)
189
- // * Trust the guard's decision to authorize
190
- // - If no guards configured, allow access (no auth required)
191
- //
192
- // allowUnauthenticatedAccess = true (freemium mode):
193
- // - Guards may let unauthenticated requests through for per-tool auth
194
- // - Only @PublicTool or tools with specific scopes/roles accessible
195
- // - Tools without decorators require authentication (user must be present)
196
- //
197
- if (allowUnauthenticatedAccess && moduleHasGuards && !user) {
198
- // Freemium mode: unauthenticated access only for @PublicTool or specific scopes
199
- // This tool has no decorators, so it requires authentication
182
+ // Freemium mode: an undecorated, non-public tool still requires a user.
183
+ // Standard mode trusts @UseGuards / auth middleware (see canAccessTool).
184
+ if (allowUnauthenticatedAccess && !user) {
200
185
  throw new McpError(
201
186
  ErrorCode.InvalidRequest,
202
187
  `Tool '${toolName}' requires authentication`,
203
188
  );
204
189
  }
205
-
206
- // Standard mode: If we're here, either:
207
- // - No guards (open access)
208
- // - Guards authorized it (trust guard decision, even without user object)
209
- // - User is present and passed all checks
210
190
  }
211
191
 
212
192
  /**
@@ -217,7 +197,7 @@ export class ToolAuthorizationService {
217
197
  * @returns true if user has all required scopes
218
198
  */
219
199
  private hasRequiredScopes(
220
- user: JwtPayload | undefined,
200
+ user: AuthenticatedUser | undefined,
221
201
  requiredScopes: string[],
222
202
  ): boolean {
223
203
  if (!user) {
@@ -247,7 +227,7 @@ export class ToolAuthorizationService {
247
227
  * @returns true if user has all required roles
248
228
  */
249
229
  private hasRequiredRoles(
250
- user: JwtPayload | undefined,
230
+ user: AuthenticatedUser | undefined,
251
231
  requiredRoles: string[],
252
232
  ): boolean {
253
233
  if (!user) {
@@ -0,0 +1,138 @@
1
+ import { Logger } from '@nestjs/common';
2
+ import { BaseRpcContext } from '@nestjs/microservices';
3
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ import { Progress } from '@modelcontextprotocol/sdk/types.js';
5
+ import { Context, McpRequest, SerializableValue } from '../interfaces';
6
+
7
+ export type McpTransportKind = 'stdio' | 'streamable-http';
8
+
9
+ export interface McpSessionInfo {
10
+ /** The MCP session id, when the transport is session-aware. */
11
+ sessionId?: string;
12
+ /** Which transport delivered this request. */
13
+ transport: McpTransportKind;
14
+ /**
15
+ * `true` only for the per-request streamable-HTTP stateless mode, where the
16
+ * server cannot push notifications/progress back to the client. stdio and
17
+ * stateful streamable-HTTP are both session-aware (`false`).
18
+ */
19
+ stateless: boolean;
20
+ }
21
+
22
+ type McpContextArgs = [
23
+ mcpServer: McpServer,
24
+ mcpRequest: McpRequest,
25
+ session: McpSessionInfo,
26
+ rawRequest: unknown,
27
+ ];
28
+
29
+ /**
30
+ * Execution context handed to every MCP capability handler via `@Ctx()`.
31
+ *
32
+ * Extends NestJS's {@link BaseRpcContext} so it is resolved as the RPC context
33
+ * argument (the strategy invokes handlers as `handler(payload, mcpContext)`),
34
+ * and implements the library's {@link Context} surface (`reportProgress`, `log`,
35
+ * `mcpServer`, `mcpRequest`) so existing handler code keeps working.
36
+ *
37
+ * Additional accessors expose the session and the raw transport request.
38
+ */
39
+ export class McpContext
40
+ extends BaseRpcContext<McpContextArgs>
41
+ implements Context
42
+ {
43
+ public readonly reportProgress: (progress: Progress) => Promise<void>;
44
+ public readonly log: Context['log'];
45
+
46
+ constructor(
47
+ args: McpContextArgs,
48
+ private readonly logger?: Logger,
49
+ ) {
50
+ super(args);
51
+ this.reportProgress = this.getSession().stateless
52
+ ? this.createStatelessReportProgress()
53
+ : this.createReportProgress();
54
+ this.log = this.getSession().stateless
55
+ ? this.createStatelessLog()
56
+ : this.createLog();
57
+ }
58
+
59
+ /** The underlying MCP SDK server instance. */
60
+ get mcpServer(): McpServer {
61
+ return this.args[0];
62
+ }
63
+
64
+ /** The parsed JSON-RPC request (tools/call, resources/read, prompts/get, ...). */
65
+ get mcpRequest(): McpRequest {
66
+ return this.args[1];
67
+ }
68
+
69
+ /** Session metadata for this request. */
70
+ getSession(): McpSessionInfo {
71
+ return this.args[2];
72
+ }
73
+
74
+ /** The raw transport request (Express/Fastify request for HTTP; `undefined` for stdio). */
75
+ getRawRequest<T = unknown>(): T | undefined {
76
+ return this.args[3] as T | undefined;
77
+ }
78
+
79
+ private get progressToken(): string | number | undefined {
80
+ return this.mcpRequest.params?._meta?.progressToken;
81
+ }
82
+
83
+ private createReportProgress(): (progress: Progress) => Promise<void> {
84
+ return async (progress: Progress) => {
85
+ const progressToken = this.progressToken;
86
+ if (progressToken === undefined) {
87
+ return;
88
+ }
89
+ await this.mcpServer.server.notification({
90
+ method: 'notifications/progress',
91
+ params: { ...progress, progressToken } as Progress,
92
+ });
93
+ };
94
+ }
95
+
96
+ private createLog(): Context['log'] {
97
+ const send = (
98
+ level: 'debug' | 'info' | 'warning' | 'error',
99
+ message: string,
100
+ context?: SerializableValue,
101
+ ) => {
102
+ void this.mcpServer.server.sendLoggingMessage({
103
+ level,
104
+ data: { message, context },
105
+ });
106
+ };
107
+ return {
108
+ debug: (message, context) => send('debug', message, context),
109
+ info: (message, context) => send('info', message, context),
110
+ warn: (message, context) => send('warning', message, context),
111
+ error: (message, context) => send('error', message, context),
112
+ };
113
+ }
114
+
115
+ private createStatelessReportProgress(): (
116
+ progress: Progress,
117
+ ) => Promise<void> {
118
+ return () => {
119
+ this.logger?.warn(
120
+ "Stateless context: 'reportProgress' is not supported.",
121
+ );
122
+ return Promise.resolve();
123
+ };
124
+ }
125
+
126
+ private createStatelessLog(): Context['log'] {
127
+ const warn = () =>
128
+ this.logger?.warn(
129
+ 'Stateless context: server-side logging is not supported.',
130
+ );
131
+ return {
132
+ debug: () => warn(),
133
+ info: () => warn(),
134
+ warn: () => warn(),
135
+ error: () => warn(),
136
+ };
137
+ }
138
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The HTTP verb handlers a streamable-HTTP MCP endpoint needs: one per method
3
+ * the transport mounts (`POST` messages, `GET` SSE stream, `DELETE` session
4
+ * teardown). This is the seam for "bring your own controller" setups.
5
+ *
6
+ * The transport owns the implementation (session handling, streaming, raw-body
7
+ * reading); you only decide HOW the route is mounted:
8
+ *
9
+ * - Do nothing — the transport self-mounts the route (no guards possible).
10
+ * - Extend {@link StreamableHttpController} (or write your own `@Controller`)
11
+ * and delegate to these handlers, so the route is a real Nest route that
12
+ * `@UseGuards()` / `@UseInterceptors()` / `@Version()` apply to.
13
+ *
14
+ * Obtain an instance from a transport via `transport.httpHandlers` and provide
15
+ * it under {@link MCP_HTTP_HANDLER} so the controller can inject it.
16
+ */
17
+ export interface McpHttpHandler {
18
+ handlePost(req: unknown, res: unknown): Promise<void> | void;
19
+ handleGet(req: unknown, res: unknown): Promise<void> | void;
20
+ handleDelete(req: unknown, res: unknown): Promise<void> | void;
21
+ }
22
+
23
+ /**
24
+ * DI token for an {@link McpHttpHandler}. Provide a transport's `httpHandlers`
25
+ * under this token so {@link StreamableHttpController} (or your own controller)
26
+ * can inject it:
27
+ *
28
+ * ```ts
29
+ * { provide: MCP_HTTP_HANDLER, useValue: mcpTransport.httpHandlers }
30
+ * ```
31
+ */
32
+ export const MCP_HTTP_HANDLER = Symbol('MCP_HTTP_HANDLER');