@contractspec/bundle.library 3.8.2 → 3.8.5

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 (121) hide show
  1. package/.turbo/turbo-build.log +130 -116
  2. package/CHANGELOG.md +80 -0
  3. package/dist/application/index.js +806 -131
  4. package/dist/application/mcp/cliMcp.js +21 -2
  5. package/dist/application/mcp/common.js +21 -2
  6. package/dist/application/mcp/common.test.d.ts +1 -0
  7. package/dist/application/mcp/contractsMcp.js +21 -2
  8. package/dist/application/mcp/docsMcp.catalog.d.ts +2 -0
  9. package/dist/application/mcp/docsMcp.catalog.js +382 -0
  10. package/dist/application/mcp/docsMcp.d.ts +5 -1
  11. package/dist/application/mcp/docsMcp.data.d.ts +85 -0
  12. package/dist/application/mcp/docsMcp.data.js +148 -0
  13. package/dist/application/mcp/docsMcp.js +776 -101
  14. package/dist/application/mcp/docsMcp.prompts.d.ts +3 -0
  15. package/dist/application/mcp/docsMcp.prompts.js +522 -0
  16. package/dist/application/mcp/docsMcp.reference.d.ts +24 -0
  17. package/dist/application/mcp/docsMcp.reference.js +236 -0
  18. package/dist/application/mcp/docsMcp.resources.d.ts +3 -0
  19. package/dist/application/mcp/docsMcp.resources.js +520 -0
  20. package/dist/application/mcp/docsMcp.test.d.ts +1 -0
  21. package/dist/application/mcp/docsMcp.tools.d.ts +3 -0
  22. package/dist/application/mcp/docsMcp.tools.js +519 -0
  23. package/dist/application/mcp/index.js +806 -131
  24. package/dist/application/mcp/internalMcp.js +21 -2
  25. package/dist/application/mcp/normalizeMcpRequest.d.ts +1 -0
  26. package/dist/application/mcp/normalizeMcpRequest.js +22 -0
  27. package/dist/application/mcp/providerRankingMcp.js +21 -2
  28. package/dist/components/docs/generated/docs-index.generated.d.ts +6 -6
  29. package/dist/components/docs/index.js +23 -24
  30. package/dist/components/docs/libraries/LibrariesAiAgentPage.js +22 -22
  31. package/dist/components/docs/libraries/LibrariesSupportBotPage.js +1 -2
  32. package/dist/components/docs/libraries/index.js +23 -24
  33. package/dist/components/templates/engine/index.d.ts +1 -1
  34. package/dist/components/templates/engine/index.js +1 -1
  35. package/dist/features/index.js +15 -15
  36. package/dist/index.js +194 -195
  37. package/dist/node/application/index.js +806 -131
  38. package/dist/node/application/mcp/cliMcp.js +21 -2
  39. package/dist/node/application/mcp/common.js +21 -2
  40. package/dist/node/application/mcp/contractsMcp.js +21 -2
  41. package/dist/node/application/mcp/docsMcp.catalog.js +381 -0
  42. package/dist/node/application/mcp/docsMcp.data.js +147 -0
  43. package/dist/node/application/mcp/docsMcp.js +776 -101
  44. package/dist/node/application/mcp/docsMcp.prompts.js +521 -0
  45. package/dist/node/application/mcp/docsMcp.reference.js +235 -0
  46. package/dist/node/application/mcp/docsMcp.resources.js +519 -0
  47. package/dist/node/application/mcp/docsMcp.tools.js +518 -0
  48. package/dist/node/application/mcp/index.js +806 -131
  49. package/dist/node/application/mcp/internalMcp.js +21 -2
  50. package/dist/node/application/mcp/normalizeMcpRequest.js +21 -0
  51. package/dist/node/application/mcp/providerRankingMcp.js +21 -2
  52. package/dist/node/components/docs/index.js +23 -24
  53. package/dist/node/components/docs/libraries/LibrariesAiAgentPage.js +22 -22
  54. package/dist/node/components/docs/libraries/LibrariesSupportBotPage.js +1 -2
  55. package/dist/node/components/docs/libraries/index.js +23 -24
  56. package/dist/node/components/templates/engine/index.js +1 -1
  57. package/dist/node/features/index.js +15 -15
  58. package/dist/node/index.js +194 -195
  59. package/dist/node/presentation/features/hooks/index.js +12 -12
  60. package/dist/node/presentation/features/hooks/useContractsRegistry.js +12 -12
  61. package/dist/node/presentation/features/index.js +12 -12
  62. package/dist/node/presentation/features/organisms/FeatureDataViewsList.js +12 -12
  63. package/dist/node/presentation/features/organisms/FeatureEventsList.js +12 -12
  64. package/dist/node/presentation/features/organisms/FeatureFormsList.js +12 -12
  65. package/dist/node/presentation/features/organisms/FeaturePresentationsList.js +12 -12
  66. package/dist/node/presentation/features/organisms/index.js +12 -12
  67. package/dist/node/presentation/features/templates/FeatureDataViewsTemplate/FeatureDataViewsTemplate.js +12 -12
  68. package/dist/node/presentation/features/templates/FeatureDataViewsTemplate/index.js +12 -12
  69. package/dist/node/presentation/features/templates/FeatureEventsTemplate/FeatureEventsTemplate.js +12 -12
  70. package/dist/node/presentation/features/templates/FeatureEventsTemplate/index.js +12 -12
  71. package/dist/node/presentation/features/templates/FeatureFormsTemplate/FeatureFormsTemplate.js +12 -12
  72. package/dist/node/presentation/features/templates/FeatureFormsTemplate/index.js +12 -12
  73. package/dist/node/presentation/features/templates/FeaturePresentationsTemplate/FeaturePresentationsTemplate.js +12 -12
  74. package/dist/node/presentation/features/templates/FeaturePresentationsTemplate/index.js +12 -12
  75. package/dist/presentation/features/hooks/index.js +12 -12
  76. package/dist/presentation/features/hooks/useContractsRegistry.js +12 -12
  77. package/dist/presentation/features/index.js +12 -12
  78. package/dist/presentation/features/organisms/FeatureDataViewsList.js +12 -12
  79. package/dist/presentation/features/organisms/FeatureEventsList.js +12 -12
  80. package/dist/presentation/features/organisms/FeatureFormsList.js +12 -12
  81. package/dist/presentation/features/organisms/FeaturePresentationsList.js +12 -12
  82. package/dist/presentation/features/organisms/index.js +12 -12
  83. package/dist/presentation/features/templates/FeatureDataViewsTemplate/FeatureDataViewsTemplate.js +12 -12
  84. package/dist/presentation/features/templates/FeatureDataViewsTemplate/index.js +12 -12
  85. package/dist/presentation/features/templates/FeatureEventsTemplate/FeatureEventsTemplate.js +12 -12
  86. package/dist/presentation/features/templates/FeatureEventsTemplate/index.js +12 -12
  87. package/dist/presentation/features/templates/FeatureFormsTemplate/FeatureFormsTemplate.js +12 -12
  88. package/dist/presentation/features/templates/FeatureFormsTemplate/index.js +12 -12
  89. package/dist/presentation/features/templates/FeaturePresentationsTemplate/FeaturePresentationsTemplate.js +12 -12
  90. package/dist/presentation/features/templates/FeaturePresentationsTemplate/index.js +12 -12
  91. package/package.json +108 -23
  92. package/src/application/mcp/common.test.ts +64 -0
  93. package/src/application/mcp/common.ts +5 -2
  94. package/src/application/mcp/docsMcp.catalog.ts +2 -0
  95. package/src/application/mcp/docsMcp.data.ts +196 -0
  96. package/src/application/mcp/docsMcp.prompts.ts +165 -0
  97. package/src/application/mcp/docsMcp.reference.ts +152 -0
  98. package/src/application/mcp/docsMcp.resources.ts +194 -0
  99. package/src/application/mcp/docsMcp.test.ts +148 -0
  100. package/src/application/mcp/docsMcp.tools.ts +183 -0
  101. package/src/application/mcp/docsMcp.ts +13 -177
  102. package/src/application/mcp/normalizeMcpRequest.ts +30 -0
  103. package/src/components/docs/generated/docs-index._common.json +1 -1
  104. package/src/components/docs/generated/docs-index.ai-chat-assistant.json +8 -0
  105. package/src/components/docs/generated/docs-index.artisan-knowledge-product.json +18 -0
  106. package/src/components/docs/generated/docs-index.artisan-payments-stripe.json +34 -0
  107. package/src/components/docs/generated/docs-index.data-grid-showcase.json +18 -0
  108. package/src/components/docs/generated/docs-index.generated.ts +6 -6
  109. package/src/components/docs/generated/docs-index.harness-lab.json +10 -0
  110. package/src/components/docs/generated/docs-index.locale-jurisdiction-gate.json +8 -0
  111. package/src/components/docs/generated/docs-index.manifest.json +50 -5
  112. package/src/components/docs/generated/docs-index.messaging-agent-actions.json +18 -0
  113. package/src/components/docs/generated/docs-index.mobile-demo-tasks.json +34 -0
  114. package/src/components/docs/generated/docs-index.opencode-cli.json +2 -2
  115. package/src/components/docs/generated/docs-index.platform-control-plane.json +250 -0
  116. package/src/components/docs/generated/docs-index.platform-harness.json +178 -0
  117. package/src/components/docs/generated/docs-index.platform-integrations.json +22 -14
  118. package/src/components/docs/generated/docs-index.visualization-showcase.json +18 -0
  119. package/src/components/docs/libraries/LibrariesAiAgentPage.tsx +20 -17
  120. package/src/components/docs/libraries/LibrariesSupportBotPage.tsx +1 -2
  121. package/src/components/templates/engine/index.ts +2 -2
@@ -26,6 +26,25 @@ var authLogger = new Logger({
26
26
  enableContext: true,
27
27
  enableColors: false
28
28
  });
29
+ // src/application/mcp/normalizeMcpRequest.ts
30
+ var REQUIRED_ACCEPT_TYPES = ["application/json", "text/event-stream"];
31
+ function canNormalizeAcceptHeader(acceptHeader) {
32
+ return !acceptHeader || acceptHeader.includes("*/*") || acceptHeader.includes("application/*") || REQUIRED_ACCEPT_TYPES.some((value) => acceptHeader.includes(value));
33
+ }
34
+ function normalizeMcpRequest(request) {
35
+ if (request.method !== "POST")
36
+ return request;
37
+ const acceptHeader = request.headers.get("accept");
38
+ if (!canNormalizeAcceptHeader(acceptHeader))
39
+ return request;
40
+ const missingTypes = REQUIRED_ACCEPT_TYPES.filter((value) => !acceptHeader?.includes(value));
41
+ if (missingTypes.length === 0)
42
+ return request;
43
+ const headers = new Headers(request.headers);
44
+ headers.set("accept", [acceptHeader, ...missingTypes].filter(Boolean).join(", "));
45
+ return new Request(request, { headers });
46
+ }
47
+
29
48
  // src/application/mcp/common.ts
30
49
  import { randomUUID } from "crypto";
31
50
  import { createMcpServer } from "@contractspec/lib.contracts-runtime-server-mcp/provider-mcp";
@@ -121,7 +140,7 @@ function createMcpElysiaHandler({
121
140
  stateful: false
122
141
  });
123
142
  try {
124
- return await state.transport.handleRequest(request);
143
+ return await state.transport.handleRequest(normalizeMcpRequest(request));
125
144
  } finally {
126
145
  await closeSessionState(state);
127
146
  }
@@ -157,7 +176,7 @@ function createMcpElysiaHandler({
157
176
  createdState = true;
158
177
  }
159
178
  try {
160
- const response = await state.transport.handleRequest(request);
179
+ const response = await state.transport.handleRequest(normalizeMcpRequest(request));
161
180
  const activeSessionId = state.transport.sessionId;
162
181
  if (activeSessionId && !sessions.has(activeSessionId)) {
163
182
  sessions.set(activeSessionId, state);
@@ -764,90 +783,393 @@ function createContractsMcpHandler(path2 = "/api/mcp/contracts", services) {
764
783
  });
765
784
  }
766
785
 
767
- // src/features/docs/docs.contracts.ts
786
+ // src/application/mcp/docsMcp.data.ts
787
+ import { defaultDocRegistry } from "@contractspec/lib.contracts-spec/docs";
788
+ var DEFAULT_LIMIT = 20;
789
+ var MAX_LIMIT = 100;
790
+ function normalizeText(value) {
791
+ return value?.trim().toLowerCase() ?? "";
792
+ }
793
+ function normalizeRoute(route) {
794
+ const decoded = decodeURIComponent(route).trim();
795
+ if (!decoded)
796
+ return "/";
797
+ return decoded.startsWith("/") ? decoded : `/${decoded}`;
798
+ }
799
+ function normalizeTags(value) {
800
+ const tags = Array.isArray(value) ? value : value ? [value] : [];
801
+ return tags.map((tag) => normalizeText(tag)).filter(Boolean);
802
+ }
803
+ function clampLimit(limit) {
804
+ if (!limit || Number.isNaN(limit))
805
+ return DEFAULT_LIMIT;
806
+ return Math.min(Math.max(limit, 1), MAX_LIMIT);
807
+ }
808
+ function clampOffset(offset) {
809
+ if (!offset || Number.isNaN(offset))
810
+ return 0;
811
+ return Math.max(offset, 0);
812
+ }
813
+ function toDocSummary({ block, route }) {
814
+ return {
815
+ id: block.id,
816
+ title: block.title,
817
+ summary: block.summary ?? "",
818
+ route,
819
+ visibility: block.visibility ?? "public",
820
+ kind: block.kind ?? "reference",
821
+ version: block.version ?? "1.0.0",
822
+ tags: block.tags ?? []
823
+ };
824
+ }
825
+ function scoreDoc(route, query) {
826
+ if (!query)
827
+ return 1;
828
+ const tokens = query.split(/\s+/).filter(Boolean);
829
+ const title = normalizeText(route.block.title);
830
+ const id = normalizeText(route.block.id);
831
+ const summary = normalizeText(route.block.summary);
832
+ const body = normalizeText(route.block.body);
833
+ const path2 = normalizeText(route.route);
834
+ const tags = (route.block.tags ?? []).map((tag) => normalizeText(tag));
835
+ const haystack = [title, id, summary, body, path2, ...tags].join(" ");
836
+ if (tokens.some((token) => !haystack.includes(token)))
837
+ return 0;
838
+ let score = 0;
839
+ for (const token of tokens) {
840
+ if (id.includes(token))
841
+ score += 8;
842
+ if (title.includes(token))
843
+ score += 7;
844
+ if (tags.some((tag) => tag.includes(token)))
845
+ score += 5;
846
+ if (summary.includes(token))
847
+ score += 4;
848
+ if (path2.includes(token))
849
+ score += 3;
850
+ if (body.includes(token))
851
+ score += 2;
852
+ }
853
+ return score;
854
+ }
855
+ function searchDocs(routes, args) {
856
+ const query = normalizeText(typeof args.query === "string" ? args.query : undefined);
857
+ const tags = normalizeTags(args.tag);
858
+ const visibility = normalizeText(typeof args.visibility === "string" ? args.visibility : undefined);
859
+ const kind = normalizeText(typeof args.kind === "string" ? args.kind : undefined);
860
+ const limit = clampLimit(typeof args.limit === "number" ? args.limit : undefined);
861
+ const offset = clampOffset(typeof args.offset === "number" ? args.offset : undefined);
862
+ const ranked = routes.map((route) => ({
863
+ doc: toDocSummary(route),
864
+ score: scoreDoc(route, query)
865
+ })).filter(({ doc, score }) => {
866
+ const matchesQuery = query ? score > 0 : true;
867
+ const matchesTags = tags.length ? tags.every((tag) => doc.tags.some((docTag) => normalizeText(docTag).includes(tag))) : true;
868
+ const matchesVisibility = visibility ? normalizeText(doc.visibility) === visibility : true;
869
+ const matchesKind = kind ? normalizeText(doc.kind) === kind : true;
870
+ return matchesQuery && matchesTags && matchesVisibility && matchesKind;
871
+ }).sort((left, right) => {
872
+ if (right.score !== left.score)
873
+ return right.score - left.score;
874
+ return left.doc.title.localeCompare(right.doc.title);
875
+ });
876
+ const docs = ranked.slice(offset, offset + limit).map(({ doc }) => doc);
877
+ const nextOffset = offset + docs.length < ranked.length ? offset + docs.length : undefined;
878
+ return {
879
+ docs,
880
+ items: docs,
881
+ total: ranked.length,
882
+ ...nextOffset != null ? { nextOffset } : {}
883
+ };
884
+ }
885
+ function getDocById(id) {
886
+ const normalizedId = decodeURIComponent(id);
887
+ const found = defaultDocRegistry.get(normalizedId);
888
+ if (!found)
889
+ return;
890
+ return {
891
+ doc: toDocSummary(found),
892
+ content: String(found.block.body ?? "")
893
+ };
894
+ }
895
+ function getDocByRoute(routes, routePath) {
896
+ const normalizedPath = normalizeRoute(routePath);
897
+ const found = routes.find((route) => normalizeRoute(route.route) === normalizedPath);
898
+ if (!found)
899
+ return;
900
+ return {
901
+ doc: toDocSummary(found),
902
+ content: String(found.block.body ?? "")
903
+ };
904
+ }
905
+ function listDocFacets(routes) {
906
+ const tags = new Map;
907
+ const kinds = new Map;
908
+ const visibilities = new Map;
909
+ for (const route of routes) {
910
+ const kind = route.block.kind ?? "reference";
911
+ const visibility = route.block.visibility ?? "public";
912
+ kinds.set(kind, (kinds.get(kind) ?? 0) + 1);
913
+ visibilities.set(visibility, (visibilities.get(visibility) ?? 0) + 1);
914
+ for (const tag of route.block.tags ?? []) {
915
+ tags.set(tag, (tags.get(tag) ?? 0) + 1);
916
+ }
917
+ }
918
+ const toEntries = (values, key) => [...values.entries()].sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0])).map(([value, count]) => ({ [key]: value, count }));
919
+ return {
920
+ totalDocs: routes.length,
921
+ tags: toEntries(tags, "tag"),
922
+ kinds: toEntries(kinds, "kind"),
923
+ visibilities: toEntries(visibilities, "visibility")
924
+ };
925
+ }
926
+
927
+ // src/features/contracts-registry.ts
928
+ import {
929
+ EventRegistry,
930
+ OperationSpecRegistry as OperationSpecRegistry3
931
+ } from "@contractspec/lib.contracts-spec";
768
932
  import {
933
+ DataViewRegistry
934
+ } from "@contractspec/lib.contracts-spec/data-views";
935
+ import {
936
+ ContractReferenceDataView,
769
937
  ContractReferenceQuery,
770
- DocSummaryModel,
771
- DocsIndexInput,
772
- DocsIndexOutput,
938
+ DocsGenerateCommand,
939
+ DocsGeneratedEvent,
940
+ DocsIndexDataView,
773
941
  DocsIndexQuery,
774
- DocsIndexQuery as DocsIndexQuery2
942
+ DocsLayoutPresentation,
943
+ DocsPublishCommand,
944
+ DocsPublishedEvent,
945
+ DocsReferencePagePresentation,
946
+ DocsSearchForm,
947
+ ExampleCatalogDataView
775
948
  } from "@contractspec/lib.contracts-spec/docs";
776
- // src/application/mcp/docsMcp.ts
949
+ import { FormRegistry } from "@contractspec/lib.contracts-spec/forms";
777
950
  import {
778
- definePrompt as definePrompt3,
779
- defineResourceTemplate as defineResourceTemplate3,
780
- installOp as installOp3,
781
- OperationSpecRegistry as OperationSpecRegistry3,
782
- PromptRegistry as PromptRegistry3,
783
- ResourceRegistry as ResourceRegistry3
784
- } from "@contractspec/lib.contracts-spec";
785
- import { defaultDocRegistry } from "@contractspec/lib.contracts-spec/docs";
786
- import z3 from "zod";
787
- var DOC_OWNERS = ["@contractspec"];
788
- var DOC_TAGS = ["docs", "mcp"];
789
- function buildDocResources(routes) {
790
- const resources = new ResourceRegistry3;
791
- resources.register(defineResourceTemplate3({
792
- meta: {
793
- uriTemplate: "docs://list",
794
- title: "DocBlocks index",
795
- description: "All registered DocBlocks with route, visibility, tags, and summary.",
796
- mimeType: "application/json",
797
- tags: DOC_TAGS
951
+ PresentationRegistry as PresentationRegistry2
952
+ } from "@contractspec/lib.contracts-spec/presentations";
953
+ import {
954
+ serializeDataViewSpec,
955
+ serializeEventSpec,
956
+ serializeFormSpec,
957
+ serializeOperationSpec,
958
+ serializePresentationSpec
959
+ } from "@contractspec/lib.contracts-spec/serialization";
960
+ var operationRegistry = null;
961
+ function createContractSpecOperationRegistry() {
962
+ const registry = new OperationSpecRegistry3;
963
+ registry.register(DocsIndexQuery).register(ContractReferenceQuery).register(DocsGenerateCommand).register(DocsPublishCommand);
964
+ return registry;
965
+ }
966
+ function getContractSpecOperationRegistry() {
967
+ if (!operationRegistry) {
968
+ operationRegistry = createContractSpecOperationRegistry();
969
+ }
970
+ return operationRegistry;
971
+ }
972
+ function resolveOperationSpec(key, version) {
973
+ return getContractSpecOperationRegistry().get(key, version);
974
+ }
975
+ var eventRegistry = null;
976
+ function createContractSpecEventRegistry() {
977
+ const registry = new EventRegistry;
978
+ registry.register(DocsGeneratedEvent).register(DocsPublishedEvent);
979
+ return registry;
980
+ }
981
+ function getContractSpecEventRegistry() {
982
+ if (!eventRegistry) {
983
+ eventRegistry = createContractSpecEventRegistry();
984
+ }
985
+ return eventRegistry;
986
+ }
987
+ function resolveEventSpec(key, version) {
988
+ return getContractSpecEventRegistry().get(key, version);
989
+ }
990
+ var presentationRegistry = null;
991
+ function createContractSpecPresentationRegistry() {
992
+ const registry = new PresentationRegistry2;
993
+ registry.register(DocsLayoutPresentation).register(DocsReferencePagePresentation);
994
+ return registry;
995
+ }
996
+ function getContractSpecPresentationRegistry() {
997
+ if (!presentationRegistry) {
998
+ presentationRegistry = createContractSpecPresentationRegistry();
999
+ }
1000
+ return presentationRegistry;
1001
+ }
1002
+ function resolvePresentationSpec(key, version) {
1003
+ return getContractSpecPresentationRegistry().get(key, version);
1004
+ }
1005
+ var dataViewRegistry = null;
1006
+ function createContractSpecDataViewRegistry() {
1007
+ const registry = new DataViewRegistry;
1008
+ registry.register(DocsIndexDataView).register(ContractReferenceDataView).register(ExampleCatalogDataView);
1009
+ return registry;
1010
+ }
1011
+ function getContractSpecDataViewRegistry() {
1012
+ if (!dataViewRegistry) {
1013
+ dataViewRegistry = createContractSpecDataViewRegistry();
1014
+ }
1015
+ return dataViewRegistry;
1016
+ }
1017
+ function resolveDataViewSpec(key, version) {
1018
+ return getContractSpecDataViewRegistry().get(key, version);
1019
+ }
1020
+ var formRegistry = null;
1021
+ function createContractSpecFormRegistry() {
1022
+ const registry = new FormRegistry;
1023
+ registry.register(DocsSearchForm);
1024
+ return registry;
1025
+ }
1026
+ function getContractSpecFormRegistry() {
1027
+ if (!formRegistry) {
1028
+ formRegistry = createContractSpecFormRegistry();
1029
+ }
1030
+ return formRegistry;
1031
+ }
1032
+ function resolveFormSpec(key, _version) {
1033
+ return getContractSpecFormRegistry().get(key);
1034
+ }
1035
+ function resolveSerializedOperationSpec(key, version) {
1036
+ const spec = resolveOperationSpec(key, version);
1037
+ return serializeOperationSpec(spec) ?? undefined;
1038
+ }
1039
+ function resolveSerializedEventSpec(key, version) {
1040
+ const spec = resolveEventSpec(key, version);
1041
+ return serializeEventSpec(spec) ?? undefined;
1042
+ }
1043
+ function resolveSerializedPresentationSpec(key, version) {
1044
+ const spec = resolvePresentationSpec(key, version);
1045
+ return serializePresentationSpec(spec) ?? undefined;
1046
+ }
1047
+ function resolveSerializedDataViewSpec(key, version) {
1048
+ const spec = resolveDataViewSpec(key, version);
1049
+ return serializeDataViewSpec(spec) ?? undefined;
1050
+ }
1051
+ function resolveSerializedFormSpec(key, version) {
1052
+ const spec = resolveFormSpec(key, version);
1053
+ return serializeFormSpec(spec) ?? undefined;
1054
+ }
1055
+ function resetContractSpecOperationRegistry() {
1056
+ operationRegistry = null;
1057
+ }
1058
+ function resetContractSpecEventRegistry() {
1059
+ eventRegistry = null;
1060
+ }
1061
+ function resetContractSpecPresentationRegistry() {
1062
+ presentationRegistry = null;
1063
+ }
1064
+ function resetContractSpecDataViewRegistry() {
1065
+ dataViewRegistry = null;
1066
+ }
1067
+ function resetContractSpecFormRegistry() {
1068
+ formRegistry = null;
1069
+ }
1070
+ function resetAllContractSpecRegistries() {
1071
+ resetContractSpecOperationRegistry();
1072
+ resetContractSpecEventRegistry();
1073
+ resetContractSpecPresentationRegistry();
1074
+ resetContractSpecDataViewRegistry();
1075
+ resetContractSpecFormRegistry();
1076
+ }
1077
+
1078
+ // src/application/mcp/docsMcp.reference.ts
1079
+ import { defaultDocRegistry as defaultDocRegistry2 } from "@contractspec/lib.contracts-spec/docs";
1080
+ function normalizeText2(value) {
1081
+ return value?.trim().toLowerCase() ?? "";
1082
+ }
1083
+ function routeFromDocIds(docIds) {
1084
+ for (const docId of docIds ?? []) {
1085
+ const doc = defaultDocRegistry2.get(docId);
1086
+ if (doc)
1087
+ return doc.route;
1088
+ }
1089
+ return;
1090
+ }
1091
+ function toReference(spec, type, schema, policy) {
1092
+ const title = spec.meta.title ?? spec.meta.key;
1093
+ const route = routeFromDocIds(spec.meta.docId);
1094
+ const description = spec.meta.description;
1095
+ return {
1096
+ key: spec.meta.key,
1097
+ version: spec.meta.version,
1098
+ type,
1099
+ title,
1100
+ description,
1101
+ markdown: [
1102
+ `# ${title}`,
1103
+ `- Key: ${spec.meta.key}`,
1104
+ `- Type: ${type}`,
1105
+ `- Version: ${spec.meta.version}`,
1106
+ route ? `- Docs route: ${route}` : "",
1107
+ description ? `
1108
+ ${description}` : ""
1109
+ ].filter(Boolean).join(`
1110
+ `),
1111
+ ...route ? { route } : {},
1112
+ ...schema ? { schema } : {},
1113
+ ...policy ? { policy } : {},
1114
+ tags: spec.meta.tags ?? [],
1115
+ owners: spec.meta.owners ?? [],
1116
+ stability: spec.meta.stability
1117
+ };
1118
+ }
1119
+ function resolveContractReference(args) {
1120
+ const includeSchema = args.includeSchema ?? false;
1121
+ const requestedType = normalizeText2(args.type);
1122
+ const operation = resolveOperationSpec(args.key, args.version);
1123
+ if (operation && (!requestedType || requestedType === "operation" || requestedType === operation.meta.kind)) {
1124
+ return {
1125
+ reference: toReference(operation, operation.meta.kind, includeSchema ? resolveSerializedOperationSpec(args.key, args.version) : undefined, operation.policy)
1126
+ };
1127
+ }
1128
+ const resolvers = [
1129
+ {
1130
+ type: "data-view",
1131
+ spec: resolveDataViewSpec(args.key, args.version),
1132
+ schema: includeSchema ? resolveSerializedDataViewSpec(args.key, args.version) : undefined
798
1133
  },
799
- input: z3.object({}),
800
- resolve: async () => {
801
- const docs = routes.map(({ block, route }) => ({
802
- id: block.id,
803
- title: block.title,
804
- summary: block.summary ?? "",
805
- tags: block.tags ?? [],
806
- visibility: block.visibility ?? "public",
807
- route
808
- }));
809
- return {
810
- uri: "docs://list",
811
- mimeType: "application/json",
812
- data: JSON.stringify(docs, null, 2)
813
- };
814
- }
815
- }));
816
- resources.register(defineResourceTemplate3({
817
- meta: {
818
- uriTemplate: "docs://doc/{id}",
819
- title: "DocBlock markdown",
820
- description: "Fetch DocBlock body by id as markdown.",
821
- mimeType: "text/markdown",
822
- tags: DOC_TAGS
1134
+ {
1135
+ type: "form",
1136
+ spec: resolveFormSpec(args.key, args.version),
1137
+ schema: includeSchema ? resolveSerializedFormSpec(args.key, args.version) : undefined
823
1138
  },
824
- input: z3.object({ id: z3.string() }),
825
- resolve: async ({ id }) => {
826
- const found = defaultDocRegistry.get(id);
827
- if (!found) {
828
- return {
829
- uri: `docs://doc/${encodeURIComponent(id)}`,
830
- mimeType: "text/plain",
831
- data: `DocBlock not found: ${id}`
832
- };
833
- }
1139
+ {
1140
+ type: "presentation",
1141
+ spec: resolvePresentationSpec(args.key, args.version),
1142
+ schema: includeSchema ? resolveSerializedPresentationSpec(args.key, args.version) : undefined
1143
+ },
1144
+ {
1145
+ type: "event",
1146
+ spec: resolveEventSpec(args.key, args.version),
1147
+ schema: includeSchema ? resolveSerializedEventSpec(args.key, args.version) : undefined
1148
+ }
1149
+ ];
1150
+ for (const candidate of resolvers) {
1151
+ if (candidate.spec && (!requestedType || requestedType === candidate.type)) {
834
1152
  return {
835
- uri: `docs://doc/${encodeURIComponent(id)}`,
836
- mimeType: "text/markdown",
837
- data: String(found.block.body ?? "")
1153
+ reference: toReference(candidate.spec, candidate.type, candidate.schema)
838
1154
  };
839
1155
  }
840
- }));
841
- return resources;
1156
+ }
1157
+ throw new Error(`Contract reference not found: ${args.key}`);
842
1158
  }
843
- function buildDocPrompts() {
1159
+
1160
+ // src/application/mcp/docsMcp.prompts.ts
1161
+ import { definePrompt as definePrompt3, PromptRegistry as PromptRegistry3 } from "@contractspec/lib.contracts-spec";
1162
+ import z3 from "zod";
1163
+ var DOC_OWNERS = ["@contractspec"];
1164
+ var DOC_TAGS = ["docs", "mcp"];
1165
+ function buildDocPrompts(routes) {
844
1166
  const prompts = new PromptRegistry3;
845
1167
  prompts.register(definePrompt3({
846
1168
  meta: {
847
1169
  key: "docs.navigator",
848
1170
  version: "1.0.0",
849
1171
  title: "Find relevant ContractSpec docs",
850
- description: "Guide agents to pick the right DocBlock by topic or tag.",
1172
+ description: "Guide agents to search, filter, and open the right ContractSpec docs.",
851
1173
  tags: DOC_TAGS,
852
1174
  stability: "beta",
853
1175
  owners: DOC_OWNERS
@@ -859,6 +1181,12 @@ function buildDocPrompts() {
859
1181
  required: false,
860
1182
  schema: z3.string().optional()
861
1183
  },
1184
+ {
1185
+ name: "kind",
1186
+ description: "Optional doc kind filter.",
1187
+ required: false,
1188
+ schema: z3.string().optional()
1189
+ },
862
1190
  {
863
1191
  name: "tag",
864
1192
  description: "Optional tag filter.",
@@ -868,82 +1196,429 @@ function buildDocPrompts() {
868
1196
  ],
869
1197
  input: z3.object({
870
1198
  topic: z3.string().optional(),
1199
+ kind: z3.string().optional(),
871
1200
  tag: z3.string().optional()
872
1201
  }),
873
- render: async ({ topic, tag }) => {
874
- const parts = [
1202
+ render: async ({ topic, kind, tag }) => {
1203
+ const matches = searchDocs(routes, {
1204
+ query: topic,
1205
+ kind,
1206
+ tag,
1207
+ limit: 3
1208
+ });
1209
+ const suggestedDocs = matches.docs.length ? matches.docs.map((doc) => `- ${doc.title} (${doc.id}) -> ${doc.route}`).join(`
1210
+ `) : "- No direct pre-match. Use docs_list_facets-v1_0_0 to browse tags and kinds.";
1211
+ return [
875
1212
  {
876
1213
  type: "text",
877
- text: `Use the docs index to choose DocBlocks. If a specific topic is provided, prefer docs whose id/title/summary match it.${topic ? ` Topic: ${topic}.` : ""}${tag ? ` Tag: ${tag}.` : ""}`
1214
+ text: [
1215
+ "Use docs_search-v1_0_0 first, then read docs://doc/{id} for the strongest matches.",
1216
+ "Use docs_resolve_route-v1_0_0 when the user already gives you a docs URL or route.",
1217
+ "Use docs_list_facets-v1_0_0 or docs://facets to browse the docs taxonomy before guessing.",
1218
+ topic ? `Topic: ${topic}` : "",
1219
+ kind ? `Kind: ${kind}` : "",
1220
+ tag ? `Tag: ${tag}` : "",
1221
+ "Suggested starting docs:",
1222
+ suggestedDocs
1223
+ ].filter(Boolean).join(`
1224
+ `)
878
1225
  },
879
1226
  {
880
1227
  type: "resource",
881
- uri: "docs://list",
1228
+ uri: "docs://index",
882
1229
  title: "DocBlocks index"
1230
+ },
1231
+ {
1232
+ type: "resource",
1233
+ uri: "docs://facets",
1234
+ title: "Docs facets"
1235
+ }
1236
+ ];
1237
+ }
1238
+ }));
1239
+ prompts.register(definePrompt3({
1240
+ meta: {
1241
+ key: "docs.reference.guide",
1242
+ version: "1.0.0",
1243
+ title: "Resolve a ContractSpec reference",
1244
+ description: "Guide agents to fetch the canonical reference payload for a ContractSpec surface.",
1245
+ tags: DOC_TAGS,
1246
+ stability: "beta",
1247
+ owners: DOC_OWNERS
1248
+ },
1249
+ args: [
1250
+ {
1251
+ name: "key",
1252
+ description: "ContractSpec key to resolve.",
1253
+ required: true,
1254
+ schema: z3.string()
1255
+ },
1256
+ {
1257
+ name: "version",
1258
+ description: "Optional version override.",
1259
+ required: false,
1260
+ schema: z3.string().optional()
1261
+ },
1262
+ {
1263
+ name: "type",
1264
+ description: "Optional surface type: command, query, form, data-view, presentation, event.",
1265
+ required: false,
1266
+ schema: z3.string().optional()
1267
+ }
1268
+ ],
1269
+ input: z3.object({
1270
+ key: z3.string(),
1271
+ version: z3.string().optional(),
1272
+ type: z3.string().optional()
1273
+ }),
1274
+ render: async ({ key, version, type }) => {
1275
+ const reference = resolveContractReference({
1276
+ key,
1277
+ version,
1278
+ type,
1279
+ includeSchema: true
1280
+ }).reference;
1281
+ return [
1282
+ {
1283
+ type: "text",
1284
+ text: [
1285
+ "Use docs_contract_reference-v1_0_0 when you need the canonical docs payload for a ContractSpec surface.",
1286
+ "Use docs_get-v1_0_0 only when you already know the exact DocBlock id and need raw markdown.",
1287
+ `Resolved key: ${reference.key}`,
1288
+ `Resolved type: ${reference.type}`,
1289
+ reference.route ? `Docs route: ${reference.route}` : "",
1290
+ `Resource URI: docs://contract-reference/${encodeURIComponent(key)}`
1291
+ ].filter(Boolean).join(`
1292
+ `)
1293
+ },
1294
+ {
1295
+ type: "resource",
1296
+ uri: `docs://contract-reference/${encodeURIComponent(key)}`,
1297
+ title: "Contract reference"
883
1298
  }
884
1299
  ];
885
- return parts;
886
1300
  }
887
1301
  }));
888
1302
  return prompts;
889
1303
  }
1304
+
1305
+ // src/application/mcp/docsMcp.resources.ts
1306
+ import {
1307
+ defineResourceTemplate as defineResourceTemplate3,
1308
+ ResourceRegistry as ResourceRegistry3
1309
+ } from "@contractspec/lib.contracts-spec";
1310
+ import z4 from "zod";
1311
+ var DOC_TAGS2 = ["docs", "mcp"];
1312
+ function buildDocResources(routes) {
1313
+ const resources = new ResourceRegistry3;
1314
+ const readDocIndex = (input) => searchDocs(routes, input);
1315
+ resources.register(defineResourceTemplate3({
1316
+ meta: {
1317
+ uriTemplate: "docs://index",
1318
+ title: "DocBlocks index",
1319
+ description: "Default ContractSpec docs index resource.",
1320
+ mimeType: "application/json",
1321
+ tags: DOC_TAGS2
1322
+ },
1323
+ input: z4.object({}),
1324
+ resolve: async () => ({
1325
+ uri: "docs://index",
1326
+ mimeType: "application/json",
1327
+ data: JSON.stringify(readDocIndex({}), null, 2)
1328
+ })
1329
+ }));
1330
+ resources.register(defineResourceTemplate3({
1331
+ meta: {
1332
+ uriTemplate: "docs://index{?query,tag,kind,visibility,limit,offset}",
1333
+ title: "DocBlocks index",
1334
+ description: "Search and paginate ContractSpec docs by query, tag, kind, or visibility.",
1335
+ mimeType: "application/json",
1336
+ tags: DOC_TAGS2
1337
+ },
1338
+ input: z4.object({
1339
+ query: z4.string().optional(),
1340
+ tag: z4.string().optional(),
1341
+ kind: z4.string().optional(),
1342
+ visibility: z4.string().optional(),
1343
+ limit: z4.coerce.number().optional(),
1344
+ offset: z4.coerce.number().optional()
1345
+ }),
1346
+ resolve: async (input) => ({
1347
+ uri: "docs://index",
1348
+ mimeType: "application/json",
1349
+ data: JSON.stringify(readDocIndex(input), null, 2)
1350
+ })
1351
+ }));
1352
+ resources.register(defineResourceTemplate3({
1353
+ meta: {
1354
+ uriTemplate: "docs://list",
1355
+ title: "DocBlocks index (legacy alias)",
1356
+ description: "Compatibility alias for the docs index resource.",
1357
+ mimeType: "application/json",
1358
+ tags: DOC_TAGS2
1359
+ },
1360
+ input: z4.object({}),
1361
+ resolve: async () => ({
1362
+ uri: "docs://list",
1363
+ mimeType: "application/json",
1364
+ data: JSON.stringify(readDocIndex({}), null, 2)
1365
+ })
1366
+ }));
1367
+ resources.register(defineResourceTemplate3({
1368
+ meta: {
1369
+ uriTemplate: "docs://doc/{id}",
1370
+ title: "Doc markdown",
1371
+ description: "Fetch a single DocBlock body by id as markdown.",
1372
+ mimeType: "text/markdown",
1373
+ tags: DOC_TAGS2
1374
+ },
1375
+ input: z4.object({ id: z4.string() }),
1376
+ resolve: async ({ id }) => {
1377
+ const found = getDocById(id);
1378
+ if (!found) {
1379
+ return {
1380
+ uri: `docs://doc/${encodeURIComponent(id)}`,
1381
+ mimeType: "text/plain",
1382
+ data: `DocBlock not found: ${id}`
1383
+ };
1384
+ }
1385
+ return {
1386
+ uri: `docs://doc/${encodeURIComponent(id)}`,
1387
+ mimeType: "text/markdown",
1388
+ data: found.content
1389
+ };
1390
+ }
1391
+ }));
1392
+ resources.register(defineResourceTemplate3({
1393
+ meta: {
1394
+ uriTemplate: "docs://route/{routePath}",
1395
+ title: "Doc by route",
1396
+ description: "Resolve a docs route to the matching DocBlock summary and body.",
1397
+ mimeType: "application/json",
1398
+ tags: DOC_TAGS2
1399
+ },
1400
+ input: z4.object({ routePath: z4.string() }),
1401
+ resolve: async ({ routePath }) => ({
1402
+ uri: `docs://route/${encodeURIComponent(routePath)}`,
1403
+ mimeType: "application/json",
1404
+ data: JSON.stringify(getDocByRoute(routes, routePath) ?? {
1405
+ error: "not_found",
1406
+ route: routePath
1407
+ }, null, 2)
1408
+ })
1409
+ }));
1410
+ resources.register(defineResourceTemplate3({
1411
+ meta: {
1412
+ uriTemplate: "docs://facets",
1413
+ title: "Docs facets",
1414
+ description: "Counts of available tags, kinds, and visibilities across docs.",
1415
+ mimeType: "application/json",
1416
+ tags: DOC_TAGS2
1417
+ },
1418
+ input: z4.object({}),
1419
+ resolve: async () => ({
1420
+ uri: "docs://facets",
1421
+ mimeType: "application/json",
1422
+ data: JSON.stringify(listDocFacets(routes), null, 2)
1423
+ })
1424
+ }));
1425
+ resources.register(defineResourceTemplate3({
1426
+ meta: {
1427
+ uriTemplate: "docs://contract-reference/{key}{?version,type,includeSchema}",
1428
+ title: "Contract reference",
1429
+ description: "Resolve a ContractSpec surface into a docs-ready reference payload.",
1430
+ mimeType: "application/json",
1431
+ tags: DOC_TAGS2
1432
+ },
1433
+ input: z4.object({
1434
+ key: z4.string(),
1435
+ version: z4.string().optional(),
1436
+ type: z4.string().optional(),
1437
+ includeSchema: z4.coerce.boolean().optional()
1438
+ }),
1439
+ resolve: async ({ key, version, type, includeSchema }) => ({
1440
+ uri: `docs://contract-reference/${encodeURIComponent(key)}`,
1441
+ mimeType: "application/json",
1442
+ data: JSON.stringify(resolveContractReference({ key, version, type, includeSchema }), null, 2)
1443
+ })
1444
+ }));
1445
+ return resources;
1446
+ }
1447
+
1448
+ // src/application/mcp/docsMcp.tools.ts
1449
+ import {
1450
+ defineCommand as defineCommand3,
1451
+ defineSchemaModel as defineSchemaModel3,
1452
+ installOp as installOp3,
1453
+ OperationSpecRegistry as OperationSpecRegistry4
1454
+ } from "@contractspec/lib.contracts-spec";
1455
+ import {
1456
+ ContractReferenceInput,
1457
+ ContractReferenceOutput,
1458
+ DocsIndexInput,
1459
+ DocsIndexOutput
1460
+ } from "@contractspec/lib.contracts-spec/docs";
1461
+ import { ScalarTypeEnum as ScalarTypeEnum3 } from "@contractspec/lib.schema";
1462
+ var DOC_OWNERS2 = ["@contractspec"];
1463
+ var DOC_TAGS3 = ["docs", "mcp"];
1464
+ var DocsGetInput = defineSchemaModel3({
1465
+ name: "DocsGetInput",
1466
+ fields: {
1467
+ id: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false }
1468
+ }
1469
+ });
1470
+ var DocsGetOutput = defineSchemaModel3({
1471
+ name: "DocsGetOutput",
1472
+ fields: {
1473
+ doc: { type: ScalarTypeEnum3.JSON(), isOptional: false },
1474
+ content: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false }
1475
+ }
1476
+ });
1477
+ var DocsResolveRouteInput = defineSchemaModel3({
1478
+ name: "DocsResolveRouteInput",
1479
+ fields: {
1480
+ route: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false }
1481
+ }
1482
+ });
1483
+ var DocsResolveRouteOutput = defineSchemaModel3({
1484
+ name: "DocsResolveRouteOutput",
1485
+ fields: {
1486
+ doc: { type: ScalarTypeEnum3.JSON(), isOptional: false },
1487
+ content: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false }
1488
+ }
1489
+ });
1490
+ var DocsFacetsInput = defineSchemaModel3({
1491
+ name: "DocsFacetsInput",
1492
+ fields: {}
1493
+ });
1494
+ var DocsFacetsOutput = defineSchemaModel3({
1495
+ name: "DocsFacetsOutput",
1496
+ fields: {
1497
+ facets: { type: ScalarTypeEnum3.JSON(), isOptional: false }
1498
+ }
1499
+ });
890
1500
  function buildDocOps(routes) {
891
- const registry = new OperationSpecRegistry3;
892
- installOp3(registry, DocsIndexQuery, async (args) => {
893
- const query = args.query?.toLowerCase().trim();
894
- const tagsFilter = args.tag?.map((t) => t.toLowerCase().trim()) ?? [];
895
- const visibility = args.visibility?.toLowerCase().trim();
896
- const docs = routes.map(({ block, route }) => ({
897
- id: block.id,
898
- title: block.title,
899
- summary: block.summary ?? "",
900
- tags: block.tags ?? [],
901
- visibility: (block.visibility ?? "public").toLowerCase(),
902
- route
903
- })).filter((doc) => {
904
- const matchesQuery = query ? doc.id.toLowerCase().includes(query) || doc.title.toLowerCase().includes(query) || doc.summary.toLowerCase().includes(query) : true;
905
- const matchesTags = tagsFilter.length ? tagsFilter.every((t) => doc.tags.some((tag) => tag.toLowerCase().includes(t))) : true;
906
- const matchesVisibility = visibility ? doc.visibility === visibility : true;
907
- return matchesQuery && matchesTags && matchesVisibility;
908
- });
909
- return {
910
- docs,
911
- items: docs,
912
- total: docs.length
913
- };
1501
+ const registry = new OperationSpecRegistry4;
1502
+ installOp3(registry, defineCommand3({
1503
+ meta: {
1504
+ key: "docs.search",
1505
+ version: "1.0.0",
1506
+ stability: "beta",
1507
+ owners: DOC_OWNERS2,
1508
+ tags: DOC_TAGS3,
1509
+ description: "Search ContractSpec docs by query, tag, kind, or visibility.",
1510
+ goal: "Find the most relevant DocBlocks without browsing the full corpus.",
1511
+ context: "Read-only docs MCP search surface."
1512
+ },
1513
+ io: { input: DocsIndexInput, output: DocsIndexOutput },
1514
+ policy: { auth: "anonymous" },
1515
+ transport: { mcp: { toolName: "docs_search-v1_0_0" } }
1516
+ }), async (args) => searchDocs(routes, args));
1517
+ installOp3(registry, defineCommand3({
1518
+ meta: {
1519
+ key: "docs.get",
1520
+ version: "1.0.0",
1521
+ stability: "beta",
1522
+ owners: DOC_OWNERS2,
1523
+ tags: DOC_TAGS3,
1524
+ description: "Read a single DocBlock by id.",
1525
+ goal: "Fetch the exact markdown content and metadata for a known doc id.",
1526
+ context: "Read-only docs MCP surface."
1527
+ },
1528
+ io: { input: DocsGetInput, output: DocsGetOutput },
1529
+ policy: { auth: "anonymous" },
1530
+ transport: { mcp: { toolName: "docs_get-v1_0_0" } }
1531
+ }), async ({ id }) => {
1532
+ const found = getDocById(id);
1533
+ if (!found)
1534
+ throw new Error(`DocBlock not found: ${id}`);
1535
+ return found;
914
1536
  });
1537
+ installOp3(registry, defineCommand3({
1538
+ meta: {
1539
+ key: "docs.resolveRoute",
1540
+ version: "1.0.0",
1541
+ stability: "beta",
1542
+ owners: DOC_OWNERS2,
1543
+ tags: DOC_TAGS3,
1544
+ description: "Resolve a docs route to the matching DocBlock.",
1545
+ goal: "Turn a route or URL path into a canonical doc id and markdown body.",
1546
+ context: "Read-only docs MCP surface."
1547
+ },
1548
+ io: { input: DocsResolveRouteInput, output: DocsResolveRouteOutput },
1549
+ policy: { auth: "anonymous" },
1550
+ transport: { mcp: { toolName: "docs_resolve_route-v1_0_0" } }
1551
+ }), async ({ route }) => {
1552
+ const found = getDocByRoute(routes, route);
1553
+ if (!found)
1554
+ throw new Error(`Doc route not found: ${route}`);
1555
+ return found;
1556
+ });
1557
+ installOp3(registry, defineCommand3({
1558
+ meta: {
1559
+ key: "docs.contract.lookup",
1560
+ version: "1.0.0",
1561
+ stability: "beta",
1562
+ owners: DOC_OWNERS2,
1563
+ tags: DOC_TAGS3,
1564
+ description: "Resolve a ContractSpec surface into a docs-ready reference payload.",
1565
+ goal: "Get canonical docs metadata, route, and optional schema for a spec key.",
1566
+ context: "Read-only docs MCP surface."
1567
+ },
1568
+ io: { input: ContractReferenceInput, output: ContractReferenceOutput },
1569
+ policy: { auth: "anonymous" },
1570
+ transport: { mcp: { toolName: "docs_contract_reference-v1_0_0" } }
1571
+ }), async (args) => resolveContractReference(args));
1572
+ installOp3(registry, defineCommand3({
1573
+ meta: {
1574
+ key: "docs.list.facets",
1575
+ version: "1.0.0",
1576
+ stability: "beta",
1577
+ owners: DOC_OWNERS2,
1578
+ tags: DOC_TAGS3,
1579
+ description: "List docs taxonomy facets such as tags, kinds, and visibilities.",
1580
+ goal: "Help agents browse the docs corpus before making targeted reads.",
1581
+ context: "Read-only docs MCP surface."
1582
+ },
1583
+ io: { input: DocsFacetsInput, output: DocsFacetsOutput },
1584
+ policy: { auth: "anonymous" },
1585
+ transport: { mcp: { toolName: "docs_list_facets-v1_0_0" } }
1586
+ }), async () => ({ facets: listDocFacets(routes) }));
915
1587
  return registry;
916
1588
  }
917
- function createDocsMcpHandler(path2 = "/api/mcp/docs") {
918
- const routes = defaultDocRegistry.list();
1589
+
1590
+ // src/application/mcp/docsMcp.ts
1591
+ import { defaultDocRegistry as defaultDocRegistry3 } from "@contractspec/lib.contracts-spec/docs";
1592
+ function createDocsMcpHandler(path2 = "/api/mcp/docs", options = {}) {
1593
+ const routes = defaultDocRegistry3.list();
919
1594
  return createMcpElysiaHandler({
920
1595
  logger: appLogger,
921
1596
  path: path2,
922
1597
  serverName: "contractspec-docs-mcp",
923
1598
  ops: buildDocOps(routes),
924
1599
  resources: buildDocResources(routes),
925
- prompts: buildDocPrompts(),
926
- presentations: routes.map(({ descriptor }) => descriptor)
1600
+ prompts: buildDocPrompts(routes),
1601
+ presentations: options.includePresentations ? routes.map(({ descriptor }) => descriptor) : undefined
927
1602
  });
928
1603
  }
929
1604
 
930
1605
  // src/application/mcp/internalMcp.ts
931
1606
  import {
932
- defineCommand as defineCommand3,
1607
+ defineCommand as defineCommand4,
933
1608
  definePrompt as definePrompt4,
934
1609
  defineResourceTemplate as defineResourceTemplate4,
935
1610
  installOp as installOp4,
936
- OperationSpecRegistry as OperationSpecRegistry4,
1611
+ OperationSpecRegistry as OperationSpecRegistry5,
937
1612
  PromptRegistry as PromptRegistry4,
938
1613
  ResourceRegistry as ResourceRegistry4
939
1614
  } from "@contractspec/lib.contracts-spec";
940
- import { defineSchemaModel as defineSchemaModel3, ScalarTypeEnum as ScalarTypeEnum3 } from "@contractspec/lib.schema";
1615
+ import { defineSchemaModel as defineSchemaModel4, ScalarTypeEnum as ScalarTypeEnum4 } from "@contractspec/lib.schema";
941
1616
  import {
942
1617
  getExample,
943
1618
  listExamples,
944
1619
  searchExamples
945
1620
  } from "@contractspec/module.examples";
946
- import z4 from "zod";
1621
+ import z5 from "zod";
947
1622
  var INTERNAL_TAGS = ["internal", "mcp"];
948
1623
  var INTERNAL_OWNERS = ["@contractspec"];
949
1624
  var ENDPOINTS = {
@@ -963,7 +1638,7 @@ function buildInternalResources() {
963
1638
  mimeType: "application/json",
964
1639
  tags: ["examples", ...INTERNAL_TAGS]
965
1640
  },
966
- input: z4.object({ q: z4.string().optional() }),
1641
+ input: z5.object({ q: z5.string().optional() }),
967
1642
  resolve: async ({ q }) => {
968
1643
  const items = q ? searchExamples(q) : [...listExamples()];
969
1644
  return {
@@ -981,7 +1656,7 @@ function buildInternalResources() {
981
1656
  mimeType: "application/json",
982
1657
  tags: ["examples", ...INTERNAL_TAGS]
983
1658
  },
984
- input: z4.object({ id: z4.string().min(1) }),
1659
+ input: z5.object({ id: z5.string().min(1) }),
985
1660
  resolve: async ({ id }) => {
986
1661
  const example = getExample(id);
987
1662
  if (!example) {
@@ -1006,7 +1681,7 @@ function buildInternalResources() {
1006
1681
  mimeType: "application/json",
1007
1682
  tags: INTERNAL_TAGS
1008
1683
  },
1009
- input: z4.object({}),
1684
+ input: z5.object({}),
1010
1685
  resolve: async () => ({
1011
1686
  uri: "internal://endpoints",
1012
1687
  mimeType: "application/json",
@@ -1021,7 +1696,7 @@ function buildInternalResources() {
1021
1696
  mimeType: "text/markdown",
1022
1697
  tags: INTERNAL_TAGS
1023
1698
  },
1024
- input: z4.object({}),
1699
+ input: z5.object({}),
1025
1700
  resolve: async () => ({
1026
1701
  uri: "internal://playbook",
1027
1702
  mimeType: "text/markdown",
@@ -1051,7 +1726,7 @@ function buildInternalPrompts() {
1051
1726
  stability: "beta"
1052
1727
  },
1053
1728
  args: [],
1054
- input: z4.object({}),
1729
+ input: z5.object({}),
1055
1730
  render: async () => [
1056
1731
  {
1057
1732
  type: "text",
@@ -1067,18 +1742,18 @@ function buildInternalPrompts() {
1067
1742
  return prompts;
1068
1743
  }
1069
1744
  function buildInternalOps() {
1070
- const registry = new OperationSpecRegistry4;
1071
- const InternalDescribeOutput = defineSchemaModel3({
1745
+ const registry = new OperationSpecRegistry5;
1746
+ const InternalDescribeOutput = defineSchemaModel4({
1072
1747
  name: "InternalDescribeOutput",
1073
1748
  fields: {
1074
1749
  endpoints: {
1075
- type: ScalarTypeEnum3.JSONObject(),
1750
+ type: ScalarTypeEnum4.JSONObject(),
1076
1751
  isOptional: false
1077
1752
  },
1078
- notes: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false }
1753
+ notes: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false }
1079
1754
  }
1080
1755
  });
1081
- const describeSpec = defineCommand3({
1756
+ const describeSpec = defineCommand4({
1082
1757
  meta: {
1083
1758
  key: "internal_describe",
1084
1759
  version: "1.0.0",
@@ -1090,7 +1765,7 @@ function buildInternalOps() {
1090
1765
  context: "Used by internal MCP surface; read-only."
1091
1766
  },
1092
1767
  io: {
1093
- input: defineSchemaModel3({
1768
+ input: defineSchemaModel4({
1094
1769
  name: "InternalDescribeInput",
1095
1770
  fields: {}
1096
1771
  }),
@@ -1123,7 +1798,7 @@ import {
1123
1798
  definePrompt as definePrompt5,
1124
1799
  defineResourceTemplate as defineResourceTemplate5,
1125
1800
  installOp as installOp5,
1126
- OperationSpecRegistry as OperationSpecRegistry5,
1801
+ OperationSpecRegistry as OperationSpecRegistry6,
1127
1802
  PromptRegistry as PromptRegistry5,
1128
1803
  ResourceRegistry as ResourceRegistry5
1129
1804
  } from "@contractspec/lib.contracts-spec";
@@ -1138,9 +1813,9 @@ import {
1138
1813
  computeModelRankings,
1139
1814
  normalizeBenchmarkResults
1140
1815
  } from "@contractspec/lib.provider-ranking/scoring";
1141
- import z5 from "zod";
1142
- var TransportFilterSchema = z5.enum(["rest", "mcp", "webhook", "sdk"]).optional();
1143
- var AuthFilterSchema = z5.enum([
1816
+ import z6 from "zod";
1817
+ var TransportFilterSchema = z6.enum(["rest", "mcp", "webhook", "sdk"]).optional();
1818
+ var AuthFilterSchema = z6.enum([
1144
1819
  "api-key",
1145
1820
  "oauth2",
1146
1821
  "bearer",
@@ -1168,7 +1843,7 @@ function buildRankingResources() {
1168
1843
  mimeType: "application/json",
1169
1844
  tags: RANKING_TAGS
1170
1845
  },
1171
- input: z5.object({
1846
+ input: z6.object({
1172
1847
  transport: TransportFilterSchema,
1173
1848
  authMethod: AuthFilterSchema
1174
1849
  }),
@@ -1194,8 +1869,8 @@ function buildRankingResources() {
1194
1869
  mimeType: "application/json",
1195
1870
  tags: RANKING_TAGS
1196
1871
  },
1197
- input: z5.object({
1198
- dimension: z5.string(),
1872
+ input: z6.object({
1873
+ dimension: z6.string(),
1199
1874
  transport: TransportFilterSchema,
1200
1875
  authMethod: AuthFilterSchema
1201
1876
  }),
@@ -1222,7 +1897,7 @@ function buildRankingResources() {
1222
1897
  mimeType: "application/json",
1223
1898
  tags: RANKING_TAGS
1224
1899
  },
1225
- input: z5.object({ modelId: z5.string() }),
1900
+ input: z6.object({ modelId: z6.string() }),
1226
1901
  resolve: async ({ modelId }) => {
1227
1902
  const store = getStore();
1228
1903
  const profile = await store.getModelProfile(modelId);
@@ -1263,7 +1938,7 @@ function buildRankingResources() {
1263
1938
  mimeType: "application/json",
1264
1939
  tags: RANKING_TAGS
1265
1940
  },
1266
- input: z5.object({}),
1941
+ input: z6.object({}),
1267
1942
  resolve: async () => {
1268
1943
  const store = getStore();
1269
1944
  const result = await store.listBenchmarkResults({ limit: 200 });
@@ -1293,13 +1968,13 @@ function buildRankingPrompts() {
1293
1968
  name: "task",
1294
1969
  description: "The task or use case to recommend a model for.",
1295
1970
  required: true,
1296
- schema: z5.string()
1971
+ schema: z6.string()
1297
1972
  },
1298
1973
  {
1299
1974
  name: "priority",
1300
1975
  description: "Priority dimension (coding, reasoning, cost, latency, etc.).",
1301
1976
  required: false,
1302
- schema: z5.string().optional()
1977
+ schema: z6.string().optional()
1303
1978
  },
1304
1979
  {
1305
1980
  name: "transport",
@@ -1314,9 +1989,9 @@ function buildRankingPrompts() {
1314
1989
  schema: AuthFilterSchema
1315
1990
  }
1316
1991
  ],
1317
- input: z5.object({
1318
- task: z5.string(),
1319
- priority: z5.string().optional(),
1992
+ input: z6.object({
1993
+ task: z6.string(),
1994
+ priority: z6.string().optional(),
1320
1995
  transport: TransportFilterSchema,
1321
1996
  authMethod: AuthFilterSchema
1322
1997
  }),
@@ -1344,7 +2019,7 @@ function buildRankingPrompts() {
1344
2019
  return prompts;
1345
2020
  }
1346
2021
  function buildRankingOps() {
1347
- const registry = new OperationSpecRegistry5;
2022
+ const registry = new OperationSpecRegistry6;
1348
2023
  const ingesterRegistry = createDefaultIngesterRegistry();
1349
2024
  installOp5(registry, BenchmarkIngestCommand, async (args) => {
1350
2025
  const store = getStore();