Credentials exposed as tool parameters: create_agent, test_connection, update_agent, check_n8n, install_n8n_plugin accept dbPassword, password as plain parameters. These will be logged in traces and agent history, violating the secret-injection pattern. Credentials must be injected server-side via environment variables or a vault.
All tool descriptions are 15-28 characters, well below the 50-200 char baseline for LLM-optimized descriptions. Descriptions fail to answer WHAT the tool does, WHEN to use it, or WHAT it returns. Example: 'Get list of agents/intelligent access platforms' lacks context for agent selection or prerequisites.
Recommendations
CRITICAL: Remove all credential parameters (dbPassword, password) from tool definitions. Implement server-side secret injection, store credentials in environment variables or a secrets vault, indexed by accessID. Accept only accessID in tool input.
CRITICAL: Define complete input schemas for all tools, especially create_sync_task. Specify every parameter with type, description (50+ chars), constraints, format, enum values (if applicable), and min/max bounds.
Expand all tool descriptions to 50-200 characters. Answer: (1) What does this tool do? (2) When should the LLM call it? (3) What does it return? (4) Any prerequisites or dependencies? Example: 'List all agent platforms configured in this MCP instance. Call this first to discover available integrations (Dify, COZE, N8N). Returns agent_id, name, type, status for pagination and filtering.'
Document output schemas for every tool. Specify all returned fields with types, enums, and descriptions. For list_* tools, include example: { agents: [{agent_id: string, name: string, type: enum, status: enum, baseUrl: string}], total: number, page: number, pageSize: number }
Add error classification to all tools. Specify possible errors, causes, and recovery hints. Example for test_connection: '400: Invalid credentials, verify username/password and try again. 404: Agent not found, check accessID. 503: Service unavailable, retry in 30 seconds.'
Implement dry-run or confirmation pattern for destructive tools (delete_agent, delete_docs, delete_code_package, delete_environment, delete_docker_volume). Return a confirmation_token and require explicit confirm_delete(tool_name, id, confirmation_token) call.
Parameters lack complete type information. Many string parameters (accessID, baseUrl, dbHost, etc.) have descriptions but no format constraints, length limits, or patterns. E.g., 'accessID' could be UUID, alphanumeric, or anything, LLMs guess.
No output schemas documented. Tools like list_agents, list_tasks, get_task_detail provide no specification of returned field names, types, or structure. LLMs cannot plan downstream calls or extract data reliably.
No error handling guidance. Tools provide no specification of possible errors, error codes, causes, or recovery steps. An LLM receiving a 500 error or 'Connection refused' has no actionable next step.
Tools source from frontend TypeScript API definitions, not backend Go service. Tool registrations are inferred from package.json and frontend API calls, not explicit MCP server code. Cannot verify actual backend implementation, error handling, or security controls.
Pagination parameters (page, pageSize) are inconsistent across tools. Some use 'number' type, others use 'string' type for the same semantic operation. No maximum limits specified, LLMs can request unbounded large pages.
accessType parameter in create_agent, test_connection, update_agent, list_namespaces lists enum values (Dify, DifyEnterprise, COZE, N8N) in description text rather than as formal enum constraint. LLMs may hallucinate invalid values.
Standardize pagination: use consistent 'number' type for page, pageSize across all list_* tools. Add constraints: page >= 1, pageSize: 1-100. Spec max results: 'Limited to 100 items per page to conserve context.'
Replace inline enum descriptions with formal JSON Schema enum constraints. E.g., for accessType: { type: 'string', enum: ['Dify', 'DifyEnterprise', 'COZE', 'N8N'], description: 'Type of agent platform. Dify and DifyEnterprise support self-hosted and cloud deployments...' }
Add permission/scope declarations to all tools. Specify what access level is required: 'Requires agent:read' for list_agents, 'Requires agent:write' for create_agent, 'Requires agent:admin' for delete_agent. Enable least-privilege agent configuration.
Add idempotency tokens to create_* tools (create_agent, create_sync_task, create_environment, create_pvc, create_docker_volume). Accept optional idempotency_key parameter so agents can safely retry without creating duplicates.
Document which outputs flow into downstream tools. E.g., list_agents returns agent_id, verify that every tool accepting agent_id will consume the format returned by list_agents. Break chains by mismatched field names.
Expose tool annotations for protocol readiness: mark destructive tools with { destructiveHint: true }, read-only tools with { readOnlyHint: true }, and idempotent tools with { idempotentHint: true }.
Provide natural-language identifiers. Tools currently accept only opaque IDs (accessID, packageId). Consider also accepting names: create_agent({ accessName: 'my-dify-instance' }) and search internally. Reduces lookup friction for agents.
Add rate limits to prevent runaway agents. Specify per-tool limits in documentation: 'list_agents: 100 calls/min; create_agent: 10 calls/min' to prevent resource exhaustion.
Validate all inputs early with actionable error messages. Instead of '500 Internal Server Error', return '400 Invalid accessType: got "dify-pro", expected one of: Dify, DifyEnterprise, COZE, N8N' so LLM can self-correct.