@feniix/bridgekit 0.9.4 → 0.9.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 (3) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +94 -53
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ 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.5] - Unreleased
8
+
9
+ ### Documentation
10
+
11
+ - README restructured to quickstart-first ordering: a copy-pasteable
12
+ three-file working example (`tools.ts`, `mcp-server.ts`,
13
+ `pi-extension.ts`) now lands above the fold; runtime requirements,
14
+ the import map, best practices, packaging, and the coding-agent
15
+ section all move below. Content preserved; no new entrypoints, no
16
+ API changes, no behavioral effects. Resolves
17
+ [#19](https://github.com/feniix/bridgekit/issues/19).
18
+ - `docs/packaging-invariants.md` adds a cross-reference under
19
+ `inv-mcp-sdk-major` pointing at `toInputSchema`'s JSDoc in
20
+ `src/adapters/mcp.ts` as the canonical record of the SDK-v1
21
+ `inputSchema.type` Zod-validation quirk that the `allOf` →
22
+ `type: "object"` synthesis addresses. Resolves
23
+ [#45](https://github.com/feniix/bridgekit/issues/45).
24
+
7
25
  ## [0.9.4] - 2026-05-27
8
26
 
9
27
  ### Fixed
package/README.md CHANGED
@@ -2,20 +2,74 @@
2
2
 
3
3
  BridgeKit provides reusable TypeBox-backed tool definitions and adapters for exposing one tool implementation through pi, MCP, and other hosts.
4
4
 
5
- ## Runtime support
5
+ ## Quickstart
6
6
 
7
- This package is ESM-only and supports Node.js 22.19.0 or newer. Published modules are import-passive and marked as side-effect free; tools are registered or servers are started only when the exported adapter functions are called.
7
+ ```ts
8
+ // src/tools.ts
9
+ import { Type } from "typebox";
10
+ import { definePortableTool } from "@feniix/bridgekit";
8
11
 
9
- ## For coding agents
12
+ export const echoTool = definePortableTool({
13
+ name: "echo",
14
+ title: "Echo",
15
+ description: "Echo text back to the caller.",
16
+ parameters: Type.Object({ text: Type.String() }),
17
+ execute(args, ctx) {
18
+ return {
19
+ text: args.text,
20
+ structuredContent: { text: args.text, host: ctx.host },
21
+ };
22
+ },
23
+ hostExtras: {
24
+ pi: { pendingMessage: "Echoing..." },
25
+ mcp: { annotations: { readOnlyHint: true } },
26
+ },
27
+ });
10
28
 
11
- Read these files in order:
29
+ export function createTools() {
30
+ return [echoTool];
31
+ }
32
+ ```
12
33
 
13
- 1. `README.md` — public API, contracts, and best practices.
14
- 2. `llms.txt` — compact agent-facing usage rules and anti-patterns.
15
- 3. `examples/README.md` — copyable layouts for shared tools, pi extensions, MCP stdio servers, and custom hosts.
16
- 4. Published declarations such as `dist/src/index.d.ts`, `dist/src/pi.d.ts`, and `dist/src/mcp.d.ts` — canonical installed-package type contracts. In a source checkout, the matching `src/` files contain the same implementation context.
34
+ ```ts
35
+ // src/mcp-server.ts
36
+ import { runMcpStdioServer } from "@feniix/bridgekit/mcp";
37
+ import { createTools } from "./tools.js";
17
38
 
18
- ## Entrypoints
39
+ await runMcpStdioServer({
40
+ name: "my-tools",
41
+ version: "0.1.0",
42
+ tools: createTools(),
43
+ });
44
+ ```
45
+
46
+ ```ts
47
+ // src/pi-extension.ts
48
+ import { registerPiTools } from "@feniix/bridgekit/pi";
49
+ import { createTools } from "./tools.js";
50
+
51
+ export default function extension(pi: Parameters<typeof registerPiTools>[0]) {
52
+ registerPiTools(pi, createTools());
53
+ }
54
+ ```
55
+
56
+ ## Install
57
+
58
+ ```bash
59
+ npm install @feniix/bridgekit typebox
60
+ ```
61
+
62
+ This package is ESM-only and supports Node.js 22.19.0 or newer. Published modules are import-passive and marked as side-effect free; tools are registered or servers are started only when the exported adapter functions are called.
63
+
64
+ ## Why
65
+
66
+ - Define a tool once; ship it to pi and MCP (and custom hosts) without per-host forks.
67
+ - Host-neutral tool files: no pi or MCP SDK imports in the tool definition itself.
68
+ - TypeBox schemas pass through to MCP `inputSchema` directly — no JSON Schema conversion step.
69
+ - Import-passive, `sideEffects: false`, three-entrypoint split (`.`, `./pi`, `./mcp`) so pi-only consumers do not pull the MCP SDK and vice versa.
70
+ - Conformance-tested public surface: a packed-install smoke test enforces the runtime export set, deep-import rejection, and type-level strictness against the installed declarations.
71
+
72
+ ## API reference
19
73
 
20
74
  ```ts
21
75
  import {
@@ -40,46 +94,7 @@ import { createMcpServer, runMcpStdioServer } from "@feniix/bridgekit/mcp";
40
94
 
41
95
  Do not deep-import from `dist/` or `src/` in consuming packages.
42
96
 
43
- ## Core tools
44
-
45
- Define tools once in host-neutral files:
46
-
47
- ```ts
48
- import { Type } from "typebox";
49
- import { definePortableTool } from "@feniix/bridgekit";
50
-
51
- export const echoTool = definePortableTool({
52
- name: "echo",
53
- title: "Echo",
54
- description: "Echo text.",
55
- parameters: Type.Object({ text: Type.String() }),
56
- execute(args, ctx) {
57
- return {
58
- text: args.text,
59
- structuredContent: { text: args.text, host: ctx.host },
60
- };
61
- },
62
- });
63
-
64
- export function createTools() {
65
- return [echoTool];
66
- }
67
- ```
68
-
69
- Tool definition best practices:
70
-
71
- - Keep tool files host-neutral: no pi imports, no MCP SDK imports.
72
- - Use TypeBox `Type.Object(...)` schemas so MCP can expose input schemas directly.
73
- - Return `text` for model-visible output and `structuredContent` for machine-readable data.
74
- - Use `isError: true` for expected/domain failures that should be represented as tool output.
75
- - Throw only for unexpected programmer, adapter, or runtime failures.
76
- - Respect `ctx.signal` in long-running tools.
77
- - Use `ctx.progress?.(...)` for incremental updates.
78
- - Keep modules import-passive; do not register tools or start servers at import time.
79
- - For stateful tools, export a `createTools()` factory instead of a module-level singleton so each host runtime gets isolated state.
80
- - TypeBox validation happens before `execute`; use a permissive schema plus domain validation if you need custom guidance for structurally invalid input.
81
-
82
- ## pi adapter
97
+ ### pi adapter
83
98
 
84
99
  ```ts
85
100
  import { registerPiTools } from "@feniix/bridgekit/pi";
@@ -141,7 +156,7 @@ new default `"return"` mode, prefer the result guards over inspecting a
141
156
  `"domain"`). The guards operate on a `PortableToolResult`; they are not
142
157
  designed to be called on the pi adapter's wire object.
143
158
 
144
- ### Per-host metadata via `hostExtras`
159
+ #### Per-host metadata via `hostExtras`
145
160
 
146
161
  `PortableTool.hostExtras` is an optional namespace for host-specific fields that should travel with the tool definition rather than a parallel sidecar map. The pi adapter reads `hostExtras.pi`; the MCP adapter reads `hostExtras.mcp`; each adapter ignores keys it does not recognise. Tools that omit `hostExtras` see no behavior change.
147
162
 
@@ -174,7 +189,7 @@ export const generateSummaryTool = definePortableTool({
174
189
 
175
190
  See `docs/rfc-host-extras.md` for the design rationale (which fields are in scope, why a top-level field beats a sidecar map, the closure rule for future additions). `PortableToolHostExtras` is module-augmentable for custom host adapters; declare your namespace via `declare module "@feniix/bridgekit"`.
176
191
 
177
- ## MCP adapter
192
+ ### MCP adapter
178
193
 
179
194
  ```ts
180
195
  import { realpathSync } from "node:fs";
@@ -217,7 +232,7 @@ Portable validation failures and portable `isError: true` results return `CallTo
217
232
 
218
233
  The two adapters now read in parallel: invalid args and portable `isError` results return `{ isError: true }` from both hosts by default, and the same result-guard helpers (`isValidationFailure`, `isDomainFailure`) narrow them on either side.
219
234
 
220
- ## Custom host typing
235
+ ### Custom host typing
221
236
 
222
237
  Default portable tools accept the built-in host union:
223
238
 
@@ -252,7 +267,24 @@ void hostValue;
252
267
 
253
268
  Use `PortableToolHost<CustomHost>` for values that may be either a built-in host or your extension. Use the `PortableTool`/`PortableToolContext` generic when a tool or adapter is custom-host-only.
254
269
 
255
- ## Package and release checklist
270
+ ## Best practices
271
+
272
+ Tool definition best practices:
273
+
274
+ - Keep tool files host-neutral: no pi imports, no MCP SDK imports.
275
+ - Use TypeBox `Type.Object(...)` schemas so MCP can expose input schemas directly.
276
+ - Return `text` for model-visible output and `structuredContent` for machine-readable data.
277
+ - Use `isError: true` for expected/domain failures that should be represented as tool output.
278
+ - Throw only for unexpected programmer, adapter, or runtime failures.
279
+ - Respect `ctx.signal` in long-running tools.
280
+ - Use `ctx.progress?.(...)` for incremental updates.
281
+ - Keep modules import-passive; do not register tools or start servers at import time.
282
+ - For stateful tools, export a `createTools()` factory instead of a module-level singleton so each host runtime gets isolated state.
283
+ - TypeBox validation happens before `execute`; use a permissive schema plus domain validation if you need custom guidance for structurally invalid input.
284
+
285
+ ## Packaging
286
+
287
+ Package and release checklist:
256
288
 
257
289
  - Publish compiled JavaScript plus generated `.d.ts` declarations for runtime entrypoints.
258
290
  - Keep `exports`, `main`, and `types` aligned with built files.
@@ -267,3 +299,12 @@ Use `PortableToolHost<CustomHost>` for values that may be either a built-in host
267
299
  - Treat `docs/releasing.md` as the future release handoff; this repository is not configured for automated publish yet.
268
300
 
269
301
  See `examples/README.md` for complete copyable examples.
302
+
303
+ ## For coding agents
304
+
305
+ Read these files in order:
306
+
307
+ 1. `README.md` — public API, contracts, and best practices.
308
+ 2. `llms.txt` — compact agent-facing usage rules and anti-patterns.
309
+ 3. `examples/README.md` — copyable layouts for shared tools, pi extensions, MCP stdio servers, and custom hosts.
310
+ 4. Published declarations such as `dist/src/index.d.ts`, `dist/src/pi.d.ts`, and `dist/src/mcp.d.ts` — canonical installed-package type contracts. In a source checkout, the matching `src/` files contain the same implementation context.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feniix/bridgekit",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "BridgeKit defines TypeBox-backed tools once and adapts them to pi, MCP, and other hosts.",
5
5
  "keywords": [
6
6
  "pi",