The SSB MCP Server provides 31 tools with consistent naming patterns and basic descriptions. All tools are registered with schemas and parameter descriptions. However, there are systematic quality gaps: descriptions are brief (most under 100 chars), parameter descriptions lack detail about constraints and valid ranges, output schemas are not documented, and error handling lacks recovery guidance. The server follows verb_noun naming conventions well but does not leverage all available quality patterns. Approximately 80% of tools have minimal descriptions that lack context for LLM decision-making. No tool annotations (readOnlyHint/destructiveHint) are present despite clear risk classifications in the metadata. Tools like `get_ssb_info()` and `list_streams()` are properly named and described at a basic level, but tools like `execute_query` lack validation rules, output structure documentation, and error guidance. The `_redact_sensitive()` helper shows awareness of security concerns but is applied post-hoc rather than integrated into tool design.
Tools (31)
configure_samplingwriteauthsource verified75/100
Configure sampling parameters for a job.
create_kafka_tablewriteauthsource verified77/100
Create a new table that only uses local-kafka connector.
Output schemas are not documented. LLMs cannot infer what fields to expect from tool responses, forcing them to parse unstructured output or make assumptions about downstream tool parameters.
Parameter descriptions lack constraint information. Tools like execute_query accept 'sql_query' with no hints about valid SQL syntax, complexity limits, or timeout expectations. Similarly, 'limit' parameter has no min/max bounds stated in description.
No tool annotations present. Risk metadata exists (READ_ONLY, WRITE, DESTRUCTIVE) but is not encoded in tool definitions via readOnlyHint, destructiveHint, or idempotentHint. LLMs cannot distinguish safe lookup calls from irreversible operations.
Recommendations
Add tool annotations to tool registration: mark read-only tools with readOnlyHint=true, destructive tools (delete_stream) with destructiveHint=true, and idempotent tools (all reads, create_* if using upsert logic) with idempotentHint=true. This enables LLMs to reason about reversibility.
Document output schemas for all tools. For list_* tools, specify: returns array of objects with fields [name, id, status, created_at, ...]. For get_* tools, specify the object structure. For execute_query, document whether results are array of rows (and row schema) or object with columns+data.
Expand parameter descriptions to include constraints. Example: 'limit (optional, 1-1000, default 20): Maximum number of results to return. Large limits may timeout.' Example: 'sql_query (string, max 10KB): SQL SELECT statement. Only read operations are allowed; DML is rejected.'
Add pagination support to list_* tools. Add optional 'limit' (1-100, default 20) and 'offset' (0+, default 0) parameters. Return {items: [...], total_count: N, has_more: bool}. Document the default limit in tool description.
Expand tool descriptions to 100-150 characters. Add WHEN context: 'List all SQL streams. Call this first to discover available streams before retrieving specific stream details.' Similarly, add prerequisites: 'Requires an active SSB cluster and valid authentication.'
Remove or redesign sampling-related tools. The configure_sampling and execute_query_with_sampling tools reflect deprecated server-initiated sampling. Instead, integrate with the LLM provider's native sampling/reasoning tokens API, or remove these tools entirely if sampling is not a core SSB feature.
Error handling lacks recovery guidance. Tools like execute_query and execute_job call _handle_ssb_operation() which returns structured error objects, but descriptions do not explain what to do on failure or how to self-correct.
Tool descriptions are minimal (most 30-80 characters). Baseline for A+ tools is 50-200 chars with context about WHEN to use the tool and prerequisites. Current descriptions state WHAT but not WHEN or WHY.
No pagination or result limit enforcement for list_ tools. list_streams, list_tables, list_udfs, list_connectors, list_topics have no limit/offset parameters and no documented cap on results. Large result sets will exhaust context windows.
Sampling-related tools (configure_sampling, execute_query_with_sampling, restart_job_with_sampling) suggest server-initiated sampling, a deprecated MCP pattern. These should integrate with the LLM provider's native sampling API instead.
Parameter names could be more explicit. 'sample_id' in get_job_sample vs 'job_id' in get_job_sample_by_id creates confusion about what identifies a sample. Inconsistent naming invites LLM selection errors.
No input validation documented or visible in tool signatures. execute_query accepts 'sql_query' as free-form string with no hints about SQL injection, length limits, or syntax validation. All user input is marked as untrusted per pattern:tool-gateway.
Add input validation logic visible in tool implementations. For execute_query, validate SQL length (<10KB), reject DML/DDL, and return actionable errors: 'SQL exceeds 10KB limit (got 15KB). Simplify your query or split into multiple calls.' For job IDs, validate format (integer >0) and provide clear error if invalid.
Enrich error responses with recovery hints. Example for execute_query failure: 'SQL syntax error near "SLEECT". Did you mean SELECT? Available columns in this table: [col1, col2, ...].' Use the existing _redact_sensitive() pattern to strip internal stack traces from LLM-facing errors.
Add 'description' parameter to all discovery tools (list_streams, etc.) to document what results represent. Example: 'Result contains all deployed SQL streams. Each stream has a name, status (running|stopped|error), and last_update timestamp. Use get_stream(stream_name) to fetch full details.'
Consolidate duplicate sample tools. get_job_sample(sample_id) and get_job_sample_by_id(job_id) overlap. Decide on a single canonical tool or clearly document when to use each (e.g., 'Use get_job_sample if you have a sample_id; use get_job_sample_by_id if you only have a job_id and want the latest sample').