@creatornader/agent-bridge 0.7.0 → 0.7.3

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stdio-http-proxy.ts"],"sourcesContent":["import { pathToFileURL } from \"node:url\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { CallToolRequestSchema, ListToolsRequestSchema, type CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { validateLoopbackMcpUrl } from \"./client-lifecycle.js\";\nimport { packageVersion } from \"./package-metadata.js\";\n\nexport interface StdioHttpProxyRuntime {\n server: Server;\n close(): Promise<void>;\n}\n\nexport async function createStdioHttpProxyRuntime(endpoint: string): Promise<StdioHttpProxyRuntime> {\n const url = validateLoopbackMcpUrl(endpoint, \"--endpoint\");\n const upstreamTransport = new StreamableHTTPClientTransport(new URL(url));\n const upstream = new Client({ name: \"agent-bridge-stdio-http-proxy\", version: packageVersion() });\n await upstream.connect(upstreamTransport);\n const listed = await upstream.listTools();\n const server = new Server(\n { name: \"agent-bridge-stdio-http-proxy\", version: packageVersion() },\n { capabilities: { tools: {} } },\n );\n server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: listed.tools }));\n server.setRequestHandler(CallToolRequestSchema, async (request) =>\n upstream.callTool(request.params) as Promise<CallToolResult>);\n return {\n server,\n close: async () => {\n await Promise.allSettled([server.close(), upstream.close(), upstreamTransport.close()]);\n },\n };\n}\n\nexport async function startStdioHttpProxy(endpoint: string): Promise<void> {\n const runtime = await createStdioHttpProxyRuntime(endpoint);\n const transport = new StdioServerTransport();\n const shutdown = () => void Promise.allSettled([transport.close(), runtime.close()]).finally(() => process.exit(0));\n process.once(\"SIGINT\", shutdown);\n process.once(\"SIGTERM\", shutdown);\n await runtime.server.connect(transport);\n}\n\nfunction usage(): string {\n return \"Usage: agent-bridge-stdio-http-proxy --endpoint http://127.0.0.1:<port>/mcp\\n\";\n}\n\nif (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {\n const args = process.argv.slice(2);\n if (args.includes(\"--help\") || args.includes(\"-h\")) process.stdout.write(usage());\n else {\n const index = args.indexOf(\"--endpoint\");\n const endpoint = index < 0 ? undefined : args[index + 1];\n if (!endpoint || args.length !== 2) {\n process.stderr.write(`agent-bridge-stdio-http-proxy: ${usage()}`);\n process.exitCode = 1;\n } else {\n void startStdioHttpProxy(endpoint).catch((error) => {\n process.stderr.write(`agent-bridge-stdio-http-proxy: ${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n });\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,qBAAqB;AAC9B,SAAS,cAAc;AACvB,SAAS,qCAAqC;AAC9C,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC,SAAS,uBAAuB,8BAAmD;AASnF,eAAsB,4BAA4B,UAAkD;AAClG,QAAM,MAAM,uBAAuB,UAAU,YAAY;AACzD,QAAM,oBAAoB,IAAI,8BAA8B,IAAI,IAAI,GAAG,CAAC;AACxE,QAAM,WAAW,IAAI,OAAO,EAAE,MAAM,iCAAiC,SAAS,eAAe,EAAE,CAAC;AAChG,QAAM,SAAS,QAAQ,iBAAiB;AACxC,QAAM,SAAS,MAAM,SAAS,UAAU;AACxC,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,iCAAiC,SAAS,eAAe,EAAE;AAAA,IACnE,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EAChC;AACA,SAAO,kBAAkB,wBAAwB,aAAa,EAAE,OAAO,OAAO,MAAM,EAAE;AACtF,SAAO,kBAAkB,uBAAuB,OAAO,YACrD,SAAS,SAAS,QAAQ,MAAM,CAA4B;AAC9D,SAAO;AAAA,IACL;AAAA,IACA,OAAO,YAAY;AACjB,YAAM,QAAQ,WAAW,CAAC,OAAO,MAAM,GAAG,SAAS,MAAM,GAAG,kBAAkB,MAAM,CAAC,CAAC;AAAA,IACxF;AAAA,EACF;AACF;AAEA,eAAsB,oBAAoB,UAAiC;AACzE,QAAM,UAAU,MAAM,4BAA4B,QAAQ;AAC1D,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,WAAW,MAAM,KAAK,QAAQ,WAAW,CAAC,UAAU,MAAM,GAAG,QAAQ,MAAM,CAAC,CAAC,EAAE,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC;AAClH,UAAQ,KAAK,UAAU,QAAQ;AAC/B,UAAQ,KAAK,WAAW,QAAQ;AAChC,QAAM,QAAQ,OAAO,QAAQ,SAAS;AACxC;AAEA,SAAS,QAAgB;AACvB,SAAO;AACT;AAEA,IAAI,QAAQ,KAAK,CAAC,KAAK,YAAY,QAAQ,cAAc,QAAQ,KAAK,CAAC,CAAC,EAAE,MAAM;AAC9E,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,EAAG,SAAQ,OAAO,MAAM,MAAM,CAAC;AAAA,OAC3E;AACH,UAAM,QAAQ,KAAK,QAAQ,YAAY;AACvC,UAAM,WAAW,QAAQ,IAAI,SAAY,KAAK,QAAQ,CAAC;AACvD,QAAI,CAAC,YAAY,KAAK,WAAW,GAAG;AAClC,cAAQ,OAAO,MAAM,kCAAkC,MAAM,CAAC,EAAE;AAChE,cAAQ,WAAW;AAAA,IACrB,OAAO;AACL,WAAK,oBAAoB,QAAQ,EAAE,MAAM,CAAC,UAAU;AAClD,gBAAQ,OAAO,MAAM,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,CAAI;AACjH,gBAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
@@ -405,6 +405,17 @@ explicit loopback HTTP URL with a port and `/mcp` path, without user information
405
405
  query, fragment, bearer-token setting, or custom header. Backend credentials remain in
406
406
  their existing private file and do not enter the native HTTP registration.
407
407
 
408
+ The public loopback host is an optional client-side process boundary for native HTTP
409
+ targets. One host process owns one exact client identity, private backend file, stable
410
+ instance, and local edge store. It binds only an explicit loopback address and exposes
411
+ `/mcp/health` as socket-backed liveness. It creates an MCP server per transport session
412
+ and closes that server when the session closes or becomes idle. The host does not share
413
+ one credential across client identities, hold SQLite's write lease during gateway I/O,
414
+ or replace the durable edge outbox and inbox semantics. On macOS, its public launchd
415
+ installer avoids scheduler priority hints and requires a successful health request
416
+ before a client registration may depend on the endpoint. Optional wrappers belong above
417
+ this host boundary and cannot be required for client availability.
418
+
408
419
  Claude Desktop represents an endpoint-backed target as an exact stdio proxy launch.
409
420
  The proxy command must be an existing absolute executable. Its bounded arguments must
410
421
  contain the exact loopback endpoint and no credential-like flags or values. Claude
@@ -271,11 +271,19 @@ messages before choosing one authority. If schema or data recovery is required,
271
271
  restore the verified native DR bundle into a fresh target and switch authority once.
272
272
  Do not run the source and restored database as active authorities at the same time.
273
273
 
274
- The manual `gateway production proof` GitHub Actions workflow runs this acceptance
275
- proof against an existing HTTPS gateway. GitHub restricts it to `main`, and every job
274
+ Release tags deploy the exact tagged revision before npm publication. The release job
276
275
  uses the approval-protected `agent-bridge-production-proof` environment. Configure
277
- `PROOF_SENDER_TOKEN`, `PROOF_RECEIVER_TOKEN`, `PROOF_HOST_SALT`, and `FLY_API_TOKEN` as
278
- environment secrets. Use a release-specific proof workspace for every run. Owner
276
+ `AGENT_BRIDGE_FLY_APP` and `AGENT_BRIDGE_GATEWAY_ORIGIN` as environment variables, and
277
+ configure `PROOF_SENDER_TOKEN`, `PROOF_RECEIVER_TOKEN`, `PROOF_HOST_SALT`, and
278
+ `FLY_API_TOKEN` as environment secrets. Configure `RELEASE_VERIFY_TOKEN` separately
279
+ for the release job. It runs the read-only Fly preflight, deploys the image with the
280
+ checked-out revision, requires `/readyz`, and verifies the running package version and
281
+ revision. A failed deployment or identity check stops npm publication.
282
+
283
+ The manual `gateway production proof` GitHub Actions workflow runs its acceptance
284
+ proof against that deployed HTTPS gateway. GitHub restricts it to `main`, and every job
285
+ uses the same approval-protected environment. Use a release-specific proof workspace
286
+ for every run. Owner
279
287
  provisioning refuses a second agent with the same principal in one workspace, and a
280
288
  revoked credential cannot serve as a rotation predecessor. The sender and receiver
281
289
  credentials must bind the requested workspace to the dedicated `proof-sender` and
@@ -48,6 +48,24 @@ another client's identity or backend file into the entry.
48
48
 
49
49
  ## Move a managed client to a local MCP HTTP host
50
50
 
51
+ The public package owns the long-lived host. Do not depend on a wrapper from another
52
+ repository for normal MCP availability. On macOS, install the host for one exact client
53
+ identity and prove the listening socket before changing that client's registration:
54
+
55
+ ```bash
56
+ agent-bridge-loopback-host --install-launchd \
57
+ --service-name codex \
58
+ --config ~/.agent-bridge/clients/<codex-backend>.config \
59
+ --agent codex --instance <stable-key> --port 8794
60
+ curl --fail http://127.0.0.1:8794/mcp/health
61
+ ```
62
+
63
+ The install returns success only after it receives a healthy HTTP response from the
64
+ new listener. Each host receives one private backend file, identity, and stable
65
+ instance. Do not point several identities at one host process.
66
+ The generated plist omits `ProcessType` and `LowPriorityIO`; these macOS hints have
67
+ previously left a Node process running without a bound socket.
68
+
51
69
  Preview the update first. Add `--apply` only after the plan names the expected
52
70
  registration and metadata steps:
53
71
 
@@ -64,8 +82,8 @@ Claude Desktop needs a stdio proxy because its managed entry remains a process l
64
82
  agent-bridge clients update claude-desktop \
65
83
  --identity claude-desktop --instance <stable-key> \
66
84
  --mcp-url http://127.0.0.1:8791/mcp \
67
- --proxy-command /absolute/path/to/node \
68
- --proxy-args-json '["/absolute/path/to/stdio-http-proxy.js","--transport","stdio-http-proxy","--endpoint","http://127.0.0.1:8791/mcp"]'
85
+ --proxy-command "$(command -v agent-bridge-stdio-http-proxy)" \
86
+ --proxy-args-json '["--endpoint","http://127.0.0.1:8791/mcp"]'
69
87
  ```
70
88
 
71
89
  The endpoint must use plain HTTP on `127.0.0.1`, `localhost`, or `::1`, include an
@@ -74,6 +92,10 @@ rejected. The update does not delete or rewrite the private backend file. A fail
74
92
  update can resume from its operation UUID, and a committed update can be reversed with
75
93
  `clients rollback`.
76
94
 
95
+ An optional observer installed outside Agent Bridge must not be the only route to a
96
+ public host. If it becomes unhealthy, keep clients on the public host and inspect the
97
+ observer separately.
98
+
77
99
  ## The executable is missing
78
100
 
79
101
  Install the published package globally, then repeat the normal client installation:
package/llms.txt CHANGED
@@ -49,6 +49,9 @@ services can call the CLI or HTTPS API or embed the Node library without a host
49
49
  - agent-bridge clients adopt <runtime> --identity <principal> --instance <stable-key> --backend-config <absolute path> [--apply]
50
50
  - agent-bridge clients repair <runtime> --identity <principal> --instance <stable-key> [--apply] [--resume <uuid>] [--recover-lock]
51
51
  - agent-bridge clients update <runtime> --identity <principal> --instance <stable-key> [--command <command> | --mcp-url <loopback-url>] [--proxy-command <command> --proxy-args-json <json-array>] [--apply] [--resume <uuid>] [--recover-lock]
52
+ - agent-bridge-loopback-host [--host 127.0.0.1] [--port <port>] [--path /mcp]: public long-lived MCP host for one client identity.
53
+ - agent-bridge-loopback-host --install-launchd --service-name <name> --config <private-backend> --agent <identity> --instance <stable-key> --port <port>: macOS lifecycle install. Prove /mcp/health before routing a client to it.
54
+ - agent-bridge-stdio-http-proxy --endpoint http://127.0.0.1:<port>/mcp: public stdio bridge for a Claude Desktop loopback target.
52
55
  - agent-bridge clients uninstall <runtime> --identity <principal> --instance <stable-key> [--apply] [--resume <uuid>] [--recover-lock]
53
56
  - agent-bridge clients rollback <update-operation-id> --identity <principal> [--apply] [--recover-lock]
54
57
  - agent-bridge clients migrate stage <runtime> --identity <principal> --instance <stable-key> --enrollment-file <private-path> [--apply] [--recover-lock]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@creatornader/agent-bridge",
3
- "version": "0.7.0",
3
+ "version": "0.7.3",
4
4
  "description": "Let AI agents message each other and hand off work across tools, sessions, and machines.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -20,6 +20,8 @@
20
20
  "bin": {
21
21
  "agent-bridge": "bin/agent-bridge",
22
22
  "agent-bridge-mcp": "dist/index.js",
23
+ "agent-bridge-loopback-host": "dist/loopback-host.js",
24
+ "agent-bridge-stdio-http-proxy": "dist/stdio-http-proxy.js",
23
25
  "agent-bridge-gateway": "dist/gateway-main.js"
24
26
  },
25
27
  "files": [