@eventcatalog/core 4.12.3 → 5.0.0-beta.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 (267) hide show
  1. package/LICENSE +226 -95
  2. package/NOTICE +30 -0
  3. package/README.md +3 -2
  4. package/dist/analytics/analytics.cjs +1 -1
  5. package/dist/analytics/analytics.js +2 -2
  6. package/dist/analytics/log-build.cjs +43 -16
  7. package/dist/analytics/log-build.d.cts +6 -5
  8. package/dist/analytics/log-build.d.ts +6 -5
  9. package/dist/analytics/log-build.js +4 -3
  10. package/dist/{chunk-U4YJSTGV.js → chunk-AYNZXUB5.js} +2 -10
  11. package/dist/{chunk-TV3YAWKQ.js → chunk-CR6AK5LR.js} +1 -1
  12. package/dist/{chunk-M577VUOX.js → chunk-LR7AGRHN.js} +13 -16
  13. package/dist/chunk-TQLRG35T.js +203 -0
  14. package/dist/{chunk-HPC6KUDQ.js → chunk-TWN43V4T.js} +1 -1
  15. package/dist/{chunk-ZYTCBNB3.js → chunk-WAIADKQE.js} +1 -1
  16. package/dist/{chunk-5BPN6QEC.js → chunk-ZHKEARLJ.js} +1 -1
  17. package/dist/constants.cjs +1 -1
  18. package/dist/constants.js +1 -1
  19. package/dist/eventcatalog.cjs +407 -291
  20. package/dist/eventcatalog.config.d.cts +2 -3
  21. package/dist/eventcatalog.config.d.ts +2 -3
  22. package/dist/eventcatalog.js +35 -98
  23. package/dist/federation/content-cache.d.cts +0 -5
  24. package/dist/federation/content-cache.d.ts +0 -5
  25. package/dist/federation/diagnostics.d.cts +0 -5
  26. package/dist/federation/diagnostics.d.ts +0 -5
  27. package/dist/federation/federate.cjs +0 -9
  28. package/dist/federation/federate.d.cts +0 -5
  29. package/dist/federation/federate.d.ts +0 -5
  30. package/dist/federation/federate.js +4 -5
  31. package/dist/federation/filesystem-source-provider.d.cts +0 -5
  32. package/dist/federation/filesystem-source-provider.d.ts +0 -5
  33. package/dist/federation/github-source-provider.d.cts +0 -5
  34. package/dist/federation/github-source-provider.d.ts +0 -5
  35. package/dist/federation/output-transaction.d.cts +0 -4
  36. package/dist/federation/output-transaction.d.ts +0 -4
  37. package/dist/federation/public-assets.d.cts +0 -5
  38. package/dist/federation/public-assets.d.ts +0 -5
  39. package/dist/federation/source-provider.d.cts +0 -5
  40. package/dist/federation/source-provider.d.ts +0 -5
  41. package/dist/federation/types.d.cts +0 -5
  42. package/dist/federation/types.d.ts +0 -5
  43. package/dist/generate.cjs +1 -1
  44. package/dist/generate.js +3 -3
  45. package/dist/license-C1y-56bb.d.cts +23 -0
  46. package/dist/license-C1y-56bb.d.ts +23 -0
  47. package/dist/runtime-dependencies/@eventcatalog__visualiser__layout.mjs +3 -0
  48. package/dist/runtime-dependencies/@modelcontextprotocol__ext-apps.mjs +3 -0
  49. package/dist/runtime-dependencies/@modelcontextprotocol__ext-apps__react.mjs +3 -0
  50. package/dist/runtime-dependencies/@modelcontextprotocol__ext-apps__server.mjs +3 -0
  51. package/dist/runtime-dependencies/@modelcontextprotocol__sdk__types.js.mjs +3 -0
  52. package/dist/runtime-dependencies/manifest.json +12 -1
  53. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__graphql.mjs +3 -0
  54. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__json.mjs +3 -0
  55. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__markup.mjs +3 -0
  56. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__protobuf.mjs +3 -0
  57. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__languages__prism__yaml.mjs +3 -0
  58. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__styles__prism__one-dark.mjs +3 -0
  59. package/dist/runtime-dependencies/react-syntax-highlighter__dist__esm__styles__prism__one-light.mjs +3 -0
  60. package/dist/utils/cli-logger.cjs +1 -1
  61. package/dist/utils/cli-logger.js +2 -2
  62. package/dist/utils/license-status.cjs +240 -0
  63. package/dist/utils/license-status.d.cts +28 -0
  64. package/dist/utils/license-status.d.ts +28 -0
  65. package/dist/utils/license-status.js +12 -0
  66. package/eventcatalog/astro.config.mjs +1 -1
  67. package/eventcatalog/integrations/eventcatalog-runtime.mjs +1 -1
  68. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +29 -19
  69. package/eventcatalog/src/components/ChatPanel/OfflineReply.tsx +74 -0
  70. package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +24 -28
  71. package/eventcatalog/src/components/FieldsExplorer/FieldNodeGraph.tsx +16 -11
  72. package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +4 -218
  73. package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +27 -36
  74. package/eventcatalog/src/components/Header.astro +43 -58
  75. package/eventcatalog/src/components/Lists/PillListFlat.styles.css +17 -17
  76. package/eventcatalog/src/components/MDX/EntityMap/EntityMap.astro +1 -1
  77. package/eventcatalog/src/components/MDX/Flow/Flow.astro +4 -0
  78. package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +14 -0
  79. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +49 -18
  80. package/eventcatalog/src/components/MDX/RemoteFile.astro +2 -24
  81. package/eventcatalog/src/components/SchemaExplorer/ApiAccessSection.tsx +59 -93
  82. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +1 -32
  83. package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +20 -67
  84. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +2 -11
  85. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +11 -60
  86. package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +1 -3
  87. package/eventcatalog/src/components/SchemaExplorer/SchemaPageViewer.tsx +0 -3
  88. package/eventcatalog/src/components/SchemaExplorer/VersionHistoryModal.tsx +2 -9
  89. package/eventcatalog/src/components/SchemaExplorer/parse-schema.ts +46 -0
  90. package/eventcatalog/src/components/SchemaExplorer/utils.ts +11 -0
  91. package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +2 -9
  92. package/eventcatalog/src/components/Settings/LicenseSettings.tsx +288 -0
  93. package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +3 -19
  94. package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +85 -30
  95. package/eventcatalog/src/components/Settings/SettingsShared.tsx +7 -75
  96. package/eventcatalog/src/components/SideNav/CustomDocsNav.astro +2 -2
  97. package/eventcatalog/src/components/TrialBadge.astro +82 -0
  98. package/eventcatalog/src/content.config.ts +9 -96
  99. package/eventcatalog/src/{enterprise → features}/ai/chat-api.ts +22 -34
  100. package/eventcatalog/src/{enterprise → features}/analytics/adapters/ga4.ts +0 -5
  101. package/eventcatalog/src/{enterprise → features}/analytics/adapters/gtm.ts +0 -5
  102. package/eventcatalog/src/{enterprise → features}/analytics/adapters/posthog.ts +0 -5
  103. package/eventcatalog/src/{enterprise → features}/analytics/components/AnalyticsHead.astro +2 -4
  104. package/eventcatalog/src/{enterprise → features}/analytics/components/AnalyticsTracker.astro +2 -4
  105. package/eventcatalog/src/{enterprise → features}/analytics/tracker.ts +0 -5
  106. package/eventcatalog/src/{enterprise → features}/api/catalog.ts +0 -5
  107. package/eventcatalog/src/{enterprise → features}/auth/[...auth].ts +0 -5
  108. package/eventcatalog/src/{enterprise → features}/auth/middleware/middleware-auth.ts +0 -5
  109. package/eventcatalog/src/{enterprise → features}/auth/middleware/middleware.ts +0 -5
  110. package/eventcatalog/src/{enterprise → features}/collections/custom-pages.ts +0 -5
  111. package/eventcatalog/src/{enterprise → features}/collections/index.ts +0 -5
  112. package/eventcatalog/src/{enterprise → features}/collections/resource-docs.ts +0 -5
  113. package/eventcatalog/src/{enterprise → features}/custom-documentation/collection.ts +0 -5
  114. package/eventcatalog/src/features/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro +9 -0
  115. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/CustomDocsNavWrapper.tsx +0 -5
  116. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/components/NestedItem.tsx +1 -6
  117. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/components/NoResultsFound.tsx +0 -5
  118. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/index.tsx +1 -6
  119. package/eventcatalog/src/{enterprise → features}/custom-documentation/components/CustomDocsNav/types.ts +0 -5
  120. package/eventcatalog/src/{enterprise/custom-documentation/pages/docs/custom/index.astro → features/custom-documentation/components/CustomDocumentationPage.astro} +5 -5
  121. package/eventcatalog/src/{enterprise → features}/custom-documentation/utils/badge-styles.ts +0 -5
  122. package/eventcatalog/src/{enterprise → features}/custom-documentation/utils/custom-docs.ts +1 -6
  123. package/eventcatalog/src/{enterprise → features}/custom-documentation/utils/docs-search.ts +0 -5
  124. package/eventcatalog/src/{enterprise → features}/custom-pages/routes.ts +0 -5
  125. package/eventcatalog/src/{enterprise → features}/directory/user-team-directory.ts +0 -5
  126. package/eventcatalog/src/{enterprise → features}/fields/field-extractor.ts +0 -5
  127. package/eventcatalog/src/{enterprise → features}/fields/field-indexer.ts +0 -5
  128. package/eventcatalog/src/{enterprise → features}/fields/fields-db.ts +0 -5
  129. package/eventcatalog/src/{enterprise → features}/fields/pages/api/fields.ts +1 -6
  130. package/eventcatalog/src/{enterprise → features}/fields/pages/fields.astro +1 -2
  131. package/eventcatalog/src/{enterprise → features}/integrations/eventcatalog-features.ts +17 -75
  132. package/eventcatalog/src/features/mcp/apps/architecture-diagram/links.ts +59 -0
  133. package/eventcatalog/src/features/mcp/apps/architecture-diagram/node-chat.tsx +299 -0
  134. package/eventcatalog/src/features/mcp/apps/architecture-diagram/shared.ts +14 -0
  135. package/eventcatalog/src/features/mcp/apps/architecture-diagram/view.tsx +454 -0
  136. package/eventcatalog/src/features/mcp/apps/generated/viewer.html +432 -0
  137. package/eventcatalog/src/features/mcp/apps/mermaid-stub.ts +10 -0
  138. package/eventcatalog/src/features/mcp/apps/schema-viewer/schema-code.tsx +65 -0
  139. package/eventcatalog/src/features/mcp/apps/schema-viewer/shared.ts +23 -0
  140. package/eventcatalog/src/features/mcp/apps/schema-viewer/view.tsx +170 -0
  141. package/eventcatalog/src/features/mcp/apps/shared/app-view.tsx +98 -0
  142. package/eventcatalog/src/features/mcp/apps/shared/resource-types.ts +15 -0
  143. package/eventcatalog/src/features/mcp/apps/viewer/shared.ts +24 -0
  144. package/eventcatalog/src/features/mcp/apps/viewer/styles.css +25 -0
  145. package/eventcatalog/src/features/mcp/apps/viewer/view.tsx +59 -0
  146. package/eventcatalog/src/features/mcp/mcp-app-icons.ts +63 -0
  147. package/eventcatalog/src/features/mcp/mcp-apps.ts +160 -0
  148. package/eventcatalog/src/{enterprise → features}/mcp/mcp-auth.ts +0 -5
  149. package/eventcatalog/src/{enterprise → features}/mcp/mcp-scope.ts +7 -7
  150. package/eventcatalog/src/{enterprise → features}/mcp/mcp-scoped-tools.ts +47 -40
  151. package/eventcatalog/src/{enterprise → features}/mcp/mcp-server.ts +347 -34
  152. package/eventcatalog/src/{enterprise → features}/mcp/oauth-protected-resource.ts +0 -5
  153. package/eventcatalog/src/features/mcp/schema-viewer.ts +24 -0
  154. package/eventcatalog/src/{enterprise → features}/tools/catalog-tools.ts +133 -102
  155. package/eventcatalog/src/features/tools/index.ts +5 -0
  156. package/eventcatalog/src/{enterprise → features}/visualizer-layout/reset.ts +0 -5
  157. package/eventcatalog/src/{enterprise → features}/visualizer-layout/save.ts +0 -5
  158. package/eventcatalog/src/layouts/BaseLayout.astro +2 -2
  159. package/eventcatalog/src/layouts/Footer.astro +31 -39
  160. package/eventcatalog/src/layouts/SettingsLayout.astro +6 -6
  161. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +7 -37
  162. package/eventcatalog/src/{enterprise → pages}/api/schemas/[collection]/[id]/[version]/index.ts +0 -22
  163. package/eventcatalog/src/{enterprise → pages}/api/schemas/services/[id]/[version]/[specification]/index.ts +0 -19
  164. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/_index.data.ts +2 -6
  165. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +1 -5
  166. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/_index.data.ts +2 -6
  167. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +1 -5
  168. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId].md.ts +2 -6
  169. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId].mdx.ts +2 -6
  170. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +9 -5
  171. package/eventcatalog/src/pages/docs/custom/[...path]/index.astro +12 -0
  172. package/eventcatalog/src/{enterprise/custom-documentation/pages/docs/custom/root-index.astro → pages/docs/custom/index.astro} +1 -23
  173. package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +4 -9
  174. package/eventcatalog/src/pages/docs/llm/llms.txt.ts +4 -4
  175. package/eventcatalog/src/pages/docs/llm/schemas.txt.ts +0 -11
  176. package/eventcatalog/src/pages/docs/services/[id]/[docType]/[docId]/index.astro +2 -2
  177. package/eventcatalog/src/pages/index.astro +2 -2
  178. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +0 -3
  179. package/eventcatalog/src/pages/schemas/explorer/index.astro +1 -4
  180. package/eventcatalog/src/pages/settings/assistant.astro +2 -4
  181. package/eventcatalog/src/pages/settings/license.astro +18 -0
  182. package/eventcatalog/src/pages/settings/llm-access.astro +1 -4
  183. package/eventcatalog/src/pages/settings/mcp.astro +33 -4
  184. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +1 -2
  185. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/index.astro +2 -45
  186. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +1 -1
  187. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version].mermaid.ts +7 -109
  188. package/eventcatalog/src/pages/visualiser/_mermaid-route.ts +78 -0
  189. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/_index.data.ts +44 -0
  190. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +1 -1
  191. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/index.astro +56 -0
  192. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +3 -40
  193. package/eventcatalog/src/pages/visualiser/domains/[id]/[version].mermaid.ts +20 -0
  194. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/_index.data.ts +29 -0
  195. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +3 -38
  196. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/index.astro +56 -0
  197. package/eventcatalog/src/pages/visualiser/systems/[id]/[version].mermaid.ts +20 -0
  198. package/eventcatalog/src/stores/sidebar-store/builders/agent.ts +1 -1
  199. package/eventcatalog/src/stores/sidebar-store/builders/container.ts +1 -1
  200. package/eventcatalog/src/stores/sidebar-store/builders/data-product.ts +1 -1
  201. package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +7 -32
  202. package/eventcatalog/src/stores/sidebar-store/builders/entity.ts +1 -1
  203. package/eventcatalog/src/stores/sidebar-store/builders/message.ts +1 -1
  204. package/eventcatalog/src/stores/sidebar-store/builders/service.ts +2 -8
  205. package/eventcatalog/src/stores/sidebar-store/builders/system.ts +2 -12
  206. package/eventcatalog/src/stores/sidebar-store/custom-sidebar.ts +0 -10
  207. package/eventcatalog/src/stores/sidebar-store/state.ts +4 -6
  208. package/eventcatalog/src/styles/theme.css +22 -18
  209. package/eventcatalog/src/styles/themes/forest.css +8 -8
  210. package/eventcatalog/src/styles/themes/ocean.css +8 -8
  211. package/eventcatalog/src/styles/themes/sapphire.css +8 -8
  212. package/eventcatalog/src/styles/themes/sunset.css +8 -8
  213. package/eventcatalog/src/utils/clipboard.ts +4 -4
  214. package/eventcatalog/src/utils/collections/flow-step-schema.ts +117 -0
  215. package/eventcatalog/src/utils/collections/pointer-schema.ts +7 -0
  216. package/eventcatalog/src/utils/collections/resource-docs.ts +677 -14
  217. package/eventcatalog/src/utils/collections/schema-loader.ts +0 -5
  218. package/eventcatalog/src/utils/feature.ts +14 -23
  219. package/eventcatalog/src/utils/license.ts +114 -0
  220. package/eventcatalog/src/utils/node-graphs/architecture-diagram-types.ts +32 -0
  221. package/eventcatalog/src/utils/node-graphs/architecture-diagram.ts +84 -0
  222. package/eventcatalog/src/utils/node-graphs/channel-node-graph.ts +4 -25
  223. package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +12 -39
  224. package/eventcatalog/src/utils/node-graphs/data-products-node-graph.ts +11 -27
  225. package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +679 -0
  226. package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +3 -20
  227. package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +51 -4
  228. package/eventcatalog/src/utils/node-graphs/field-node-graph.ts +8 -23
  229. package/eventcatalog/src/utils/node-graphs/flow-lanes.ts +119 -0
  230. package/eventcatalog/src/utils/node-graphs/flows-node-graph.ts +133 -47
  231. package/eventcatalog/src/utils/node-graphs/layout-node-graph.ts +28 -0
  232. package/eventcatalog/src/utils/node-graphs/layout-persistence.ts +3 -3
  233. package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +16 -34
  234. package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +11 -25
  235. package/eventcatalog/src/utils/node-graphs/system-context-node-graph.ts +18 -54
  236. package/eventcatalog/src/utils/node-graphs/system-levels-node-graph.ts +59 -0
  237. package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +20 -80
  238. package/eventcatalog/src/utils/node-graphs/utils/utils.ts +1 -78
  239. package/eventcatalog/src/utils/trial.ts +36 -0
  240. package/eventcatalog/tsconfig.json +1 -1
  241. package/package.json +11 -11
  242. package/dist/chunk-FV56YFM4.js +0 -7
  243. package/dist/federation/entitlement.cjs +0 -31
  244. package/dist/federation/entitlement.d.cts +0 -12
  245. package/dist/federation/entitlement.d.ts +0 -12
  246. package/dist/federation/entitlement.js +0 -6
  247. package/dist/runtime-dependencies/dagre.mjs +0 -3
  248. package/eventcatalog/src/components/Settings/BillingSettingsForm.tsx +0 -265
  249. package/eventcatalog/src/enterprise/LICENSE +0 -57
  250. package/eventcatalog/src/enterprise/README.md +0 -5
  251. package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +0 -691
  252. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro +0 -9
  253. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/[...path]/index.astro +0 -18
  254. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/feature.astro +0 -171
  255. package/eventcatalog/src/enterprise/feature.ts +0 -75
  256. package/eventcatalog/src/enterprise/tools/index.ts +0 -10
  257. package/eventcatalog/src/hooks/eventcatalog-visualizer.ts +0 -126
  258. package/eventcatalog/src/pages/settings/billing.astro +0 -17
  259. package/eventcatalog/src/pages/visualiser/domain-integrations/index.astro +0 -26
  260. package/eventcatalog/src/types/mcp-modules.d.ts +0 -67
  261. package/eventcatalog/src/utils/node-graphs/domains-canvas.ts +0 -261
  262. package/eventcatalog/src/utils/node-graphs/export-node-graph.ts +0 -91
  263. /package/eventcatalog/src/{enterprise → features}/auth/error.astro +0 -0
  264. /package/eventcatalog/src/{enterprise → features}/auth/login.astro +0 -0
  265. /package/eventcatalog/src/{enterprise → features}/auth/unauthorized.astro +0 -0
  266. /package/eventcatalog/src/{enterprise/custom-documentation/pages → pages}/docs/custom/[...path]/_index.data.ts +0 -0
  267. /package/eventcatalog/src/{enterprise/custom-documentation/pages → pages}/docs/custom/[...path].mdx.ts +0 -0
@@ -1,20 +1,42 @@
1
- /**
2
- * Licensed under the EventCatalog Commercial License.
3
- * See /packages/core/eventcatalog/src/enterprise/LICENSE
4
- */
5
-
6
1
  import type { APIRoute } from 'astro';
7
2
  import { Hono, type Context } from 'hono';
8
3
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
4
  import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
10
5
  import { z } from 'zod';
11
6
  import { join } from 'node:path';
12
- import { isEventCatalogScaleEnabled } from '@utils/feature';
13
- import * as catalogTools from '@enterprise/tools/catalog-tools';
7
+ import * as catalogTools from '@features/tools/catalog-tools';
14
8
  import { getCollection } from 'astro:content';
15
9
  import { createMcpAuthErrorResponse, validateMcpRequest } from './mcp-auth';
16
10
  import { createScopedCatalogTools } from './mcp-scoped-tools';
17
11
  import { McpScopeNotFoundError, resolveMcpScope, type McpScope, type McpScopeKind } from './mcp-scope';
12
+ import { getArchitectureDiagramView } from '@utils/node-graphs/architecture-diagram';
13
+ import type {
14
+ ArchitectureDiagramCollection,
15
+ ArchitectureDiagramView,
16
+ Graph,
17
+ } from '@utils/node-graphs/architecture-diagram-types';
18
+ import { inlineNodeIcons } from './mcp-app-icons';
19
+ import type { ArchitectureDiagramPayload } from './apps/architecture-diagram/shared';
20
+ import type { SchemaViewerPayload } from './apps/schema-viewer/shared';
21
+ import { RESOURCE_VIEWS, VIEWER_META_KEY, VIEWER_RESOURCE_URI, VIEWER_VIEW_TOOL, type ViewerPayload } from './apps/viewer/shared';
22
+ import { toSchemaViewerSchemas } from './schema-viewer';
23
+ import { getMcpAppViewLoader, mcpAppNote, registerMcpApp } from './mcp-apps';
24
+ import { buildUrl } from '@utils/url-builder';
25
+
26
+ const loadViewerView = getMcpAppViewLoader('viewer');
27
+
28
+ const SHOW_RESOURCE_DESCRIPTION = [
29
+ "Show the user a resource in EventCatalog's interactive viewer. Pick what to show with view:",
30
+ '"architecture" shows an architecture diagram of a domain, system, service, agent, event, command, query, flow, data store or data product: what it connects to, what it publishes and consumes, and the systems and domains around it. Use it whenever the user wants to see or understand how something works or fits together, e.g. "show me how the Order Service works", "how does the Ordering domain fit together", "what does Payments talk to", or asks for a diagram, map or visual of something. Prefer it over drawing your own diagram. For domains and systems, pass detail "overview" for just the domains, systems and their relationships, or "full" (default) to include services, messages and channels.',
31
+ '"schema" shows the schema of a message (event, command or query) or other resource: its properties, types, descriptions and which ones are required. Use it whenever the user wants to see or understand a schema or payload, e.g. "show me the schema for OrderCreated", "what fields does PlaceOrder have", "what does the OrderShipped payload look like".',
32
+ 'Clients that support MCP Apps show one viewer and switch it to each thing you show, so call this again to show the user something else. The result also contains what is shown (the diagram as Mermaid in mermaidCode, or the schema code) so you can understand it.',
33
+ 'When the client shows the viewer, do not redraw the diagram or print the whole schema again in your reply: explain it and point out what matters. Otherwise, show the user the mermaidCode or the relevant parts of the schema code.',
34
+ ].join(' ');
35
+
36
+ type McpServerOptions = {
37
+ /** Where this EventCatalog is served, for links from MCP App views back to it */
38
+ catalogUrl: string;
39
+ };
18
40
 
19
41
  const catalogDirectory = process.env.PROJECT_DIR || process.cwd();
20
42
 
@@ -50,7 +72,7 @@ let extendedToolNames: string[] = [];
50
72
  try {
51
73
  const providerConfiguration = await import(/* @vite-ignore */ join(catalogDirectory, 'eventcatalog.chat.js'));
52
74
 
53
- if (isEventCatalogScaleEnabled() && providerConfiguration.tools) {
75
+ if (providerConfiguration.tools) {
54
76
  extendedTools = providerConfiguration.tools;
55
77
  extendedToolNames = Object.keys(extendedTools);
56
78
  }
@@ -58,12 +80,49 @@ try {
58
80
  // No chat configuration or tools defined - this is fine
59
81
  }
60
82
 
83
+ const MCP_SERVER_VERSION = '1.3.0';
84
+
85
+ // Every built-in tool only reads the catalog, so clients can safely auto-approve them
86
+ const readOnlyAnnotations = {
87
+ readOnlyHint: true,
88
+ destructiveHint: false,
89
+ idempotentHint: true,
90
+ openWorldHint: false,
91
+ } as const;
92
+
93
+ const optionalVersion = (resource: string) =>
94
+ z.string().optional().describe(`The version of the ${resource}. Omit it (or pass "latest") to use the latest version.`);
95
+
96
+ function getServerInstructions(scope?: McpScope) {
97
+ return [
98
+ 'EventCatalog documents an event-driven architecture: domains, systems, services, agents, the messages they exchange (events, commands, queries), channels, flows, entities, data products, schemas, owners (teams and users) and custom documentation.',
99
+ ...(scope
100
+ ? [
101
+ `This server is scoped to the ${scope.name} ${scope.ref.kind} (version ${scope.ref.version}). Only resources inside this ${scope.ref.kind} are available.`,
102
+ ]
103
+ : []),
104
+ 'Resources are identified by an id and a version. Versions are optional on every tool: omit the version to use the latest version.',
105
+ 'To find something, call getResources with a collection and a search term, then fetch the details with getResource. Use getSchemaForResource when you need a schema or OpenAPI/AsyncAPI specification for yourself, not to show it to the user.',
106
+ 'When the user wants to see or understand how something works or fits together (e.g. "show me how the Order Service works"), call showResource with view "architecture": it shows them an interactive diagram. Do not draw your own diagram of the architecture.',
107
+ 'When the user wants to see a schema, payload or the fields of a message (e.g. "show me the schema for OrderCreated"), call showResource with view "schema", not getSchemaForResource: it shows them an interactive schema viewer. Do not print the schema yourself.',
108
+ 'For relationships use getMessagesProducedOrConsumedByResource, getProducersOfMessage and getConsumersOfMessage. Before changing a message, call analyzeChangeImpact to find the affected services, agents and owning teams.',
109
+ ...(scope
110
+ ? []
111
+ : [
112
+ 'Use findResourcesByOwner, getTeam and getUser to find who owns something and how to contact them. Guides, runbooks and architecture notes live in custom documentation: use searchCustomDocs, then getCustomDoc.',
113
+ ]),
114
+ ].join('\n');
115
+ }
116
+
61
117
  // Create MCP Server with tools that access Astro collections
62
- function createMcpServer(scope?: McpScope) {
63
- const server = new McpServer({
64
- name: scope ? `EventCatalog MCP Server — ${scope.name} ${scope.ref.kind}` : 'EventCatalog MCP Server',
65
- version: '1.0.0',
66
- });
118
+ function createMcpServer(scope: McpScope | undefined, { catalogUrl }: McpServerOptions) {
119
+ const server = new McpServer(
120
+ {
121
+ name: scope ? `EventCatalog MCP Server — ${scope.name} ${scope.ref.kind}` : 'EventCatalog MCP Server',
122
+ version: MCP_SERVER_VERSION,
123
+ },
124
+ { instructions: getServerInstructions(scope) }
125
+ );
67
126
 
68
127
  const tools = scope ? createScopedCatalogTools(scope) : catalogTools;
69
128
 
@@ -71,12 +130,14 @@ function createMcpServer(scope?: McpScope) {
71
130
  server.registerTool(
72
131
  'getResources',
73
132
  {
133
+ title: 'List catalog resources',
74
134
  description: catalogTools.toolDescriptions.getResources,
75
135
  inputSchema: z.object({
76
136
  collection: catalogTools.collectionSchema.describe('The collection to get the resources from'),
77
137
  cursor: z.string().optional().describe('Pagination cursor from previous response'),
78
138
  search: z.string().optional().describe('Search term to filter resources by name, id, or summary (case-insensitive)'),
79
139
  }),
140
+ annotations: readOnlyAnnotations,
80
141
  },
81
142
  createToolHandler(tools.getResources, 'Failed to get resources')
82
143
  );
@@ -84,12 +145,14 @@ function createMcpServer(scope?: McpScope) {
84
145
  server.registerTool(
85
146
  'getResource',
86
147
  {
148
+ title: 'Get a catalog resource',
87
149
  description: catalogTools.toolDescriptions.getResource,
88
150
  inputSchema: z.object({
89
151
  collection: catalogTools.collectionSchema.describe('The collection to get the resource from'),
90
152
  id: z.string().describe('The id of the resource to get'),
91
- version: z.string().describe('The version of the resource to get'),
153
+ version: optionalVersion('resource'),
92
154
  }),
155
+ annotations: readOnlyAnnotations,
93
156
  },
94
157
  createToolHandler(tools.getResource, 'Failed to get resource')
95
158
  );
@@ -97,14 +160,16 @@ function createMcpServer(scope?: McpScope) {
97
160
  server.registerTool(
98
161
  'getMessagesProducedOrConsumedByResource',
99
162
  {
163
+ title: 'Get messages a resource sends and receives',
100
164
  description: catalogTools.toolDescriptions.getMessagesProducedOrConsumedByResource,
101
165
  inputSchema: z.object({
102
166
  resourceId: z.string().describe('The id of the resource to get the messages produced or consumed for'),
103
- resourceVersion: z.string().describe('The version of the resource to get the messages produced or consumed for'),
167
+ resourceVersion: optionalVersion('resource'),
104
168
  resourceCollection: catalogTools.resourceCollectionSchema
105
169
  .describe('The collection of the resource to get the messages produced or consumed for')
106
170
  .default('services'),
107
171
  }),
172
+ annotations: readOnlyAnnotations,
108
173
  },
109
174
  createToolHandler(tools.getMessagesProducedOrConsumedByResource, 'Failed to get messages')
110
175
  );
@@ -112,14 +177,16 @@ function createMcpServer(scope?: McpScope) {
112
177
  server.registerTool(
113
178
  'getSchemaForResource',
114
179
  {
115
- description: catalogTools.toolDescriptions.getSchemaForResource,
180
+ title: 'Get schemas and specifications',
181
+ description: `${catalogTools.toolDescriptions.getSchemaForResource}. To show the user a schema, use showResource with view "schema" instead: it shows them an interactive schema viewer.`,
116
182
  inputSchema: z.object({
117
183
  resourceId: z.string().describe('The id of the resource to get the schema for'),
118
- resourceVersion: z.string().describe('The version of the resource to get the schema for'),
184
+ resourceVersion: optionalVersion('resource'),
119
185
  resourceCollection: catalogTools.resourceCollectionSchema
120
186
  .describe('The collection of the resource to get the schema for')
121
187
  .default('services'),
122
188
  }),
189
+ annotations: readOnlyAnnotations,
123
190
  },
124
191
  createToolHandler(tools.getSchemaForResource, 'Failed to get schema')
125
192
  );
@@ -127,10 +194,12 @@ function createMcpServer(scope?: McpScope) {
127
194
  server.registerTool(
128
195
  'findResourcesByOwner',
129
196
  {
197
+ title: 'Find resources by owner',
130
198
  description: catalogTools.toolDescriptions.findResourcesByOwner,
131
199
  inputSchema: z.object({
132
200
  ownerId: z.string().describe('The id of the owner (team or user) to find resources for'),
133
201
  }),
202
+ annotations: readOnlyAnnotations,
134
203
  },
135
204
  createToolHandler(tools.findResourcesByOwner, 'Failed to find resources')
136
205
  );
@@ -138,14 +207,16 @@ function createMcpServer(scope?: McpScope) {
138
207
  server.registerTool(
139
208
  'getProducersOfMessage',
140
209
  {
210
+ title: 'Find producers of a message',
141
211
  description: catalogTools.toolDescriptions.getProducersOfMessage,
142
212
  inputSchema: z.object({
143
213
  messageId: z.string().describe('The id of the message to find producers for'),
144
- messageVersion: z.string().describe('The version of the message'),
214
+ messageVersion: optionalVersion('message'),
145
215
  messageCollection: catalogTools.messageCollectionSchema
146
216
  .describe('The collection type of the message (events, commands, or queries)')
147
217
  .default('events'),
148
218
  }),
219
+ annotations: readOnlyAnnotations,
149
220
  },
150
221
  createToolHandler(tools.getProducersOfMessage, 'Failed to get producers')
151
222
  );
@@ -153,14 +224,16 @@ function createMcpServer(scope?: McpScope) {
153
224
  server.registerTool(
154
225
  'getConsumersOfMessage',
155
226
  {
227
+ title: 'Find consumers of a message',
156
228
  description: catalogTools.toolDescriptions.getConsumersOfMessage,
157
229
  inputSchema: z.object({
158
230
  messageId: z.string().describe('The id of the message to find consumers for'),
159
- messageVersion: z.string().describe('The version of the message'),
231
+ messageVersion: optionalVersion('message'),
160
232
  messageCollection: catalogTools.messageCollectionSchema
161
233
  .describe('The collection type of the message (events, commands, or queries)')
162
234
  .default('events'),
163
235
  }),
236
+ annotations: readOnlyAnnotations,
164
237
  },
165
238
  createToolHandler(tools.getConsumersOfMessage, 'Failed to get consumers')
166
239
  );
@@ -169,10 +242,12 @@ function createMcpServer(scope?: McpScope) {
169
242
  server.registerTool(
170
243
  'getC4Diagram',
171
244
  {
245
+ title: 'Get C4 (LikeC4) diagrams',
172
246
  description: catalogTools.toolDescriptions.getC4Diagram,
173
247
  inputSchema: z.object({
174
248
  viewId: z.string().describe('The id of the LikeC4 view to return source files for').optional(),
175
249
  }),
250
+ annotations: readOnlyAnnotations,
176
251
  },
177
252
  createToolHandler(catalogTools.getC4Diagram, 'Failed to get c4 diagram')
178
253
  );
@@ -181,14 +256,16 @@ function createMcpServer(scope?: McpScope) {
181
256
  server.registerTool(
182
257
  'analyzeChangeImpact',
183
258
  {
259
+ title: 'Analyze the impact of changing a message',
184
260
  description: catalogTools.toolDescriptions.analyzeChangeImpact,
185
261
  inputSchema: z.object({
186
262
  messageId: z.string().describe('The id of the message to analyze impact for'),
187
- messageVersion: z.string().describe('The version of the message'),
263
+ messageVersion: optionalVersion('message'),
188
264
  messageCollection: catalogTools.messageCollectionSchema
189
265
  .describe('The collection type of the message (events, commands, or queries)')
190
266
  .default('events'),
191
267
  }),
268
+ annotations: readOnlyAnnotations,
192
269
  },
193
270
  createToolHandler(tools.analyzeChangeImpact, 'Failed to analyze impact')
194
271
  );
@@ -196,11 +273,13 @@ function createMcpServer(scope?: McpScope) {
196
273
  server.registerTool(
197
274
  'explainBusinessFlow',
198
275
  {
276
+ title: 'Explain a business flow',
199
277
  description: catalogTools.toolDescriptions.explainBusinessFlow,
200
278
  inputSchema: z.object({
201
279
  flowId: z.string().describe('The id of the flow to explain'),
202
- flowVersion: z.string().describe('The version of the flow'),
280
+ flowVersion: optionalVersion('flow'),
203
281
  }),
282
+ annotations: readOnlyAnnotations,
204
283
  },
205
284
  createToolHandler(tools.explainBusinessFlow, 'Failed to explain flow')
206
285
  );
@@ -209,10 +288,12 @@ function createMcpServer(scope?: McpScope) {
209
288
  server.registerTool(
210
289
  'getTeams',
211
290
  {
291
+ title: 'List teams',
212
292
  description: catalogTools.toolDescriptions.getTeams,
213
293
  inputSchema: z.object({
214
294
  cursor: z.string().optional().describe('Pagination cursor from previous response'),
215
295
  }),
296
+ annotations: readOnlyAnnotations,
216
297
  },
217
298
  createToolHandler(catalogTools.getTeams, 'Failed to get teams')
218
299
  );
@@ -220,10 +301,12 @@ function createMcpServer(scope?: McpScope) {
220
301
  server.registerTool(
221
302
  'getTeam',
222
303
  {
304
+ title: 'Get a team',
223
305
  description: catalogTools.toolDescriptions.getTeam,
224
306
  inputSchema: z.object({
225
307
  id: z.string().describe('The id of the team to get'),
226
308
  }),
309
+ annotations: readOnlyAnnotations,
227
310
  },
228
311
  createToolHandler(catalogTools.getTeam, 'Failed to get team')
229
312
  );
@@ -231,10 +314,12 @@ function createMcpServer(scope?: McpScope) {
231
314
  server.registerTool(
232
315
  'getUsers',
233
316
  {
317
+ title: 'List users',
234
318
  description: catalogTools.toolDescriptions.getUsers,
235
319
  inputSchema: z.object({
236
320
  cursor: z.string().optional().describe('Pagination cursor from previous response'),
237
321
  }),
322
+ annotations: readOnlyAnnotations,
238
323
  },
239
324
  createToolHandler(catalogTools.getUsers, 'Failed to get users')
240
325
  );
@@ -242,18 +327,195 @@ function createMcpServer(scope?: McpScope) {
242
327
  server.registerTool(
243
328
  'getUser',
244
329
  {
330
+ title: 'Get a user',
245
331
  description: catalogTools.toolDescriptions.getUser,
246
332
  inputSchema: z.object({
247
333
  id: z.string().describe('The id of the user to get'),
248
334
  }),
335
+ annotations: readOnlyAnnotations,
249
336
  },
250
337
  createToolHandler(catalogTools.getUser, 'Failed to get user')
251
338
  );
252
339
  }
253
340
 
341
+ // Icons served by EventCatalog don't load in the host's sandbox, so they are embedded in the diagram
342
+ const withInlineIcons = async ({ overview, hiddenMessages, ...graph }: ArchitectureDiagramView) => {
343
+ const publicDirectory = join(catalogDirectory, 'public');
344
+ const inline = async (level: Graph) => ({ ...level, nodes: await inlineNodeIcons(level.nodes, publicDirectory) });
345
+ return {
346
+ ...(await inline(graph)),
347
+ ...(overview && { overview: await inline(overview) }),
348
+ ...(hiddenMessages && { hiddenMessages: await inline(hiddenMessages) }),
349
+ };
350
+ };
351
+
352
+ const getResourceName = async (diagram: { resourceCollection: string; resourceId: string; resourceVersion: string }) => {
353
+ const resource = await catalogTools.getResource({
354
+ collection: diagram.resourceCollection,
355
+ id: diagram.resourceId,
356
+ version: diagram.resourceVersion,
357
+ });
358
+ return ('data' in resource && resource.data.name) || diagram.resourceId;
359
+ };
360
+
361
+ // The diagram with its levels for the MCP App view, as the resource's Diagram page shows it
362
+ const getArchitectureDiagramPayload = async (diagram: {
363
+ resourceCollection: ArchitectureDiagramCollection;
364
+ resourceId: string;
365
+ resourceVersion: string;
366
+ visualiserUrl: string;
367
+ }): Promise<ArchitectureDiagramPayload> => ({
368
+ resource: {
369
+ collection: diagram.resourceCollection,
370
+ id: diagram.resourceId,
371
+ version: diagram.resourceVersion,
372
+ name: await getResourceName(diagram),
373
+ },
374
+ catalogUrl,
375
+ visualiserPath: diagram.visualiserUrl,
376
+ view: await withInlineIcons(
377
+ await getArchitectureDiagramView({
378
+ collection: diagram.resourceCollection,
379
+ id: diagram.resourceId,
380
+ version: diagram.resourceVersion,
381
+ })
382
+ ),
383
+ });
384
+
385
+ // The resource's schemas, parsed for the view's JSON Schema, Avro and Protobuf viewers
386
+ const getSchemaViewerPayload = async (params: {
387
+ resourceId: string;
388
+ resourceVersion?: string;
389
+ resourceCollection: string;
390
+ }): Promise<SchemaViewerPayload | { error: string }> => {
391
+ const resource = await tools.getResource({
392
+ collection: params.resourceCollection,
393
+ id: params.resourceId,
394
+ version: params.resourceVersion,
395
+ });
396
+ if (resource.error !== undefined) return { error: resource.error };
397
+
398
+ const schemas = await tools.getSchemaForResource({ ...params, resourceVersion: resource.version });
399
+ if ('error' in schemas) return schemas;
400
+
401
+ return {
402
+ resource: {
403
+ collection: params.resourceCollection,
404
+ id: resource.id,
405
+ version: resource.version,
406
+ name: resource.data.name || resource.id,
407
+ },
408
+ catalogUrl,
409
+ docsPath: buildUrl(`/docs/${params.resourceCollection}/${resource.id}/${resource.version}`),
410
+ schemas: Array.isArray(schemas) ? toSchemaViewerSchemas(schemas) : [],
411
+ };
412
+ };
413
+
414
+ // Every collection that has an architecture diagram or a schema
415
+ const viewCollectionSchema = z.enum([
416
+ ...new Set([...catalogTools.resourceCollectionSchema.options, ...catalogTools.visualiserCollectionSchema.options]),
417
+ ] as [string, ...string[]]);
418
+
419
+ const resourceViewInput = {
420
+ view: z
421
+ .enum(RESOURCE_VIEWS)
422
+ .describe('What to show: "architecture" for an architecture diagram, "schema" for the schema of a message'),
423
+ resourceId: z.string().describe('The id of the resource to show'),
424
+ resourceVersion: optionalVersion('resource'),
425
+ resourceCollection: viewCollectionSchema.describe('The collection of the resource (defaults to events)').default('events'),
426
+ };
427
+
428
+ type ResourceViewParams = {
429
+ view: (typeof RESOURCE_VIEWS)[number];
430
+ resourceId: string;
431
+ resourceVersion?: string;
432
+ resourceCollection: string;
433
+ detail?: 'overview' | 'full';
434
+ };
435
+
436
+ const loadArchitectureView = async ({ view, ...params }: ResourceViewParams) => {
437
+ const result = await tools.getArchitectureDiagramAsMermaid(params);
438
+ if (result.error !== undefined) return { error: result.error };
439
+ return {
440
+ forModel: {
441
+ note: mcpAppNote('diagram', 'redraw it as Mermaid or ASCII', 'show the user the mermaidCode'),
442
+ view,
443
+ ...result,
444
+ },
445
+ label: `the architecture diagram for ${result.resourceCollection}/${result.resourceId}`,
446
+ getPayload: async (): Promise<ViewerPayload> => ({
447
+ view: 'architecture',
448
+ diagram: await getArchitectureDiagramPayload(result),
449
+ }),
450
+ };
451
+ };
452
+
453
+ const loadSchemaView = async ({ view, ...params }: ResourceViewParams) => {
454
+ const payload = await getSchemaViewerPayload(params);
455
+ if ('error' in payload) return payload;
456
+ const { resource, schemas } = payload;
457
+ return {
458
+ // The model reads the schema code; the view gets it parsed for its Properties tab
459
+ forModel: {
460
+ note: mcpAppNote('schema', 'print the whole schema again', 'show the user the relevant parts of the code'),
461
+ view,
462
+ resourceId: resource.id,
463
+ resourceVersion: resource.version,
464
+ resourceCollection: resource.collection,
465
+ resource,
466
+ schemas: schemas.map(({ name, format, code }) => ({ name, format, code })),
467
+ ...(schemas.length === 0 && { message: `${resource.name} has no schema` }),
468
+ },
469
+ label: `the schema for ${resource.collection}/${resource.id}`,
470
+ getPayload: async (): Promise<ViewerPayload> => ({ view: 'schema', schema: payload }),
471
+ };
472
+ };
473
+
474
+ registerMcpApp(server, {
475
+ loadView: loadViewerView,
476
+ resource: {
477
+ name: 'EventCatalog viewer',
478
+ uri: VIEWER_RESOURCE_URI,
479
+ description:
480
+ 'Interactive EventCatalog viewer (architecture diagrams and schemas), shown by MCP hosts that support MCP Apps',
481
+ // Diagram nodes show icons (languages, databases...) served by this EventCatalog
482
+ csp: { resourceDomains: [catalogUrl] },
483
+ // Diagrams and schemas need the room, so hosts that can open the viewer full screen straight away
484
+ displayModes: { preferred: 'fullscreen', available: ['inline', 'fullscreen'] },
485
+ },
486
+ // One viewer per server: each result updates the viewer the host already shows
487
+ sessionId: scope ? `eventcatalog:${scope.ref.kind}:${scope.ref.id}` : 'eventcatalog',
488
+ metaKey: VIEWER_META_KEY,
489
+ tool: {
490
+ name: 'showResource',
491
+ title: 'Show a resource',
492
+ description: SHOW_RESOURCE_DESCRIPTION,
493
+ input: {
494
+ ...resourceViewInput,
495
+ detail: z
496
+ .enum(['overview', 'full'])
497
+ .optional()
498
+ .describe(
499
+ 'For view "architecture" of domains and systems: "overview" shows only domains, systems and their relationships; "full" (default) also shows services, messages and channels'
500
+ ),
501
+ },
502
+ },
503
+ viewTool: {
504
+ name: VIEWER_VIEW_TOOL,
505
+ title: 'Load a resource for the viewer',
506
+ description:
507
+ 'Loads the architecture diagram or schema shown by the EventCatalog viewer. To show the user a resource, use showResource instead.',
508
+ input: resourceViewInput,
509
+ },
510
+ annotations: readOnlyAnnotations,
511
+ errorMessage: 'Failed to show resource',
512
+ load: (params) => (params.view === 'schema' ? loadSchemaView(params) : loadArchitectureView(params)),
513
+ });
514
+
254
515
  server.registerTool(
255
516
  'findMessageBySchemaId',
256
517
  {
518
+ title: 'Find a message from a schema',
257
519
  description: catalogTools.toolDescriptions.findMessageBySchemaId,
258
520
  inputSchema: z.object({
259
521
  messageId: z.string().describe('The message id (from x-eventcatalog-id in the schema)'),
@@ -267,6 +529,7 @@ function createMcpServer(scope?: McpScope) {
267
529
  .optional()
268
530
  .describe('Optional hint for which collection to search (events, commands, or queries)'),
269
531
  }),
532
+ annotations: readOnlyAnnotations,
270
533
  },
271
534
  createToolHandler(tools.findMessageBySchemaId, 'Failed to find message')
272
535
  );
@@ -275,25 +538,57 @@ function createMcpServer(scope?: McpScope) {
275
538
  server.registerTool(
276
539
  'explainUbiquitousLanguageTerms',
277
540
  {
541
+ title: 'Explain ubiquitous language terms',
278
542
  description: catalogTools.toolDescriptions.explainUbiquitousLanguageTerms,
279
543
  inputSchema: z.object({
280
544
  domainId: z.string().describe('The id of the domain to get ubiquitous language terms for'),
281
- domainVersion: z.string().optional().describe('The version of the domain. If not provided, uses the latest version.'),
545
+ domainVersion: optionalVersion('domain'),
282
546
  }),
547
+ annotations: readOnlyAnnotations,
283
548
  },
284
549
  createToolHandler(tools.explainUbiquitousLanguageTerms, 'Failed to get ubiquitous language terms')
285
550
  );
286
551
  }
287
552
 
288
553
  if (!scope) {
554
+ server.registerTool(
555
+ 'getDataProductInputs',
556
+ {
557
+ title: 'Get data product inputs',
558
+ description: catalogTools.toolDescriptions.getDataProductInputs,
559
+ inputSchema: z.object({
560
+ dataProductId: z.string().describe('The id of the data product'),
561
+ dataProductVersion: optionalVersion('data product'),
562
+ }),
563
+ annotations: readOnlyAnnotations,
564
+ },
565
+ createToolHandler(catalogTools.getDataProductInputs, 'Failed to get data product inputs')
566
+ );
567
+
568
+ server.registerTool(
569
+ 'getDataProductOutputs',
570
+ {
571
+ title: 'Get data product outputs and contracts',
572
+ description: catalogTools.toolDescriptions.getDataProductOutputs,
573
+ inputSchema: z.object({
574
+ dataProductId: z.string().describe('The id of the data product'),
575
+ dataProductVersion: optionalVersion('data product'),
576
+ }),
577
+ annotations: readOnlyAnnotations,
578
+ },
579
+ createToolHandler(catalogTools.getDataProductOutputs, 'Failed to get data product outputs')
580
+ );
581
+
289
582
  server.registerTool(
290
583
  'getCustomDocs',
291
584
  {
585
+ title: 'List custom documentation',
292
586
  description: catalogTools.toolDescriptions.getCustomDocs,
293
587
  inputSchema: z.object({
294
588
  cursor: z.string().optional().describe('Pagination cursor from previous response'),
295
589
  search: z.string().optional().describe('Search term to filter docs by title, id, or summary (case-insensitive)'),
296
590
  }),
591
+ annotations: readOnlyAnnotations,
297
592
  },
298
593
  createToolHandler(catalogTools.getCustomDocs, 'Failed to get custom documentation pages')
299
594
  );
@@ -301,11 +596,13 @@ function createMcpServer(scope?: McpScope) {
301
596
  server.registerTool(
302
597
  'searchCustomDocs',
303
598
  {
599
+ title: 'Search custom documentation',
304
600
  description: catalogTools.toolDescriptions.searchCustomDocs,
305
601
  inputSchema: z.object({
306
602
  query: z.string().describe('Full-text search query, e.g. keywords describing the topic to find'),
307
603
  limit: z.number().optional().describe('Maximum number of results to return (default 10)'),
308
604
  }),
605
+ annotations: readOnlyAnnotations,
309
606
  },
310
607
  createToolHandler(catalogTools.searchCustomDocs, 'Failed to search custom documentation')
311
608
  );
@@ -313,11 +610,13 @@ function createMcpServer(scope?: McpScope) {
313
610
  server.registerTool(
314
611
  'getCustomDoc',
315
612
  {
613
+ title: 'Get a custom documentation page',
316
614
  description: catalogTools.toolDescriptions.getCustomDoc,
317
615
  inputSchema: z.object({
318
616
  id: z.string().describe('The id or slug of the custom documentation page'),
319
617
  section: z.string().optional().describe('Optional section heading to return only that section of the page'),
320
618
  }),
619
+ annotations: readOnlyAnnotations,
321
620
  },
322
621
  createToolHandler(catalogTools.getCustomDoc, 'Failed to get custom documentation page')
323
622
  );
@@ -329,7 +628,7 @@ function createMcpServer(scope?: McpScope) {
329
628
 
330
629
  // Extract tool properties (Vercel AI SDK format)
331
630
  // The AI SDK tool() helper uses "inputSchema" for Zod schemas
332
- const { description, parameters, inputSchema, execute } = toolConfig;
631
+ const { title, description, parameters, inputSchema, annotations, execute } = toolConfig;
333
632
 
334
633
  if (!description || !execute) {
335
634
  console.warn(`[MCP] Skipping invalid extended tool: ${toolName}`);
@@ -339,8 +638,10 @@ function createMcpServer(scope?: McpScope) {
339
638
  server.registerTool(
340
639
  toolName,
341
640
  {
641
+ ...(title && { title }),
342
642
  description: description || `Custom tool: ${toolName}`,
343
643
  inputSchema: inputSchema || parameters || z.object({}),
644
+ ...(annotations && { annotations }),
344
645
  },
345
646
  async (params: any) => {
346
647
  try {
@@ -537,7 +838,8 @@ function createMcpServer(scope?: McpScope) {
537
838
  // "Stateless transport cannot be reused across requests" errors.
538
839
 
539
840
  // Create Hono app for MCP routes
540
- const app = new Hono().basePath('/docs/mcp');
841
+ // Not strict, so /docs/mcp/ works too: MCP clients are often configured with a trailing slash
842
+ const app = new Hono({ strict: false }).basePath('/docs/mcp');
541
843
 
542
844
  const globalBuiltInTools = [
543
845
  'getResources',
@@ -556,17 +858,28 @@ const globalBuiltInTools = [
556
858
  'getUser',
557
859
  'findMessageBySchemaId',
558
860
  'explainUbiquitousLanguageTerms',
861
+ 'getDataProductInputs',
862
+ 'getDataProductOutputs',
863
+ 'showResource',
864
+ 'getCustomDocs',
865
+ 'searchCustomDocs',
866
+ 'getCustomDoc',
867
+ ];
868
+
869
+ const globalOnlyTools = [
870
+ 'getC4Diagram',
871
+ 'getTeams',
872
+ 'getTeam',
873
+ 'getUsers',
874
+ 'getUser',
875
+ 'getDataProductInputs',
876
+ 'getDataProductOutputs',
559
877
  'getCustomDocs',
560
878
  'searchCustomDocs',
561
879
  'getCustomDoc',
562
880
  ];
563
881
 
564
- const scopedBuiltInTools = globalBuiltInTools.filter(
565
- (tool) =>
566
- !['getC4Diagram', 'getTeams', 'getTeam', 'getUsers', 'getUser', 'getCustomDocs', 'searchCustomDocs', 'getCustomDoc'].includes(
567
- tool
568
- )
569
- );
882
+ const scopedBuiltInTools = globalBuiltInTools.filter((tool) => !globalOnlyTools.includes(tool));
570
883
 
571
884
  const getScopedBuiltInTools = (scope: McpScope) =>
572
885
  scope.ref.kind === 'system'
@@ -605,7 +918,7 @@ const getMcpResourceUris = (scope?: McpScope) =>
605
918
 
606
919
  const getScopeRef = (c: Context, kind: McpScopeKind) => ({
607
920
  kind,
608
- id: c.req.param('id'),
921
+ id: c.req.param('id') ?? '',
609
922
  version: c.req.param('version') || 'latest',
610
923
  });
611
924
 
@@ -648,7 +961,7 @@ const handleGetRequest = async (c: Context, kind?: McpScopeKind) => {
648
961
  const scope = await resolveRequestScope(c, kind);
649
962
  return c.json({
650
963
  name: scope ? `EventCatalog MCP Server — ${scope.name} ${scope.ref.kind}` : 'EventCatalog MCP Server',
651
- version: '1.2.0',
964
+ version: MCP_SERVER_VERSION,
652
965
  status: 'running',
653
966
  ...(scope && { scope: scope.ref }),
654
967
  tools: scope ? getScopedBuiltInTools(scope) : [...globalBuiltInTools, ...extendedToolNames],
@@ -670,7 +983,7 @@ const handleMcpRequest = async (c: Context, kind?: McpScopeKind) => {
670
983
  }
671
984
 
672
985
  const scope = await resolveRequestScope(c, kind);
673
- const server = createMcpServer(scope);
986
+ const server = createMcpServer(scope, { catalogUrl: new URL(c.req.url).origin });
674
987
  const transport = new WebStandardStreamableHTTPServerTransport({
675
988
  sessionIdGenerator: undefined,
676
989
  });
@@ -709,7 +1022,7 @@ for (const kind of ['domain', 'system'] as const) {
709
1022
  app.post('/', (c: Context) => handleMcpRequest(c));
710
1023
 
711
1024
  // Astro API route handler - delegates all requests to Hono
712
- // Note: SSR and Scale plan checks are handled at build time by the integration
1025
+ // Note: SSR checks are handled at build time by the integration
713
1026
  // This route is only injected when isEventCatalogMCPEnabled() returns true
714
1027
  export const ALL: APIRoute = async ({ request }) => {
715
1028
  return app.fetch(request);