@supershaneski/tool-registry
v0.3.3
Published
Lightweight Tool Registry for LLM Function Calling.
Maintainers
Readme
tool-registry
Lightweight Tool Registry for LLM Function Calling
A minimal, zero-overhead alternative to the full Model Context Protocol (MCP). Perfect when you just need clean tool registration + execution without the complexity of servers, network hops, or heavy protocol layers.
LLM向けの軽量なFunction Calling用ツールレジストリ
Model Context Protocol(MCP) のミニマルな代替実装。サーバーやネットワーク通信、複雑なプロトコルを必要とせず、ツールの登録と実行だけをシンプルに提供します。
Motivation
I created this package while learning about the Model Context Protocol (MCP). After exploring numerous projects that use MCP, I found that some of them don’t actually require the full protocol. In many cases, the core requirement is simply registering tools and executing them in a structured way.
This package is not intended to replace MCP when its features are needed. Instead, it offers a lightweight alternative for projects that only need tool registration and execution, without the added complexity of servers, network communication, and protocol layers that often accompany MCP adoption for simple use cases.
Why This Instead of Full MCP?
- Much simpler — No extra servers or protocol overhead
- Faster — Direct in-process function calls
- Flexible — Easy to use different toolsets per context
Use full MCP when you need true distributed tool discovery across multiple applications.
Features
- Simple register → execute workflow
- Optional metadata (categories, tags) during registration for categorization
- Custom querying capability with
findTools(predicate) - Sandboxed tool execution by combining metadata queries with execution access control
- Built-in support for
include/excludetool filtering (great for context-aware agents) - Runtime access control (
allowed) to prevent unauthorized/hallucinated tool execution - Works with Gemini, OpenAI, Anthropic, and other LLM tool-calling APIs
- Tiny footprint — no dependencies
Installation
npm install @supershaneski/tool-registryQuick Start
import ToolRegistry from '@supershaneski/tool-registry';
const registry = new ToolRegistry();
// Register tools
registry.register('get_weather', {
name: 'get_weather',
description: 'Get current weather for a city',
parameters: {
type: 'object',
properties: { city: { type: 'string' } },
required: ['city']
}
}, async (args) => {
// Your implementation here
return { temperature: 28, condition: 'sunny' };
});
// Get tool schemas for LLM
const toolSchemas = registry.getTools();
// or with filtering:
const limitedTools = registry.getTools({
include: ['get_weather', 'search_web']
});
// Execute tool
const toolCall = { name: 'get_weather', args: { city: 'Sapporo' } }; // from LLM
const result = await registry.execute(toolCall.name, toolCall.args);Examples
For a complete example demonstrating actual LLM integration (e.g., Gemini SDK), check out the examples/gemini-integration.js file.
[!NOTE] You will need actual Gemini API Key to run the example. Create or view a Gemini API Key.
API
register(name, schema, handler, metadata?)
Registers a new tool, optionally specifying a metadata object (e.g. for categories, tags, etc.).
registry.register(
'get_weather',
weatherSchema,
weatherHandler,
{ category: 'weather', tags: ['api', 'env'] }
);getTools(options?)
Returns tool schemas with optional filtering.
registry.getTools({ include: ['tool1', 'tool2'] }); // whitelist
registry.getTools({ exclude: ['admin_tool'] }); // blacklistexecute(name, args?, options?)
Executes a tool with optional runtime access control.
await registry.execute('get_weather', { city: 'Tokyo' });
// With runtime whitelist (recommended when using filtered schemas)
await registry.execute('get_weather', { city: 'Tokyo' }, {
allowed: ['get_weather', 'search_web']
});findTools(predicate)
Finds registered tools matching a predicate function. Each tool entry passed to the predicate is of the form { name, schema, handler, metadata }.
// Find tools in the 'weather' category
const weatherTools = registry.findTools(t => t.metadata.category === 'weather');
// Find tools that have a specific tag
const mathTools = registry.findTools(t => t.metadata.tags?.includes('math'));Example: Context-Aware / Sandboxed Execution
You can combine findTools and execute({ allowed }) to create context-aware execution filters (e.g., dynamically sandbox a request to only run non-administrative tools):
// Find all tools that do not require administrative privileges
const safeTools = registry.findTools(t => t.metadata.role !== 'admin');
const allowedNames = safeTools.map(t => t.name); // ['get_weather', 'search_web']
// Safely execute tools based on LLM output
const toolCall = { name: 'restart_server', args: {} };
try {
await registry.execute(toolCall.name, toolCall.args, { allowed: allowedNames });
} catch (error) {
console.error(error.message); // "Tool access denied: restart_server"
}Other Methods
has(name)→ booleanlist()→ string[] of tool names
License
MIT © supershaneski
