|
| 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` |
0 commit comments