SkillAgentSearch skills...

toollens

Give your agent 2,468 tools. It sees 3. A Rust MCP gateway: dependency-aware tool discovery, policy-checked execution, measured on 110 real vendor MCP servers (26/28 tasks at half the cost of Anthropic's tool search).

Install / Use

claude mcp add krishnashakula -- npx -y github:krishnashakula/toollens

If the server publishes to npm under a different name, use that package instead โ€” check the repo README.

About this skill
๐Ÿ”Œ

MCP Server

Model Context Protocol server

Quality Score

76/100

Supported Platforms

Claude Code
Claude Desktop

Our assessment of toollens

toollens scores 76/100 on our quality scale, 818th of 955 AI & Machine Learning skills we index.

Its MCP Server is 20 KB long, well organised into 19 sections with 11 code examples: a thorough specification that gives an agent plenty to work with.

It has 10 GitHub stars, so there is little community track record yet; judge it on its content.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
4/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 5 days ago, so toollens is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 97/100, with no cautions. These come from repository metadata, not a code audit โ€” read the skill file before letting an agent act on it.

toollens compared with similar skills

All 4 of these similar skills score higher than toollens; compare them before choosing.

SkillScoreStarsUpdatedFormat
toollens (this skill)by krishnashakula76105d agoMCP Server
claude-memby thedotmack100113.8ktodayCLAUDE.md
Agent-Reachby Panniantong100109.5k1d agoCLAUDE.md
Understand-Anythingby Egonex-AI10091.0ktodayCLAUDE.md
headroomby headroomlabs-ai10079.0ktodayCLAUDE.md

Frequently asked questions

How do I install toollens?
Run claude mcp add krishnashakula -- npx -y github:krishnashakula/toollens. The install tabs above show the steps for each supported agent.
Which AI agents does toollens work with?
It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
Is toollens safe to use?
It is MIT-licensed and scores 97/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is toollens still maintained?
The repository was last updated 5 days ago, so toollens is actively maintained.
<div align="center">

๐Ÿ” ToolLens

Give your agent 2,468 tools. It sees 3.

An MCP gateway in Rust. Put any number of MCP servers behind it: your agent discovers, inspects and calls exactly the tools it needs, and finding a tool never grants permission to run it.

CI License: MIT Rust 1.89+ MCP PRs welcome

<img src="docs/demo.gif" alt="Claude answers through ToolLens with 5 of 2,468 tools in view; the same request with every tool exposed is rejected by the API at 1.43M tokens; then the benchmark results" width="900">

<sub>Real run, not a mock-up: Claude Opus 5.5 against 110 vendor-published MCP servers. Full 4K/60 fps video in the <a href="https://github.com/krishnashakula/toollens/releases/tag/v0.1.0">v0.1.0 release</a>.</sub>

</div>

MCP clients send every tool definition with every request. Connect enough servers and that stops working: the 110 real vendor servers in this repo's benchmark expose 2,453 tool definitions, which come to 1.43M tokens per request, and the API rejects every call before the model runs. Below that limit you still pay for, and distract the model with, hundreds of tools it will never use.

ToolLens sits between the agent and your servers and shows the agent three tools instead:

| Tool | What it does | |---|---| | discover_tools(goal, limit?) | Up to 10 tool ids for a goal: direct matches plus the tools they depend on, each with the reason it is there | | inspect_tool(tool_id) | Full input/output schema, server provenance, and the current policy decision | | invoke_tool(tool_id, arguments) | Checks policy, validates the arguments against the schema, then forwards the call to the owning server |

Results

Same 28 tasks, same model (Claude Opus 5.5), 110 real MCP servers, 2,468 tools:

| | Every tool exposed | ToolLens | Anthropic's built-in tool search | |---|---:|---:|---:| | Tasks completed | 0/28 (every request rejected) | 26/28 | 25/28 | | Tool tokens per request | 1,428,973 | 951 | 643 | | Input tokens per task | n/a | 18.4K | 25.5K | | Cost per task (list price) | n/a | $0.043 | $0.090 |

One run per task: 26 vs 25 is a tie. The result is that ToolLens matched Anthropic's server-side tool search at half the cost per task, while exposing every tool was not an option at all. Methodology, the controlled benchmark and every caveat are below; every number comes from transcripts committed in bench/results/.

What do your MCP servers cost you?

toollens tax starts the servers in your existing client config and measures what their tool definitions add to every request. It runs locally; --exact instead counts with Anthropic's free count_tokens endpoint, which means sending it the tool definitions (never env or args).

toollens tax --config .mcp.json        # Claude Code project servers; ~/.claude.json for user-scope ones
toollens tax --config "<Claude Desktop config>"   # %APPDATA%\Claude\ or ~/Library/Application Support/Claude/claude_desktop_config.json

It ranks servers and tools by tokens and lists tools whose schemas the Claude API refuses and servers that failed to start. Across the benchmark's 110 servers (full table), DigitalOcean alone is about 130K tokens per request, and its apps-create-app-from-spec tool about 19.7K by itself.

Quick start

Download the archive for your platform (Linux x86_64, macOS Apple silicon, Windows x86_64) from the latest release and unpack it. Or build from source with Rust 1.89+, then use ./target/release/toollens:

git clone https://github.com/krishnashakula/toollens && cd toollens && cargo build --release

From the unpacked folder:

# Three simulated servers (deploy, observability, vcs) plus 982 generated distractor tools:
./toollens discover --config examples/gateway.json --noise 982 --goal "investigate a failed deployment"

On macOS the binary is unsigned; if it is blocked, run xattr -d com.apple.quarantine toollens.

{
  "tools": [
    { "id": "deploy/get_deployment",   "role": "match",      "why": "matches fail, deploy" },
    { "id": "deploy/list_deployments", "role": "dependency", "why": "provides `deployment_id` that deploy/get_deployment requires" },
    { "id": "deploy/search",           "role": "dependency", "why": "provides `service_id` that deploy/list_deployments requires" },
    { "id": "vcs/get_commit",          "role": "dependency", "why": "can use `commit_sha` returned by deploy/get_deployment" },
    { "id": "observability/get_logs",  "role": "dependency", "why": "can use `deployment_id` returned by deploy/get_deployment" }
    // โ€ฆ 3 more direct matches
  ],
  "catalog_size": 1000,
  "latency_ms": 0.27
}

Keyword search alone finds the deployment tool. The dependency graph adds the chain the agent will actually need: the lookup that resolves a service name to its id, the logs, and the commit.

Use it from Claude Code, Claude Desktop or any MCP client

1. Put your servers behind the gateway. toollens init reads your client config, writes a gateway config with the same server entries (toollens.json beside it), and prints the client change; --write applies it and keeps a .bak. ~/.claude.json is never edited, only printed, because Claude Code rewrites it while running.

toollens init --from .mcp.json         # or claude_desktop_config.json

The gateway config uses the same mcpServers shape as Claude Desktop and Claude Code, including ${VAR} and ${VAR:-default} references, plus a policy:

{
  "mcpServers": {
    "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "..." } },
    "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/work"] }
  },
  "policy": { "default": "allow", "deny": ["github/merge_pull_request"], "allow": [], "denyDestructive": true }
}

2. Point your client at ToolLens instead of at the servers. This is what init prints. For Claude Code it goes in .mcp.json at your project root; Claude Desktop uses claude_desktop_config.json:

{
  "mcpServers": {
    "toollens": {
      "command": "/path/to/toollens",
      "args": ["serve", "--config", "/path/to/gateway.json"]
    }
  }
}

The agent now sees three tools however many servers sit behind them. To check what a goal would find before involving an agent: toollens discover --config gateway.json --goal "...".

For many servers, set "lazy": true (and optionally "maxLive": 12): tool lists are indexed once and cached in SQLite, and each server starts only when one of its tools is called, with at most maxLive running and the least recently used stopped first. Bare launcher names such as npx and uvx resolve on Windows too.

The end-to-end test drives serve with the official rmcp client over stdio. Tested in Claude Code 2.1.312 with examples/gateway.json: asked to investigate a failed deployment and roll it back, Claude found the cause through the gateway (deployment, commit, logs) and did not attempt the rollback because inspect_tool showed the policy denies it. Claude Desktop is untested (#1); reports welcome.

The console

./target/release/toollens console --config examples/gateway.json --noise 982
#   ToolLens console: http://127.0.0.1:7300/#token=โ€ฆ

A local web UI over the running gateway: browse the catalog, try discovery for any goal, replay recorded benchmark runs, and run a live agent (needs ANTHROPIC_API_KEY) to watch every discover, inspect and invoke step as it happens, next to the gateway's own audit log. The demo above is this console. It binds to 127.0.0.1, and every API call needs the token it prints.

How it works

flowchart LR
    A["Agent<br/>Claude Code ยท Claude Desktop ยท any MCP client"] -- "3 tools" --> G
    subgraph G["ToolLens"]
        D["discover_tools<br/>BM25 ยท embeddings ยท dependency graph"]
        I["inspect_tool<br/>schema ยท provenance ยท policy decision"]
        V["invoke_tool<br/>policy โ†’ schema check โ†’ audit log"]
    end
    G -- "started on demand, at most maxLive" --> S["Your MCP servers<br/>110 in the benchmark, 2,468 tools"]
  1. Index. Servers start six at a time with a timeout each; one that fails is reported with its last stderr lines and the rest keep working. Names, descriptions, input and output schemas and server identity are indexed. Ids are server/tool, so overlapping names (get_status exists on 13 servers in the demo) are never ambiguous.

  2. Retrieve. BM25 keyword search (default), semantic search (Ollama embeddings, cached in SQLite), or a hybrid of the two (reciprocal rank fusion). At most two direct matches per tool family, so five CRUD variants of one near miss cannot fill the result.

  3. Expand with dependencies.

    • Schema edges: tool A's output has a field that tool B takes as input. Producers that resolve names to ids rank first, and each shared field is weighted by how rare it is, so commit_sha is strong evidence and service_id is weak. Tools of different servers are linked only through fields used by at most 3 servers: across real vendors, region matching is coincidence, not a data flow.
    • Observed edges: B was called successfully with a value A returned earlier in the same session. Learned at runtime and persisted.

    Destructive tools are never suggested as speculative next steps, and dependencies fill at most half the result slots, so they never push out the best direct matches.

  4. Execute. Policy is checked; arguments are validated against the JSON schema (failing closed if the schema itself is broken); the call is forwarded with a 30 s timeout, and a timeout or a client cancellation cancels it upstream through MCP. At most 8 calls per server are in flight.

Security model

  • Discovery never grants permission. Policy is checked on every invoke and nowhere else. Deny globs win; then denyDestructive; then allow globs; then the default. With no policy, everything is denied, and a misspelled policy key fails the config instead of being ignored.
  • Server annotations may only tighten policy. denyDestructive denies tools a server marks destructiveHint: true unless an allow glob names them.
  • Upstream servers never see the gateway's secrets. They get system basics plus their own configured env, never the gateway's environment (API keys).
  • Nothing sensitive reaches the model or the audit log. Provenance shows a server's program name, never its arguments (which often carry credentials). The SQLite audit log records argument names, never values.
  • The console is not an open door. Binding to 127.0.0.1 is not enough on its own: Docker containers and DNS-rebinding pages can reach it. Every API call needs the per-start token.

Found a hole? See SECURITY.md.

Known limitations

  • denyDestructive acts only on tools explicitly annotated destructiveHint: true. Tools with no annotations are not treated as destructive (the MCP spec's default would be); deny them by glob.
  • Lazy mode trusts the cached tool list until --reindex. Pin server versions (pkg@1.2.3, image digests) so an upstream update cannot change a tool behind the gateway's back.
  • `maxL

Truncated for display โ€” read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars10
CategoryAI
Updated5d ago
Forks1

Languages

Rust

Trust signals

97/100

From repository metadata: license, adoption, age and documentation. Not a code audit โ€” see the Safety scan above for what the skill file itself contains.

1 info
toollens โ€” MCP Server: Install & Safety Check | SkillAgent