Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
FROM python:3.12-alpine
FROM python:3.11-alpine

# Install dependencies
RUN apk add --no-cache gcc musl-dev linux-headers
Expand Down
110 changes: 107 additions & 3 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,31 @@ IoTDB MCP Server 是一个基于模型上下文协议(Model Context Protocol,

此服务器不提供任何提示。

## 权限模型

IoTDB MCP 权限默认是提示层。服务器为 SQL 操作返回所需权限、风险级别和确认参数,
由宿主 agent system 负责用户审批。执行 DDL/DML 或破坏性 SQL 前,如果可用,应先使用
`inspect_sql_permission`。

长期托管 agent 可以通过环境变量提供 full permission 默认值,例如
`IOTDB_SQL_DRIVER_MODE=full` 和 `TIMESEEK_MCP_PERMISSION_ENFORCEMENT=advisory`。
只有需要 MCP server 自身硬阻断时,才设置
`TIMESEEK_MCP_PERMISSION_ENFORCEMENT=strict`。

### 工具

服务器为 IoTDB 的树模型(Tree Model)和表模型(Table Model)提供了不同的工具。您可以通过设置 "IOTDB_SQL_DIALECT" 配置为 "tree" 或 "table" 来选择使用哪种模型。

方言相关的标识符语义:

- 树模型:
- `FROM` 中使用显式的 `root...` 路径。
- `SELECT` 投影通常应使用测点名,而不是完整 `root...` 路径。
- `IOTDB_DATABASE` 只作为连接/会话范围提示,树模型 SQL 仍应显式写出 `root...` 路径。
- 表模型:
- `FROM` 中使用当前数据库下的表名。
- `SELECT` 投影使用列名。

#### 树模型 (Tree Model)

- `metadata_query`
Expand Down Expand Up @@ -49,13 +70,70 @@ IoTDB MCP Server 是一个基于模型上下文协议(Model Context Protocol,
- SUM, COUNT, MAX_VALUE, MIN_VALUE, AVG, VARIANCE, MAX_TIME, MIN_TIME 等
- 返回: 查询结果作为对象数组

- `sql_executor_batch`

- 并行执行多条只读 SQL,并将每个子结果写入 ResultStore
- 输入:
- `sqls` (数组): 显式单语句 SQL,或
- `sql_template` + `param_sets`: SQL 模板和参数对象列表
- `max_concurrency` (整数): 并发语句上限,默认 4
- `worker_pool_size` (整数): 线程 worker pool 大小,默认跟随并发度,并受 `IOTDB_SQL_EXECUTOR_BATCH_MAX_WORKER_POOL_SIZE` 限制(默认 16)
- `per_item_timeout_ms` (整数): 单条语句等待超时,默认 60000
- `batch_timeout_ms` (整数): 整个 batch 等待超时,默认 300000
- `max_result_rows_per_item` / `max_result_bytes_per_item`: 单条语句结果 quota,默认 10000 行和 16 MiB
- `max_batch_result_rows` / `max_batch_result_bytes`: 整个 batch 结果 quota,默认 100000 行和 64 MiB
- 模板占位符:
- `{{name}}` 表示 SQL 字面量,`{{name:path}}` 表示 IoTDB 路径,`{{name:identifier}}` 表示 SQL 标识符
- 返回: batch 汇总,以及每条 SQL 的 `result_id`、行数、预览行和分页信息

- `read_result_pages`

- 一次 MCP 调用读取多个 ResultStore page
- 输入:
- `pages` (数组): page 请求对象,包含 `result_id`,可选 `cursor`、`offset`、`limit`、`owner_session_id`
- `default_limit` (整数): 未设置 `limit` 时的默认 page 大小
- `max_pages` / `max_total_rows`: 单次调用 quota,默认 32 个 page 和 10000 行
- `continue_on_error` (布尔): 是否以 per-item error 返回,默认 true
- 返回: 批量读页汇总,以及每个 page 的 rows、cursor 和错误信息

- `export_query`
- 执行查询并将结果导出为 CSV 或 Excel 文件
- 输入:
- `query_sql` (字符串): 要执行的 SQL 查询(使用树模型方言)
- `format` (字符串): 导出格式,可以是 "csv" 或 "excel"(默认: "csv")
- `filename` (字符串): 导出文件的文件名(可选,如果未提供,将生成唯一文件名)
- 返回: 有关导出文件的信息和数据预览(最多 10 行)
- `model_inference`
- 执行 AINode `CALL INFERENCE(...)` SQL 并返回结果集
- 输入:
- `inference_sql` (字符串): 以 `CALL INFERENCE` 开头的单条树模型 SQL
- 执行前校验模型 ID、带引号的输入 SELECT SQL、显式非通配列,以及支持的参数
(`generateTime`, `outputLength`)
- 权限信息:模型管理能力通过 MCP advisory policy 层返回。仅在 strict 模式下才硬性执行
`IOTDB_ENABLE_MODEL_MANAGEMENT=true` 和 `IOTDB_MODEL_ALLOWED_USERS`。
- `prepare_model_inference_request`
- 通过结构化字段构造并校验 AINode `CALL INFERENCE(...)` SQL
- 输入:
- `model_id` (字符串): 已注册的 AINode 模型 ID
- `input_sql` (字符串): 作为模型输入的有界树模型 SELECT 查询
- `output_length` (整数): 预测输出长度(默认: 96)
- `generate_time` (布尔): 是否请求 Time 列(默认: false)

#### UDF 工具

- `list_udf_functions`
- 对所选 IoTDB target 执行 `SHOW FUNCTIONS`。
- `prepare_udf_query`
- 使用结构化参数生成只读 UDF `SELECT`。
- 树模型形式:`SELECT UDF(measurement, "k"="v") FROM root.sg.d1 ...`
- 表模型形式:`SELECT UDF(column, "k"="v") FROM table ...`
- `execute_udf_query`
- 执行校验后的 UDF 查询,并返回 ResultStore 支持的预览结果。
- `export_udf_query`
- 执行校验后的 UDF 查询,并导出为 CSV 或 Excel。

UDF 工具会拒绝表达式和过滤条件中的分号、SQL 注释以及 DDL/DML 关键字。
它们用于只读 UDF 调用,例如数据质量、画像、修复规划和异常评分。

#### 表模型 (Table Model)

Expand Down Expand Up @@ -96,11 +174,37 @@ IoTDB MCP Server 支持以下配置选项,可以通过环境变量或命令行
| --host | IOTDB_HOST | 127.0.0.1 | IoTDB 主机地址 |
| --port | IOTDB_PORT | 6667 | IoTDB 端口 |
| --user | IOTDB_USER | root | IoTDB 用户名 |
| --password | IOTDB_PASSWORD | root | IoTDB 密码 |
| --database | IOTDB_DATABASE | test | IoTDB 数据库名称 |
| --password | IOTDB_PASSWORD | | IoTDB 密码 |
| --database | IOTDB_DATABASE | test | 表模型: 当前数据库名;树模型: 可选的连接/范围提示,查询仍需显式使用 `root...` 路径 |
| --sql-dialect | IOTDB_SQL_DIALECT | table | SQL 方言: tree 或 table |
| --export-path | IOTDB_EXPORT_PATH | /tmp | 查询结果导出路径 |

target registry 只保存已经成功登录的连接。先用 `prepare_iotdb_target` 创建
不含凭据、不可执行 SQL 的临时 candidate,再把用户明确提供的账号密码传给
`connect_iotdb_target`,并且只认证一次。缺少凭据时必须询问用户,禁止探测空
密码或默认密码;用户明确说明空密码时,空字符串才是有效凭据。

登录成功后,MCP 会原子发布 target,并自动记录 per-target
`last_known_good_credential`。任何连接层错误都会消费 candidate 或驱逐已发布
target。只有用户明确要求重连后,才能创建新 candidate,并传入
`user_confirmed_retry=true`。公开 target 响应会脱敏当前密码和
last-known-good 密码。

配置 `TIMESEEK_IOTDB_TARGETS_FILE` 后,成功连接默认会持久化。通过
`iotdb-target-cli` 启动本地 Java CLI,即可复用完全相同的 target:

```bash
iotdb-target-cli --target-id cloud \
--cli /opt/iotdb/sbin/start-cli.sh -- -e "SHOW VERSION"
```

wrapper 每次启动都会重新加载已验证 target,并注入 host、port、方言、用户名和
last-known-good 密码。Java CLI 不支持 `-db`,因此 wrapper 不会向
`start-cli.sh` 传该参数;Table 数据库应通过 SQL `USE <database>` 选择。对于支持
`-db` 的 `import-data.sh` 和 `import-data.bat`,wrapper 仍会自动注入 Table
target 的数据库。已验证的空密码会省略 `-pw`,命令预览会脱敏非空密码。直接调用
`start-cli.sh` 不会读取 target registry。

## 性能优化

IoTDB MCP Server 包含以下性能优化特性:
Expand Down Expand Up @@ -166,7 +270,7 @@ uv sync
"IOTDB_HOST": "127.0.0.1",
"IOTDB_PORT": "6667",
"IOTDB_USER": "root",
"IOTDB_PASSWORD": "root",
"IOTDB_PASSWORD": "",
"IOTDB_DATABASE": "test",
"IOTDB_SQL_DIALECT": "table",
"IOTDB_EXPORT_PATH": "/path/to/export/folder"
Expand Down
114 changes: 111 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,33 @@ The server doesn't expose any resources.

The server doesn't provide any prompts.

## Permission Model

IoTDB MCP permissions are advisory by default. The server reports the required
permission, risk level, and confirmation parameter for SQL actions, while the
host agent system owns user approval. Use `inspect_sql_permission` before
executing DDL/DML or destructive SQL when the tool is available.

Long-running hosted agents can provide full-permission defaults with
environment variables such as `IOTDB_SQL_DRIVER_MODE=full` and
`TIMESEEK_MCP_PERMISSION_ENFORCEMENT=advisory`. Set
`TIMESEEK_MCP_PERMISSION_ENFORCEMENT=strict` only when the MCP server itself
should hard-block disallowed operations.

### Tools

The server offers different tools for IoTDB Tree Model and Table Model. You can choose between them by setting the "IOTDB_SQL_DIALECT" configuration to either "tree" or "table".

Dialect-specific identifier semantics:

- Tree dialect:
- `FROM` targets use explicit `root...` paths.
- Projection expressions should usually use measurement names instead of full `root...` paths.
- `IOTDB_DATABASE` is only a connection/session hint; tree SQL still needs explicit root paths.
- Table dialect:
- `FROM` targets use table names in the current database.
- Projection expressions use column names.

#### Tree Model

- `metadata_query`
Expand All @@ -45,13 +68,68 @@ The server offers different tools for IoTDB Tree Model and Table Model. You can
- Supported functions:
- SUM, COUNT, MAX_VALUE, MIN_VALUE, AVG, VARIANCE, MAX_TIME, MIN_TIME, etc.
- Returns: Query results as array of objects
- `sql_executor_batch`
- Execute multiple readonly SQL statements in parallel and store each result in ResultStore
- Input:
- `sqls` (array): Explicit single SQL statements, or
- `sql_template` + `param_sets`: Repeated SQL template with parameter objects
- `max_concurrency` (integer): Concurrent statement limit, default 4
- `worker_pool_size` (integer): Thread worker pool size, default follows concurrency and is capped by `IOTDB_SQL_EXECUTOR_BATCH_MAX_WORKER_POOL_SIZE` (default 16)
- `per_item_timeout_ms` (integer): Per-statement wait timeout, default 60000
- `batch_timeout_ms` (integer): Whole-batch wait timeout, default 300000
- `max_result_rows_per_item` / `max_result_bytes_per_item`: Per-statement result quota, defaults 10000 rows and 16 MiB
- `max_batch_result_rows` / `max_batch_result_bytes`: Whole-batch result quota, defaults 100000 rows and 64 MiB
- Template placeholders:
- `{{name}}` for SQL literals, `{{name:path}}` for IoTDB paths, `{{name:identifier}}` for SQL identifiers
- Returns: Batch summary plus per-statement `result_id`, row count, preview rows, and paging metadata
- `read_result_pages`
- Read multiple ResultStore pages in one MCP call
- Input:
- `pages` (array): Page request objects with `result_id` plus optional `cursor`, `offset`, `limit`, and `owner_session_id`
- `default_limit` (integer): Default page size for items without `limit`
- `max_pages` / `max_total_rows`: Per-call quotas, defaults 32 pages and 10000 rows
- `continue_on_error` (boolean): Return per-item errors instead of aborting, default true
- Returns: Batch page summary plus per-page rows, cursors, and errors
- `export_query`
- Execute a query and export the results to a CSV or Excel file
- Input:
- `query_sql` (string): The SQL query to execute (using TREE dialect)
- `format` (string): Export format, either "csv" or "excel" (default: "csv")
- `filename` (string): Optional filename for the exported file. If not provided, a unique filename will be generated.
- Returns: Information about the exported file and a preview of the data (max 10 rows)
- `model_inference`
- Execute AINode `CALL INFERENCE(...)` SQL and return the result set
- Input:
- `inference_sql` (string): A single Tree-dialect SQL statement starting with `CALL INFERENCE`
- Validates model id, quoted input SELECT SQL, explicit non-wildcard columns,
and supported parameters (`generateTime`, `outputLength`) before execution
- Permission metadata: model management is reported through the advisory MCP
policy layer. In strict mode, `IOTDB_ENABLE_MODEL_MANAGEMENT=true` and
`IOTDB_MODEL_ALLOWED_USERS` are enforced.
- `prepare_model_inference_request`
- Build and validate AINode `CALL INFERENCE(...)` SQL from structured fields
- Input:
- `model_id` (string): Registered AINode model id
- `input_sql` (string): Bounded Tree-dialect SELECT query used as model input
- `output_length` (int): Forecast output length (default: 96)
- `generate_time` (bool): Whether to request a Time column (default: false)

#### UDF Tools

- `list_udf_functions`
- Execute `SHOW FUNCTIONS` for the selected IoTDB target.
- `prepare_udf_query`
- Build a read-only UDF `SELECT` from structured inputs.
- Tree form: `SELECT UDF(measurement, "k"="v") FROM root.sg.d1 ...`
- Table form: `SELECT UDF(column, "k"="v") FROM table ...`
- `execute_udf_query`
- Execute the validated UDF query and return a ResultStore-backed preview.
- `export_udf_query`
- Execute the validated UDF query and export the result set to CSV or Excel.

UDF tools reject semicolons, SQL comments, and DDL/DML keywords in expressions
and filter clauses. They are intended for read-only UDF calls such as data
quality, profiling, repair planning, and anomaly scoring.

#### Table Model

Expand Down Expand Up @@ -95,11 +173,41 @@ IoTDB MCP Server supports the following configuration options, which can be set
| --host | IOTDB_HOST | 127.0.0.1 | IoTDB host address |
| --port | IOTDB_PORT | 6667 | IoTDB port |
| --user | IOTDB_USER | root | IoTDB username |
| --password | IOTDB_PASSWORD | root | IoTDB password |
| --database | IOTDB_DATABASE | test | IoTDB database name |
| --password | IOTDB_PASSWORD | empty | IoTDB password |
| --database | IOTDB_DATABASE | test | Table dialect: current database name. Tree dialect: optional session/root scope hint; queries still use explicit `root...` paths. |
| --sql-dialect | IOTDB_SQL_DIALECT | table | SQL dialect: tree or table |
| --export-path | IOTDB_EXPORT_PATH | /tmp | Path for exporting query results |

The target registry contains only connections that have completed a successful
login. Call `prepare_iotdb_target` with non-secret fields, then pass explicitly
user-supplied credentials to `connect_iotdb_target` for one authentication
attempt. If credentials are absent, ask the user; never probe empty or default
passwords. An explicitly supplied empty password remains valid input.

Successful login atomically publishes the target and records its per-target
`last_known_good_credential`. Any connection-layer failure consumes the
candidate or evicts the published target. A retry requires a new candidate and
`user_confirmed_retry=true` after explicit user instruction. Public target
responses redact both the active password and last-known-good password.

When `TIMESEEK_IOTDB_TARGETS_FILE` is configured, successful connections are
persisted by default. The local Java CLI can reuse exactly that target through
`iotdb-target-cli`:

```bash
iotdb-target-cli --target-id cloud \
--cli /opt/iotdb/sbin/start-cli.sh -- -e "SHOW VERSION"
```

The wrapper reloads the verified target on every invocation and supplies its
host, port, dialect, username, and last-known-good password. It does not pass
`-db` to `start-cli.sh`, because the Java CLI does not support that option;
select a table database with SQL `USE <database>`. For `import-data.sh` and
`import-data.bat`, which do support `-db`, a table target's database is injected
automatically. A verified empty password is represented by omitting `-pw`, and
command previews redact non-empty passwords. Calling `start-cli.sh` directly
does not read the target registry.

## Performance Optimizations

IoTDB MCP Server includes the following performance optimization features:
Expand Down Expand Up @@ -165,7 +273,7 @@ Add the following configuration to Claude Desktop's configuration file:
"IOTDB_HOST": "127.0.0.1",
"IOTDB_PORT": "6667",
"IOTDB_USER": "root",
"IOTDB_PASSWORD": "root",
"IOTDB_PASSWORD": "",
"IOTDB_DATABASE": "test",
"IOTDB_SQL_DIALECT": "table",
"IOTDB_EXPORT_PATH": "/path/to/export/folder"
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description = "A Model Context Protocol (MCP) server that enables secure interac
readme = "README.md"
license = "Apache-2.0"
license-file="LICENSE"
requires-python = ">=3.12"
requires-python = ">=3.11"
dependencies = [
"fastmcp>=2.8.1",
"apache-iotdb>=2.0.4",
Expand All @@ -33,3 +33,4 @@ dev-dependencies = [

[project.scripts]
iotdb-mcp-server = "iotdb_mcp_server:main"
iotdb-target-cli = "iotdb_mcp_server.target_cli:main"
4 changes: 2 additions & 2 deletions smithery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ startCommand:
description: IoTDB username
password:
type: string
default: root
default: ""
description: IoTDB password
database:
type: string
Expand All @@ -50,5 +50,5 @@ startCommand:
host: 127.0.0.1
port: 6667
user: root
password: root
password: ""
database: test
Loading