@hed-hog/core 0.0.328 → 0.0.330

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 (206) hide show
  1. package/dist/ai/ai.service.d.ts +1 -1
  2. package/dist/auth/auth.controller.d.ts +23 -23
  3. package/dist/auth/auth.service.d.ts +41 -41
  4. package/dist/challenge/challenge.service.d.ts +14 -14
  5. package/dist/core/system.controller.d.ts +1 -1
  6. package/dist/core/system.service.d.ts +1 -1
  7. package/dist/core.module.d.ts.map +1 -1
  8. package/dist/core.module.js +9 -2
  9. package/dist/core.module.js.map +1 -1
  10. package/dist/dashboard/dashboard/dashboard.controller.d.ts +84 -84
  11. package/dist/dashboard/dashboard/dashboard.service.d.ts +84 -84
  12. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +29 -29
  13. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +29 -29
  14. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +42 -42
  15. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +42 -42
  16. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +11 -11
  17. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +11 -11
  18. package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts +6 -6
  19. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts +6 -6
  20. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +33 -33
  21. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +33 -33
  22. package/dist/dashboard/dashboard-user/dashboard-user.controller.d.ts +3 -3
  23. package/dist/dashboard/dashboard-user/dashboard-user.service.d.ts +3 -3
  24. package/dist/file/file.controller.d.ts +10 -10
  25. package/dist/file/file.service.d.ts +22 -22
  26. package/dist/index.d.ts +11 -4
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +12 -4
  29. package/dist/index.js.map +1 -1
  30. package/dist/mail/mail.controller.d.ts +15 -15
  31. package/dist/mail/mail.service.d.ts +15 -15
  32. package/dist/mail-profile/mail-profile.controller.d.ts +9 -9
  33. package/dist/mail-profile/mail-profile.service.d.ts +9 -9
  34. package/dist/mail-sent/mail-sent.controller.d.ts +17 -17
  35. package/dist/mail-sent/mail-sent.service.d.ts +17 -17
  36. package/dist/mcp/decorators/mcp-tool.decorator.d.ts +4 -0
  37. package/dist/mcp/decorators/mcp-tool.decorator.d.ts.map +1 -0
  38. package/dist/mcp/decorators/mcp-tool.decorator.js +8 -0
  39. package/dist/mcp/decorators/mcp-tool.decorator.js.map +1 -0
  40. package/dist/mcp/guards/mcp-auth.guard.d.ts +9 -0
  41. package/dist/mcp/guards/mcp-auth.guard.d.ts.map +1 -0
  42. package/dist/mcp/guards/mcp-auth.guard.js +41 -0
  43. package/dist/mcp/guards/mcp-auth.guard.js.map +1 -0
  44. package/dist/mcp/guards/mcp-permission.guard.d.ts +8 -0
  45. package/dist/mcp/guards/mcp-permission.guard.d.ts.map +1 -0
  46. package/dist/mcp/guards/mcp-permission.guard.js +57 -0
  47. package/dist/mcp/guards/mcp-permission.guard.js.map +1 -0
  48. package/dist/mcp/interfaces/mcp-tool-definition.interface.d.ts +7 -0
  49. package/dist/mcp/interfaces/mcp-tool-definition.interface.d.ts.map +1 -0
  50. package/dist/mcp/interfaces/mcp-tool-definition.interface.js +3 -0
  51. package/dist/mcp/interfaces/mcp-tool-definition.interface.js.map +1 -0
  52. package/dist/mcp/mcp-audit.service.d.ts +17 -0
  53. package/dist/mcp/mcp-audit.service.d.ts.map +1 -0
  54. package/dist/mcp/mcp-audit.service.js +46 -0
  55. package/dist/mcp/mcp-audit.service.js.map +1 -0
  56. package/dist/mcp/mcp-registry.service.d.ts +21 -0
  57. package/dist/mcp/mcp-registry.service.d.ts.map +1 -0
  58. package/dist/mcp/mcp-registry.service.js +69 -0
  59. package/dist/mcp/mcp-registry.service.js.map +1 -0
  60. package/dist/mcp/mcp-server.service.d.ts +12 -0
  61. package/dist/mcp/mcp-server.service.d.ts.map +1 -0
  62. package/dist/mcp/mcp-server.service.js +94 -0
  63. package/dist/mcp/mcp-server.service.js.map +1 -0
  64. package/dist/mcp/mcp.controller.d.ts +8 -0
  65. package/dist/mcp/mcp.controller.d.ts.map +1 -0
  66. package/dist/mcp/mcp.controller.js +54 -0
  67. package/dist/mcp/mcp.controller.js.map +1 -0
  68. package/dist/mcp/mcp.module.d.ts +3 -0
  69. package/dist/mcp/mcp.module.d.ts.map +1 -0
  70. package/dist/mcp/mcp.module.js +49 -0
  71. package/dist/mcp/mcp.module.js.map +1 -0
  72. package/dist/mcp/tools/core-settings.mcp-tools.d.ts +12 -0
  73. package/dist/mcp/tools/core-settings.mcp-tools.d.ts.map +1 -0
  74. package/dist/mcp/tools/core-settings.mcp-tools.js +66 -0
  75. package/dist/mcp/tools/core-settings.mcp-tools.js.map +1 -0
  76. package/dist/mcp/tools/core-users.mcp-tools.d.ts +55 -0
  77. package/dist/mcp/tools/core-users.mcp-tools.d.ts.map +1 -0
  78. package/dist/mcp/tools/core-users.mcp-tools.js +295 -0
  79. package/dist/mcp/tools/core-users.mcp-tools.js.map +1 -0
  80. package/dist/mcp/types/mcp-context.type.d.ts +7 -0
  81. package/dist/mcp/types/mcp-context.type.d.ts.map +1 -0
  82. package/dist/mcp/types/mcp-context.type.js +3 -0
  83. package/dist/mcp/types/mcp-context.type.js.map +1 -0
  84. package/dist/mcp-chat/dto/create-conversation.dto.d.ts +4 -0
  85. package/dist/mcp-chat/dto/create-conversation.dto.d.ts.map +1 -0
  86. package/dist/mcp-chat/dto/create-conversation.dto.js +22 -0
  87. package/dist/mcp-chat/dto/create-conversation.dto.js.map +1 -0
  88. package/dist/mcp-chat/dto/send-message.dto.d.ts +4 -0
  89. package/dist/mcp-chat/dto/send-message.dto.d.ts.map +1 -0
  90. package/dist/mcp-chat/dto/send-message.dto.js +22 -0
  91. package/dist/mcp-chat/dto/send-message.dto.js.map +1 -0
  92. package/dist/mcp-chat/mcp-chat.controller.d.ts +55 -0
  93. package/dist/mcp-chat/mcp-chat.controller.d.ts.map +1 -0
  94. package/dist/mcp-chat/mcp-chat.controller.js +90 -0
  95. package/dist/mcp-chat/mcp-chat.controller.js.map +1 -0
  96. package/dist/mcp-chat/mcp-chat.module.d.ts +3 -0
  97. package/dist/mcp-chat/mcp-chat.module.d.ts.map +1 -0
  98. package/dist/mcp-chat/mcp-chat.module.js +30 -0
  99. package/dist/mcp-chat/mcp-chat.module.js.map +1 -0
  100. package/dist/mcp-chat/mcp-chat.service.d.ts +50 -0
  101. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -0
  102. package/dist/mcp-chat/mcp-chat.service.js +290 -0
  103. package/dist/mcp-chat/mcp-chat.service.js.map +1 -0
  104. package/dist/menu/menu.controller.d.ts +8 -8
  105. package/dist/menu/menu.service.d.ts +8 -8
  106. package/dist/oauth/oauth.service.js +1 -1
  107. package/dist/oauth/oauth.service.js.map +1 -1
  108. package/dist/pdf/components/index.d.ts +57 -0
  109. package/dist/pdf/components/index.d.ts.map +1 -0
  110. package/dist/pdf/components/index.js +258 -0
  111. package/dist/pdf/components/index.js.map +1 -0
  112. package/dist/pdf/dto/generate-pdf.dto.d.ts +5 -0
  113. package/dist/pdf/dto/generate-pdf.dto.d.ts.map +1 -0
  114. package/dist/pdf/dto/generate-pdf.dto.js +27 -0
  115. package/dist/pdf/dto/generate-pdf.dto.js.map +1 -0
  116. package/dist/pdf/interfaces/pdf-theme-config.interface.d.ts +10 -0
  117. package/dist/pdf/interfaces/pdf-theme-config.interface.d.ts.map +1 -0
  118. package/dist/pdf/interfaces/pdf-theme-config.interface.js +3 -0
  119. package/dist/pdf/interfaces/pdf-theme-config.interface.js.map +1 -0
  120. package/dist/pdf/pdf.controller.d.ts +16 -0
  121. package/dist/pdf/pdf.controller.d.ts.map +1 -0
  122. package/dist/pdf/pdf.controller.js +100 -0
  123. package/dist/pdf/pdf.controller.js.map +1 -0
  124. package/dist/pdf/pdf.module.d.ts +3 -0
  125. package/dist/pdf/pdf.module.d.ts.map +1 -0
  126. package/dist/pdf/pdf.module.js +29 -0
  127. package/dist/pdf/pdf.module.js.map +1 -0
  128. package/dist/pdf/pdf.service.d.ts +44 -0
  129. package/dist/pdf/pdf.service.d.ts.map +1 -0
  130. package/dist/pdf/pdf.service.js +185 -0
  131. package/dist/pdf/pdf.service.js.map +1 -0
  132. package/dist/pdf/templates/hcode-institutional.template.d.ts +36 -0
  133. package/dist/pdf/templates/hcode-institutional.template.d.ts.map +1 -0
  134. package/dist/pdf/templates/hcode-institutional.template.js +67 -0
  135. package/dist/pdf/templates/hcode-institutional.template.js.map +1 -0
  136. package/dist/pdf/themes/hcode.theme.d.ts +25 -0
  137. package/dist/pdf/themes/hcode.theme.d.ts.map +1 -0
  138. package/dist/pdf/themes/hcode.theme.js +504 -0
  139. package/dist/pdf/themes/hcode.theme.js.map +1 -0
  140. package/dist/profile/profile.controller.d.ts +16 -16
  141. package/dist/profile/profile.service.d.ts +16 -16
  142. package/dist/role/role.controller.d.ts +12 -12
  143. package/dist/role/role.service.d.ts +12 -12
  144. package/dist/route/dto/create.dto.d.ts +6 -2
  145. package/dist/route/dto/create.dto.d.ts.map +1 -1
  146. package/dist/route/dto/create.dto.js +19 -1
  147. package/dist/route/dto/create.dto.js.map +1 -1
  148. package/dist/route/dto/update.dto.d.ts +4 -0
  149. package/dist/route/dto/update.dto.d.ts.map +1 -1
  150. package/dist/route/dto/update.dto.js +19 -3
  151. package/dist/route/dto/update.dto.js.map +1 -1
  152. package/dist/route/route.service.d.ts +1 -1
  153. package/dist/route/route.service.d.ts.map +1 -1
  154. package/dist/route/route.service.js +18 -11
  155. package/dist/route/route.service.js.map +1 -1
  156. package/dist/screen/screen.controller.d.ts +3 -3
  157. package/dist/screen/screen.service.d.ts +3 -3
  158. package/dist/session/session.controller.d.ts +4 -4
  159. package/dist/session/session.service.d.ts +12 -12
  160. package/dist/setting/setting.controller.d.ts +13 -13
  161. package/dist/setting/setting.service.d.ts +13 -13
  162. package/dist/user/user.controller.d.ts +24 -24
  163. package/dist/user/user.service.d.ts +55 -55
  164. package/hedhog/data/menu.yaml +40 -26
  165. package/hedhog/data/route.yaml +583 -152
  166. package/hedhog/data/setting_group.yaml +60 -0
  167. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +574 -0
  168. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +5 -9
  169. package/hedhog/frontend/messages/en.json +19 -0
  170. package/hedhog/frontend/messages/pt.json +19 -0
  171. package/hedhog/table/mcp_conversation.yaml +12 -0
  172. package/hedhog/table/mcp_conversation_message.yaml +23 -0
  173. package/hedhog/table/mcp_tool_call_log.yaml +22 -0
  174. package/hedhog/table/route.yaml +33 -22
  175. package/package.json +7 -6
  176. package/src/core.module.ts +18 -11
  177. package/src/index.ts +22 -12
  178. package/src/mcp/decorators/mcp-tool.decorator.ts +7 -0
  179. package/src/mcp/guards/mcp-auth.guard.ts +32 -0
  180. package/src/mcp/guards/mcp-permission.guard.ts +51 -0
  181. package/src/mcp/interfaces/mcp-tool-definition.interface.ts +6 -0
  182. package/src/mcp/mcp-audit.service.ts +36 -0
  183. package/src/mcp/mcp-registry.service.ts +69 -0
  184. package/src/mcp/mcp-server.service.ts +87 -0
  185. package/src/mcp/mcp.controller.ts +30 -0
  186. package/src/mcp/mcp.module.ts +36 -0
  187. package/src/mcp/tools/core-settings.mcp-tools.ts +53 -0
  188. package/src/mcp/tools/core-users.mcp-tools.ts +267 -0
  189. package/src/mcp/types/mcp-context.type.ts +6 -0
  190. package/src/mcp-chat/dto/create-conversation.dto.ts +7 -0
  191. package/src/mcp-chat/dto/send-message.dto.ts +7 -0
  192. package/src/mcp-chat/mcp-chat.controller.ts +60 -0
  193. package/src/mcp-chat/mcp-chat.module.ts +17 -0
  194. package/src/mcp-chat/mcp-chat.service.ts +332 -0
  195. package/src/oauth/oauth.service.ts +12 -12
  196. package/src/pdf/components/index.ts +316 -0
  197. package/src/pdf/dto/generate-pdf.dto.ts +11 -0
  198. package/src/pdf/interfaces/pdf-theme-config.interface.ts +10 -0
  199. package/src/pdf/pdf.controller.ts +86 -0
  200. package/src/pdf/pdf.module.ts +17 -0
  201. package/src/pdf/pdf.service.ts +229 -0
  202. package/src/pdf/templates/hcode-institutional.template.ts +122 -0
  203. package/src/pdf/themes/hcode.theme.ts +515 -0
  204. package/src/route/dto/create.dto.ts +32 -14
  205. package/src/route/dto/update.dto.ts +31 -16
  206. package/src/route/route.service.ts +23 -12
@@ -127,6 +127,7 @@
127
127
  "errorName": "Name must be at least 2 characters",
128
128
  "errorEmail": "Invalid email address",
129
129
  "errorPassword": "Password must be at least 6 characters",
130
+ "draftStatus": "Draft saved {relativeLabel} • Last saved: {absoluteLabel}",
130
131
  "userDeletedSuccess": "User deleted successfully.",
131
132
  "serverError": "An error occurred. Please try again later.",
132
133
  "pictureUpdatedSuccess": "Profile picture updated successfully.",
@@ -1643,5 +1644,23 @@
1643
1644
  "noUsersWithAccess": "No users are currently linked to the assigned roles.",
1644
1645
  "grantedByRole": "Granted by",
1645
1646
  "moreUsers": "+{count} more users"
1647
+ },
1648
+ "McpChatPage": {
1649
+ "title": "MCP Chat",
1650
+ "description": "Chat with AI using MCP tools",
1651
+ "newConversation": "New Conversation",
1652
+ "conversations": "Conversations",
1653
+ "placeholder": "Type your message... (Enter to send, Shift+Enter for new line)",
1654
+ "send": "Send",
1655
+ "sending": "Sending...",
1656
+ "noConversation": "Select or create a conversation",
1657
+ "toolCalled": "Tool called",
1658
+ "toolResult": "Tool result",
1659
+ "cancel": "Cancel",
1660
+ "deleteConversation": "Delete",
1661
+ "emptyConversations": "No conversations yet",
1662
+ "breadcrumbDashboard": "Dashboard",
1663
+ "breadcrumbManagement": "Management",
1664
+ "breadcrumbCurrent": "MCP Chat"
1646
1665
  }
1647
1666
  }
@@ -127,6 +127,7 @@
127
127
  "errorName": "O nome deve ter pelo menos 2 caracteres",
128
128
  "errorEmail": "Endereço de e-mail inválido",
129
129
  "errorPassword": "A senha deve ter pelo menos 6 caracteres",
130
+ "draftStatus": "Rascunho salvo {relativeLabel} • Último salvamento: {absoluteLabel}",
130
131
  "userDeletedSuccess": "Usuário excluído com sucesso.",
131
132
  "serverError": "Ocorreu um erro. Por favor, tente novamente mais tarde.",
132
133
  "pictureUpdatedSuccess": "Foto de perfil atualizada com sucesso.",
@@ -1698,5 +1699,23 @@
1698
1699
  "noUsersWithAccess": "Nenhum usuário está vinculado aos cargos atribuídos no momento.",
1699
1700
  "grantedByRole": "Liberado por",
1700
1701
  "moreUsers": "+{count} usuários"
1702
+ },
1703
+ "McpChatPage": {
1704
+ "title": "Chat MCP",
1705
+ "description": "Converse com IA usando ferramentas MCP",
1706
+ "newConversation": "Nova Conversa",
1707
+ "conversations": "Conversas",
1708
+ "placeholder": "Digite sua mensagem... (Enter para enviar, Shift+Enter para nova linha)",
1709
+ "send": "Enviar",
1710
+ "sending": "Enviando...",
1711
+ "noConversation": "Selecione ou crie uma conversa",
1712
+ "toolCalled": "Ferramenta chamada",
1713
+ "toolResult": "Resultado da ferramenta",
1714
+ "cancel": "Cancelar",
1715
+ "deleteConversation": "Excluir",
1716
+ "emptyConversations": "Nenhuma conversa ainda",
1717
+ "breadcrumbDashboard": "Painel",
1718
+ "breadcrumbManagement": "Gerenciamento",
1719
+ "breadcrumbCurrent": "Chat MCP"
1701
1720
  }
1702
1721
  }
@@ -0,0 +1,12 @@
1
+ columns:
2
+ - type: pk
3
+ - name: user_id
4
+ type: fk
5
+ references:
6
+ table: user
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: title
10
+ isNullable: true
11
+ - type: created_at
12
+ - type: updated_at
@@ -0,0 +1,23 @@
1
+ columns:
2
+ - type: pk
3
+ - name: conversation_id
4
+ type: fk
5
+ references:
6
+ table: mcp_conversation
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: role
10
+ type: enum
11
+ enum:
12
+ - user
13
+ - assistant
14
+ - tool_call
15
+ - tool_result
16
+ - name: content
17
+ type: text
18
+ - name: tool_name
19
+ isNullable: true
20
+ - name: tool_call_id
21
+ isNullable: true
22
+ - type: created_at
23
+ - type: updated_at
@@ -0,0 +1,22 @@
1
+ columns:
2
+ - type: pk
3
+ - name: user_id
4
+ type: fk
5
+ references:
6
+ table: user
7
+ column: id
8
+ onDelete: SET NULL
9
+ isNullable: true
10
+ - name: tool_name
11
+ - name: input
12
+ type: text
13
+ isNullable: true
14
+ - name: success
15
+ type: boolean
16
+ default: false
17
+ - name: error
18
+ isNullable: true
19
+ - name: duration_ms
20
+ type: int
21
+ - type: created_at
22
+ - type: updated_at
@@ -1,22 +1,33 @@
1
- columns:
2
- - type: pk
3
- - name: url
4
- - name: method
5
- type: enum
6
- enum:
7
- - GET
8
- - POST
9
- - PATCH
10
- - DELETE
11
- - PUT
12
- - OPTIONS
13
- - HEAD
14
- - name: description
15
- isNullable: true
16
- - type: created_at
17
- - type: updated_at
18
- indices:
19
- - columns:
20
- - url
21
- - method
22
- isUnique: true
1
+ columns:
2
+ - type: pk
3
+ - name: type
4
+ type: enum
5
+ enum:
6
+ - HTTP
7
+ - MCP
8
+ default: HTTP
9
+ - name: name
10
+ isNullable: true
11
+ - name: url
12
+ isNullable: true
13
+ - name: method
14
+ type: enum
15
+ enum:
16
+ - GET
17
+ - POST
18
+ - PATCH
19
+ - DELETE
20
+ - PUT
21
+ - OPTIONS
22
+ - HEAD
23
+ isNullable: true
24
+ - name: tool_name
25
+ isNullable: true
26
+ - name: description
27
+ isNullable: true
28
+ - type: created_at
29
+ - type: updated_at
30
+ indices:
31
+ - columns:
32
+ - tool_name
33
+ isUnique: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hed-hog/core",
3
- "version": "0.0.328",
3
+ "version": "0.0.330",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
@@ -30,12 +30,13 @@
30
30
  "sharp": "^0.34.2",
31
31
  "speakeasy": "^2.0.0",
32
32
  "uuid": "^11.1.0",
33
- "@hed-hog/api-locale": "0.0.14",
34
- "@hed-hog/api": "0.0.8",
35
- "@hed-hog/api-pagination": "0.0.7",
36
- "@hed-hog/api-prisma": "0.0.6",
33
+ "@modelcontextprotocol/sdk": "^1.12.0",
37
34
  "@hed-hog/api-types": "0.0.1",
38
- "@hed-hog/api-mail": "0.0.9"
35
+ "@hed-hog/api-prisma": "0.0.6",
36
+ "@hed-hog/api": "0.0.8",
37
+ "@hed-hog/api-locale": "0.0.14",
38
+ "@hed-hog/api-mail": "0.0.9",
39
+ "@hed-hog/api-pagination": "0.0.7"
39
40
  },
40
41
  "exports": {
41
42
  ".": {
@@ -14,12 +14,15 @@ import { DashboardModule } from './dashboard/dashboard.module';
14
14
  import { FileModule } from './file/file.module';
15
15
  import { InstallModule } from './install/install.module';
16
16
  import { IntegrationModule } from './integration/integration.module';
17
- import { MailSentModule } from './mail-sent/mail-sent.module';
18
17
  import { MailProfileModule } from './mail-profile/mail-profile.module';
18
+ import { MailSentModule } from './mail-sent/mail-sent.module';
19
19
  import { MailModule } from './mail/mail.module';
20
+ import { McpChatModule } from './mcp-chat/mcp-chat.module';
21
+ import { McpModule } from './mcp/mcp.module';
20
22
  import { MenuModule } from './menu/menu.module';
21
23
  import { LocaleInjectionMiddleware } from './middlewares/locale-injection.middleware';
22
24
  import { OAuthModule } from './oauth/oauth.module';
25
+ import { PdfModule } from './pdf/pdf.module';
23
26
  import { ProfileModule } from './profile/profile.module';
24
27
  import { RoleModule } from './role/role.module';
25
28
  import { RouteModule } from './route/route.module';
@@ -29,12 +32,12 @@ import { SessionModule } from './session/session.module';
29
32
  import { SettingModule } from './setting/setting.module';
30
33
  import { SettingService } from './setting/setting.service';
31
34
  import { TaskModule } from './task/task.module';
32
- import { UserModule } from './user/user.module';
33
- import { WebhookIntegrationModule } from './webhook-integration/webhook-integration.module';
35
+ import { UserModule } from './user/user.module';
34
36
  import { IsEmailWithSettingsConstraint } from './validators/is-email-with-settings.validator';
35
37
  import { IsPinCodeWithSettingConstraint } from './validators/is-pin-code-with-setting.validator';
36
38
  import { IsStrongPasswordWithSettingsConstraint } from './validators/is-strong-password-with-settings.validator';
37
39
  import { ValidatorServiceLocator } from './validators/service-locator';
40
+ import { WebhookIntegrationModule } from './webhook-integration/webhook-integration.module';
38
41
 
39
42
  @Global()
40
43
  @Module({
@@ -64,10 +67,13 @@ import { ValidatorServiceLocator } from './validators/service-locator';
64
67
  forwardRef(() => SecurityModule),
65
68
  forwardRef(() => ProfileModule),
66
69
  forwardRef(() => SessionModule),
67
- forwardRef(() => OAuthModule),
68
- forwardRef(() => IntegrationModule),
69
- forwardRef(() => WebhookIntegrationModule),
70
- ],
70
+ forwardRef(() => OAuthModule),
71
+ forwardRef(() => IntegrationModule),
72
+ forwardRef(() => WebhookIntegrationModule),
73
+ forwardRef(() => McpModule),
74
+ forwardRef(() => McpChatModule),
75
+ forwardRef(() => PdfModule),
76
+ ],
71
77
  exports: [
72
78
  UserModule,
73
79
  AuthModule,
@@ -81,12 +87,13 @@ import { ValidatorServiceLocator } from './validators/service-locator';
81
87
  SettingModule,
82
88
  FileModule,
83
89
  SessionModule,
84
- AiModule,
85
- IntegrationModule,
86
- WebhookIntegrationModule,
87
- IsStrongPasswordWithSettingsConstraint,
90
+ AiModule,
91
+ IntegrationModule,
92
+ WebhookIntegrationModule,
93
+ IsStrongPasswordWithSettingsConstraint,
88
94
  IsEmailWithSettingsConstraint,
89
95
  IsPinCodeWithSettingConstraint,
96
+ PdfModule,
90
97
  ],
91
98
  providers: [
92
99
  Reflector,
package/src/index.ts CHANGED
@@ -19,26 +19,29 @@ export * from './screen/screen.service';
19
19
  export * from './user/constants/user.constants';
20
20
  export * from './user/user.service';
21
21
 
22
- export * from './mail/mail.module';
23
- export * from './mail/mail.service';
24
22
  export * from './mail-profile/mail-profile.module';
25
23
  export * from './mail-profile/mail-profile.service';
24
+ export * from './mail/mail.module';
25
+ export * from './mail/mail.service';
26
26
 
27
27
  export * from './file/file.module';
28
28
  export * from './file/file.service';
29
+
30
+ export * from './pdf/pdf.module';
31
+ export * from './pdf/pdf.service';
29
32
  export * from './setting/setting.module';
30
33
  export * from './setting/setting.service';
31
34
 
32
- export * from './ai/ai.module';
33
- export * from './ai/ai.service';
34
-
35
- export * from './webhook-integration/webhook-integration.module';
36
- export * from './webhook-integration/integration-event-catalog.service';
37
- export * from './webhook-integration/webhook-integration.service';
38
- export * from './webhook-integration/event-webhook.service';
39
-
40
- // Integration Module
41
- export * from './integration/integration.module';
35
+ export * from './ai/ai.module';
36
+ export * from './ai/ai.service';
37
+
38
+ export * from './webhook-integration/event-webhook.service';
39
+ export * from './webhook-integration/integration-event-catalog.service';
40
+ export * from './webhook-integration/webhook-integration.module';
41
+ export * from './webhook-integration/webhook-integration.service';
42
+
43
+ // Integration Module
44
+ export * from './integration/integration.module';
42
45
  export * from './integration/services/domain-event.publisher';
43
46
  export * from './integration/services/event-subscriber.registry';
44
47
  export * from './integration/services/inbox.service';
@@ -57,6 +60,13 @@ export * from './validators/is-email-with-settings.validator';
57
60
  export * from './validators/is-pin-code-with-setting.validator';
58
61
  export * from './validators/is-strong-password-with-settings.validator';
59
62
 
63
+ // MCP Module
64
+ export * from './mcp/decorators/mcp-tool.decorator';
65
+ export * from './mcp/interfaces/mcp-tool-definition.interface';
66
+ export * from './mcp/mcp-registry.service';
67
+ export * from './mcp/mcp.module';
68
+ export * from './mcp/types/mcp-context.type';
69
+
60
70
  // Utilities
61
71
  export * from './utils/locale-context';
62
72
 
@@ -0,0 +1,7 @@
1
+ import { SetMetadata } from '@nestjs/common';
2
+ import { McpToolDefinition } from '../interfaces/mcp-tool-definition.interface';
3
+
4
+ export const MCP_TOOL_METADATA = 'mcp:tool';
5
+
6
+ export const McpTool = (definition: McpToolDefinition): MethodDecorator =>
7
+ SetMetadata(MCP_TOOL_METADATA, definition);
@@ -0,0 +1,32 @@
1
+ import {
2
+ CanActivate,
3
+ ExecutionContext,
4
+ Injectable,
5
+ UnauthorizedException,
6
+ } from '@nestjs/common';
7
+ import { Request } from 'express';
8
+ import { TokenService } from '../../token/token.service';
9
+
10
+ @Injectable()
11
+ export class McpAuthGuard implements CanActivate {
12
+ constructor(private readonly tokenService: TokenService) {}
13
+
14
+ async canActivate(context: ExecutionContext): Promise<boolean> {
15
+ const request = context.switchToHttp().getRequest<Request>();
16
+ const locale =
17
+ request.headers['accept-language']?.split(',')[0]?.split('-')[0] ?? 'en';
18
+
19
+ const token = this.extractToken(request);
20
+ if (!token) {
21
+ throw new UnauthorizedException('MCP: Bearer token required');
22
+ }
23
+
24
+ request['auth'] = await this.tokenService.verify(locale, token);
25
+ return true;
26
+ }
27
+
28
+ private extractToken(request: Request): string | undefined {
29
+ const [type, token] = request.headers.authorization?.split(' ') ?? [];
30
+ return type === 'Bearer' ? token : undefined;
31
+ }
32
+ }
@@ -0,0 +1,51 @@
1
+ import { PrismaService } from '@hed-hog/api-prisma';
2
+ import {
3
+ CanActivate,
4
+ ExecutionContext,
5
+ ForbiddenException,
6
+ Injectable,
7
+ } from '@nestjs/common';
8
+ import { Request } from 'express';
9
+
10
+ @Injectable()
11
+ export class McpPermissionGuard implements CanActivate {
12
+ constructor(private readonly prisma: PrismaService) {}
13
+
14
+ async canActivate(context: ExecutionContext): Promise<boolean> {
15
+ const request = context.switchToHttp().getRequest<Request>();
16
+
17
+ // Only POST requests carry tool invocations
18
+ if (request.method !== 'POST') return true;
19
+
20
+ const body = request.body as any;
21
+ const toolName: string | undefined =
22
+ body?.method === 'tools/call' ? body?.params?.name : undefined;
23
+
24
+ // tools/list, initialize, ping, etc. — no per-tool permission check needed
25
+ if (!toolName) return true;
26
+
27
+ const userId = (request as any)?.auth?.sub;
28
+
29
+ const count = await this.prisma.route.count({
30
+ where: {
31
+ type: 'MCP' as any,
32
+ tool_name: toolName,
33
+ role_route: {
34
+ some: {
35
+ role: {
36
+ role_user: {
37
+ some: { user_id: userId },
38
+ },
39
+ },
40
+ },
41
+ },
42
+ },
43
+ });
44
+
45
+ if (count === 0) {
46
+ throw new ForbiddenException(`Access denied to MCP tool '${toolName}'`);
47
+ }
48
+
49
+ return true;
50
+ }
51
+ }
@@ -0,0 +1,6 @@
1
+ export interface McpToolDefinition {
2
+ name: string;
3
+ description: string;
4
+ inputSchema?: Record<string, any>;
5
+ readOnly?: boolean;
6
+ }
@@ -0,0 +1,36 @@
1
+ import { PrismaService } from '@hed-hog/api-prisma';
2
+ import { Injectable, Logger } from '@nestjs/common';
3
+
4
+ interface AuditRecord {
5
+ userId: number;
6
+ toolName: string;
7
+ input: Record<string, any>;
8
+ success: boolean;
9
+ error?: string;
10
+ durationMs: number;
11
+ }
12
+
13
+ @Injectable()
14
+ export class McpAuditService {
15
+ private readonly logger = new Logger(McpAuditService.name);
16
+
17
+ constructor(private readonly prisma: PrismaService) {}
18
+
19
+ async record(data: AuditRecord): Promise<void> {
20
+ const sanitized = JSON.stringify(data.input).slice(0, 1000);
21
+ try {
22
+ await this.prisma.mcp_tool_call_log.create({
23
+ data: {
24
+ user_id: data.userId || null,
25
+ tool_name: data.toolName,
26
+ input: sanitized,
27
+ success: data.success,
28
+ error: data.error ?? null,
29
+ duration_ms: data.durationMs,
30
+ },
31
+ });
32
+ } catch (e: any) {
33
+ this.logger.warn(`Failed to persist MCP audit record: ${e.message}`);
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,69 @@
1
+ import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
2
+ import { DiscoveryService } from '@nestjs/core';
3
+ import { Reflector } from '@nestjs/core';
4
+ import { MCP_TOOL_METADATA } from './decorators/mcp-tool.decorator';
5
+ import { McpToolDefinition } from './interfaces/mcp-tool-definition.interface';
6
+ import { McpContext } from './types/mcp-context.type';
7
+
8
+ export interface McpToolEntry {
9
+ definition: McpToolDefinition;
10
+ handler: (args: Record<string, any>, context: McpContext) => Promise<any>;
11
+ }
12
+
13
+ @Injectable()
14
+ export class McpRegistryService implements OnModuleInit {
15
+ private readonly logger = new Logger(McpRegistryService.name);
16
+ private readonly tools = new Map<string, McpToolEntry>();
17
+
18
+ constructor(
19
+ private readonly discovery: DiscoveryService,
20
+ private readonly reflector: Reflector,
21
+ ) {}
22
+
23
+ onModuleInit(): void {
24
+ const providers = this.discovery.getProviders();
25
+
26
+ for (const wrapper of providers) {
27
+ const { instance } = wrapper;
28
+ if (!instance || typeof instance !== 'object') continue;
29
+
30
+ const prototype = Object.getPrototypeOf(instance);
31
+ if (!prototype) continue;
32
+
33
+ const methodNames = Object.getOwnPropertyNames(prototype).filter((key) => {
34
+ if (key === 'constructor') return false;
35
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, key);
36
+ return descriptor !== undefined && typeof descriptor.value === 'function';
37
+ });
38
+
39
+ for (const methodName of methodNames) {
40
+ const definition = this.reflector.get<McpToolDefinition>(
41
+ MCP_TOOL_METADATA,
42
+ prototype[methodName],
43
+ );
44
+
45
+ if (!definition) continue;
46
+
47
+ this.logger.log(`Registered MCP tool: ${definition.name}`);
48
+ this.tools.set(definition.name, {
49
+ definition,
50
+ handler: (instance as any)[methodName].bind(instance),
51
+ });
52
+ }
53
+ }
54
+
55
+ this.logger.log(`McpRegistryService: ${this.tools.size} tools registered`);
56
+ }
57
+
58
+ getAll(): McpToolEntry[] {
59
+ return Array.from(this.tools.values());
60
+ }
61
+
62
+ get(toolName: string): McpToolEntry | undefined {
63
+ return this.tools.get(toolName);
64
+ }
65
+
66
+ has(toolName: string): boolean {
67
+ return this.tools.has(toolName);
68
+ }
69
+ }
@@ -0,0 +1,87 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
+ import {
4
+ CallToolRequestSchema,
5
+ ListToolsRequestSchema,
6
+ } from '@modelcontextprotocol/sdk/types.js';
7
+ import { Injectable } from '@nestjs/common';
8
+ import { Request, Response } from 'express';
9
+ import { McpAuditService } from './mcp-audit.service';
10
+ import { McpRegistryService } from './mcp-registry.service';
11
+ import { McpContext } from './types/mcp-context.type';
12
+
13
+ @Injectable()
14
+ export class McpServerService {
15
+ constructor(
16
+ private readonly registry: McpRegistryService,
17
+ private readonly audit: McpAuditService,
18
+ ) {}
19
+
20
+ async handleRequest(req: Request, res: Response, context: McpContext): Promise<void> {
21
+ const server = this.buildServer(context);
22
+ const transport = new StreamableHTTPServerTransport({
23
+ sessionIdGenerator: undefined,
24
+ });
25
+ await server.connect(transport);
26
+ await transport.handleRequest(req, res, req.body);
27
+ }
28
+
29
+ private buildServer(context: McpContext): Server {
30
+ const server = new Server(
31
+ { name: 'hedhog-mcp', version: '1.0.0' },
32
+ { capabilities: { tools: {} } },
33
+ );
34
+
35
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
36
+ tools: this.registry.getAll().map((e) => ({
37
+ name: e.definition.name,
38
+ description: e.definition.description,
39
+ inputSchema: e.definition.inputSchema ?? {
40
+ type: 'object',
41
+ properties: {},
42
+ },
43
+ })),
44
+ }));
45
+
46
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
47
+ const toolName = request.params.name;
48
+ const args = (request.params.arguments ?? {}) as Record<string, any>;
49
+ const entry = this.registry.get(toolName);
50
+
51
+ if (!entry) {
52
+ return {
53
+ isError: true,
54
+ content: [{ type: 'text', text: `Tool '${toolName}' not found` }],
55
+ };
56
+ }
57
+
58
+ const start = Date.now();
59
+ try {
60
+ const result = await entry.handler(args, { ...context, toolName });
61
+ await this.audit.record({
62
+ userId: context.userId,
63
+ toolName,
64
+ input: args,
65
+ success: true,
66
+ durationMs: Date.now() - start,
67
+ });
68
+ return { content: [{ type: 'text', text: JSON.stringify(result) }] };
69
+ } catch (e: any) {
70
+ await this.audit.record({
71
+ userId: context.userId,
72
+ toolName,
73
+ input: args,
74
+ success: false,
75
+ error: e.message,
76
+ durationMs: Date.now() - start,
77
+ });
78
+ return {
79
+ isError: true,
80
+ content: [{ type: 'text', text: e.message }],
81
+ };
82
+ }
83
+ });
84
+
85
+ return server;
86
+ }
87
+ }
@@ -0,0 +1,30 @@
1
+ import { NoRole } from '@hed-hog/api';
2
+ import { All, Controller, Req, Res, UseGuards } from '@nestjs/common';
3
+ import { Request, Response } from 'express';
4
+ import { McpAuthGuard } from './guards/mcp-auth.guard';
5
+ import { McpPermissionGuard } from './guards/mcp-permission.guard';
6
+ import { McpServerService } from './mcp-server.service';
7
+
8
+ @NoRole()
9
+ @UseGuards(McpAuthGuard, McpPermissionGuard)
10
+ @Controller('mcp')
11
+ export class McpController {
12
+ constructor(private readonly mcpServer: McpServerService) {}
13
+
14
+ @All()
15
+ async handle(@Req() req: Request, @Res() res: Response): Promise<void> {
16
+ const auth = (req as any).auth;
17
+ const locale =
18
+ req.headers['accept-language']?.split(',')[0]?.split('-')[0] ?? 'en';
19
+ const body = req.body as any;
20
+ const toolName: string =
21
+ body?.method === 'tools/call' ? (body?.params?.name ?? '') : '';
22
+
23
+ await this.mcpServer.handleRequest(req, res, {
24
+ userId: auth.sub,
25
+ sessionId: String(auth.sessionId),
26
+ locale,
27
+ toolName,
28
+ });
29
+ }
30
+ }