The server defines 26 tools with explicit schemas visible in src/n8n_fabric/mcp/server.py. All tool names follow verb_noun patterns (workflow_list, execution_get, credential_create, etc.), which is good. However, descriptions are uniformly terse (10-50 chars), well below the 194-char baseline for production tools. Parameter descriptions exist but are minimal. No output schemas are documented, callers cannot know what fields to expect from responses. Error handling, recovery guidance, and input validation are not visible in the code provided. Tools lack context about consequences (create vs delete) in descriptions. Security patterns (secret injection, permission gates, audit trails) are not evident. The server exposes potentially destructive operations (workflow_delete, execution_delete, credential_delete, tag_delete, variable_delete) without visible confirmation/dry-run support. Parameter constraints are sparse, e.g., 'limit' has no bounds enforcement visible.
Destructive tools lack safety guardrails. workflow_delete, execution_delete, credential_delete, tag_delete, variable_delete have no visible confirmation mechanism, dry-run support, or warning in description. Agents can permanently destroy data without hesitation.
Descriptions are uniformly terse (20-55 chars), well below the 194-char production baseline. Examples: 'Delete a workflow' (18 chars), 'Delete a tag' (12 chars). LLMs cannot infer when to use these tools vs alternatives, increasing misselection risk.
Expand all tool descriptions to 100-250 characters. Include WHAT the tool does, WHEN to use it (vs similar tools), and any state-modifying consequences. Example: 'Delete a workflow by ID. This is irreversible, all associated executions will also be deleted. Use with caution; consider deactivating instead.' (vs current 'Delete a workflow').
Document output schemas for every tool. Add a 'returns' field in comments above each handler. Example: 'Returns: {workflow_id: string, name: string, active: boolean, created_at: ISO8601, nodes_count: integer}'.
Add maximum bounds to all integer parameters. Change limit defaults and specs to include min/max: 'limit: {type: integer, default: 100, minimum: 1, maximum: 1000}'.
Implement confirmation/dry-run for destructive tools. Before workflow_delete, execution_delete, credential_delete, offer a 'dry_run: boolean' parameter or a separate 'prepare_delete_workflow' tool that returns a confirmation token. Require agents to explicitly acknowledge consequences.
Add pagination support (offset/cursor) to all list tools. Change signature from 'limit' alone to 'limit' + 'offset' (or 'cursor' for cursor-based pagination). Return a 'next_offset' or 'has_more' field so agents can iterate large result sets.
Implement structured error responses. Categorize errors as 'retryable', 'user_input_required', or 'fatal'. Include the invalid value in error messages. Example: 'Invalid status value: got "pending", must be one of: success, error, running, waiting. Try calling execution_list with status="success" first.'
No output schemas documented. Tool responses are not described anywhere in the code provided. LLMs cannot know what fields (workflow_id, execution_id, timestamp, status) to expect from responses, forcing them to make blind assumptions about downstream tool chaining.
Unbounded integer parameters. 'limit' parameters in workflow_list, execution_list, credential_list, tag_list, variable_list, project_list have defaults (100) but no visible maximum constraints. Agents can pass limit=999999, potentially causing timeouts or resource exhaustion.
Error handling and recovery guidance not visible. No evidence of categorized errors (retryable, user-fixable, fatal) or actionable error messages. If a workflow_execute fails, LLMs have no guidance on what to try next.
credential_create and credential_update expose a 'data' parameter accepting arbitrary JSON. If credential secrets are passed here, they would be logged in traces. No visible server-side secret injection or masking.
No permission gates or scope declarations visible. Tools like workflow_delete and credential_delete should require explicit permission checks, but none are evident in the code.
Parameter validation rules not visible. E.g., 'workflow_id' is described as 'Workflow ID' but no guidance on format, length, or example. 'status' enum in execution_list is declared but no description explains which status values mean success vs failure.
No pagination offset/cursor for list tools. workflow_list, execution_list, credential_list, tag_list, variable_list, project_list accept 'limit' but no 'offset' or 'cursor'. Large result sets will be truncated with no way to iterate.
Add parameter descriptions for all enum values. For execution_list status field, document what each enum means: 'success = completed without errors, error = failed, running = currently executing, waiting = paused/blocked'.
Never expose secrets as parameters. For credential_create, do not accept raw 'data' containing API keys. Instead, require an OAuth flow, environment variable injection, or a separate credential vault lookup.
Add permission/scope declarations to tools. Document requirements: 'workflow_delete requires scope: write:workflows' so agents and operators know what permissions are needed.
Add audit logging. Log every tool call with: timestamp, user/agent ID, tool name, parameters (excluding secrets), success/failure, result. This enables compliance and incident response.
Consider adding helper/discovery tools. E.g., 'workflow_validate' (dry-run check before workflow_create) or 'execution_analyze' (suggest why an execution failed). These reduce agent errors.
Implement rate limiting to prevent runaway agents. Cap execution frequency (e.g., 10 calls/sec per agent) and return a 'too_many_requests' error with a retry-after hint.
Add idempotency support where applicable. workflow_create should accept an optional 'idempotency_key' to prevent duplicate workflows if the agent retries. Return the same result on retry.
Provide natural identifiers alongside IDs. If workflow names are unique, accept 'workflow_name' as an alternative to 'workflow_id'. Resolve internally and return both in responses.