automagik-tools: Command for Claude Code

.claude/commands/tester.md

tester is a command for Claude Code from namastexlabs/automagik-tools. It costs 0 tokens per session (2,796 once invoked), scanned A, original, Apache-2.0.

A testing workflow for MCP tools, which are tools that follow the Model Context Protocol for connecting software to AI systems. It creates tests for normal behavior, errors, integrations, configuration, and protocol compliance.

In plain words
What is it for?
It is for writing unit, integration, protocol, mock, performance, edge-case, and error-handling tests, including checks for asynchronous behavior and resource management.
Why use it?
It helps catch broken behavior and compatibility problems before tools are used in production.

Command for Claude Code

Written for Claude Code: installed under .claude/.

This is namastexlabs/automagik-tools's own configuration. It tells Claude Code how to work on automagik-tools itself, so it is not a mod to install elsewhere. Copy it as a starting point and replace the rules that are about this project. Everything automagik-tools configures →

Not installable: its command points at a path on the author’s own machine, so it runs nowhere else. The line is /home/namastex/workspace/automagik-tools.

Reuse

Borrowing it

Nothing to install: this file belongs to namastexlabs/automagik-tools. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.

Copy the file
curl -O https://raw.githubusercontent.com/namastexlabs/automagik-tools/main/.claude/commands/tester.md
Clone the repo
git clone --depth 1 https://github.com/namastexlabs/automagik-tools

Made for: Claude Code.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for tester

README.md
[![agentmods](https://agentmods.dev/badge/commands/namastexlabs/automagik-tools/tester/github.svg)](https://agentmods.dev/commands/namastexlabs/automagik-tools/tester)
Your own site
<a href="https://agentmods.dev/commands/namastexlabs/automagik-tools/tester"><img src="https://agentmods.dev/badge/commands/namastexlabs/automagik-tools/tester/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for tester

Your own site · 80×15
<a href="https://agentmods.dev/commands/namastexlabs/automagik-tools/tester"><img src="https://agentmods.dev/badge/commands/namastexlabs/automagik-tools/tester.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 0 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 2,796 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 1 finding. A grade says what 26 rules found in the file — not that it is safe.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00000 $0.02796
Opus 5 $0.00000 $0.01398
Sonnet 5 $0.00000 $0.00559
Haiku 4.5 $0.00000 $0.00280

Measured 9d ago against content hash 4224228a792d, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-09, from the pricing page.

Security

Grade A, and why

tester scanned grade A with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 9d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Runs shell commandslowCapability

Expected in a hook, worth knowing in a rule or an instructions file.

result = subprocess.run(
.claude/commands/tester.md · 375 lines

How it starts

The opening of the file, as written. The whole thing — 375 lines — stays where its author put it; the contents beside it link to each section on GitHub.

TESTER - Comprehensive Testing Workflow

🧪 Your Mission

You are the TESTER workflow for automagik-tools. Your role is to create comprehensive test suites for MCP tools, ensuring quality, reliability, and MCP protocol compliance.

🎯 Core Responsibilities

1. Test Creation

  • Write unit tests for core functionality
  • Create integration tests for hub compatibility
  • Implement MCP protocol compliance tests
  • Add edge case and error handling tests
  • Ensure minimum 30% code coverage

2. Test Categories

  • Unit Tests: Individual function testing
  • Integration Tests: Hub mounting and discovery
  • MCP Protocol Tests: Compliance validation
  • Mock Tests: External API simulation
  • Performance Tests: Basic benchmarks

3. Quality Assurance

  • Validate all tool functions
  • Test error scenarios
  • Verify configuration handling
  • Check resource management
  • Ensure proper async behavior

🧪 Testing Process

Step 1: Analyze Implementation

# Read the tool implementation
Read("automagik_tools/tools/{tool_name}/__init__.py")
Read("automagik_tools/tools/{tool_name}/config.py")

# Check existing test patterns
similar_tests = Glob(pattern="test_*.py", path="tests/tools/")

# Load testing patterns from memory
mcp__agent_memory__search_memory_nodes(
  query="mcp tool testing patterns mock strategy",
  group_ids=["automagik_patterns"],
  max_nodes=5
)

Step 2: Create Test Structure

Write("tests/tools/test_{tool_name}.py", '''
"""
Tests for {tool_name} MCP tool
"""
import pytest
from unittest.mock import Mock, patch, AsyncMock
# Import pattern depends on actual tool exports
from automagik_tools.tools.{tool_name} import create_server
# Note: Some tools may also export get_metadata, get_config_class
# Check actual tool implementation for available exports

try:
    from automagik_tools.tools.{tool_name} import get_metadata, get_config_class
    from automagik_tools.tools.{tool_name}.config import {ToolName}Config
except ImportError:
    # Handle tools with different export patterns
    pass

class Test{ToolName}Metadata:
    """Test tool metadata and discovery"""
    
    def test_metadata_structure(self):
        """Test that metadata has required fields"""
        metadata = get_metadata()
        assert "name" in metadata
        assert "version" in metadata
        assert "description" in metadata
        assert metadata["name"] == "{tool-name}"
    
    def test_config_class(self):
        """Test config class is returned correctly (if available)"""
        try:
            config_class = get_config_class()
            assert config_class == {ToolName}Config
        except NameError:
            # Some tools may not export get_config_class
            pytest.skip("Tool does not export get_config_class")

class Test{ToolName}Config:
    """Test configuration management"""
    
    def test_default_config(self):
        """Test default configuration values"""
        config = {ToolName}Config()
        assert config.base_url == "{default_base_url}"
        assert config.timeout == 30
    
    def test_env_config(self, monkeypatch):
        """Test configuration from environment"""
        monkeypatch.setenv("{TOOL_NAME}_API_KEY", "test-key")
        monkeypatch.setenv("{TOOL_NAME}_BASE_URL", "https://test.com")
        
        config = {ToolName}Config()
        assert config.api_key == "test-key"  
        assert config.base_url == "https://test.com"

class Test{ToolName}Server:
    """Test MCP server creation and tools"""
    
    @pytest.fixture
    def mock_config(self):
        """Create mock configuration"""
        config = Mock(spec={ToolName}Config)
        config.api_key = "test-key"
        config.base_url = "https://api.test.com"
        config.timeout = 30
        return config
    
    @pytest.fixture
    def server(self, mock_config):
        """Create test server instance"""
        return create_server(mock_config)
    
    def test_server_creation(self, server):
        """Test server is created with correct metadata"""
        assert server.name == "{tool_name}"
        assert server.version == "0.1.0"
    
    @pytest.mark.asyncio
    async def test_server_has_tools(self, server):
        """Test server has expected tools registered"""
        # FastMCP uses get_tools() which returns a dict, not list_tools()
        tools_dict = await server.get_tools()
        tool_names = list(tools_dict.keys())
        
        assert "{primary_function}" in tool_names
        # Add assertions for other expected tools
    
    @pytest.mark.asyncio
    async def test_{primary_function}(self, server):
        """Test primary function with mocked response"""
        with patch('httpx.AsyncClient.request') as mock_request:
            # Mock the API response
            mock_response = Mock()
            mock_response.status_code = 200
            mock_response.json.return_value = {
                "result": "success",
                "data": {"key": "value"}
            }
            mock_request.return_value = mock_response
            
            # Call the tool using FastMCP patterns
            tool_func = tools_dict["{primary_function}"]
            result = await tool_func(param1="test_value")
            
            # Verify the result
            assert result["result"] == "success"
            assert "data" in result

class Test{ToolName}Integration:
    """Test integration with automagik hub"""
    
    def test_hub_mounting(self):
        """Test tool can be mounted in hub"""
        # Test tool discovery using actual CLI
        import subprocess
        result = subprocess.run(
            ["uvx", "automagik-tools", "list"], 
            capture_output=True, text=True, cwd="/home/namastex/workspace/automagik-tools"
        )
        
        # Tool should be discoverable
        assert "{tool-name}" in result.stdout or "{tool_name}" in result.stdout
    
    @pytest.mark.mcp
    @pytest.mark.asyncio
    async def test_mcp_protocol_compliance(self, server):
        """Test MCP protocol compliance"""
        # Test tool listing using correct FastMCP API
        tools_dict = await server.get_tools()
        assert len(tools_dict) > 0
        
        # Test each tool has required properties
        for tool_name, tool_func in tools_dict.items():
            assert tool_name is not None
            assert callable(tool_func)
            # FastMCP tools have docstrings for descriptions
            assert tool_func.__doc__ is not None

class Test{ToolName}ErrorHandling:
    """Test error scenarios"""
    
    @pytest.mark.asyncio
    async def test_api_error_handling(self, server):
        """Test handling of API errors"""
        with patch('httpx.AsyncClient.request') as mock_request:
            # Mock an API error
            mock_request.side_effect = Exception("API Error")
            
            # Tool should handle error gracefully
            tools_dict = await server.get_tools()
            tool_func = tools_dict["{primary_function}"]
            
            with pytest.raises(Exception) as exc_info:
                await tool_func(param1="test")
            
            assert "API Error" in str(exc_info.value)
    
    def test_missing_config(self):
        """Test behavior with missing configuration"""
        config = {ToolName}Config(api_key=None)
        
        # Should still create server but with limited functionality
        server = create_server(config)
        assert server is not None

# Performance tests (optional)
class Test{ToolName}Performance:
    """Basic performance tests"""
    
    @pytest.mark.asyncio
    async def test_response_time(self, server):
        """Test tool response time"""
        import time
        
        with patch('httpx.AsyncClient.request') as mock_request:
            mock_response = Mock()
            mock_response.status_code = 200
            mock_response.json.return_value = {"result": "success"}
            mock_request.return_value = mock_response
            
            start = time.time()
            await server.call_tool("{primary_function}", {"param1": "test"})
            duration = time.time() - start
            
            # Should respond quickly (adjust threshold as needed)
            assert duration < 1.0  # 1 second threshold
''')

Read the full file on GitHub · 375 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 9d ago First seen · 375 lines · 0 tokens per session scan A 4224228a792d

Subscribe to this mod's changes

tester is a command published in the GitHub repository namastexlabs/automagik-tools (15 stars, last pushed 9mo ago), licensed Apache-2.0. It costs nothing until one of its globs matches a file; then it loads 2,796 tokens. A static security scan graded it A with 1 finding (runs shell commands). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.