@feniix/bridgekit 0.9.2 → 0.9.4
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/CHANGELOG.md +26 -0
- package/dist/src/adapters/mcp.js +28 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,32 @@ All notable changes to `@feniix/bridgekit` are documented here. The format
|
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project
|
|
5
5
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.9.4] - 2026-05-27
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `isObjectSchema` now short-circuits on `$ref` before checking
|
|
12
|
+
`type === "object"`, closing a hole where a hybrid `{type: "object", $ref:
|
|
13
|
+
"..."}` schema would bypass the construction-time `$ref` rejection
|
|
14
|
+
introduced in 0.9.3. The hybrid shape is not produced by TypeBox today;
|
|
15
|
+
the fix guards against future schema producers (including hand-crafted
|
|
16
|
+
JSON Schema). Existing `Type.Object` (no `$ref`), `Type.Cyclic` (`$ref`
|
|
17
|
+
without `type`), and `Type.Intersect` (`allOf` at root, no `$ref`)
|
|
18
|
+
behavior is unchanged. Resolves [#51](https://github.com/feniix/bridgekit/issues/51).
|
|
19
|
+
|
|
20
|
+
## [0.9.3] - 2026-05-27
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- `createMcpServer` construction errors now recognize top-level `$ref` /
|
|
25
|
+
`Type.Cyclic` / `Type.Recursive` schemas as a distinct rejection class with
|
|
26
|
+
`$ref`-specific guidance (inline the referenced shape or split recursive
|
|
27
|
+
shapes into multiple non-recursive tools), instead of falling through to
|
|
28
|
+
the misdirecting "wrap with `Type.Object`" recipe. New stable error code
|
|
29
|
+
`BRIDGEKIT_MCP_REF_PARAMETERS` for consumer branching. Existing
|
|
30
|
+
`BRIDGEKIT_MCP_NON_OBJECT_PARAMETERS` and `BRIDGEKIT_MCP_DUPLICATE_TOOL_NAME`
|
|
31
|
+
codes are unchanged. Resolves [#44](https://github.com/feniix/bridgekit/issues/44).
|
|
32
|
+
|
|
7
33
|
## [0.9.2] - 2026-05-26
|
|
8
34
|
|
|
9
35
|
### Fixed
|
package/dist/src/adapters/mcp.js
CHANGED
|
@@ -24,6 +24,12 @@ function isObjectSchema(schema) {
|
|
|
24
24
|
if (typeof schema !== "object" || schema === null)
|
|
25
25
|
return false;
|
|
26
26
|
const candidate = schema;
|
|
27
|
+
// $ref takes structural precedence: a hybrid {type: "object", $ref: "..."}
|
|
28
|
+
// is not an inlined object schema — it's a reference, and
|
|
29
|
+
// assertObjectShapedParameters owns the rejection recipe. Return false so
|
|
30
|
+
// the $ref branch runs.
|
|
31
|
+
if (typeof candidate.$ref === "string")
|
|
32
|
+
return false;
|
|
27
33
|
if (candidate.type === "object")
|
|
28
34
|
return true;
|
|
29
35
|
if (Array.isArray(candidate.allOf) && candidate.allOf.length > 0) {
|
|
@@ -37,11 +43,19 @@ function isObjectSchema(schema) {
|
|
|
37
43
|
* branches and surface the first non-object branch by index — a bare `"allOf"`
|
|
38
44
|
* label is misleading because the rejection is owned by one specific branch,
|
|
39
45
|
* not the composition itself.
|
|
46
|
+
*
|
|
47
|
+
* The `$ref` check is first because `Type.Cyclic` produces
|
|
48
|
+
* `{ $defs: {...}, $ref: "..." }` at the root; the `$ref` is the load-bearing
|
|
49
|
+
* structural signal regardless of what else is set, and the recipe for that
|
|
50
|
+
* shape (inline or split) is different from the generic `Type.Object(...)`
|
|
51
|
+
* wrap recipe.
|
|
40
52
|
*/
|
|
41
53
|
function schemaTypeLabel(schema) {
|
|
42
54
|
if (typeof schema !== "object" || schema === null)
|
|
43
55
|
return "unknown";
|
|
44
56
|
const candidate = schema;
|
|
57
|
+
if (typeof candidate.$ref === "string")
|
|
58
|
+
return "$ref";
|
|
45
59
|
if (typeof candidate.type === "string")
|
|
46
60
|
return candidate.type;
|
|
47
61
|
if (Array.isArray(candidate.anyOf))
|
|
@@ -83,6 +97,7 @@ function toInputSchema(parameters) {
|
|
|
83
97
|
* recipe-shaped and may evolve; the code is part of the public contract).
|
|
84
98
|
*/
|
|
85
99
|
const ERROR_CODE_NON_OBJECT_PARAMETERS = "BRIDGEKIT_MCP_NON_OBJECT_PARAMETERS";
|
|
100
|
+
const ERROR_CODE_REF_PARAMETERS = "BRIDGEKIT_MCP_REF_PARAMETERS";
|
|
86
101
|
const ERROR_CODE_DUPLICATE_TOOL_NAME = "BRIDGEKIT_MCP_DUPLICATE_TOOL_NAME";
|
|
87
102
|
function throwWithCode(message, code) {
|
|
88
103
|
const error = new Error(message);
|
|
@@ -93,6 +108,19 @@ function assertObjectShapedParameters(tools) {
|
|
|
93
108
|
for (const tool of tools) {
|
|
94
109
|
if (!isObjectSchema(tool.parameters)) {
|
|
95
110
|
const typeLabel = schemaTypeLabel(tool.parameters);
|
|
111
|
+
// Top-level $ref (TypeBox's `Type.Cyclic` lowering, or a bare `Type.Ref`)
|
|
112
|
+
// gets its own branch and code. The generic "wrap with Type.Object(...)"
|
|
113
|
+
// recipe is the wrong fix for a recursive schema — the user wants to
|
|
114
|
+
// express recursion, not wrap a primitive — so a $ref shape needs
|
|
115
|
+
// $ref-specific guidance (inline or split) before the generic branch
|
|
116
|
+
// can run.
|
|
117
|
+
if (typeLabel === "$ref") {
|
|
118
|
+
throwWithCode(`createMcpServer: tool "${tool.name}" has a top-level $ref schema (type="$ref"). ` +
|
|
119
|
+
"Top-level $ref / Type.Cyclic schemas are not currently supported by the MCP wire layer " +
|
|
120
|
+
"because tools/list ships inputSchema by value and the SDK client does not resolve $refs. " +
|
|
121
|
+
"Inline the referenced schema (wrap the target shape directly with Type.Object(...)) " +
|
|
122
|
+
"or split recursive shapes into multiple non-recursive tools.", ERROR_CODE_REF_PARAMETERS);
|
|
123
|
+
}
|
|
96
124
|
let message = `createMcpServer: tool "${tool.name}" has a non-object parameters schema (type="${typeLabel}"). ` +
|
|
97
125
|
"MCP requires Type.Object(...) at the top level; use Type.Object({ value: Type.String() }) " +
|
|
98
126
|
"to wrap a single-field schema, or Type.Intersect([Type.Object(...), Type.Object(...)]) for " +
|