toolpal

Getting started

toolpal is a package manager and runtime for AI agent tools in Node.js (22.15 or newer). A tool is one function with JSON Schemas for its input and output. It runs on your machine, in its own permission-restricted process.

Use a tool

npm i toolpal
npx toolpal add @demo/weather
import { toolpal, ToolpalError } from "toolpal/sdk";

try {
  const out = await toolpal.execute({
    tool: "@demo/weather",
    input: { latitude: 48.85, longitude: 2.35 },
    env: { OPEN_METEO_API_KEY: process.env.MY_KEY }, // only declared vars are passed
  });
} catch (err) {
  if (err instanceof ToolpalError) console.error(err.code, err.message);
}

toolpal add downloads the tool, verifies the registry's signature and the tarball hash, pins it in toolpal.json and toolpal.lock, and prints what it may do. Commit both files. After that, the tool runs from the local store without the network.

execute only runs tools added to the project: any other name fails with NOT_ADDED instead of downloading code. For a particular version, add that version: npx toolpal add @demo/[email protected].

Permissions

Each tool page lists what the tool may do: network access, specific environment variables, a private temp directory. The registry derives these from the code with static analysis and refuses to publish a tool that uses something it didn't declare. Look at the Permissions tab to see every finding, linked to the exact line in the bundle that runs.

Before updating, check the Versions tab: a version that adds a permission is marked, and toolpal update prints new permissions too.

MCP

npx toolpal login
npx toolpal add --account @demo/weather
claude mcp add toolpal -- npx toolpal mcp

toolpal mcp serves the tools on your account: the ones you created and the ones you added (with toolpal add --account or the Add button on a tool page). Each becomes an MCP tool (@demo/weather is exposed as demo__weather), using the manifest's JSON Schemas. Tools pinned in a project's toolpal.json are not served.

The agent can also look for tools with search_tools and add one with install_tool, which asks you first and then adds it to your account. An added tool stays on the version it was installed at until toolpal update --account moves it.

Your account

Sign in with GitHub or Google, whichever this registry offers. toolpal only asks for a public profile: no OAuth scopes from GitHub, and openid profile (no email address) from Google.

The first time you sign in, you choose a username. It is also your scope, the @name your tools are published under, and it can't be changed later. To sign in to the same account with the other provider too, connect it in Settings → Sign-in methods.

The CLI signs in through this site. toolpal login prints a link and a short code; open the link (or go to /cli and type the code), check that the code matches your terminal, and approve. The CLI then receives its own API token, which you can revoke in Settings → API tokens.

Publish a tool

npx toolpal login                          # approve the code on this site
npx toolpal init my-tool --name @your-login/word-count
cd my-tool && npm install
npx toolpal build                          # bundle + analyze + manifest
npx toolpal publish

Your scope is your username: everything you publish goes under @your-login/…, and only you can publish there.

Private tools

A tool is public unless you say otherwise. To keep one to yourself:

npx toolpal publish --private                            # a new tool, created private
npx toolpal visibility @your-login/word-count private    # an existing tool; "public" undoes it
  • Only you can see, add or install a private tool. Signed in (toolpal login, or TOOLPAL_TOKEN with a CI token for its scope), it installs and runs like any other tool, and toolpal mcp serves it.
  • Everyone else gets “not found” for it, exactly as for a name that doesn't exist. It is in no search or listing, and its pages, files and downloads are withheld.
  • It stays private. Visibility belongs to the tool, so later versions need no flag. --private on a public tool (or --public on a private one) refuses to publish rather than changing it.
  • Going private doesn't recall copies. People who already installed a public tool keep running it from their machine, but their fresh installs fail.

On this site every tool page says whether the tool is public or private, next to its name and under Details. Your dashboard lists the visibility of each of your tools, and your private ones also show on your profile and your scope page, where only you see them. To switch a tool between private and public, open it and use the ⋯ menu. Registry moderators can read a private tool.

Publish from CI

Create a CI token in Settings → API tokens. It is bound to one scope: it can publish and yank there, and install that scope's private tools. Store it as a secret:

TOOLPAL_TOKEN=${{ secrets.TOOLPAL_TOKEN }} npx toolpal publish

Maintain a tool

  • Yank a broken version: new installs skip it, existing lockfiles keep working (toolpal yank @scope/[email protected] or the Versions tab).
  • Deprecate a tool you no longer maintain: installs print your message as a warning.
  • Reports go to the registry moderators, who can quarantine a version: no client will install or run it, even when pinned. toolpal audit checks your project for yanked, quarantined and deprecated tools.

Security model

toolpal runs each tool with Node's permission model. That stops buggy and casually malicious code, but it is not a hard security boundary: a tool that exploits a permission-model bypass or a V8 bug runs as your OS user. Read the source before you run a tool (every file is on its Files tab), keep Node.js patched (toolpal doctor), and run agents as a low-privilege user.

A tool with network access can reach any host, including internal addresses. The hosts shown on a tool page are the ones seen in its code, not an allow-list.

The HTTP API is documented at https://api.toolpal.dev/docs.