# Test via Inspector Guide

MCP Inspector is a tool for testing and debugging MCP servers. This guide explains how to use it to test the BanyanDB MCP server.

## Prerequisites

- MCP server set up (see [Setup Guide](setup.md))
- BanyanDB running and accessible
- Node.js 20+ installed (for running Inspector)

## Installation

Install MCP Inspector globally:

```bash
npm install -g @modelcontextprotocol/inspector
```

Or use it directly with npx (no installation needed):

```bash
npx @modelcontextprotocol/inspector
```

## Basic Setup

### 1. Create Configuration File

```bash
cp example-config.json inspector-config.json
```

Edit `inspector-config.json` with absolute path, api key and base url.

**Important:** Use absolute paths for the binary location.

### 2. Start Inspector (UI Mode)

```bash
npx @modelcontextprotocol/inspector --config inspector-config.json
```

This will:
- Start the MCP server
- Open a web UI at `http://localhost:6274` in your default browser
- Allow you to interactively test MCP tools

### 3. Using the Inspector UI

1. **View Available Tools**: The UI shows all available MCP tools:
   - `list_groups_schemas` — discover groups, streams, measures, traces, and properties
   - `list_resources_bydbql` — execute a BydbQL query against BanyanDB
   - `get_generate_bydbql_prompt` — get the full prompt text for BydbQL generation (useful for external integrations)
2. **Test Queries**: Use `get_generate_bydbql_prompt` to generate BydbQL from a natural language description, then pass the result to `list_resources_bydbql`
3. **View Results**: See the query results returned from BanyanDB
4. **Debug**: Check logs and error messages in the Inspector console

The MCP server also exposes a prompt named `generate_BydbQL`. MCP clients that support prompts (e.g., Claude Desktop) can invoke it directly to produce BydbQL from natural language. It accepts the same optional hints (`resource_type`, `resource_name`, `group`) as the tools.

## CLI Mode

You can also use Inspector in CLI mode for scripting and automation:

```bash
# Step 1: generate a BydbQL query from natural language
npx @modelcontextprotocol/inspector --cli node dist/index.js \
  -e BANYANDB_ADDRESS=localhost:17900 \
  --method tools/call \
  --tool-name get_generate_bydbql_prompt \
  --tool-arg "description=Show MEASURE service_cpm_minute in sw_metricsMinute from last hour"

# Step 2: execute the generated BydbQL
npx @modelcontextprotocol/inspector --cli node dist/index.js \
  -e BANYANDB_ADDRESS=localhost:17900 \
  --method tools/call \
  --tool-name list_resources_bydbql \
  --tool-arg "BydbQL=SELECT * FROM MEASURE service_cpm_minute IN sw_metricsMinute TIME > '-1h'"
```

## Available Tools

### `list_groups_schemas`

Discover resources in BanyanDB. Use this before querying to find available groups and resource names.

| Parameter | Required | Description |
|-----------|----------|-------------|
| `resource_type` | Yes | `groups`, `streams`, `measures`, `traces`, or `properties` |
| `group` | Conditional | Required for all types except `groups` |

### `list_resources_bydbql`

Execute a BydbQL query against BanyanDB and return the results.

| Parameter | Required | Description |
|-----------|----------|-------------|
| `BydbQL` | Yes | BydbQL query string to execute |
| `resource_type` | No | Hint: `stream`, `measure`, `trace`, or `property` |
| `resource_name` | No | Resource name hint |
| `group` | No | Group name hint |

### `get_generate_bydbql_prompt`

Return the full prompt text used by `generate_BydbQL`, including live BanyanDB schema hints. Useful for external integrations that need to call their own LLM to produce BydbQL.

| Parameter | Required | Description |
|-----------|----------|-------------|
| `description` | Yes | Natural language query description |
| `resource_type` | No | Optional type hint |
| `resource_name` | No | Optional resource name hint |
| `group` | No | Optional group hint |

### `generate_BydbQL` (MCP Prompt)

An MCP prompt (not a tool) that converts natural language to BydbQL. MCP clients that support prompts (such as Claude Desktop) can invoke it directly — the server fetches live schema information and returns a structured prompt for the client's LLM to process.

## Usage Examples

The MCP server provides BydbQL query generation from natural language. The typical workflow is:

1. Use `list_groups_schemas` to discover available resources
2. Use `get_generate_bydbql_prompt` (or the `generate_BydbQL` prompt) to obtain a BydbQL query from a natural language description
3. Use `list_resources_bydbql` to execute the BydbQL query

### Example 1: Measure Query

**Natural Language Description:**
```
list the last 30 minutes service_cpm_minute
```

**Generated BydbQL Query:**
```sql
SELECT * FROM MEASURE service_cpm_minute IN metricsMinute TIME > '-30m'
```

**Result:**
```
=== Query Result ===

Measure Query Result:
[{
    "timestamp": "2025-11-24T09:21:00Z",
    "tagFamilies": [
      {
        "name": "storage-only",
        "tags": [
          {
            "key": "entity_id",
            "value": {
              "str": {
                "value": "Ki01fGRldi1lc2hvcHxhcHAtY2x1c3Rlci0xLTA=.1"
              }
            }
          } 
        ],
        "fields": [
          {
            "name": "value",
            "value": {
              "int": {
                "value": "8"
              }
            }
          }
        ],
        "sid": "3370749934026519158",
        "version": "77686909415634"
      },
    ]
}]
=== BydbQL Query ===
SELECT * FROM MEASURE service_cpm_minute IN metricsMinute TIME > '-30m'

=== Debug Information ===
Description: list the last day service_cpm_minute
Resource Type: measure
Resource Name: service_cpm_minute
Group: metricsMinute

=== Explanations ===
This query selects all data from the resource 'service_cpm_minute' of type MEASURE in the group 'metricsMinute' for the last 30 minutes, as specified in the description.
```

### Example 2: Querying a Stream

**Natural Language Description:**
```
list log data in last day
```

**Generated BydbQL Query:**
```sql
SELECT * FROM STREAM log IN recordsLog TIME >= '-1h'
```

**Result:**
```
=== Query Result ===

Stream Query Result:
{
  "elements": [
    {
      "elementId": "da29bd8e7d4c8192",
      "timestamp": "2025-11-24T09:20:00Z",
      "tagFamilies": [
        {
          "name": "searchable",
          "tags": [
            {
              "key": "tags",
              "value": {
                "null": null
              }
            },
            {
              "key": "unique_id",
              "value": {
                "str": {
                  "value": "898482062a414e54b805aa3f106d52bc_3559"
                }
              }
            },]
      }]
    },
  ]
}

=== BydbQL Query ===
SELECT * FROM STREAM log IN recordsLog TIME > '-1d'

=== Debug Information ===
Description: list log data in the last day
Resource Type: stream
Resource Name: log
Group: recordsLog

=== Explanations ===
This query retrieves all log data from the 'recordsLog' group for the last day. The resource type is determined as STREAM from the keyword 'log', the resource name is extracted as 'log', and the group name is explicitly given as 'recordsLog'.
```

### Example 3: Querying Traces with LIMIT

**Natural Language Description:**
```
list the last 3 zipkin_span order by time
```

**Generated BydbQL Query:**
```sql
SELECT * FROM TRACE zipkin_span IN zipkinTrace ORDER BY timestamp_millis DESC LIMIT 3
```

**Result:**
```
=== Query Result ===

Trace Query Result:
{
  "traces": [
    {
      "spans":[
        {
          "tags": [],
          "span": "Cu4BCusBChBL/bXJzPoKPwA/2QwaTjL9Eghq7IDHs8/JEBoIU4Jqwt3AekAgASoIaHR0cC9nZXQxwENbkIc/BgA4mMIMQgoKCGNoZWNrb3V0WhIKC2h0dHAubWV0aG9kEgNHRVRaKwoJaHR0cC5wYXRoEh4vcHJveHkvYWNjb3VudGluZy5kZXYtcGF5bWVudHNaGgoSaHR0cC5yZXNwb25zZS5zaXplEgQxMjkwWkEKB3RldHJhdGUSNnYxLjEwLjAtaW50ZXJuYWwtcmMwLW9ic3Rlc3Rlci1lcnJvciAoOWNkOGFhNTJlLCArMzAxKRAC",
          "spanId": "53826ac2ddc07a40.5.15"
        },
      ]
      "traceId": "4bfdb5c9ccfa0a3f003fd90c1a4e32fd-6356"
    },
    {
      "spans": [
        {
          "tags": [],
          "span": "Cu4BCusBChBL/bXJzPoKPwA/2QwaTjL9Eghq7IDHs8/JEBoIU4Jqwt3AekAgASoIaHR0cC9nZXQxwENbkIc/BgA4mMIMQgoKCGNoZWNrb3V0WhIKC2h0dHAubWV0aG9kEgNHRVRaKwoJaHR0cC5wYXRoEh4vcHJveHkvYWNjb3VudGluZy5kZXYtcGF5bWVudHNaGgoSaHR0cC5yZXNwb25zZS5zaXplEgQxMjkwWkEKB3RldHJhdGUSNnYxLjEwLjAtaW50ZXJuYWwtcmMwLW9ic3Rlc3Rlci1lcnJvciAoOWNkOGFhNTJlLCArMzAxKRAC",
          "spanId": "53826ac2ddc07a40.5.15"
        },
      ]
      "traceId": "4bfdb5c9ccfa0a3f003fd90c1a4e32fd-6353"
    },
    {
      "spans": [
        {
          "tags": [],
          "span": "Cu4BCusBChBL/bXJzPoKPwA/2QwaTjL9Eghq7IDHs8/JEBoIU4Jqwt3AekAgASoIaHR0cC9nZXQxwENbkIc/BgA4mMIMQgoKCGNoZWNrb3V0WhIKC2h0dHAubWV0aG9kEgNHRVRaKwoJaHR0cC5wYXRoEh4vcHJveHkvYWNjb3VudGluZy5kZXYtcGF5bWVudHNaGgoSaHR0cC5yZXNwb25zZS5zaXplEgQxMjkwWkEKB3RldHJhdGUSNnYxLjEwLjAtaW50ZXJuYWwtcmMwLW9ic3Rlc3Rlci1lcnJvciAoOWNkOGFhNTJlLCArMzAxKRAC",
          "spanId": "53826ac2ddc07a40.5.15"
        },
      ]
      "traceId": "4bfdb5c9ccfa0a3f003fd90c1a4e32fd-6347"
    }
  ],
  "traceQueryResult": null
}

=== BydbQL Query ===
SELECT * FROM TRACE zipkin_span IN zipkinTrace ORDER BY timestamp_millis DESC LIMIT 3

=== Debug Information ===
Description: list the last 3 zipkin_span order by time
Resource Type: trace
Resource Name: zipkin_span
Group: zipkinTrace

=== Explanations ===
This query retrieves the last 3 entries of zipkin_span from the zipkinTrace group, ordered by timestamp_millis in descending order. The number of results is explicitly requested as 3.
```

### Example 4: Top-N Query with Aggregation

**Natural Language Description:**
```
Show TOP3 MEASURE endpoint_2xx from last 30 minutes, AGGREGATE BY MAX and ORDER BY DESC
```

**Generated BydbQL Query:**
```sql
SHOW TOP 3 FROM MEASURE endpoint_2xx IN metricsMinute TIME >= '-30m' AGGREGATE BY MAX ORDER BY DESC
```

**Result:**
```
=== Query Result ===

TopN Query Result:
{
  "lists": [
    {
      "timestamp": null,
      "items": [
        {
          "entity": [
            {
              "key": "entity_id",
              "value": {
                "str": {
                  "value": "ZGV2LXN0YWJsZXx0c2ItZ2F0ZXdheS1kZXYtZWRnZS0wfGRldi1lZGdlfHRyYW5zaXQtY2x1c3Rlci0xLTB8LQ==.1_R0VUOi9wcm94eS9vcmRlcnMvcHJveHkvY2hlY2tvdXQuZGV2LWNoZWNrb3V0L3Byb3h5L3BheW1lbnRzLnRldHJhdGUuZGV2L3Byb3h5L2FjY291bnRpbmcuZGV2LXBheW1lbnRzLTE="
                }
              }
            }
          ],
          "value": {
            "int": {
              "value": "1"
            }
          }
        }
      ]
    }
  ],
  "trace": null
}

=== BydbQL Query ===
SHOW TOP 3 FROM MEASURE endpoint_2xx IN metricsMinute TIME > '-30m' AGGREGATE BY MAX ORDER BY DESC

=== Debug Information ===
Description: Show TOP3 MEASURE endpoint_2xx from last 30 minutes, AGGREGATE BY MAX and ORDER BY DESC
Resource Type: measure
Resource Name: endpoint_2xx
Group: metricsMinute

=== Explanations ===
This query fetches the top 3 maximum values of the measure 'endpoint_2xx' from the group 'metricsMinute' over the last 30 minutes. The values were explicitly provided for resource name, group name, and aggregate function, while the time condition is derived from the description.
```

## Resource Lookup Behavior

The MCP server uses intelligent resource lookup when generating queries from natural language descriptions. Understanding this behavior helps you write more effective queries.

### Resource Name Lookup Across Groups

When the same resource name exists in multiple groups, the LLM will use the **first group it can look up** from the available resource mappings. The lookup process follows this order:

1. **Exact Match**: The LLM first attempts to find an exact match for the resource name
2. **First Available Group**: If the resource name appears in multiple groups, the LLM will use the first group it encounters during lookup
3. **Similarity Matching**: If an exact match cannot be found, the LLM will match the most similar resource name from the available resources

### Example Scenarios

**Scenario 1: Same Resource Name in Multiple Groups**

If you have a resource named `service_cpm` in both `metricsMinute` and `metricsHour` groups:

```
Description: "list service_cpm from last hour"
```

The LLM will use the first group it finds in the resource mapping. To ensure a specific group is used, explicitly mention it:

```
Description: "list service_cpm in metricsHour from last hour"
```

**Scenario 2: Similarity Matching**

If you request a resource that doesn't exist exactly, the LLM will find the most similar match:

```
Description: "list service_cpm from last hour"
Available resources: service_cpm_minute, service_cpm_hour
```

The LLM will match `service_cpm_minute` or `service_cpm_hour` based on similarity, preferring the closest match.

### Best Practices

- **Be Explicit**: When you know the exact group name, include it in your description (e.g., "in metricsMinute")
- **Use Specific Names**: Use the exact resource names from your BanyanDB schema when possible
- **Check Available Resources**: Use the `list_resources_bydbql` tool to see available resources and their groups before querying

## Troubleshooting

**Inspector UI not opening:**
- Check if port 6274 is available
- Verify the MCP server binary path is correct
- Check Inspector logs for errors

**MCP server not starting:**
- Verify Node.js 20+ is installed: `node --version`
- Check environment variables are set correctly
- Verify BanyanDB is accessible: `curl http://localhost:17913/api/healthz`

**Query generation fails:**
- Check Inspector console for error messages
- Verify BanyanDB is accessible: `curl http://localhost:17913/api/healthz`
- Use `list_groups_schemas` to confirm resource names and groups exist

**No results returned:**
- Verify BanyanDB has data for the queried resources
- Check time range is appropriate
- Verify resource names and groups are correct

## Resources

- [MCP Inspector Documentation](https://github.com/modelcontextprotocol/inspector)
- [MCP Protocol Documentation](https://modelcontextprotocol.io/)
- [BanyanDB Documentation](../../../README.md)

