JSPM

  • Created
  • Published
  • Downloads 730
  • Score
    100M100P100Q105368F
  • License Apache-2.0

Official TypeScript/JavaScript SDK for the IICP protocol (ADR-016)

Package Exports

  • @iicp/client
  • @iicp/client/cli

Readme

iicp-client · TypeScript / JavaScript SDK

CI License Protocol npm

Official TypeScript client library for the IICP protocol — route AI agent tasks by intent across a self-organising mesh of provider nodes. No central broker. No hardcoded endpoints.

Works in Node.js ≥ 18, Deno, Bun, and modern browsers with the native Fetch API.

urn:iicp:intent:llm:chat:v1  →  discover  →  select  →  submit

Install

npm install iicp-client
# yarn add iicp-client
# pnpm add iicp-client

Upgrade note (0.5.3) — if you operate a node and use the native IICP TCP transport on port 9484, upgrade to ^0.5.3. Releases 0.5.0–0.5.2 emitted a non-standard CBOR dialect that does not interoperate with the Python or Rust SDK on the binary transport. The HTTP /v1/task path is unaffected. See CHANGELOG.md for details.


Quickstart

import { IicpClient } from "iicp-client";

const client = new IicpClient({ directory_url: "https://iicp.network" });

// chat() discovers, selects the best node, and submits in one call
const response = await client.chat(
  [{ role: "user", content: "Hello from IICP!" }],
);
console.log(response.choices[0].message.content);

For more control over node selection:

const nodes = await client.discover("urn:iicp:intent:llm:chat:v1");
if (!nodes.length) throw new Error("No nodes available");

const result = await client.submit({
  intent: "urn:iicp:intent:llm:chat:v1",
  payload: { messages: [{ role: "user", content: "Hello!" }] },
});

Configuration

import { IicpClient } from "iicp-client";

const client = new IicpClient({
  directory_url : "https://iicp.network",  // IICP directory
  timeout_ms    : 30_000,                  // max 120 000 (SDK-04)
  region        : "eu-central",            // prefer nodes in region
  api_token     : "your-token",            // optional auth token
});
Option Default Description
directory_url "https://iicp.network" IICP directory endpoint
timeout_ms 30000 Request timeout — max 120 000 ms
region undefined Preferred node region
api_token undefined Bearer token for authenticated nodes

Discover options

const nodes = await client.discover("urn:iicp:intent:llm:chat:v1", {
  region        : "eu-central",
  model         : "phi3:mini",
  min_reputation: 0.7,
  limit         : 5,
});

Error handling

import { IicpClient, IicpError } from "iicp-client";

const client = new IicpClient();
try {
  const response = await client.chat([{ role: "user", content: "hi" }]);
} catch (e) {
  if (e instanceof IicpError) {
    console.error(`[${e.code}] ${e.message}  (HTTP ${e.status_code})`);
  }
}

Error codes match the IICP error reference — e.g. task_timeout, capacity_exceeded, no_nodes_available.


Serving as a provider node

import { IicpNode } from "iicp-client";

const node = new IicpNode({
  nodeId  : "my-node-001",
  endpoint: "http://my.public.host:8020",
  intent  : "urn:iicp:intent:llm:chat:v1",
  model   : "llama3:8b",
});

const token = await node.register();
const stop = node.serve(async (task) => {
  // Return the inner result value — serve() wraps it in {result: ...}
  return { choices: [{ message: { role: "assistant", content: "Hello!" } }] };
}, { port: 8020, nodeToken: token });

process.on("SIGINT", () => { stop(); });

NAT traversal — v0.7.0

IICP nodes pick the best available NAT path automatically (ADR-041):

Tier Method Requirement
0 Direct — publicly routable Open port 8020
1 UPnP/IGD port mapping Home router with UPnP
2 IPv6 firewall pinhole IPv6 + UPnP/IGD2
3 Relay-as-last-resort A relay operator in the mesh

Relay-as-last-resort lets a node behind CGNAT stay reachable by binding an outbound channel to a public relay node that forwards inbound tasks down it.

Running a relay-capable node (relay operator)

const node = new IicpNode({
  nodeId         : "relay-eu-01",
  endpoint       : "http://relay.example.com:8020",
  intent         : "urn:iicp:intent:llm:chat:v1",
  relayCapable   : true,   // accept RELAY_BIND on TCP port 9485
  relayAcceptPort: 9485,
  enableMesh     : true,   // gossip relayCapable=true to peers
});

Node behind CGNAT (connects outbound to relay)

const node = new IicpNode({
  nodeId              : "cgnat-worker-001",
  endpoint            : "http://placeholder",       // overwritten on bind
  intent              : "urn:iicp:intent:llm:chat:v1",
  relayWorkerEndpoint : "relay.example.com:9485",   // outbound target
  // or: env IICP_RELAY_WORKER_ENDPOINT=relay.example.com:9485
});

When the worker binds it re-registers with the relay's public address (transport_method: "turn_relay"), making it discoverable.


SDK conformance

Rule Description Status
SDK-01 discover → select → submit pipeline with node retry
SDK-02 task_id auto-generated (UUID v4)
SDK-03 Intent URN pattern validation
SDK-04 timeout_ms capped at 120 000 ms
SDK-05 Retry on 429 / 503 with exponential back-off
SDK-06 W3C traceparent propagation

Conformance tier: iicp:sdk:v1 (spec S.14) · Request a badge


Development

npm install        # install deps
npm run typecheck  # tsc strict
npm test           # 184 unit tests
npm run build      # emit to dist/


Apache 2.0 · iicp.network