@sengol/instrument
v0.1.1
Published
TypeScript MCP tool-hash producer for Sengol rug-pull detection (ADR-0105/ADR-0107) — decorates an MCP Transport, hashes tool definitions byte-identically to the Python producer, and delivers them to a Sengol server.
Readme
@sengol/instrument
TypeScript/Node MCP tool-hash producer for Sengol rug-pull
detection (ADR-0105 / ADR-0107). Decorates an
MCP Transport, hashes every observed tool
definition byte-identically to Sengol's Python producer, and delivers the hash
so MCPToolIntegrity can flag a rug pull (a tool's definition silently
changing between tools/list and tools/call) CRITICAL.
Zero runtime dependencies. @modelcontextprotocol/sdk is an optional peer
dependency.
Usage
Recommended: wrap the transport
Wrap your transport with sengolTransport(...) at the client.connect(...)
call site. This is the reliable path — it works identically for ESM and
CommonJS and needs no monkeypatch:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { configure, sengolTransport } from "@sengol/instrument";
configure({
apiUrl: process.env.SENGOL_API_URL,
apiToken: process.env.SENGOL_API_TOKEN,
agentId: "my-agent",
});
const client = new Client({ name: "my-agent", version: "1.0.0" });
await client.connect(sengolTransport(transport));Convenience: instrument() auto-wiring (CommonJS only)
instrument() monkeypatches Client.prototype.connect so a plain
client.connect(transport) is auto-wrapped with no call-site change:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { instrument } from "@sengol/instrument";
instrument({
apiUrl: process.env.SENGOL_API_URL,
apiToken: process.env.SENGOL_API_TOKEN,
agentId: "my-agent",
});
const client = new Client({ name: "my-agent", version: "1.0.0" });
await client.connect(transport); // auto-wrappedCaveat: the patch is applied via require(), so it reliably reaches only
consumers who load the SDK through CommonJS. Because a dual-published package
resolves to different module instances for require() vs import, an ESM
import { Client } may get an un-patched constructor — instrument() then
silently no-ops. If you use ESM import, use the transport wrapper above.
Environment variables
| Variable | Purpose |
| --- | --- |
| SENGOL_API_URL | Base URL of your Sengol server. |
| SENGOL_API_TOKEN | Bearer token, or an sk_-prefixed local-user token. |
| SENGOL_AGENT_ID | This agent's identity. |
| SENGOL_AGENT_VERSION | Optional version string. |
Unset SENGOL_API_URL/SENGOL_API_TOKEN -> the package still hashes and
caches tool definitions; it simply never delivers them anywhere.
