# MCP Toolset Pruner (`firstrate/mcp-toolset-pruner`) Actor

Reduce bloated MCP or AI-agent tool catalogs to a smaller evidence-based allowlist for stated tasks. Detect routing confusion, preserve task coverage, and identify what can stay dormant — without using an LLM or pretending lexical similarity proves behavioral equivalence.

- **URL**: https://apify.com/firstrate/mcp-toolset-pruner.md
- **Developed by:** [First Rate](https://apify.com/firstrate) (community)
- **Categories:** AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 toolset pruneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## MCP Toolset Pruner

Reduce a large MCP or AI-agent tool catalog to a smaller **candidate allowlist** for the tasks your agent actually needs to perform.

Agents often see too many tools. That increases context size and can make neighboring tools harder to distinguish. This Actor takes MCP-style tool definitions plus explicit task intents, ranks coverage deterministically, flags confusing neighbors, and returns the smallest shortlist it can justify under your configured cap.

It does **not** call an LLM and it does **not** claim that removing tools is safe without representative replay evidence.

### Best for

- MCP servers with large `tools/list` responses
- AI agents that expose dozens or hundreds of tools
- CI checks before publishing a tool catalog
- reducing tool-selection noise and schema/context overhead
- identifying redundant tools that need clearer `use when / avoid when` boundaries
- creating a candidate tool allowlist before agent evaluation

### What you get

One dataset item containing:

- `selectedTools` — candidate shortlist with per-intent evidence
- `droppedTools` — tools outside the shortlist and why
- `taskCoverage` — best matching tool for each stated intent
- `uncoveredIntents` — tasks for which the catalog does not show enough evidence
- `confusedPairs` — tools with substantially overlapping routing signals
- `selectedConfusedPairs` — ambiguity that remains inside the proposed shortlist
- `recommendation` — the next verification step
- `authority.productionRemovalAuthorized = false` — explicit reminder that lexical/schema evidence is not behavioral equivalence

### Example input

```json
{
  "tools": [
    {
      "name": "search_docs",
      "description": "Search internal documentation by keyword.",
      "inputSchema": {
        "type": "object",
        "properties": { "query": { "type": "string" } },
        "required": ["query"]
      }
    },
    {
      "name": "search_web",
      "description": "Search the public web for current information.",
      "inputSchema": {
        "type": "object",
        "properties": { "query": { "type": "string" } },
        "required": ["query"]
      }
    }
  ],
  "taskIntents": [
    "search internal documentation",
    "search current web information"
  ],
  "maxTools": 12
}
```

You may alternatively pass a raw `toolsJson` string containing a single tool, an array, or a standard `{ "tools": [...] }` response.

### How the pruning works

The Actor normalizes tool names, descriptions, schema properties, and required arguments into routing signals. It then:

1. scores each tool against each stated task intent;
2. preserves the strongest evidenced tool for each covered intent;
3. fills remaining slots with tools that add evidenced coverage;
4. detects overlapping neighboring tools using token/schema similarity;
5. reports uncovered intents rather than pretending the catalog can perform them;
6. returns a **candidate** allowlist for replay, not a production deletion order.

This is deliberately conservative. A tool catalog can look redundant lexically while still containing behaviorally distinct tools.

### Why this is useful for AI agents

A model does not benefit from seeing every possible tool on every turn. Smaller task-relevant toolsets can reduce prompt/schema burden and make tool routing easier, but pruning the wrong tool can destroy capability. This Actor separates those two questions:

- **Which tools look necessary from the declared tasks and schemas?** — deterministic shortlist.
- **Is removing the others actually safe?** — must be answered by replaying representative tasks.

### Pricing

The intended Store pricing is one small pay-per-event charge per successfully emitted toolset audit. The Actor has no external API, browser, proxy, or model dependency, so platform cost stays small and predictable.

### Privacy and permissions

The Actor uses limited permissions. Tool definitions are processed inside the Actor run. It does not call external AI APIs.

### Search phrases this Actor is designed for

MCP tool selection, MCP tool pruning, AI agent tool catalog optimization, reduce MCP tools, tool allowlist, tool routing confusion, tools/list optimizer, agent tool selection accuracy, MCP context reduction.

# Actor input Schema

## `tools` (type: `array`):

MCP-style tool definitions. Each item should include name, description, and optionally inputSchema.

## `toolsJson` (type: `string`):

Optional raw JSON string containing a single tool, array of tools, or tools/list response. Used only when tools is empty.

## `taskIntents` (type: `array`):

Short descriptions of tasks the agent must still be able to perform, e.g. 'search internal documentation' or 'find current web information'.

## `maxTools` (type: `integer`):

Maximum candidate allowlist size. Coverage warnings remain visible when the cap is too small.

## `minIntentScore` (type: `number`):

Minimum lexical/schema evidence required to say an intent has a matching tool. Higher is stricter.

## `confusionThreshold` (type: `number`):

Jaccard similarity threshold for flagging tool pairs with overlapping routing signals.

## Actor input object example

```json
{
  "tools": [
    {
      "name": "search_docs",
      "description": "Search internal documentation by keyword.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          }
        },
        "required": [
          "query"
        ]
      }
    },
    {
      "name": "search_web",
      "description": "Search the public web for current information.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          }
        },
        "required": [
          "query"
        ]
      }
    },
    {
      "name": "delete_document",
      "description": "Delete a document by ID after explicit approval.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          }
        },
        "required": [
          "id"
        ]
      }
    },
    {
      "name": "find_documents",
      "description": "Find internal documents matching a query.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          }
        },
        "required": [
          "query"
        ]
      }
    }
  ],
  "taskIntents": [
    "search internal documentation",
    "search current web information"
  ],
  "maxTools": 12,
  "minIntentScore": 0.2,
  "confusionThreshold": 0.55
}
```

# Actor output Schema

## `results` (type: `string`):

Machine-readable candidate allowlist and evidence for every keep/drop decision.

## `summary` (type: `string`):

Input/selected/dropped tool counts and coverage status.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("firstrate/mcp-toolset-pruner").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("firstrate/mcp-toolset-pruner").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call firstrate/mcp-toolset-pruner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,firstrate/mcp-toolset-pruner"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/negCd0HzBapwGxr7U/builds/ZIN0fFGI3a6qeMcHz/openapi.json
