Skip to content

Commit 4d57352

Browse files
committed
implements dynamic_tools for clickhouse config section, fix #27
Signed-off-by: Slach <bloodjazman@gmail.com>
1 parent 8f214a5 commit 4d57352

File tree

6 files changed

+417
-12
lines changed

6 files changed

+417
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ AGENTS.md
1010
.kilocode/
1111
.crush/
1212
.code/
13+
.claude/
1314
build/
1415
dist/
1516
coverage.out

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ A Model Context Protocol (MCP) server that provides tools for interacting with C
1010
- **JWE Authentication**: Optional JWE-based authentication with encryption for secure database access
1111
- **TLS Support**: Full TLS encryption support for both ClickHouse® connections and MCP server endpoints
1212
- **Comprehensive Tools**: Built-in tools for listing tables, describing schemas, and executing queries
13+
- **Dynamic Tools**: Automatically generate MCP tools from ClickHouse® views (see [Dynamic Tools Documentation](docs/dynamic_tools.md))
1314
- **Resource Templates**: Dynamic resource discovery for database schemas and table information
1415
- **Query Prompts**: AI-assisted query building and optimization prompts
1516
- **Configuration Management**: Flexible configuration via files, environment variables, or CLI flags
@@ -183,11 +184,18 @@ server:
183184
openapi:
184185
enabled: false
185186
tls: false
187+
dynamic_tools:
188+
- regexp: "mydb\\..*"
189+
prefix: "db_"
190+
- name: "get_user_data"
191+
regexp: "users\\.user_info_view"
186192

187193
logging:
188194
level: "info"
189195
```
190196
197+
> **Note**: For detailed information about dynamic tools configuration, see the [Dynamic Tools Documentation](docs/dynamic_tools.md).
198+
191199
Use the configuration file:
192200
193201
```bash

docs/dynamic_tools.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
# Dynamic Tools
2+
3+
Dynamic tools in Altinity MCP Server allow you to automatically generate MCP tools from ClickHouse views. This feature enables you to expose parameterized views as callable tools through the MCP interface.
4+
5+
## Overview
6+
7+
Dynamic tools are configured in the `server.dynamic_tools` section of the configuration file. The server will query `system.tables` for views and create corresponding MCP tools based on the rules you define.
8+
9+
## Configuration
10+
11+
Each dynamic tool rule consists of three optional fields:
12+
13+
- **`name`** (optional): The explicit name for the generated tool. When specified, the regexp must match exactly one view from `system.tables`. If not specified, the tool name is generated from the matched view name.
14+
- **`regexp`** (required): A regular expression pattern to match against view names in the format `database.view_name`.
15+
- **`prefix`** (optional): A prefix to prepend to the tool name (applied before name generation or to the explicit name).
16+
17+
### Basic Configuration
18+
19+
```yaml
20+
server:
21+
dynamic_tools:
22+
- regexp: "mydb\\..*"
23+
prefix: "db_"
24+
```
25+
26+
This configuration will:
27+
- Match all views in the `mydb` database
28+
- Generate tool names like `db_mydb_my_view` for each matched view
29+
30+
### Named Tool Configuration
31+
32+
```yaml
33+
server:
34+
dynamic_tools:
35+
- name: "get_user_data"
36+
regexp: "users\\.user_info_view"
37+
prefix: "api_"
38+
```
39+
40+
This configuration will:
41+
- Match exactly one view: `users.user_info_view`
42+
- Create a tool named `api_get_user_data`
43+
- Log an error if the regexp matches zero or multiple views
44+
45+
### Mixed Configuration
46+
47+
You can combine both approaches:
48+
49+
```yaml
50+
server:
51+
dynamic_tools:
52+
# Generate tools for all views in analytics database
53+
- regexp: "analytics\\..*"
54+
prefix: "analytics_"
55+
56+
# Specific tool with custom name
57+
- name: "get_current_metrics"
58+
regexp: "monitoring\\.current_metrics_view"
59+
60+
# Another specific tool with prefix
61+
- name: "user_report"
62+
regexp: "reports\\.user_activity"
63+
prefix: "report_"
64+
```
65+
66+
## View Parameters
67+
68+
Dynamic tools automatically detect parameters in your ClickHouse view definitions. Parameters are defined using the `{parameter_name: type}` syntax in the view's SQL.
69+
70+
### Example View with Parameters
71+
72+
```sql
73+
CREATE VIEW analytics.user_sessions AS
74+
SELECT
75+
user_id,
76+
session_start,
77+
session_end,
78+
duration_seconds
79+
FROM sessions
80+
WHERE user_id = {user_id: UInt64}
81+
AND session_start >= {start_date: Date}
82+
AND session_start < {end_date: Date}
83+
COMMENT 'Get user session data for a specific date range'
84+
```
85+
86+
This view will generate a tool with three parameters:
87+
- `user_id` (number/integer)
88+
- `start_date` (string/date)
89+
- `end_date` (string/date)
90+
91+
The view's `COMMENT` will be used as the tool's description. If no comment is provided, a default description is generated.
92+
93+
## Type Mapping
94+
95+
ClickHouse types are automatically mapped to JSON Schema types for the MCP tool interface:
96+
97+
| ClickHouse Type | JSON Type | JSON Format |
98+
|----------------|-----------|-------------|
99+
| Int*, UInt* | integer | int64 |
100+
| Float*, Decimal* | number | double |
101+
| Bool, UInt8 | boolean | - |
102+
| Date, Date32 | string | date |
103+
| DateTime* | string | date-time |
104+
| UUID | string | uuid |
105+
| Other types | string | - |
106+
107+
## Tool Name Generation
108+
109+
Tool names are generated using the following rules:
110+
111+
1. If `name` is specified: `snake_case(prefix + name)`
112+
2. If `name` is not specified: `snake_case(prefix + database.view_name)`
113+
114+
The `snake_case` function converts the name to lowercase and replaces non-alphanumeric characters with underscores.
115+
116+
### Examples
117+
118+
| Name | Regexp | Prefix | Matched View | Generated Tool Name |
119+
|------|--------|--------|--------------|---------------------|
120+
| - | `mydb\\.my_view` | `api_` | `mydb.my_view` | `api_mydb_my_view` |
121+
| `get_data` | `mydb\\.my_view` | `api_` | `mydb.my_view` | `api_get_data` |
122+
| `get_data` | `mydb\\.my_view` | - | `mydb.my_view` | `get_data` |
123+
| - | `mydb\\..*` | - | `mydb.users` | `mydb_users` |
124+
125+
## Validation Rules
126+
127+
The dynamic tools system enforces several validation rules:
128+
129+
1. **Regexp Validity**: All regular expressions must be valid. Invalid patterns are logged as errors and skipped.
130+
131+
2. **No Overlaps**: Each view can only be matched by one rule. If a view matches multiple rules, it will be logged as an error and skipped.
132+
133+
3. **Named Rules Must Match Exactly Once**: When a rule specifies a `name`, the `regexp` must match exactly one view from `system.tables`. The system will log an error if:
134+
- The regexp matches zero views
135+
- The regexp matches more than one view
136+
137+
4. **View Requirements**: Only views with `engine='View'` are considered for dynamic tool generation.
138+
139+
## Error Handling
140+
141+
The dynamic tools system logs errors in the following cases:
142+
143+
- **Invalid regexp**: `dynamic_tools: invalid regexp, skipping rule`
144+
- **Overlap detected**: `dynamic_tools: overlap between rules detected for view`
145+
- **Named rule matches zero views**: `dynamic_tools: named rule matched no views`
146+
- **Named rule matches multiple views**: `dynamic_tools: named rule matched multiple views, expected exactly one`
147+
148+
These errors are logged but do not prevent the server from starting. Valid rules will still be processed.
149+
150+
## Complete Example
151+
152+
```yaml
153+
clickhouse:
154+
host: localhost
155+
port: 8123
156+
database: default
157+
username: default
158+
password: ""
159+
protocol: http
160+
161+
server:
162+
transport: http
163+
address: 0.0.0.0
164+
port: 8080
165+
openapi:
166+
enabled: true
167+
dynamic_tools:
168+
# Match all views in analytics database
169+
- regexp: "analytics\\..*"
170+
prefix: "analytics_"
171+
172+
# Specific tool for user data
173+
- name: "get_user_info"
174+
regexp: "users\\.user_info_view"
175+
prefix: "api_"
176+
177+
# Specific tool for metrics (no prefix)
178+
- name: "current_metrics"
179+
regexp: "monitoring\\.metrics_view"
180+
181+
logging:
182+
level: info
183+
```
184+
185+
## OpenAPI Integration
186+
187+
Dynamic tools are automatically exposed through the OpenAPI endpoints when `server.openapi.enabled` is set to `true`. Each tool gets:
188+
189+
- A POST endpoint at `/{jwe_token}/openapi/{tool_name}`
190+
- Request body schema based on the view parameters
191+
- Response schema for the query results
192+
193+
## Best Practices
194+
195+
1. **Use descriptive names**: When using the `name` field, choose clear, descriptive names that indicate the tool's purpose.
196+
197+
2. **Add comments to views**: Use the `COMMENT` clause in your view definitions to provide meaningful descriptions for the generated tools.
198+
199+
3. **Use specific regexps**: For named tools, use specific regular expressions to ensure only one view matches.
200+
201+
4. **Organize by database**: Group related views in the same database and use regexp patterns to generate tools for entire databases.
202+
203+
5. **Test your regexps**: Before deploying, test your regular expressions to ensure they match the intended views.
204+
205+
6. **Monitor logs**: Check the server logs during startup to catch any validation errors or misconfigurations.
206+
207+
## Troubleshooting
208+
209+
### Tool not being generated
210+
211+
1. Check that the view exists in `system.tables` with `engine='View'`
212+
2. Verify the regexp pattern matches the view name in the format `database.view_name`
213+
3. Check for overlap errors in the logs
214+
215+
### Named tool reports "matched no views"
216+
217+
1. Verify the view name format is `database.view_name`
218+
2. Check that the view exists in ClickHouse
219+
3. Ensure the regexp pattern correctly escapes special characters (e.g., `\\.` for dots)
220+
221+
### Named tool reports "matched multiple views"
222+
223+
1. Make the regexp more specific to match only one view
224+
2. Consider using a different approach or splitting into multiple rules
225+
226+
### Parameters not detected
227+
228+
1. Ensure parameters are defined using the correct syntax: `{param_name: Type}`
229+
2. Check that the parameter names are valid identifiers (letters, numbers, underscores)
230+
3. Verify the view's `CREATE` statement is accessible in `system.tables.create_table_query`

pkg/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ type OpenAPIConfig struct {
9292

9393
// DynamicToolRule describes a rule to create dynamic tools from views
9494
type DynamicToolRule struct {
95+
Name string `json:"name" yaml:"name"`
9596
Regexp string `json:"regexp" yaml:"regexp"`
9697
Prefix string `json:"prefix" yaml:"prefix"`
9798
}

0 commit comments

Comments
 (0)