# How Tool Availability Is Tracked in Reverse-Skill: Discovery, Indexing, and MCP Verification

> Learn how Reverse-Skill tracks tool availability using discovery, indexing, and MCP verification for seamless integration and readiness.

- Repository: [ZhaoXu/reverse-skill](https://github.com/zhaoxuya520/reverse-skill)
- Tags: internals
- Published: 2026-08-26

---

**Reverse-Skill tracks tool availability through a three-stage pipeline that discovers binaries on the host, generates machine-readable indexes, and verifies MCP registration and service health to determine if a tool is truly ready for use.**

The reverse-skill repository maintains a sophisticated inventory system for security and reverse-engineering workflows. Understanding how tool availability is tracked in reverse-skill is essential for ensuring your environment meets the execution requirements for specific skills, from APK decompilation to binary analysis.

## The Three-Stage Tracking Pipeline

The repository implements a **platform-agnostic detection system** that separates raw tool presence from operational capability. This design allows the system to distinguish between a tool being installed versus being fully integrated with the Model-Client-Protocol (MCP) infrastructure.

### Stage 1: Host Discovery via tool-discovery.sh

The process begins with [`kali/scripts/lib/tool-discovery.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/kali/scripts/lib/tool-discovery.sh) (Kali Linux) or the analogous logic in [`skills/scripts/refresh-tool-index.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/scripts/refresh-tool-index.sh) (Linux/macOS). These scripts scan the host using `command -v` lookups and explicit path probing to locate each binary.

Each tool is defined in a **pipe-delimited catalog format**:

```

name|skill|purpose|version_args|fallback_commands

```

For example, entries for `jadx` and `radare2` follow this pattern:

```bash
"jadx|apk-reverse|Java 反编译|--version|jadx,${HOME}/tools/jadx/bin/jadx,/opt/jadx/bin/jadx"
"r2|radare2|radare2 主分析器|-v|r2,radare2,${HOME}/tools/radare2/bin/r2,/usr/bin/r2"

```

The `resolve_tool()` function (lines 64–95 in [`tool-discovery.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/tool-discovery.sh)) iterates over candidate paths and commands. It expands glob patterns like `${HOME}/tools/*/apksigner`, checks executable permissions, and falls back to `command -v` lookups when path probes fail. This dual strategy ensures tools are found whether they reside in system `PATH` or custom installation directories.

### Stage 2: Index Generation with Dual Output

Once discovered, tool metadata is formatted into two synchronized artifacts:

- **[`tool-index.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/tool-index.md)**: A human-readable Markdown table with columns for Tool, Skill, Purpose, Available, Path, Version, Source, and Install hint.
- **[`tool-index.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/tool-index.json)**: A machine-readable JSON file consumed by automation scripts and UI components.

The generation logic resides in [`skills/scripts/refresh-tool-index.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/scripts/refresh-tool-index.sh) (lines 58–103). For each entry in the static `TOOLS` array, the script calls:

- `has_cmd` and `cmd_path` to determine availability and location
- `run_version` to execute version arguments and capture output
- `install_hint` to suggest installation commands for missing binaries

Missing tools are explicitly marked with `available=no` and empty version fields, ensuring the index accurately reflects the current host state.

### Stage 3: MCP-Aware Capability Verification

The final stage enriches the basic index with **service-health and registration checks**. This occurs in a Python block within [`refresh-tool-index.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/refresh-tool-index.sh) (starting at line 37) that processes [`bootstrap-manifest.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/bootstrap-manifest.json).

The system validates four dimensions of readiness:

1. **Tool Presence**: Whether the binary exists (from Stage 1)
2. **MCP Registration**: Whether the tool's MCP server is listed in client configs (`~/.claude/mcp.json` or `~/.codex/config.toml`)
3. **TCP Connectivity**: Whether the advertised `servicePort` accepts connections
4. **HTTP Handshake**: Whether the MCP server responds to JSON-RPC requests at the `/mcp` endpoint

The `verificationMode` field in the bootstrap manifest dictates the final logic:

- `registration-only`: Ready if registered in client configs
- `service-and-registration`: Ready only if both registered and TCP port is open
- `service-or-registration`: Ready if either condition is met
- `npm-mcp`: Requires both registration and a functioning `npx` runtime

## Core Implementation Details

### Version Extraction and Source Attribution

When `resolve_tool()` locates a binary, it calls `get_tool_version` to execute the tool with predefined version arguments (e.g., `--version` or `-v`). The first line of output is captured and sanitized for the index.

The system records the **discovery source** to aid debugging:

- `command`: Found via `command -v` in shell `PATH`
- `path`: Located via explicit filesystem probe
- `missing`: Binary not found via any method

### Capability Status Calculation

The Python enrichment block performs the final readiness calculation using data from [`bootstrap-manifest.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/bootstrap-manifest.json):

```python
for cap in capabilities:
    name = cap.get('name')
    bootstrap_kind = cap.get('bootstrapKind', '')
    mcp_names = cap.get('mcpNames') or []
    service_port = cap.get('servicePort')
    verification_mode = cap.get('verificationMode', '')

    registered = any(n in registered_names for n in mcp_names) if mcp_names else False
    service_online = tcp_open(service_port) if service_port else False
    mcp_http_verified = mcp_http_handshake(service_port) if service_online else False

    tool_ready = tool_available.get(name, False)
    runtime_ready = tool_available.get('npx', False) if bootstrap_kind == 'npm-mcp' else tool_ready

    if verification_mode == 'registration-only':
        ready = registered
    elif verification_mode == 'service-and-registration':
        ready = registered and service_online
    elif verification_mode == 'service-or-registration':
        ready = registered or service_online
    elif bootstrap_kind == 'npm-mcp':
        ready = registered and runtime_ready
    else:
        ready = registered or tool_ready

```

This logic allows reverse-skill to report nuanced states, such as "Tool installed but MCP server not registered" or "MCP registered but service offline."

## Practical Code Examples

### Resolving Tool Paths in Kali

The `resolve_tool()` function in [`tool-discovery.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/tool-discovery.sh) demonstrates the fallback resolution strategy:

```bash
resolve_tool() {
    local entry="$1"
    IFS='|' read -r name skill purpose version_args fallbacks <<< "$entry"
    IFS=',' read -ra candidates <<< "$fallbacks"

    for candidate in "${candidates[@]}"; do
        # Expand globs like ${HOME}/tools/*/apksigner

        local expanded=$(compgen -G "$candidate" 2>/dev/null | head -n1) || expanded=""
        if [[ -n "$expanded" && -x "$expanded" ]]; then
            local ver=$(get_tool_version "$expanded" "$version_args")
            echo "${name}|${skill}|${purpose}|yes|${expanded}|${ver}|path"
            return
        fi
        # Fallback to command lookup

        local cmd_path=$(command -v "$candidate")
        if [[ -n "$cmd_path" ]]; then
            local ver=$(get_tool_version "$cmd_path" "$version_args")
            echo "${name}|${skill}|${purpose}|yes|${cmd_path}|${ver}|command"
            return
        fi
    done
    echo "${name}|${skill}|${purpose}|no|||missing"
}

```

### Generating Markdown Rows

The main loop in [`refresh-tool-index.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/refresh-tool-index.sh) constructs the inventory table:

```bash
for entry in "${TOOLS[@]}"; do
    IFS='|' read -r name skill purpose commands version_spec probes <<< "$entry"
    available="no"; path=""; version=""; source=""
    if [[ "$commands" != "none" ]]; then
        IFS=',' read -ra cmd_list <<< "$commands"
        for cmd in "${cmd_list[@]}"; do
            if has_cmd "$cmd"; then
                available="yes"
                path=$(cmd_path "$cmd")
                source="command"
                break
            fi
        done
    fi
    # …probe handling omitted for brevity…

    [[ -z "$path" ]] && path="—"
    [[ -z "$version" ]] && version="—"
    hint=$(install_hint "$name")
    echo "| $name | $skill | $purpose | $available | $path | $version | $source | $hint |"
done >> "$OUTPUT_MD"

```

## Summary

- **Reverse-Skill** tracks tool availability through a coordinated pipeline of discovery, indexing, and capability verification.
- The **[`tool-discovery.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/tool-discovery.sh)** script performs host scanning using both `command -v` lookups and explicit path globbing to locate binaries.
- Results are persisted to **[`tool-index.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/tool-index.json)** (machine-readable) and **[`tool-index.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/tool-index.md)** (human-readable) via [`refresh-tool-index.sh`](https://github.com/zhaoxuya520/reverse-skill/blob/main/refresh-tool-index.sh).
- **Capability status** is determined by checking MCP registration in `~/.claude/mcp.json`/`~/.codex/config.toml` and verifying TCP/HTTP service health against [`bootstrap-manifest.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/bootstrap-manifest.json) definitions.
- The system respects distinct **verification modes** (registration-only, service-and-registration, etc.) to accurately report whether a tool is truly ready for automated use.

## Frequently Asked Questions

### How does reverse-skill find tools that are not in the system PATH?

The discovery scripts check both `command -v` and explicit fallback paths defined in the tool catalog. For example, `jadx` is searched not only as a command but also at `${HOME}/tools/jadx/bin/jadx` and `/opt/jadx/bin/jadx`. The `compgen -G` command expands glob patterns, allowing the system to find tools installed in versioned directories without knowing the exact path.

### What is the difference between "available" and "ready" in the tool index?

**Available** indicates the binary exists on the filesystem and is executable. **Ready** indicates the full operational capability is online, which may require MCP registration in client config files and active TCP service listeners. A tool can be available but not ready if its MCP server is unregistered or offline.

### Where does reverse-skill store MCP registration information?

The system reads client-specific configuration files: `~/.claude/mcp.json` for Claude-based agents and `~/.codex/config.toml` for CodeX-based agents. These files are parsed during the capability enrichment stage to build a `registered_names` set used in readiness calculations.

### Can the refresh scripts install missing tools automatically?

No. According to the repository's design philosophy, the refresh scripts are **detection-only** and never modify the host system. When a tool is missing, the index includes an install hint generated by the `install_hint()` function, but the actual installation must be performed manually or through separate bootstrap procedures.