@contractspec/bundle.library 3.0.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +178 -166
- package/AGENTS.md +19 -12
- package/CHANGELOG.md +46 -0
- package/dist/application/context-storage/index.d.ts +18 -0
- package/dist/application/context-storage/index.js +29 -0
- package/dist/application/index.d.ts +1 -0
- package/dist/application/index.js +662 -2
- package/dist/application/mcp/cliMcp.js +12 -2
- package/dist/application/mcp/common.d.ts +11 -1
- package/dist/application/mcp/common.js +12 -2
- package/dist/application/mcp/contractsMcp.d.ts +51 -0
- package/dist/application/mcp/contractsMcp.js +531 -0
- package/dist/application/mcp/contractsMcpResources.d.ts +7 -0
- package/dist/application/mcp/contractsMcpResources.js +124 -0
- package/dist/application/mcp/contractsMcpTools.d.ts +9 -0
- package/dist/application/mcp/contractsMcpTools.js +200 -0
- package/dist/application/mcp/contractsMcpTypes.d.ts +50 -0
- package/dist/application/mcp/contractsMcpTypes.js +1 -0
- package/dist/application/mcp/docsMcp.js +12 -2
- package/dist/application/mcp/index.d.ts +2 -0
- package/dist/application/mcp/index.js +635 -2
- package/dist/application/mcp/internalMcp.js +12 -2
- package/dist/application/mcp/providerRankingMcp.d.ts +46 -0
- package/dist/application/mcp/providerRankingMcp.js +494 -0
- package/dist/node/application/context-storage/index.js +28 -0
- package/dist/node/application/index.js +662 -2
- package/dist/node/application/mcp/cliMcp.js +12 -2
- package/dist/node/application/mcp/common.js +12 -2
- package/dist/node/application/mcp/contractsMcp.js +530 -0
- package/dist/node/application/mcp/contractsMcpResources.js +123 -0
- package/dist/node/application/mcp/contractsMcpTools.js +199 -0
- package/dist/node/application/mcp/contractsMcpTypes.js +0 -0
- package/dist/node/application/mcp/docsMcp.js +12 -2
- package/dist/node/application/mcp/index.js +635 -2
- package/dist/node/application/mcp/internalMcp.js +12 -2
- package/dist/node/application/mcp/providerRankingMcp.js +493 -0
- package/package.json +111 -25
- package/src/application/context-storage/index.ts +58 -0
- package/src/application/index.ts +1 -0
- package/src/application/mcp/common.ts +28 -1
- package/src/application/mcp/contractsMcp.ts +34 -0
- package/src/application/mcp/contractsMcpResources.ts +142 -0
- package/src/application/mcp/contractsMcpTools.ts +246 -0
- package/src/application/mcp/contractsMcpTypes.ts +47 -0
- package/src/application/mcp/index.ts +2 -0
- package/src/application/mcp/providerRankingMcp.ts +380 -0
- package/src/components/docs/generated/docs-index._common.json +879 -1
- package/src/components/docs/generated/docs-index.manifest.json +5 -5
- package/src/components/docs/generated/docs-index.metrics.json +8 -0
- package/src/components/docs/generated/docs-index.platform-integrations.json +8 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// src/application/mcp/contractsMcpTools.ts
|
|
2
|
+
import {
|
|
3
|
+
defineCommand,
|
|
4
|
+
installOp,
|
|
5
|
+
OperationSpecRegistry
|
|
6
|
+
} from "@contractspec/lib.contracts-spec";
|
|
7
|
+
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
8
|
+
var OWNERS = ["@contractspec"];
|
|
9
|
+
var TAGS = ["contracts", "mcp"];
|
|
10
|
+
function buildContractsOps(services) {
|
|
11
|
+
const registry = new OperationSpecRegistry;
|
|
12
|
+
const ListInput = defineSchemaModel({
|
|
13
|
+
name: "ContractsListInput",
|
|
14
|
+
fields: {
|
|
15
|
+
pattern: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
16
|
+
type: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const ListOutput = defineSchemaModel({
|
|
20
|
+
name: "ContractsListOutput",
|
|
21
|
+
fields: {
|
|
22
|
+
specs: { type: ScalarTypeEnum.JSON(), isOptional: false },
|
|
23
|
+
total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false }
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
installOp(registry, defineCommand({
|
|
27
|
+
meta: {
|
|
28
|
+
key: "contracts.list",
|
|
29
|
+
version: "1.0.0",
|
|
30
|
+
stability: "beta",
|
|
31
|
+
owners: OWNERS,
|
|
32
|
+
tags: TAGS,
|
|
33
|
+
description: "List contract specs in the workspace.",
|
|
34
|
+
goal: "Discover available contracts by type, pattern, or owner.",
|
|
35
|
+
context: "Contracts MCP server."
|
|
36
|
+
},
|
|
37
|
+
io: { input: ListInput, output: ListOutput },
|
|
38
|
+
policy: { auth: "anonymous" }
|
|
39
|
+
}), async ({ pattern, type }) => {
|
|
40
|
+
const specs = await services.listSpecs({ pattern, type });
|
|
41
|
+
return { specs, total: specs.length };
|
|
42
|
+
});
|
|
43
|
+
const GetInput = defineSchemaModel({
|
|
44
|
+
name: "ContractsGetInput",
|
|
45
|
+
fields: {
|
|
46
|
+
path: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const GetOutput = defineSchemaModel({
|
|
50
|
+
name: "ContractsGetOutput",
|
|
51
|
+
fields: {
|
|
52
|
+
content: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
53
|
+
info: { type: ScalarTypeEnum.JSON(), isOptional: false }
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
installOp(registry, defineCommand({
|
|
57
|
+
meta: {
|
|
58
|
+
key: "contracts.get",
|
|
59
|
+
version: "1.0.0",
|
|
60
|
+
stability: "beta",
|
|
61
|
+
owners: OWNERS,
|
|
62
|
+
tags: TAGS,
|
|
63
|
+
description: "Read a single contract spec file.",
|
|
64
|
+
goal: "Fetch spec content and parsed metadata.",
|
|
65
|
+
context: "Contracts MCP server."
|
|
66
|
+
},
|
|
67
|
+
io: { input: GetInput, output: GetOutput },
|
|
68
|
+
policy: { auth: "anonymous" }
|
|
69
|
+
}), async ({ path }) => {
|
|
70
|
+
const result = await services.getSpec(path);
|
|
71
|
+
if (!result)
|
|
72
|
+
throw new Error(`Spec not found: ${path}`);
|
|
73
|
+
return result;
|
|
74
|
+
});
|
|
75
|
+
const ValidateInput = defineSchemaModel({
|
|
76
|
+
name: "ContractsValidateInput",
|
|
77
|
+
fields: {
|
|
78
|
+
path: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const ValidateOutput = defineSchemaModel({
|
|
82
|
+
name: "ContractsValidateOutput",
|
|
83
|
+
fields: {
|
|
84
|
+
valid: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
85
|
+
errors: { type: ScalarTypeEnum.JSON(), isOptional: false },
|
|
86
|
+
warnings: { type: ScalarTypeEnum.JSON(), isOptional: false }
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
installOp(registry, defineCommand({
|
|
90
|
+
meta: {
|
|
91
|
+
key: "contracts.validate",
|
|
92
|
+
version: "1.0.0",
|
|
93
|
+
stability: "beta",
|
|
94
|
+
owners: OWNERS,
|
|
95
|
+
tags: TAGS,
|
|
96
|
+
description: "Validate a contract spec structure.",
|
|
97
|
+
goal: "Check spec for structural or policy issues.",
|
|
98
|
+
context: "Contracts MCP server."
|
|
99
|
+
},
|
|
100
|
+
io: { input: ValidateInput, output: ValidateOutput },
|
|
101
|
+
policy: { auth: "anonymous" }
|
|
102
|
+
}), async ({ path }) => services.validateSpec(path));
|
|
103
|
+
const BuildInput = defineSchemaModel({
|
|
104
|
+
name: "ContractsBuildInput",
|
|
105
|
+
fields: {
|
|
106
|
+
path: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
107
|
+
dryRun: { type: ScalarTypeEnum.Boolean(), isOptional: true }
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
const BuildOutput = defineSchemaModel({
|
|
111
|
+
name: "ContractsBuildOutput",
|
|
112
|
+
fields: {
|
|
113
|
+
results: { type: ScalarTypeEnum.JSON(), isOptional: false }
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
installOp(registry, defineCommand({
|
|
117
|
+
meta: {
|
|
118
|
+
key: "contracts.build",
|
|
119
|
+
version: "1.0.0",
|
|
120
|
+
stability: "beta",
|
|
121
|
+
owners: OWNERS,
|
|
122
|
+
tags: TAGS,
|
|
123
|
+
description: "Generate implementation code from a contract spec.",
|
|
124
|
+
goal: "Produce handler, component, or test skeletons.",
|
|
125
|
+
context: "Contracts MCP server."
|
|
126
|
+
},
|
|
127
|
+
io: { input: BuildInput, output: BuildOutput },
|
|
128
|
+
policy: { auth: "user" }
|
|
129
|
+
}), async ({ path, dryRun }) => services.buildSpec(path, { dryRun }));
|
|
130
|
+
registerMutationTools(registry, services);
|
|
131
|
+
return registry;
|
|
132
|
+
}
|
|
133
|
+
function registerMutationTools(registry, services) {
|
|
134
|
+
const UpdateInput = defineSchemaModel({
|
|
135
|
+
name: "ContractsUpdateInput",
|
|
136
|
+
fields: {
|
|
137
|
+
path: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
138
|
+
content: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
139
|
+
fields: { type: ScalarTypeEnum.JSON(), isOptional: true }
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
const UpdateOutput = defineSchemaModel({
|
|
143
|
+
name: "ContractsUpdateOutput",
|
|
144
|
+
fields: {
|
|
145
|
+
updated: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
146
|
+
errors: { type: ScalarTypeEnum.JSON(), isOptional: false },
|
|
147
|
+
warnings: { type: ScalarTypeEnum.JSON(), isOptional: false }
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
installOp(registry, defineCommand({
|
|
151
|
+
meta: {
|
|
152
|
+
key: "contracts.update",
|
|
153
|
+
version: "1.0.0",
|
|
154
|
+
stability: "beta",
|
|
155
|
+
owners: OWNERS,
|
|
156
|
+
tags: TAGS,
|
|
157
|
+
description: "Update an existing contract spec.",
|
|
158
|
+
goal: "Modify spec content or individual fields with validation.",
|
|
159
|
+
context: "Contracts MCP server."
|
|
160
|
+
},
|
|
161
|
+
io: { input: UpdateInput, output: UpdateOutput },
|
|
162
|
+
policy: { auth: "user" }
|
|
163
|
+
}), async ({ path, content, fields }) => services.updateSpec(path, {
|
|
164
|
+
content,
|
|
165
|
+
fields: Array.isArray(fields) ? fields : undefined
|
|
166
|
+
}));
|
|
167
|
+
const DeleteInput = defineSchemaModel({
|
|
168
|
+
name: "ContractsDeleteInput",
|
|
169
|
+
fields: {
|
|
170
|
+
path: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
171
|
+
clean: { type: ScalarTypeEnum.Boolean(), isOptional: true }
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
const DeleteOutput = defineSchemaModel({
|
|
175
|
+
name: "ContractsDeleteOutput",
|
|
176
|
+
fields: {
|
|
177
|
+
deleted: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
178
|
+
cleanedFiles: { type: ScalarTypeEnum.JSON(), isOptional: false },
|
|
179
|
+
errors: { type: ScalarTypeEnum.JSON(), isOptional: false }
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
installOp(registry, defineCommand({
|
|
183
|
+
meta: {
|
|
184
|
+
key: "contracts.delete",
|
|
185
|
+
version: "1.0.0",
|
|
186
|
+
stability: "beta",
|
|
187
|
+
owners: OWNERS,
|
|
188
|
+
tags: TAGS,
|
|
189
|
+
description: "Delete a contract spec and optionally its artifacts.",
|
|
190
|
+
goal: "Remove a spec file and clean generated handlers/tests.",
|
|
191
|
+
context: "Contracts MCP server."
|
|
192
|
+
},
|
|
193
|
+
io: { input: DeleteInput, output: DeleteOutput },
|
|
194
|
+
policy: { auth: "user" }
|
|
195
|
+
}), async ({ path, clean }) => services.deleteSpec(path, { clean }));
|
|
196
|
+
}
|
|
197
|
+
export {
|
|
198
|
+
buildContractsOps
|
|
199
|
+
};
|
|
File without changes
|
|
@@ -72,9 +72,13 @@ function createMcpElysiaHandler({
|
|
|
72
72
|
ops,
|
|
73
73
|
resources,
|
|
74
74
|
prompts,
|
|
75
|
-
presentations
|
|
75
|
+
presentations,
|
|
76
|
+
validateAuth,
|
|
77
|
+
requiredAuthMethods
|
|
76
78
|
}) {
|
|
77
|
-
logger.info("Setting up MCP handler..."
|
|
79
|
+
logger.info("Setting up MCP handler...", {
|
|
80
|
+
requiredAuthMethods: requiredAuthMethods ?? []
|
|
81
|
+
});
|
|
78
82
|
const isStateful = process.env.CONTRACTSPEC_MCP_STATEFUL === "1";
|
|
79
83
|
const sessions = new Map;
|
|
80
84
|
async function handleStateless(request) {
|
|
@@ -145,6 +149,12 @@ function createMcpElysiaHandler({
|
|
|
145
149
|
}
|
|
146
150
|
return new Elysia({ name: `mcp-${serverName}` }).all(path, async ({ request }) => {
|
|
147
151
|
try {
|
|
152
|
+
if (validateAuth) {
|
|
153
|
+
const authResult = await validateAuth(request);
|
|
154
|
+
if (!authResult.valid) {
|
|
155
|
+
return createJsonRpcErrorResponse(401, -32002, "Authentication failed", authResult.reason);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
148
158
|
if (isStateful) {
|
|
149
159
|
return await handleStateful(request);
|
|
150
160
|
}
|