npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@warlock.js/ai-tools

v4.7.0

Published

Ready-made agent tools (web search, fetch, HTTP, calculator, date-time) + an MCP client/server for @warlock.js/ai

Downloads

577

Readme

@warlock.js/ai-tools

Ready-made agent tools (web search, fetch, HTTP, calculator, date-time) + an MCP client/server for @warlock.js/ai.

A batteries-included tool belt for @warlock.js/ai agents plus a Model Context Protocol (MCP) client and server — built entirely on the framework's vendor-neutral ai.tool() seam, so every tool returns a ToolContract that drops straight into ai.agent({ tools: [...] }). Importing the package registers the tools on the shared ai object, so they are reached as ai.tools.* and ai.mcp per the ai.-namespace convention.

What's in the belt

All five tools attach onto the shared ai object at import time under the ai.tools.* namespace (via a declare module "@warlock.js/ai" augmentation), so a bare import "@warlock.js/ai-tools" makes them available and statically typed.

| Tool | LLM-visible name | What it does | |---|---|---| | ai.tools.webSearch(options) | web_search | Web search via a chosen provider (tavily / brave / serpapi) — ranked title/URL/snippet hits. | | ai.tools.fetchUrl(options?) | fetch_url | Fetch a URL → readability text (default), raw html, or markdown; host allowlist + byte cap. | | ai.tools.http(options?) | http_request | A guarded HTTP/REST client — method + host allowlists, baseUrl join, byte/timeout caps. | | ai.tools.calculator(options?) | calculator | A SAFE arithmetic evaluator (shunting-yard; never eval/Function). | | ai.tools.dateTime(options?) | date_time | now / add / diff / format over ISO-8601 instants, IANA time zones. |

MCP — both directions

  • ai.mcp(server, options?) — connect to an external MCP server and adapt each of its tools into a native ToolContract (Direction A: server → agent tools).
  • ai.mcp.serve(source, options) — expose a warlock agent / supervisor / orchestrator (or a raw ToolContract[]) as an MCP server other clients consume (Direction B: primitive → server).

There is no SQL tool. An LLM-driven SQL surface is sensitive and must be audited per app, so it is deliberately not part of this belt.

Install

npm install @warlock.js/ai-tools

@warlock.js/ai is the only required runtime peer. Everything heavy — a search provider, the readability scraper, the MCP SDK, and a JSON-Schema validator — is an optional peer, lazily import()ed only when the relevant path runs; a missing one surfaces a curated npm install string rather than crashing at import time. Beyond @warlock.js/ai the package uses only Node built-ins and the global fetch (Node 18+). Import the package once for its side effect so the surface is registered:

import "@warlock.js/ai-tools";

Usage

1. An agent with web search + HTTP

Hand an agent the web tools and let it research, then hit an API — both bounded by a host allowlist. A failing tool call comes back as { error } data, so the agent self-corrects instead of crashing.

import "@warlock.js/ai-tools"; // registers ai.tools.* + ai.mcp on import
import { ai } from "@warlock.js/ai";

const agent = ai.agent({
  model: ai.openai.model({ name: "gpt-4o" }),
  systemPrompt: "Research with web_search, then call the API with http_request.",
  tools: [
    ai.tools.webSearch({ provider: "tavily" }), // TAVILY_API_KEY from env, or pass { apiKey }
    ai.tools.http({
      baseUrl: "https://api.github.com",
      allowHosts: ["api.github.com"],
      allowMethods: ["GET"],
      headers: { "user-agent": "warlock-agent" },
    }),
  ],
  maxTrips: 12,
});

await agent.execute("Find the latest @warlock.js release and summarize its notes.");

2. Consume an external MCP server

ai.mcp(server) connects to any MCP server, lists its tools, and adapts each into a ToolContract. await client.tools() runs the handshake once and is cached; spread the result into tools: [...].

import "@warlock.js/ai-tools";
import { ai } from "@warlock.js/ai";

const github = ai.mcp(
  { type: "stdio", command: "npx", args: ["-y", "@modelcontextprotocol/server-github"] },
  { namePrefix: "github." }, // avoid colliding with local tool names
);

const dev = ai.agent({
  model: ai.openai.model({ name: "gpt-4o" }),
  systemPrompt: "Use the GitHub tools to triage issues.",
  tools: [...(await github.tools())],
  maxTrips: 20,
});

await dev.execute("List the open issues labeled 'bug' and propose a fix for the oldest.");

// On teardown:
await github.close();

3. Expose an agent's tools AS an MCP server

ai.mcp.serve(source, options) turns a local ToolContract[] (or anything with a tools() method) into an MCP server. The default stdio transport is auto-pumped over process.stdin/process.stdout, so Cursor / Claude Desktop / any MCP client can call these tools.

import "@warlock.js/ai-tools";

const server = ai.mcp.serve(
  [ai.tools.calculator(), ai.tools.dateTime()],
  { name: "warlock-utils", transport: { type: "stdio" } },
);

await server.start();
// ...later:
await server.stop();

Errors flow as data, not throws

Every tool follows the framework's errors-as-data contract: a guardrail rejection or a failed call is thrown inside the tool handler, caught by tool(), and surfaced in the returned { error } field — invoke() never throws. Each error class extends the @warlock.js/ai AIError base and carries a type discriminator you can branch on:

import { HttpPolicyError } from "@warlock.js/ai-tools";

const http = ai.tools.http({ allowHosts: ["api.github.com"] });
const { error } = await http.invoke({ url: "https://evil.test" });

if (error instanceof HttpPolicyError && error.type === "host-not-allowed") {
  // rejected before any network call — an SSRF guardrail
}
  • WebToolError.type: "missing-peer" | "missing-key" | "denied-host" | "invalid-url" | "request-failed"
  • HttpPolicyError.type: "method-not-allowed" | "host-not-allowed" | "invalid-url"
  • CalculatorError.type: "syntax" | "divide-by-zero" | "overflow"
  • DateTimeError.type: "invalid-input" | "invalid-unit" | "invalid-time-zone" | "unsupported-op"
  • McpTransportError.type: "connect" | "protocol" | "timeout" | "closed"

Skills

Progressive-disclosure, per-task docs live under skills/:

  • use-web-and-http-tools/ — wire web_search, fetch_url, http_request, calculator, and date_time into an agent under their guardrails.
  • connect-mcp-server/ — adapt an external MCP server's tools with ai.mcp(server) (Direction A).
  • expose-as-mcp-server/ — publish a local primitive AS an MCP server with ai.mcp.serve(source) (Direction B).

License

MIT © Hassan Zohdy