@nekzus/liop 1.2.0-alpha.10 → 1.2.0-alpha.9

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 (48) hide show
  1. package/README.md +2 -11
  2. package/dist/bin/agent.js +51 -222
  3. package/dist/bridge/index.js +6 -7
  4. package/dist/bridge/stream.js +11 -11
  5. package/dist/client/index.js +35 -46
  6. package/dist/crypto/verifier.js +19 -7
  7. package/dist/gateway/hybrid.d.ts +1 -3
  8. package/dist/gateway/hybrid.js +13 -38
  9. package/dist/gateway/router.d.ts +9 -25
  10. package/dist/gateway/router.js +133 -484
  11. package/dist/index.d.ts +0 -2
  12. package/dist/index.js +0 -2
  13. package/dist/mesh/node.d.ts +0 -16
  14. package/dist/mesh/node.js +113 -394
  15. package/dist/rpc/proto.js +1 -2
  16. package/dist/rpc/server.d.ts +1 -1
  17. package/dist/rpc/server.js +3 -4
  18. package/dist/rpc/tls.js +2 -3
  19. package/dist/sandbox/wasi.d.ts +1 -1
  20. package/dist/sandbox/wasi.js +2 -13
  21. package/dist/security/guardian.js +2 -3
  22. package/dist/security/zk.d.ts +3 -2
  23. package/dist/security/zk.js +9 -22
  24. package/dist/server/index.d.ts +3 -47
  25. package/dist/server/index.js +41 -350
  26. package/dist/server/pii.d.ts +0 -12
  27. package/dist/server/pii.js +0 -90
  28. package/dist/types.d.ts +0 -16
  29. package/dist/workers/logic-execution.d.ts +1 -1
  30. package/dist/workers/logic-execution.js +20 -38
  31. package/dist/workers/zk-verifier.js +33 -37
  32. package/package.json +2 -14
  33. package/dist/crypto/logic-image-id.d.ts +0 -3
  34. package/dist/crypto/logic-image-id.js +0 -27
  35. package/dist/economy/estimator.d.ts +0 -53
  36. package/dist/economy/estimator.js +0 -69
  37. package/dist/economy/index.d.ts +0 -5
  38. package/dist/economy/index.js +0 -3
  39. package/dist/economy/otel.d.ts +0 -38
  40. package/dist/economy/otel.js +0 -100
  41. package/dist/economy/telemetry.d.ts +0 -77
  42. package/dist/economy/telemetry.js +0 -224
  43. package/dist/prompts/adapters.d.ts +0 -16
  44. package/dist/prompts/adapters.js +0 -55
  45. package/dist/utils/logger.d.ts +0 -21
  46. package/dist/utils/logger.js +0 -70
  47. package/dist/utils/mcpCompact.d.ts +0 -11
  48. package/dist/utils/mcpCompact.js +0 -29
package/README.md CHANGED
@@ -36,10 +36,9 @@ This fundamentally solves the data privacy, bandwidth, and latency challenges of
36
36
  | **MCP Drop-in Replacement** | `LiopServer` mirrors the Anthropic MCP `Server` API — tools, resources, and prompts with `Zod` schemas. |
37
37
  | **Guardian AST** | Zero-time heuristic inspection blocks sandbox escapes (`require`, `fs`, `eval`, `fetch`, prototype pollution). |
38
38
  | **WASI Sandbox** | JavaScript payloads execute inside V8 isolates with CPU fuel limits and no access to Node.js globals. |
39
- | **PII Shield** | Multi-layer egress filter with Regional Presets (Email, Credit Card with Luhn, IP, Phone, SSN, IBAN Mod-97, Passport MRZ) and custom keys. |
39
+ | **PII Shield** | Multi-layer egress filter with NIST/OWASP patterns (Email, Credit Card with Luhn, IP, Phone) and configurable forbidden keys. |
40
40
  | **ZK-Receipts** | Cryptographic proof (SHA-256 + SHA-512 seal) that the returned result was computed honestly from the injected logic. |
41
41
  | **Worker Pool** | Heavy computation (crypto, sandboxing) dispatched to OS threads via `piscina`, unblocking the V8 event loop. |
42
- | **Cross-AI Adapters**| Zero-Shot system prompts automatically adapt instructions for Claude (XML-heavy) vs OpenAI/Gemini (JSON-schema). |
43
42
  | **MCP Bridge** | `LiopMcpBridge` adapts any `LiopServer` to the JSON-RPC 2.0 / stdio protocol used by Claude Desktop, Cursor, etc. |
44
43
  | **Post-Quantum Ready** | ML-KEM-768 (Kyber) handshake + AES-256-GCM symmetric encryption for transport-layer security. |
45
44
  | **P2P Mesh** | Kademlia DHT discovery via `libp2p` with TCP + WebSocket + Yamux multiplexing and Noise encryption. |
@@ -264,21 +263,13 @@ await bridge.connect();
264
263
  Built-in patterns with multi-layer verification:
265
264
 
266
265
  ```typescript
267
- import { PII_PATTERNS, PII_PRESETS } from "@nekzus/liop/server";
266
+ import { PII_PATTERNS } from "@nekzus/liop/server";
268
267
 
269
268
  // Available patterns:
270
269
  PII_PATTERNS.EMAIL // RFC 5322 compliant, excludes @example.com/@test.com
271
270
  PII_PATTERNS.CREDIT_CARD // Visa/MC/Amex + Luhn algorithm validation
272
271
  PII_PATTERNS.IP_ADDRESS // IPv4 with octet range validation (excludes localhost)
273
272
  PII_PATTERNS.PHONE // International phone formats with digit-length validation
274
- PII_PATTERNS.SSN // USA Social Security Number rules (blocks 000 segments)
275
- PII_PATTERNS.IBAN // ISO 7064 Modulo 97-10 algorithm precision via BigInt
276
- PII_PATTERNS.PASSPORT_MRZ // Strict 44-character TD3 international passport MRZ string
277
-
278
- // Pre-built Regional Presets ready to drop-in via LiopServer(options):
279
- PII_PRESETS.GLOBAL_STRICT
280
- PII_PRESETS.US_COMPLIANT
281
- PII_PRESETS.EU_GDPR
282
273
  ```
283
274
 
284
275
  ### Forbidden Keys
package/dist/bin/agent.js CHANGED
@@ -2,105 +2,9 @@
2
2
  import * as fs from "node:fs";
3
3
  import * as os from "node:os";
4
4
  import * as path from "node:path";
5
- import { multiaddr } from "@multiformats/multiaddr";
6
5
  import { LiopMcpRouter } from "../gateway/router.js";
7
6
  import { MeshNode } from "../mesh/index.js";
8
7
  import { LiopServer } from "../server/index.js";
9
- import { log } from "../utils/logger.js";
10
- /**
11
- * Resolves a full libp2p multiaddr (with PeerID) from a LIOP node's
12
- * HTTP health endpoint. This enables zero-config bootstrap — users
13
- * only need to provide a URL, not a cryptographic PeerID.
14
- *
15
- * @param url - HTTP URL of a LIOP node's health endpoint (e.g. "http://host:3000")
16
- * @returns Full multiaddr string with PeerID, or null if resolution fails
17
- */
18
- async function resolveBootstrapFromUrl(url) {
19
- try {
20
- const healthUrl = url.endsWith("/health") ? url : `${url}/health`;
21
- const response = await fetch(healthUrl, {
22
- headers: { Accept: "application/json" },
23
- signal: AbortSignal.timeout(10000), // Increased to 10s
24
- });
25
- if (!response.ok)
26
- return null;
27
- const data = await response.json();
28
- if (!data.mesh?.multiaddrs?.length || !data.mesh?.peerId)
29
- return null;
30
- // Find TCP multiaddr (prefer non-websocket for stability)
31
- const tcpAddr = data.mesh.multiaddrs.find((a) => a.includes("/tcp/") &&
32
- !a.includes("/ws") &&
33
- !a.includes("/ip4/127.0.0.1/"));
34
- if (!tcpAddr)
35
- return null;
36
- // Rewrite internal Docker IP using industrial mapper if available
37
- let resolved = industrialAddressMapper(tcpAddr);
38
- if (!resolved || resolved === tcpAddr) {
39
- const urlHost = new URL(url).hostname;
40
- resolved = tcpAddr.replace(/\/ip4\/[^/]+/, `/ip4/${urlHost}`);
41
- }
42
- if (!resolved)
43
- return null;
44
- resolved += resolved.includes("/p2p/") ? "" : `/p2p/${data.mesh.peerId}`;
45
- return resolved;
46
- }
47
- catch {
48
- return null;
49
- }
50
- }
51
- /**
52
- * Normalizes a bootstrap multiaddr string.
53
- * If the address contains a Docker bridge IP (172.16-31.x.x) or Loopback (127.0.0.1),
54
- * rewrites it to the host accessible via LIOP_NEXUS_URL (e.g. WSL2 IP).
55
- * This is critical when WSL2 mirror-mode networking is broken.
56
- */
57
- function normalizeBootstrap(addr) {
58
- const trimmed = addr.trim();
59
- // Remap Docker bridge IPs and ANY external physical IPs to 127.0.0.1
60
- // because Test-NetConnection confirmed 127.0.0.1 is the only reliable path to Docker ports.
61
- const dockerIpRegex = /\/ip4\/172\.(1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3}/;
62
- const loopbackRegex = /\/ip4\/127\.0\.0\.1/;
63
- const physicalIpRegex = /\/ip4\/192\.168\.[0-9]{1,3}\.[0-9]{1,3}/;
64
- if (dockerIpRegex.test(trimmed) ||
65
- loopbackRegex.test(trimmed) ||
66
- physicalIpRegex.test(trimmed)) {
67
- const targetIp = "127.0.0.1";
68
- const normalized = trimmed
69
- .replace(dockerIpRegex, `/ip4/${targetIp}`)
70
- .replace(loopbackRegex, `/ip4/${targetIp}`)
71
- .replace(physicalIpRegex, `/ip4/${targetIp}`);
72
- if (normalized !== trimmed) {
73
- log.info(`[LIOP-Agent] 🔄 Local Routing Hack → Forced 127.0.0.1: ${normalized}`);
74
- }
75
- return normalized;
76
- }
77
- return trimmed;
78
- }
79
- /**
80
- * industrialAddressMapper
81
- *
82
- * Mapea IPs internas de Docker a puertos industriales mapeados en el Host.
83
- * Nexus (172.20.0.10) -> 13001
84
- * Vault (172.20.0.11) -> 13003
85
- * Bank (172.20.0.12) -> 13004
86
- * Oracle(172.20.0.13) -> 13005
87
- */
88
- function industrialAddressMapper(addr) {
89
- if (addr.includes("/ip4/172.20.0.10"))
90
- return addr.replace(/\/ip4\/172\.20\.0\.10\/tcp\/[0-9]+/, "/ip4/127.0.0.1/tcp/13001");
91
- if (addr.includes("/ip4/172.20.0.11"))
92
- return addr.replace(/\/ip4\/172\.20\.0\.11\/tcp\/[0-9]+/, "/ip4/127.0.0.1/tcp/13003");
93
- if (addr.includes("/ip4/172.20.0.12"))
94
- return addr.replace(/\/ip4\/172\.20\.0\.12\/tcp\/[0-9]+/, "/ip4/127.0.0.1/tcp/13004");
95
- if (addr.includes("/ip4/172.20.0.13"))
96
- return addr.replace(/\/ip4\/172\.20\.0\.13\/tcp\/[0-9]+/, "/ip4/127.0.0.1/tcp/13005");
97
- // Drop container-internal loopbacks to prevent the Host Agent from dialing itself or conflicting ports
98
- if (addr.includes("/ip4/127.0.0.1/tcp/4000") ||
99
- addr.includes("/ip4/127.0.0.1/tcp/3000")) {
100
- return null;
101
- }
102
- return addr;
103
- }
104
8
  /**
105
9
  * LIOP Agent (Zero-Config CLI)
106
10
  *
@@ -111,8 +15,6 @@ function industrialAddressMapper(addr) {
111
15
  * No hardcoded tools, PeerIDs, or port mappings.
112
16
  */
113
17
  async function main() {
114
- const buildTime = new Date().toISOString();
115
- log.info(`[LIOP-Agent] 🚀 Version 1.2.0-alpha.9 | Build: ${buildTime}`);
116
18
  const liopDir = path.join(os.homedir(), ".liop");
117
19
  const identityPath = path.join(liopDir, "identity.json");
118
20
  if (!fs.existsSync(liopDir)) {
@@ -125,41 +27,31 @@ async function main() {
125
27
  if (args.length > 0) {
126
28
  bootstrapNodes = args.filter((a) => a.startsWith("/"));
127
29
  }
128
- // Priority 1: Physical Beacons (Industrial Pattern) - DETERMINISTIC & INSTANT
30
+ // Environment variable
31
+ if (bootstrapNodes.length === 0 && process.env.LIOP_BOOTSTRAP) {
32
+ bootstrapNodes.push(process.env.LIOP_BOOTSTRAP.trim());
33
+ }
34
+ // Convenience: Try to read nexus.multiaddr from multiple locations
129
35
  if (bootstrapNodes.length === 0) {
130
- const searchDirs = [];
131
- // Priority 1.1: Explicit file from environment variable
132
- if (process.env.LIOP_BOOTSTRAP_FILE) {
133
- const filePath = path.resolve(process.env.LIOP_BOOTSTRAP_FILE);
134
- if (fs.existsSync(filePath)) {
135
- const addr = fs.readFileSync(filePath, "utf8").trim();
136
- if (addr)
137
- bootstrapNodes.push(normalizeBootstrap(addr));
138
- }
139
- }
140
- // Priority 1.2: Traditional locations (Scan for all *.multiaddr)
141
- searchDirs.push(process.cwd(), path.join(process.cwd(), "tests/infra/nexus-data"), liopDir, path.join(path
142
- .dirname(new URL(import.meta.url).pathname)
143
- .replace(/^\/([A-Z]:)/, "$1"), "../../tests/infra/nexus-data"));
144
- for (const dir of searchDirs) {
36
+ const searchPaths = [
37
+ path.join(process.cwd(), "nexus.multiaddr"),
38
+ path.join(liopDir, "nexus.multiaddr"),
39
+ // Try relative to the agent binary (dist/bin/agent.js -> root/nexus.multiaddr)
40
+ path.join(path.dirname(new URL(import.meta.url).pathname), "../../nexus.multiaddr"),
41
+ // Windows path fix (remove leading slash if present)
42
+ path.join(path
43
+ .dirname(new URL(import.meta.url).pathname)
44
+ .replace(/^\/([A-Z]:)/, "$1"), "../../nexus.multiaddr"),
45
+ ];
46
+ for (const nexusPath of searchPaths) {
145
47
  try {
146
- if (fs.existsSync(dir)) {
147
- const files = fs.readdirSync(dir);
148
- const multiaddrFiles = files.filter((f) => f.endsWith(".multiaddr"));
149
- for (const file of multiaddrFiles) {
150
- const filePath = path.join(dir, file);
151
- const addr = fs.readFileSync(filePath, "utf8").trim();
152
- if (addr) {
153
- const normalized = normalizeBootstrap(addr);
154
- if (!bootstrapNodes.includes(normalized)) {
155
- bootstrapNodes.push(normalized);
156
- log.info(`[LIOP-Agent] ✅ Loaded beacon: ${file} from ${dir}`);
157
- }
158
- }
159
- }
160
- // If we found any beacons in this directory, we consider discovery successful for this layer
161
- if (bootstrapNodes.length > 0)
48
+ if (fs.existsSync(nexusPath)) {
49
+ const addr = fs.readFileSync(nexusPath, "utf8").trim();
50
+ if (addr && !bootstrapNodes.includes(addr)) {
51
+ bootstrapNodes.push(addr);
52
+ console.error(`[LIOP-Agent] Found bootstrap at: ${nexusPath}`);
162
53
  break;
54
+ }
163
55
  }
164
56
  }
165
57
  catch (_e) {
@@ -167,141 +59,78 @@ async function main() {
167
59
  }
168
60
  }
169
61
  }
170
- // Priority 2: Auto-Discovery via NEXUS URL (Aggressive Parallel Discovery)
171
- if (process.env.LIOP_NEXUS_URL) {
172
- const nexusUrl = process.env.LIOP_NEXUS_URL;
173
- log.info(`[LIOP-Agent] 🌐 Running parallel discovery from: ${nexusUrl} (Sources Found: ${bootstrapNodes.length})`);
174
- const resolved = await resolveBootstrapFromUrl(nexusUrl);
175
- if (resolved) {
176
- const normalized = normalizeBootstrap(resolved);
177
- if (!bootstrapNodes.includes(normalized)) {
178
- bootstrapNodes.push(normalized);
179
- log.info(`[LIOP-Agent] ✅ Added bootstrap from URL discovery: ${normalized}`);
180
- }
181
- }
182
- }
183
- // Priority 3: Environment variable (direct multiaddr)
184
- if (bootstrapNodes.length === 0 && process.env.LIOP_BOOTSTRAP) {
185
- bootstrapNodes.push(process.env.LIOP_BOOTSTRAP.trim());
186
- }
187
- // Final fallback: local Nexus bootstrap for demo environments.
188
- // Avoid injecting stale static peer IDs when discovery already found valid peers.
189
- if (bootstrapNodes.length === 0) {
190
- bootstrapNodes.push("/ip4/127.0.0.1/tcp/13001/p2p/12D3KooWD8FUFdnLQzzLFNdicsaTknM5cpD7os9sK9NWVSVABJMD");
191
- }
192
- // Sanitize/validate all candidate multiaddrs so malformed PeerIDs don't crash startup.
193
- bootstrapNodes = bootstrapNodes.filter((addr) => {
194
- try {
195
- multiaddr(addr);
196
- return true;
197
- }
198
- catch {
199
- log.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${addr}`);
200
- return false;
201
- }
202
- });
203
62
  // If no bootstrap nodes found, the agent operates in standalone mode.
204
63
  // It will only serve local tools until peers are discovered.
205
64
  if (bootstrapNodes.length === 0) {
206
- log.info("[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode.");
207
- log.info("[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file.");
65
+ console.error("[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode.");
66
+ console.error("[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file.");
208
67
  }
209
68
  // Initialize local server node (lightweight, no tools registered locally)
210
69
  const liopServer = new LiopServer({
211
70
  name: "@nekzus/liop-agent",
212
71
  version: "1.0.0",
213
72
  });
214
- // Enable Zero-Shot Autonomy (Industrial Prompt Injection)
215
- liopServer.enableZeroShotAutonomy();
216
73
  // 2. Mesh Node Configuration
217
74
  const meshNode = new MeshNode({
218
75
  identityPath: identityPath,
219
76
  bootstrapNodes: bootstrapNodes,
220
- addressMapper: industrialAddressMapper,
221
77
  });
222
78
  // Start P2P Mesh
223
79
  await meshNode.start();
224
80
  // 3. Initialize the Dynamic Router
225
81
  // No hardcoded tools — all discovery happens via liop:manifest protocol
226
82
  const router = new LiopMcpRouter(liopServer, meshNode);
227
- // Proactive Notification to Claude Desktop when tools/resources are discovered dynamically
83
+ // Proactive Notification to Claude Desktop when tools are discovered dynamically
228
84
  router.onToolsChanged = () => {
229
85
  process.stdout.write(`{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}\n`);
230
- process.stdout.write(`{"jsonrpc":"2.0","method":"notifications/resources/list_changed"}\n`);
231
86
  };
232
- // Initial warming period (2s) then Adaptive Background Discovery
233
- // Polls DHT for new nodes and triggers onToolsChanged when topology shifts.
234
- // Uses exponential backoff to reduce polling load on stable meshes.
87
+ // Initial warming period (2s) then Periodic Discovery Worker (every 10 seconds)
88
+ // This silently polls the DHT for new nodes and triggers onToolsChanged if the topology shifts.
235
89
  setTimeout(() => {
236
90
  // biome-ignore lint/suspicious/noExplicitAny: access internal for telemetry
237
91
  const rtSize = meshNode.getRoutingTableSize?.() || 0;
238
- log.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${rtSize}`);
92
+ console.error(`[LIOP-Agent] Warm-up complete. Routing Table size: ${rtSize}`);
239
93
  router.refreshManifestCache(true).catch(() => { });
240
94
  }, 2000);
241
- const POLL_BASE_MS = 10_000;
242
- const POLL_MAX_MS = 120_000;
243
- let pollIntervalMs = POLL_BASE_MS;
244
- const scheduleAdaptivePoll = () => {
245
- setTimeout(async () => {
246
- const prevSize = router.getCacheSize();
247
- await router.refreshManifestCache(true).catch(() => { });
248
- const newSize = router.getCacheSize();
249
- if (newSize !== prevSize) {
250
- // Topology changed — reset to aggressive polling
251
- pollIntervalMs = POLL_BASE_MS;
252
- log.info(`[LIOP-Agent] Topology change detected (${prevSize} → ${newSize}). Resetting poll to ${POLL_BASE_MS / 1000}s.`);
253
- }
254
- else {
255
- // Stable — relax polling interval (factor 1.5)
256
- pollIntervalMs = Math.min(Math.round(pollIntervalMs * 1.5), POLL_MAX_MS);
257
- }
258
- scheduleAdaptivePoll();
259
- }, pollIntervalMs);
260
- };
261
- scheduleAdaptivePoll();
262
- // 4. STDIO Transport — Buffered Line Reader
263
- // Uses readline to guarantee complete JSON-RPC messages before parsing.
264
- // Raw stdin.on("data") can fragment large payloads across multiple chunks.
265
- const readline = await import("node:readline");
266
- const rl = readline.createInterface({
267
- input: process.stdin,
268
- terminal: false,
269
- });
95
+ setInterval(() => {
96
+ router.refreshManifestCache(true).catch(() => { });
97
+ }, 15000);
98
+ // 4. STDIO Transport implementation
270
99
  process.stdout.on("error", (err) => {
271
100
  if (err.code === "EPIPE") {
272
101
  process.exit(0); // Graceful exit when Claude Desktop disconnects
273
102
  }
274
103
  });
275
- rl.on("line", async (line) => {
276
- const trimmed = line.trim();
277
- if (!trimmed)
104
+ process.stdin.on("data", async (data) => {
105
+ const payload = data.toString().trim();
106
+ if (!payload)
278
107
  return;
279
- try {
280
- const request = JSON.parse(trimmed);
281
- if (request.method) {
282
- const response = await router.dispatch(request);
283
- if (response) {
284
- process.stdout.write(`${JSON.stringify(response)}\n`);
108
+ const messages = payload.split("\n");
109
+ for (const msg of messages) {
110
+ try {
111
+ const request = JSON.parse(msg);
112
+ if (request.method) {
113
+ const response = await router.dispatch(request);
114
+ if (response) {
115
+ process.stdout.write(`${JSON.stringify(response)}\n`);
116
+ }
285
117
  }
286
118
  }
119
+ catch (_err) {
120
+ // Silent catch for binary noise
121
+ }
287
122
  }
288
- catch (_err) {
289
- // Silent catch for binary noise or malformed lines
290
- }
291
- });
292
- rl.on("close", () => {
293
- process.exit(0);
294
123
  });
295
124
  // Status directed only to stderr
296
- log.info(`[LIOP-Agent] Guarding Claude Desktop via STDIO.`);
297
- log.info(`[LIOP-Agent] P2P Mesh: Joined (${bootstrapNodes.length} bootstraps)`);
298
- log.info("[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0");
125
+ console.error(`[LIOP-Agent] Guarding Claude Desktop via STDIO.`);
126
+ console.error(`[LIOP-Agent] P2P Mesh: Joined (${bootstrapNodes.length} bootstraps)`);
127
+ console.error("[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0");
299
128
  process.on("SIGINT", async () => {
300
129
  await meshNode.stop();
301
130
  process.exit(0);
302
131
  });
303
132
  }
304
133
  main().catch((err) => {
305
- log.error(`[LIOP-Agent] Fatal Error: ${err.message}`);
134
+ console.error(`[LIOP-Agent] Fatal Error: ${err.message}`);
306
135
  process.exit(1);
307
136
  });
@@ -1,6 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { LiopServer } from "../server/index.js";
3
- import { log } from "../utils/logger.js";
4
3
  /**
5
4
  * LIOP MCP Bridge
6
5
  * A bi-directional bridge that allows legacy MCP servers to join the LIOP mesh,
@@ -15,11 +14,11 @@ export class LiopMcpBridge {
15
14
  // Determine mode: Exposing LIOP to MCP (Claude) or Wrapping MCP to LIOP (Mesh)
16
15
  if (source instanceof LiopServer) {
17
16
  this.liopServer = source;
18
- log.info("[LIOP-Bridge] Mode: EXPOSE (LIOP -> MCP Stdio)");
17
+ console.error("[LIOP-Bridge] Mode: EXPOSE (LIOP -> MCP Stdio)");
19
18
  }
20
19
  else if (source instanceof McpServer) {
21
20
  this.legacyMcpServer = source;
22
- log.info("[LIOP-Bridge] Mode: WRAP (Legacy MCP -> LIOP Mesh)");
21
+ console.error("[LIOP-Bridge] Mode: WRAP (Legacy MCP -> LIOP Mesh)");
23
22
  }
24
23
  }
25
24
  /**
@@ -48,7 +47,7 @@ export class LiopMcpBridge {
48
47
  return null;
49
48
  if (method === "initialize") {
50
49
  return this.successResponse(id, {
51
- protocolVersion: "2025-11-25",
50
+ protocolVersion: "2025-03-26",
52
51
  capabilities: {
53
52
  prompts: {},
54
53
  resources: {},
@@ -168,7 +167,7 @@ export class LiopMcpBridge {
168
167
  return true;
169
168
  }
170
169
  catch (e) {
171
- log.info("[LIOP-Bridge] ZK-Verifier Failure:", e);
170
+ console.error("[LIOP-Bridge] ZK-Verifier Failure:", e);
172
171
  return false;
173
172
  }
174
173
  }
@@ -222,7 +221,7 @@ export class LiopMcpBridge {
222
221
  terminal: false,
223
222
  });
224
223
  const shutdown = async () => {
225
- log.info("[LIOP-Bridge] Disconnecting session...");
224
+ console.error("[LIOP-Bridge] Disconnecting session...");
226
225
  if (this.liopServer)
227
226
  await this.liopServer.close();
228
227
  process.exit(0);
@@ -241,7 +240,7 @@ export class LiopMcpBridge {
241
240
  }
242
241
  }
243
242
  catch (e) {
244
- log.error(`[LIOP-Bridge] Error: ${e.message}`);
243
+ console.error(`[LIOP-Bridge] Error: ${e.message}`);
245
244
  }
246
245
  });
247
246
  }
@@ -3,7 +3,6 @@ import { serve } from "@hono/node-server";
3
3
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
4
4
  import { Hono } from "hono";
5
5
  import { cors } from "hono/cors";
6
- import { log } from "../utils/logger.js";
7
6
  import { LiopMcpBridge } from "./index.js";
8
7
  const DEFAULT_MAX_SESSIONS_PER_IP = 10;
9
8
  const DEFAULT_SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
@@ -54,7 +53,7 @@ export class LiopStreamBridge {
54
53
  lastActivity: Date.now(),
55
54
  clientIp,
56
55
  });
57
- log.info(`[LIOP-StreamBridge] Session opened: ${sessionId} (IP: ${clientIp})`);
56
+ console.error(`[LIOP-StreamBridge] Session opened: ${sessionId} (IP: ${clientIp})`);
58
57
  },
59
58
  });
60
59
  // Wire the transport's incoming messages to the LiopMcpBridge JSON-RPC router
@@ -73,13 +72,13 @@ export class LiopStreamBridge {
73
72
  }
74
73
  }
75
74
  catch (err) {
76
- log.info("[LIOP-StreamBridge] JSON-RPC error:", err.message);
75
+ console.error("[LIOP-StreamBridge] JSON-RPC error:", err.message);
77
76
  }
78
77
  };
79
78
  transport.onclose = () => {
80
79
  if (transport.sessionId) {
81
80
  this.activeSessions.delete(transport.sessionId);
82
- log.info(`[LIOP-StreamBridge] Session closed: ${transport.sessionId}`);
81
+ console.error(`[LIOP-StreamBridge] Session closed: ${transport.sessionId}`);
83
82
  }
84
83
  };
85
84
  return transport;
@@ -110,7 +109,7 @@ export class LiopStreamBridge {
110
109
  const now = Date.now();
111
110
  for (const [sessionId, entry] of this.activeSessions) {
112
111
  if (now - entry.lastActivity > this.sessionTimeoutMs) {
113
- log.info(`[LIOP-StreamBridge] Evicting idle session: ${sessionId}`);
112
+ console.error(`[LIOP-StreamBridge] Evicting idle session: ${sessionId}`);
114
113
  entry.transport.close().catch(() => {
115
114
  /* Swallow close errors */
116
115
  });
@@ -125,9 +124,10 @@ export class LiopStreamBridge {
125
124
  const auth = c.req.header("Authorization");
126
125
  const expectedToken = process.env.ZERO_TRUST_TOKEN;
127
126
  if (expectedToken) {
128
- if (!auth?.startsWith("Bearer ") ||
127
+ if (!auth ||
128
+ !auth.startsWith("Bearer ") ||
129
129
  auth.split(" ")[1] !== expectedToken) {
130
- log.info("[LIOP-StreamBridge] ALERT: Access denied - Invalid Zero-Trust token.");
130
+ console.error("[LIOP-StreamBridge] ALERT: Access denied - Invalid Zero-Trust token.");
131
131
  return c.json({ error: "Unauthorized: LIOP Zero-Trust Policy Enforced" }, 401);
132
132
  }
133
133
  }
@@ -149,7 +149,7 @@ export class LiopStreamBridge {
149
149
  // Explicitly clean up the session from the Map.
150
150
  if (c.req.method === "DELETE") {
151
151
  this.activeSessions.delete(sessionId);
152
- log.info(`[LIOP-StreamBridge] Session closed (DELETE): ${sessionId}`);
152
+ console.error(`[LIOP-StreamBridge] Session closed (DELETE): ${sessionId}`);
153
153
  }
154
154
  return response;
155
155
  }
@@ -158,7 +158,7 @@ export class LiopStreamBridge {
158
158
  const clientIp = this.getClientIp(c);
159
159
  const currentSessions = this.countSessionsByIp(clientIp);
160
160
  if (currentSessions >= this.maxSessionsPerIp) {
161
- log.info(`[LIOP-StreamBridge] Rate limit hit for IP: ${clientIp} (${currentSessions} sessions)`);
161
+ console.error(`[LIOP-StreamBridge] Rate limit hit for IP: ${clientIp} (${currentSessions} sessions)`);
162
162
  return c.json({ error: "Too Many Sessions: Rate limit exceeded" }, 429);
163
163
  }
164
164
  const transport = this.createSessionTransport(clientIp);
@@ -177,7 +177,7 @@ export class LiopStreamBridge {
177
177
  fetch: this.app.fetch,
178
178
  port: listenPort,
179
179
  }, (info) => {
180
- log.info(`[LIOP-StreamBridge] Streamable HTTP Gateway on http://localhost:${info.port}/mcp`);
180
+ console.error(`[LIOP-StreamBridge] Streamable HTTP Gateway on http://localhost:${info.port}/mcp`);
181
181
  resolve();
182
182
  });
183
183
  });
@@ -196,7 +196,7 @@ export class LiopStreamBridge {
196
196
  }
197
197
  if (this.httpServer) {
198
198
  this.httpServer.close();
199
- log.info("[LIOP-StreamBridge] HTTP ports released.");
199
+ console.error("[LIOP-StreamBridge] HTTP ports released.");
200
200
  }
201
201
  }
202
202
  }