RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/enuno/unifi-mcp-server/diff

Two files, one repository

enuno/unifi-mcp-server ships 6 formats across 13 indexed files. The question worth asking is whether the second one says anything the first does not.

CompareAGENTS.md ↔ CLAUDE.mdAGENTS.md ↔ Cline rulesAGENTS.md ↔ .cursorrulesAGENTS.md ↔ GEMINI.mdAGENTS.md ↔ Cursor rulesCLAUDE.md ↔ Cline rulesCLAUDE.md ↔ .cursorrulesCLAUDE.md ↔ GEMINI.mdCLAUDE.md ↔ Cursor rulesCline rules ↔ .cursorrulesCline rules ↔ GEMINI.mdCline rules ↔ Cursor rules.cursorrules ↔ GEMINI.md.cursorrules ↔ Cursor rulesGEMINI.md ↔ Cursor rules
A · AGENTS.md · 2748 wordsB · CLAUDE.md · 653 words
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections157111%
Commands26318%
Section tags86057%

What each file covers

Sections

1 shared · 57 only in A · 11 only in B
  • − AI Agent Guidelines for UniFi MCP Server
  • − Table of Contents
  • − Core Principles
  • − 1. Safety First
  • − 2. Clarity and Transparency
  • − 3. Consistency
  • − 4. Quality Over Speed
  • − File Structure and Organization
  • − Project Layout
  • − File Naming Conventions
  • − Workflow Guidelines
  • − During Development
  • − After Implementation
  • − Do's and Don'ts
  • − Do's ✅
  • − Don'ts ❌
  • − Testing Requirements
  • − Test Coverage
  • − Test Types
  • − Running Tests
  • − Run all tests
  • − Run with coverage
  • − Run only unit tests
  • − Run only integration tests (requires UniFi controller)
  • − Run specific test file
  • − Run tests matching pattern
  • − Security Guardrails
  • − Credential Management
  • − ❌ BAD - Hardcoded API key
  • − ✅ GOOD - Load from environment
  • − Input Validation
  • − Error Handling
  • − ❌ BAD - Exposes API key in logs
  • − ✅ GOOD - Safe error message
  • − ✅ EVEN BETTER - No key exposure
  • − Secret Detection
  • − Initialize pre-commit
  • − Manually check for secrets
  • − UniFi API Guidelines
  • − Authentication with API Keys
  • − API Access Modes
  • − Base URL: https://api.ui.com/v1/
  • − Base URL: https://{gateway-ip}/proxy/network/integration/v1/
  • − Read-Only Limitation
  • − ✅ ALLOWED - Read operations
  • − ❌ NOT AVAILABLE - Write operations (will fail)
  • − Rate Limiting Considerations
  • − API Error Handling
  • − Official API Documentation
  • − API Key Security Checklist
  • − Code Quality Standards
  • − Type Hints
  • − Docstrings
  • − Code Formatting
  • − Format code
  • − Sort imports
  • − Lint code
  • + UniFi MCP Server - Claude Instructions
  • + Project Overview
  • + Quick Start for AI Assistants
  • + Development Workflow
  • + Technology Stack
  • + API Modes
  • + Current Development Focus
  • + Important Constraints
  • + Getting Help
  • + Key Principles
  • + Additional Resources
  •   Before Starting Work

Commands

2 shared · 6 only in A · 3 only in B
  • − pytest
  • − pytest --cov=src --cov-report=html --cov-report=term-missing
  • − pytest -m unit
  • − pytest -m integration
  • − pytest tests/unit/test_client.py
  • − pytest -k "test_device"
  • + git checkout -b feature/your-feature
  • + pytest tests/unit/
  • + mypy src/
  •   black src/ tests/
  •   ruff check src/ tests/ --fix

Section tags

8 shared · 6 only in A · 0 only in B
  • − setup
  • − code-style
  • − types
  • − git-pr
  • − ui
  • − docs
  •   test
  •   lint-format
  •   architecture
  •   testing-strategy
  •   security
  •   api
  •   do-not
  •   agent-behaviour

Line diff

+99 added−769 removed40 unchanged4.9% identical
enuno/unifi-mcp-server · AGENTS.md
@@ −1 @@
1# AI Agent Guidelines for UniFi MCP Server
2 
3This document provides universal rules, workflows, and best practices for all AI coding agents contributing to the UniFi MCP Server project. These guidelines ensure consistency, quality, and security across all AI-assisted development.
4 
5## Table of Contents
6 
7- [Core Principles](#core-principles)
8- [File Structure and Organization](#file-structure-and-organization)
9- [Workflow Guidelines](#workflow-guidelines)
10- [Do's and Don'ts](#dos-and-donts)
11- [Testing Requirements](#testing-requirements)
12- [Security Guardrails](#security-guardrails)
13- [Code Quality Standards](#code-quality-standards)
14- [Documentation Requirements](#documentation-requirements)
15- [Approval and Merge Policies](#approval-and-merge-policies)
16 
17## Core Principles
 
 
18 
19All AI agents must adhere to these fundamental principles:
20 
21### 1. Safety First
22 
23- Never perform destructive operations without explicit confirmation
24- Always validate inputs and handle errors gracefully
25- Implement proper authentication and authorization checks
26- Never commit or expose sensitive data
27 
28### 2. Clarity and Transparency
29 
30- Write clear, self-documenting code with appropriate comments
31- Document all decisions and trade-offs
32- Tag AI-generated contributions appropriately
33- Explain complex logic in docstrings
34 
35### 3. Consistency
36 
37- Follow the project's established patterns and conventions
38- Maintain consistent code style (enforced by linting tools)
39- Use consistent naming conventions throughout the codebase
40- Adhere to the project's architecture and design patterns
41 
42### 4. Quality Over Speed
43 
44- Prioritize correctness and maintainability over quick delivery
45- Include comprehensive tests for all code changes
46- Ensure code passes all quality checks before submission
47- Perform self-review before requesting human review
48 
49## File Structure and Organization
50 
51### Project Layout
52 
53```
54unifi-mcp-server/
55├── .github/
56│ └── workflows/ # CI/CD pipeline definitions
57├── src/
58│ ├── __init__.py
59│ ├── main.py # MCP server entry point
60│ ├── config/ # Configuration management
61│ │ ├── __init__.py
62│ │ ├── settings.py # Pydantic settings models
63│ │ └── config.yaml # Default configuration
64│ ├── api/ # UniFi API client
65│ │ ├── __init__.py
66│ │ ├── client.py # HTTP client wrapper
67│ │ └── endpoints.py # API endpoint definitions
68│ ├── tools/ # MCP tool definitions
69│ │ ├── __init__.py
70│ │ ├── devices.py # Device management tools
71│ │ ├── networks.py # Network configuration tools
72│ │ └── firewall.py # Firewall rule tools
73│ ├── resources/ # MCP resource definitions
74│ │ ├── __init__.py
75│ │ └── schemas.py # Resource URI schemas
76│ └── utils/ # Utility functions
77│ ├── __init__.py
78│ └── validators.py # Input validation helpers
79├── tests/
80│ ├── __init__.py
81│ ├── conftest.py # Pytest fixtures
82│ ├── unit/ # Unit tests
83│ └── integration/ # Integration tests
84├── docs/ # Additional documentation
85├── .env.example # Environment variable template
86├── .gitignore
87├── .aiignore
88├── pyproject.toml
89├── README.md
90└── ...
91```
92 
93### File Naming Conventions
94 
95- **Python files:** Use `snake_case` (e.g., `device_manager.py`)
96- **Classes:** Use `PascalCase` (e.g., `UniFiClient`)
97- **Functions/variables:** Use `snake_case` (e.g., `get_devices()`)
98- **Constants:** Use `UPPER_SNAKE_CASE` (e.g., `DEFAULT_TIMEOUT`)
99- **Test files:** Prefix with `test_` (e.g., `test_device_manager.py`)
100 
101## Workflow Guidelines
102 
103### Before Starting Work
104 
1051. **Understand the Context:**
106 - Read relevant documentation (`README.md`, `API.md`, `CONTRIBUTING.md`)
107 - Review related issues and pull requests
108 - Understand the feature request or bug report completely
 
 
109 
1102. **Plan Your Approach:**
111 - Break down the task into smaller, manageable steps
112 - Identify affected files and components
113 - Consider potential edge cases and error conditions
114 - Plan for comprehensive test coverage
 
115 
1163. **Check Existing Code:**
117 - Review similar implementations in the codebase
118 - Identify reusable functions and patterns
119 - Ensure your approach is consistent with existing code
120 
121### During Development
 
 
 
 
 
122 
1231. **Write Code Incrementally:**
124 - Implement one feature or fix at a time
125 - Test each change before moving to the next
126 - Commit logical units of work separately
 
 
127 
1282. **Follow TDD (Test-Driven Development):**
129 - Write tests first when possible
130 - Ensure tests fail before implementing the feature
131 - Verify tests pass after implementation
132 - Maintain minimum 80% code coverage
 
133 
1343. **Document as You Go:**
135 - Add docstrings to all public functions and classes
136 - Update relevant documentation files
137 - Add inline comments for complex logic
138 - Keep `API.md` updated for new MCP tools/resources
139 
140### After Implementation
 
 
 
 
 
 
141 
1421. **Self-Review:**
143 - Review your own code critically
144 - Ensure all tests pass: `pytest`
145 - Run linting and formatting: `pre-commit run --all-files`
146 - Check for security issues: `bandit -r src/`
147 
1482. **Create a Pull Request:**
149 - Write a clear, descriptive PR title (conventional commits format)
150 - Fill out the PR template completely
151 - Link related issues
152 - Tag the PR as AI-assisted
153 - Request human review
154 
1553. **Respond to Feedback:**
156 - Address all review comments
157 - Make requested changes promptly
158 - Explain decisions when necessary
159 - Re-request review after making changes
160 
161## Do's and Don'ts
 
162 
163### Do's ✅
 
164 
165- **DO** validate all user inputs
166- **DO** handle errors gracefully with try/except blocks
167- **DO** use type hints for all function signatures
168- **DO** write comprehensive docstrings
169- **DO** add tests for all new code
170- **DO** use async/await for I/O-bound operations
171- **DO** centralize API interactions in dedicated modules
172- **DO** use environment variables for configuration
173- **DO** log important events and errors appropriately
174- **DO** follow the principle of least privilege
175- **DO** ask for clarification when requirements are unclear
176- **DO** use Pydantic models for data validation
177- **DO** keep functions small and focused (single responsibility)
178- **DO** reuse existing code when possible
179 
180### Don'ts ❌
181 
182- **DON'T** commit credentials, API keys, or secrets
183- **DON'T** merge code without human approval
184- **DON'T** skip writing tests
185- **DON'T** ignore linting errors or warnings
186- **DON'T** expose sensitive information in logs or error messages
187- **DON'T** make breaking changes without discussion
188- **DON'T** copy-paste code - create reusable functions instead
189- **DON'T** use bare except clauses - catch specific exceptions
190- **DON'T** hardcode values that should be configurable
191- **DON'T** submit incomplete or experimental code to main
192- **DON'T** bypass security checks or pre-commit hooks
193- **DON'T** write code without understanding its purpose
194- **DON'T** use deprecated libraries or functions
195- **DON'T** ignore type errors from MyPy
196 
197## Testing Requirements
198 
199### Test Coverage
 
 
 
200 
201All AI-generated code must include tests:
202 
203- **Minimum Coverage:** 80% overall
204- **New Features:** 100% coverage of new code paths
205- **Bug Fixes:** Regression tests for the fixed bug
206- **Refactoring:** Maintain or improve existing coverage
 
 
 
 
 
207 
208### Test Types
209 
2101. **Unit Tests:**
211 
212 ```python
213 import pytest
214 from src.api.client import UniFiClient
 
215 
216 @pytest.mark.unit
217 async def test_client_initialization():
218 """Test that UniFi client initializes correctly."""
219 client = UniFiClient(
220 api_key="test-api-key",
221 api_type="cloud",
222 host="api.ui.com"
223 )
224 assert client.host == "api.ui.com"
225 assert client.api_type == "cloud"
226 assert client.api_key == "test-api-key"
227 ```
228 
2292. **Integration Tests:**
 
 
230 
231 ```python
232 import pytest
233 
234 @pytest.mark.integration
235 async def test_get_devices_from_real_api():
236 """Test fetching devices from real UniFi Cloud API."""
237 # This test requires UNIFI_API_KEY environment variable
238 client = UniFiClient.from_env()
239 devices = await client.get_devices()
240 assert isinstance(devices, list)
241 ```
242 
2433. **Mock Tests:**
244 
245 ```python
246 from unittest.mock import AsyncMock, patch
 
 
 
247 
248 @pytest.mark.unit
249 async def test_get_devices_handles_error():
250 """Test error handling when API fails."""
251 with patch('src.api.client.httpx.AsyncClient.get') as mock_get:
252 mock_get.side_effect = httpx.HTTPError("Connection failed")
253 client = UniFiClient(
254 api_key="test-key",
255 host="api.ui.com",
256 api_type="cloud"
257 )
258 with pytest.raises(APIError):
259 await client.get_devices()
260 ```
261 
262### Running Tests
263 
264```bash
265# Run all tests
266pytest
267 
268# Run with coverage
269pytest --cov=src --cov-report=html --cov-report=term-missing
270 
271# Run only unit tests
272pytest -m unit
273 
274# Run only integration tests (requires UniFi controller)
275pytest -m integration
276 
277# Run specific test file
278pytest tests/unit/test_client.py
279 
280# Run tests matching pattern
281pytest -k "test_device"
282```
283 
284## Security Guardrails
285 
286### Credential Management
287 
288**NEVER include API keys or credentials in code:**
289 
290```python
291# ❌ BAD - Hardcoded API key
292client = UniFiClient(
293 api_key="abc123def456ghi789...",
294 host="api.ui.com"
295)
296 
297# ✅ GOOD - Load from environment
298from src.config.settings import Settings
299 
300settings = Settings() # Loads from environment
301client = UniFiClient(
302 api_key=settings.unifi_api_key,
303 host=settings.unifi_host,
304 api_type=settings.unifi_api_type
305)
306```
307 
308### Input Validation
309 
310Always validate and sanitize inputs:
311 
312```python
313from pydantic import BaseModel, Field, validator
314 
315class NetworkConfig(BaseModel):
316 name: str = Field(..., min_length=1, max_length=32)
317 vlan_id: int = Field(..., ge=1, le=4094)
318 subnet: str
319 
320 @validator('subnet')
321 def validate_subnet(cls, v):
322 import ipaddress
323 try:
324 ipaddress.ip_network(v)
325 except ValueError:
326 raise ValueError('Invalid subnet format')
327 return v
328```
329 
330### Error Handling
331 
332Don't expose sensitive information in errors:
333 
334```python
335# ❌ BAD - Exposes API key in logs
336logging.error(f"Auth failed with API key: {api_key}")
337 
338# ✅ GOOD - Safe error message
339logging.error(f"Authentication failed for host '{host}' (API key: {api_key[:8]}...)")
340 
341# ✅ EVEN BETTER - No key exposure
342logging.error(f"Authentication failed for host '{host}'. Check your UNIFI_API_KEY.")
343```
344 
345### Secret Detection
346 
347Pre-commit hooks will prevent committing secrets:
348 
349```bash
350# Initialize pre-commit
351pre-commit install
352 
353# Manually check for secrets
354detect-secrets scan
355```
356 
357## UniFi API Guidelines
358 
359### Authentication with API Keys
360 
361This project uses the **official UniFi Cloud API** with API key authentication. All AI agents must follow these guidelines:
362 
363**Authentication Method:**
364 
365- Use `UNIFI_API_KEY` environment variable for authentication
366- API key is passed via the `X-API-Key` HTTP header
367- No session management or cookies required (stateless authentication)
368 
369**NEVER hardcode API keys:**
370 
371```python
372# ❌ BAD - Hardcoded API key
373headers = {
374 "X-API-Key": "abc123def456..."
375}
376 
377# ✅ GOOD - Load from environment
378from src.config.settings import Settings
379 
380settings = Settings()
381headers = {
382 "X-API-Key": settings.unifi_api_key
383}
384```
385 
386### API Access Modes
387 
388Support both cloud and local gateway access modes:
389 
390**Cloud API (Default):**
391 
392```python
393# Base URL: https://api.ui.com/v1/
394settings.unifi_api_type = "cloud"
395settings.unifi_host = "api.ui.com"
396settings.unifi_port = 443
397```
398 
399**Local Gateway Proxy:**
400 
401```python
402# Base URL: https://{gateway-ip}/proxy/network/integration/v1/
403settings.unifi_api_type = "local"
404settings.unifi_host = "192.168.2.1"
405settings.unifi_port = 443
406```
407 
408### Read-Only Limitation
409 
410**IMPORTANT:** The Early Access API is currently **read-only**.
411 
412```python
413# ✅ ALLOWED - Read operations
414async def list_devices(site_id: str):
415 """List all devices - read operation."""
416 devices = await client.get(f"/v1/sites/{site_id}/devices")
417 return devices
418 
419# ❌ NOT AVAILABLE - Write operations (will fail)
420async def create_network(name: str, vlan_id: int):
421 """Create network - not yet supported in EA API."""
422 # This will return 403 Forbidden in current API version
423 raise NotImplementedError(
424 "Write operations are not available in the Early Access API. "
425 "This feature will be available in v1 Stable release."
426 )
427```
428 
429**Handling write requests:**
430 
431- Document that write operations are not yet available
432- Return clear error messages to users
433- Consider implementing a "preview" mode that shows what would be created
434- Monitor UniFi API release notes for v1 Stable availability
435 
436### Rate Limiting Considerations
437 
438Implement proper rate limiting to respect API limits:
439 
440**Current Limits:**
441 
442- Early Access: 100 requests/minute
443- v1 Stable (future): 10,000 requests/minute
444 
445**Implementation Example:**
446 
447```python
448import asyncio
449from collections import deque
450from datetime import datetime, timedelta
451 
452class UniFiRateLimiter:
453 """Rate limiter for UniFi API requests."""
454 
455 def __init__(self, max_requests: int = 100, window_seconds: int = 60):
456 self.max_requests = max_requests
457 self.window = timedelta(seconds=window_seconds)
458 self.requests = deque()
459 
460 async def acquire(self):
461 """Wait if necessary to respect rate limits."""
462 now = datetime.now()
463 
464 # Remove old requests outside the window
465 while self.requests and self.requests[0] < now - self.window:
466 self.requests.popleft()
467 
468 # Wait if at limit
469 if len(self.requests) >= self.max_requests:
470 sleep_time = (self.requests[0] + self.window - now).total_seconds()
471 if sleep_time > 0:
472 await asyncio.sleep(sleep_time)
473 
474 self.requests.append(now)
475```
476 
477**Best Practices:**
478 
479- Cache frequently accessed data (devices, sites, networks)
480- Batch operations when possible
481- Implement exponential backoff for 429 errors
482- Use configurable rate limits via `UNIFI_RATE_LIMIT` environment variable
483- Log rate limit warnings for monitoring
484 
485### API Error Handling
486 
487Handle UniFi API-specific errors gracefully:
488 
489```python
490import httpx
491from typing import Dict, Any
492 
493class UniFiAPIError(Exception):
494 """Base exception for UniFi API errors."""
495 pass
496 
497class UniFiAuthenticationError(UniFiAPIError):
498 """Authentication failed - invalid API key."""
499 pass
500 
501class UniFiRateLimitError(UniFiAPIError):
502 """Rate limit exceeded."""
503 pass
504 
505async def safe_api_request(
506 client: httpx.AsyncClient,
507 method: str,
508 endpoint: str,
509 **kwargs
510) -> Dict[str, Any]:
511 """
512 Make a safe API request with proper error handling.
513 
514 Args:
515 client: HTTP client
516 method: HTTP method (GET, POST, etc.)
517 endpoint: API endpoint
518 **kwargs: Additional request parameters
519 
520 Returns:
521 Response data as dictionary
522 
523 Raises:
524 UniFiAuthenticationError: Invalid API key
525 UniFiRateLimitError: Rate limit exceeded
526 UniFiAPIError: Other API errors
527 """
528 try:
529 response = await client.request(method, endpoint, **kwargs)
530 response.raise_for_status()
531 return response.json()
532 
533 except httpx.HTTPStatusError as e:
534 if e.response.status_code == 401:
535 raise UniFiAuthenticationError(
536 "Invalid API key. Please check your UNIFI_API_KEY."
537 )
538 elif e.response.status_code == 429:
539 retry_after = e.response.headers.get("Retry-After", 60)
540 raise UniFiRateLimitError(
541 f"Rate limit exceeded. Retry after {retry_after} seconds."
542 )
543 else:
544 raise UniFiAPIError(f"API error: {e.response.status_code}")
545 
546 except httpx.RequestError as e:
547 raise UniFiAPIError(f"Request failed: {str(e)}")
548```
549 
550### Official API Documentation
551 
552Always reference the official UniFi API documentation:
553 
554**Primary Resources:**
555 
556- **Getting Started**: [https://developer.ui.com/site-manager-api/gettingstarted](https://developer.ui.com/site-manager-api/gettingstarted)
557- **Project Reference**: `docs/UNIFI_API.md` (comprehensive guide)
558- **API Tutorial**: [https://www.makewithdata.tech/p/build-a-mcp-server-for-ai-access](https://www.makewithdata.tech/p/build-a-mcp-server-for-ai-access)
559 
560**When implementing new features:**
561 
5621. Review official API documentation first
5632. Check `docs/UNIFI_API.md` for project-specific guidance
5643. Ensure endpoint paths match official specifications
5654. Test against real UniFi Cloud API or gateway proxy
5665. Document any API limitations or quirks discovered
567 
568### API Key Security Checklist
569 
570Before committing code, verify:
571 
572- [ ] No hardcoded API keys in source code
573- [ ] API key loaded from environment variables
574- [ ] No API keys in log messages (even debug logs)
575- [ ] API keys redacted in error messages
576- [ ] `.env` file in `.gitignore`
577- [ ] `.env.example` has placeholder, not real key
578- [ ] Pre-commit hooks detect-secrets passing
579- [ ] Documentation mentions API key security
580 
581## Code Quality Standards
582 
583### Type Hints
584 
585All functions must have type hints:
586 
587```python
588from typing import List, Dict, Optional
589import httpx
590 
591async def get_devices(
592 client: httpx.AsyncClient,
593 site_id: str = "default"
594) -> List[Dict[str, Any]]:
595 """Fetch devices from UniFi controller."""
596 response = await client.get(f"/api/s/{site_id}/stat/device")
597 return response.json()["data"]
598```
599 
600### Docstrings
601 
602Use Google-style docstrings:
603 
604```python
605def calculate_network_capacity(
606 bandwidth_mbps: int,
607 devices: int,
608 overhead_percent: float = 0.2
609) -> float:
610 """
611 Calculate available bandwidth per device.
612 
613 Args:
614 bandwidth_mbps: Total bandwidth in Mbps
615 devices: Number of connected devices
616 overhead_percent: Network overhead as decimal (default: 0.2 for 20%)
617 
618 Returns:
619 Available bandwidth per device in Mbps
620 
621 Raises:
622 ValueError: If bandwidth or devices is less than 1
623 
624 Example:
625 >>> calculate_network_capacity(100, 10)
626 8.0
627 """
628 if bandwidth_mbps < 1 or devices < 1:
629 raise ValueError("Bandwidth and devices must be positive")
630 
631 available = bandwidth_mbps * (1 - overhead_percent)
632 return available / devices
633```
634 
635### Code Formatting
636 
637Code is automatically formatted by pre-commit hooks:
638 
639```bash
640# Format code
641black src/ tests/
642 
643# Sort imports
644isort src/ tests/
645 
646# Lint code
647ruff check src/ tests/ --fix
648```
649 
650## Documentation Requirements
651 
652### Code Documentation
653 
654- **All public functions:** Require docstrings
655- **Complex logic:** Add inline comments
656- **Type hints:** Required for all functions
657- **Examples:** Include in docstrings when helpful
658 
659### Project Documentation
660 
661Update relevant documentation files:
662 
663- `README.md` - For user-facing changes
664- `API.md` - For new MCP tools or resources
665- `CONTRIBUTING.md` - For workflow changes
666- `SECURITY.md` - For security-related changes
667 
668### API Documentation
669 
670When adding new MCP tools, document in `API.md`:
671 
672```markdown
673### get_device
674 
675Retrieve information about a specific UniFi device.
676 
677**Parameters:**
678- `mac_address` (string, required): Device MAC address
679- `site_id` (string, optional): Site identifier (default: "default")
680 
681**Returns:**
682Object containing device information
683 
684**Example:**
685\`\`\`python
686result = await mcp.call_tool("get_device", {
687 "mac_address": "aa:bb:cc:dd:ee:ff",
688 "site_id": "default"
689})
690\`\`\`
691```
692 
693## Approval and Merge Policies
694 
695### Auto-Merge Restrictions
696 
697AI agents **MUST NOT**:
698 
699- Automatically merge pull requests
700- Bypass code review requirements
701- Push directly to the `main` branch
702- Override branch protection rules
703- Disable or skip CI/CD checks
704 
705### Required Approvals
706 
707All AI-generated code requires:
708 
709- At least one human reviewer approval
710- All CI/CD checks passing
711- No unresolved review comments
712- Up-to-date with the `main` branch
713 
714### Human-in-the-Loop
715 
716Critical changes require additional human review:
717 
718- Security-related code
719- Authentication/authorization logic
720- Data deletion or modification
721- API contract changes
722- Database schema changes
723- Configuration changes affecting production
724 
725### Tagging AI Contributions
726 
727Mark AI-assisted PRs in the description:
728 
729```markdown
730## AI Assistance
731 
732This PR was created with assistance from Claude Code.
733 
734**Human Review Status:** ✅ Reviewed and approved by @username
735**Test Coverage:** 95%
736**Security Review:** Completed
737```
738 
739## Special Considerations
740 
741### MCP-Specific Guidelines
742 
743When implementing MCP tools and resources:
744 
745```python
746from fastmcp import FastMCP
747 
748mcp = FastMCP("UniFi Network")
749 
750@mcp.tool()
751async def get_devices(site_id: str = "default") -> list:
752 """
753 Get all devices for a site.
754 
755 Args:
756 site_id: Site identifier (default: "default")
757 
758 Returns:
759 List of device objects
760 """
761 # Implementation
762 pass
763 
764@mcp.resource("sites://{site_id}/devices")
765async def list_site_devices(site_id: str) -> str:
766 """List all devices in a site."""
767 # Return JSON string of devices
768 pass
769```
770 
771### UniFi API Integration
772 
773Centralize API calls in dedicated modules:
774 
775```python
776# src/api/client.py
777class UniFiClient:
778 async def request(
779 self,
780 method: str,
781 endpoint: str,
782 **kwargs
783 ) -> Dict[str, Any]:
784 """
785 Make authenticated request to UniFi API.
786 
787 Handles authentication, retries, and error handling.
788 """
789 # Centralized implementation
790 pass
791```
792 
793## Conclusion
794 
795By following these guidelines, AI agents can contribute effectively to the UniFi MCP Server project while maintaining high standards of quality, security, and maintainability.
796 
797**Remember:** When in doubt, ask for human guidance. It's better to request clarification than to make assumptions that could introduce bugs or security issues.
798 
799---
800 
801**Last Updated:** 2025-10-17
802 
803For additional guidance, see:
804 
805- `AI_CODING_ASSISTANT.md` - Project-specific AI guidelines
806- `AI_GIT_PRACTICES.md` - AI-specific Git practices
807- `CONTRIBUTING.md` - General contribution guidelines
808- `SECURITY.md` - Security policies
809 
enuno/unifi-mcp-server · CLAUDE.md
@@ +1 @@
1# UniFi MCP Server - Claude Instructions
2 
3This file provides project-specific instructions for AI coding assistants working on the UniFi MCP Server.
4 
5## Project Overview
6 
7The UniFi MCP Server is a Model Context Protocol (MCP) server that exposes the UniFi Network Controller API, enabling AI agents and applications to interact with UniFi network infrastructure in a standardized way.
 
 
 
 
 
 
 
 
8 
9**Current Version**: v0.2.3
10**Python Version**: 3.10+
11**Framework**: FastMCP
12 
13## Quick Start for AI Assistants
14 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15### Before Starting Work
16 
171. **Read Key Documentation**:
18 - `README.md` - Project overview and features
19 - `AGENTS.md` - Universal AI agent guidelines
20 - `DEVELOPMENT_PLAN.md` - Roadmap and priorities
21 - `TODO.md` - Current tasks and phase breakdown
22 - `API.md` - Complete MCP tool documentation
23 
242. **Understand the Architecture**:
25 - `src/main.py` - MCP server entry point
26 - `src/api/` - UniFi API client
27 - `src/models/` - Pydantic data models
28 - `src/tools/` - MCP tool implementations
29 - `tests/unit/` - Unit tests (1,156 tests passing)
30 
31### Development Workflow
 
 
 
32 
331. **Feature Development**:
34 - Create feature branch: `git checkout -b feature/your-feature`
35 - Follow TDD: Write tests first, then implementation
36 - Maintain 80% minimum test coverage for new code
37 - Use Pydantic models for all data structures
38 - Add comprehensive docstrings (Google style)
39 
402. **Code Quality**:
41 - Run tests: `pytest tests/unit/`
42 - Format: `black src/ tests/` and `isort src/ tests/`
43 - Lint: `ruff check src/ tests/ --fix`
44 - Type check: `mypy src/`
45 - Pre-commit: `pre-commit run --all-files`
46 
473. **Safety Mechanisms**:
48 - All mutating operations require `confirm=True`
49 - Implement dry-run mode for preview
50 - Add audit logging for operations
51 - Validate all user inputs
52 - Never commit secrets or credentials
53 
54### Technology Stack
 
 
 
 
55 
56- **Language**: Python 3.10+
57- **Framework**: FastMCP (MCP server framework)
58- **API Client**: httpx (async HTTP)
59- **Data Validation**: Pydantic v2
60- **Testing**: pytest with asyncio support
61- **Caching**: Redis (optional)
62- **Monitoring**: agnost.ai (optional)
63 
64### API Modes
 
 
 
 
65 
66The server supports three UniFi API access modes:
 
 
 
 
 
67 
681. **Local Gateway API** (Recommended): Full feature support
69 - `UNIFI_API_TYPE=local`
70 - `UNIFI_LOCAL_HOST=192.168.2.1`
 
 
71 
722. **Cloud V1 API**: Stable, aggregate statistics only
73 - `UNIFI_API_TYPE=cloud-v1`
74 
753. **Cloud EA API**: Early Access, aggregate statistics only
76 - `UNIFI_API_TYPE=cloud-ea`
77 
78### Current Development Focus
 
 
 
 
 
 
 
 
 
 
 
 
 
79 
80**Version 0.2.3** (Current):
81 
82- ✅ P1 API bug fixes (QoS audit_action, Site Manager decorator, Topology warnings, Backup client methods)
83- ✅ P2 RADIUS & Guest Portal — Complete CRUD (get/update for RADIUS accounts and hotspot packages)
 
 
 
 
 
 
 
 
 
 
 
 
84 
85**Version 0.2.2** (Complete ✅):
86 
87- ✅ Port Profile & Switch Port Management (8 tools)
88- ✅ Security hardening (dependency updates, PII removal)
89- ✅ API endpoint fixes (RADIUS, firewall, WLAN, network)
90- ✅ Bug fixes (dry_run, list handling, type hints)
91 
92**Version 0.2.0** (Complete ✅):
93 
94- ✅ Zone-Based Firewall (7 working tools)
95- ✅ Traffic Flow Monitoring (15 tools)
96- ✅ Advanced QoS (11 tools)
97- ✅ Backup & Restore (8 tools)
98- ✅ Multi-Site Aggregation (4 tools)
99- ✅ ACL & Traffic Filtering (7 tools)
100- ✅ Site Management (9 tools)
101- ✅ RADIUS & Guest Portal (10 tools — full CRUD)
102- ✅ Network Topology (5 tools)
103 
104**Total**: 86+ MCP tools, 1,156 tests passing
105 
106### Important Constraints
107 
1081. **UniFi Network 9.0+ Required**: Some features require Network 9.0+
1092. **Local API Recommended**: Cloud APIs have limited functionality
1103. **Endpoint Verification**: Some documented API endpoints may not exist in all versions
1114. **Testing**: Integration tests require real UniFi hardware
112 
113### Getting Help
 
 
 
 
 
 
 
 
 
 
 
114 
115- **Issues**: [GitHub Issues](https://github.com/enuno/unifi-mcp-server/issues)
116- **Documentation**: See `API.md` for complete tool reference
117- **Examples**: Check `docs/examples/` for AI assistant prompts
118 
119## Key Principles
 
120 
1211. **Safety First**: Never perform destructive operations without confirmation
1222. **Quality Over Speed**: Maintain high test coverage and code quality
1233. **Clarity**: Write self-documenting code with clear docstrings
1244. **Consistency**: Follow existing patterns and conventions
1255. **Security**: Never commit credentials, validate all inputs
 
 
 
126 
127## Additional Resources
128 
129- [CONTRIBUTING.md](CONTRIBUTING.md) - Contribution guidelines
130- [SECURITY.md](SECURITY.md) - Security policy and best practices
131- [AGENTS.md](AGENTS.md) - Detailed AI agent guidelines
132- [TESTING_PLAN.md](docs/archive/TESTING_PLAN.md) - Testing strategy
133- [DEVELOPMENT_PLAN.md](DEVELOPMENT_PLAN.md) - Complete roadmap
134 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135---
136 
137**Last Updated**: 2026-02-18
138**Maintained By**: Development Team
 
 
 
 
 
 
139 
@@ −1 +1 @@
1−# AI Agent Guidelines for UniFi MCP Server
1+# UniFi MCP Server - Claude Instructions
22  
3−This document provides universal rules, workflows, and best practices for all AI coding agents contributing to the UniFi MCP Server project. These guidelines ensure consistency, quality, and security across all AI-assisted development.
3+This file provides project-specific instructions for AI coding assistants working on the UniFi MCP Server.
44  
5−## Table of Contents
5+## Project Overview
66  
7−- [Core Principles](#core-principles)
8−- [File Structure and Organization](#file-structure-and-organization)
9−- [Workflow Guidelines](#workflow-guidelines)
10−- [Do's and Don'ts](#dos-and-donts)
11−- [Testing Requirements](#testing-requirements)
12−- [Security Guardrails](#security-guardrails)
13−- [Code Quality Standards](#code-quality-standards)
14−- [Documentation Requirements](#documentation-requirements)
15−- [Approval and Merge Policies](#approval-and-merge-policies)
7+The UniFi MCP Server is a Model Context Protocol (MCP) server that exposes the UniFi Network Controller API, enabling AI agents and applications to interact with UniFi network infrastructure in a standardized way.
168  
17−## Core Principles
9+**Current Version**: v0.2.3
10+**Python Version**: 3.10+
11+**Framework**: FastMCP
1812  
19−All AI agents must adhere to these fundamental principles:
13+## Quick Start for AI Assistants
2014  
21−### 1. Safety First
22− 
23−- Never perform destructive operations without explicit confirmation
24−- Always validate inputs and handle errors gracefully
25−- Implement proper authentication and authorization checks
26−- Never commit or expose sensitive data
27− 
28−### 2. Clarity and Transparency
29− 
30−- Write clear, self-documenting code with appropriate comments
31−- Document all decisions and trade-offs
32−- Tag AI-generated contributions appropriately
33−- Explain complex logic in docstrings
34− 
35−### 3. Consistency
36− 
37−- Follow the project's established patterns and conventions
38−- Maintain consistent code style (enforced by linting tools)
39−- Use consistent naming conventions throughout the codebase
40−- Adhere to the project's architecture and design patterns
41− 
42−### 4. Quality Over Speed
43− 
44−- Prioritize correctness and maintainability over quick delivery
45−- Include comprehensive tests for all code changes
46−- Ensure code passes all quality checks before submission
47−- Perform self-review before requesting human review
48− 
49−## File Structure and Organization
50− 
51−### Project Layout
52− 
53−```
54−unifi-mcp-server/
55−├── .github/
56−│ └── workflows/ # CI/CD pipeline definitions
57−├── src/
58−│ ├── __init__.py
59−│ ├── main.py # MCP server entry point
60−│ ├── config/ # Configuration management
61−│ │ ├── __init__.py
62−│ │ ├── settings.py # Pydantic settings models
63−│ │ └── config.yaml # Default configuration
64−│ ├── api/ # UniFi API client
65−│ │ ├── __init__.py
66−│ │ ├── client.py # HTTP client wrapper
67−│ │ └── endpoints.py # API endpoint definitions
68−│ ├── tools/ # MCP tool definitions
69−│ │ ├── __init__.py
70−│ │ ├── devices.py # Device management tools
71−│ │ ├── networks.py # Network configuration tools
72−│ │ └── firewall.py # Firewall rule tools
73−│ ├── resources/ # MCP resource definitions
74−│ │ ├── __init__.py
75−│ │ └── schemas.py # Resource URI schemas
76−│ └── utils/ # Utility functions
77−│ ├── __init__.py
78−│ └── validators.py # Input validation helpers
79−├── tests/
80−│ ├── __init__.py
81−│ ├── conftest.py # Pytest fixtures
82−│ ├── unit/ # Unit tests
83−│ └── integration/ # Integration tests
84−├── docs/ # Additional documentation
85−├── .env.example # Environment variable template
86−├── .gitignore
87−├── .aiignore
88−├── pyproject.toml
89−├── README.md
90−└── ...
91−```
92− 
93−### File Naming Conventions
94− 
95−- **Python files:** Use `snake_case` (e.g., `device_manager.py`)
96−- **Classes:** Use `PascalCase` (e.g., `UniFiClient`)
97−- **Functions/variables:** Use `snake_case` (e.g., `get_devices()`)
98−- **Constants:** Use `UPPER_SNAKE_CASE` (e.g., `DEFAULT_TIMEOUT`)
99−- **Test files:** Prefix with `test_` (e.g., `test_device_manager.py`)
100− 
101−## Workflow Guidelines
102− 
10315 ### Before Starting Work
10416  
105−1. **Understand the Context:**
106− - Read relevant documentation (`README.md`, `API.md`, `CONTRIBUTING.md`)
107− - Review related issues and pull requests
108− - Understand the feature request or bug report completely
17+1. **Read Key Documentation**:
18+ - `README.md` - Project overview and features
19+ - `AGENTS.md` - Universal AI agent guidelines
20+ - `DEVELOPMENT_PLAN.md` - Roadmap and priorities
21+ - `TODO.md` - Current tasks and phase breakdown
22+ - `API.md` - Complete MCP tool documentation
10923  
110−2. **Plan Your Approach:**
111− - Break down the task into smaller, manageable steps
112− - Identify affected files and components
113− - Consider potential edge cases and error conditions
114− - Plan for comprehensive test coverage
24+2. **Understand the Architecture**:
25+ - `src/main.py` - MCP server entry point
26+ - `src/api/` - UniFi API client
27+ - `src/models/` - Pydantic data models
28+ - `src/tools/` - MCP tool implementations
29+ - `tests/unit/` - Unit tests (1,156 tests passing)
11530  
116−3. **Check Existing Code:**
117− - Review similar implementations in the codebase
118− - Identify reusable functions and patterns
119− - Ensure your approach is consistent with existing code
31+### Development Workflow
12032  
121−### During Development
33+1. **Feature Development**:
34+ - Create feature branch: `git checkout -b feature/your-feature`
35+ - Follow TDD: Write tests first, then implementation
36+ - Maintain 80% minimum test coverage for new code
37+ - Use Pydantic models for all data structures
38+ - Add comprehensive docstrings (Google style)
12239  
123−1. **Write Code Incrementally:**
124− - Implement one feature or fix at a time
125− - Test each change before moving to the next
126− - Commit logical units of work separately
40+2. **Code Quality**:
41+ - Run tests: `pytest tests/unit/`
42+ - Format: `black src/ tests/` and `isort src/ tests/`
43+ - Lint: `ruff check src/ tests/ --fix`
44+ - Type check: `mypy src/`
45+ - Pre-commit: `pre-commit run --all-files`
12746  
128−2. **Follow TDD (Test-Driven Development):**
129− - Write tests first when possible
130− - Ensure tests fail before implementing the feature
131− - Verify tests pass after implementation
132− - Maintain minimum 80% code coverage
47+3. **Safety Mechanisms**:
48+ - All mutating operations require `confirm=True`
49+ - Implement dry-run mode for preview
50+ - Add audit logging for operations
51+ - Validate all user inputs
52+ - Never commit secrets or credentials
13353  
134−3. **Document as You Go:**
135− - Add docstrings to all public functions and classes
136− - Update relevant documentation files
137− - Add inline comments for complex logic
138− - Keep `API.md` updated for new MCP tools/resources
54+### Technology Stack
13955  
140−### After Implementation
56+- **Language**: Python 3.10+
57+- **Framework**: FastMCP (MCP server framework)
58+- **API Client**: httpx (async HTTP)
59+- **Data Validation**: Pydantic v2
60+- **Testing**: pytest with asyncio support
61+- **Caching**: Redis (optional)
62+- **Monitoring**: agnost.ai (optional)
14163  
142−1. **Self-Review:**
143− - Review your own code critically
144− - Ensure all tests pass: `pytest`
145− - Run linting and formatting: `pre-commit run --all-files`
146− - Check for security issues: `bandit -r src/`
64+### API Modes
14765  
148−2. **Create a Pull Request:**
149− - Write a clear, descriptive PR title (conventional commits format)
150− - Fill out the PR template completely
151− - Link related issues
152− - Tag the PR as AI-assisted
153− - Request human review
66+The server supports three UniFi API access modes:
15467  
155−3. **Respond to Feedback:**
156− - Address all review comments
157− - Make requested changes promptly
158− - Explain decisions when necessary
159− - Re-request review after making changes
68+1. **Local Gateway API** (Recommended): Full feature support
69+ - `UNIFI_API_TYPE=local`
70+ - `UNIFI_LOCAL_HOST=192.168.2.1`
16071  
161−## Do's and Don'ts
72+2. **Cloud V1 API**: Stable, aggregate statistics only
73+ - `UNIFI_API_TYPE=cloud-v1`
16274  
163−### Do's ✅
75+3. **Cloud EA API**: Early Access, aggregate statistics only
76+ - `UNIFI_API_TYPE=cloud-ea`
16477  
165−- **DO** validate all user inputs
166−- **DO** handle errors gracefully with try/except blocks
167−- **DO** use type hints for all function signatures
168−- **DO** write comprehensive docstrings
169−- **DO** add tests for all new code
170−- **DO** use async/await for I/O-bound operations
171−- **DO** centralize API interactions in dedicated modules
172−- **DO** use environment variables for configuration
173−- **DO** log important events and errors appropriately
174−- **DO** follow the principle of least privilege
175−- **DO** ask for clarification when requirements are unclear
176−- **DO** use Pydantic models for data validation
177−- **DO** keep functions small and focused (single responsibility)
178−- **DO** reuse existing code when possible
78+### Current Development Focus
17979  
180−### Don'ts ❌
80+**Version 0.2.3** (Current):
18181  
182−- **DON'T** commit credentials, API keys, or secrets
183−- **DON'T** merge code without human approval
184−- **DON'T** skip writing tests
185−- **DON'T** ignore linting errors or warnings
186−- **DON'T** expose sensitive information in logs or error messages
187−- **DON'T** make breaking changes without discussion
188−- **DON'T** copy-paste code - create reusable functions instead
189−- **DON'T** use bare except clauses - catch specific exceptions
190−- **DON'T** hardcode values that should be configurable
191−- **DON'T** submit incomplete or experimental code to main
192−- **DON'T** bypass security checks or pre-commit hooks
193−- **DON'T** write code without understanding its purpose
194−- **DON'T** use deprecated libraries or functions
195−- **DON'T** ignore type errors from MyPy
82+- ✅ P1 API bug fixes (QoS audit_action, Site Manager decorator, Topology warnings, Backup client methods)
83+- ✅ P2 RADIUS & Guest Portal — Complete CRUD (get/update for RADIUS accounts and hotspot packages)
19684  
197−## Testing Requirements
85+**Version 0.2.2** (Complete ✅):
19886  
199−### Test Coverage
87+- ✅ Port Profile & Switch Port Management (8 tools)
88+- ✅ Security hardening (dependency updates, PII removal)
89+- ✅ API endpoint fixes (RADIUS, firewall, WLAN, network)
90+- ✅ Bug fixes (dry_run, list handling, type hints)
20091  
201−All AI-generated code must include tests:
92+**Version 0.2.0** (Complete ✅):
20293  
203−- **Minimum Coverage:** 80% overall
204−- **New Features:** 100% coverage of new code paths
205−- **Bug Fixes:** Regression tests for the fixed bug
206−- **Refactoring:** Maintain or improve existing coverage
94+- ✅ Zone-Based Firewall (7 working tools)
95+- ✅ Traffic Flow Monitoring (15 tools)
96+- ✅ Advanced QoS (11 tools)
97+- ✅ Backup & Restore (8 tools)
98+- ✅ Multi-Site Aggregation (4 tools)
99+- ✅ ACL & Traffic Filtering (7 tools)
100+- ✅ Site Management (9 tools)
101+- ✅ RADIUS & Guest Portal (10 tools — full CRUD)
102+- ✅ Network Topology (5 tools)
207103  
208−### Test Types
104+**Total**: 86+ MCP tools, 1,156 tests passing
209105  
210−1. **Unit Tests:**
106+### Important Constraints
211107  
212− ```python
213− import pytest
214− from src.api.client import UniFiClient
108+1. **UniFi Network 9.0+ Required**: Some features require Network 9.0+
109+2. **Local API Recommended**: Cloud APIs have limited functionality
110+3. **Endpoint Verification**: Some documented API endpoints may not exist in all versions
111+4. **Testing**: Integration tests require real UniFi hardware
215112  
216− @pytest.mark.unit
217− async def test_client_initialization():
218− """Test that UniFi client initializes correctly."""
219− client = UniFiClient(
220− api_key="test-api-key",
221− api_type="cloud",
222− host="api.ui.com"
223− )
224− assert client.host == "api.ui.com"
225− assert client.api_type == "cloud"
226− assert client.api_key == "test-api-key"
227− ```
113+### Getting Help
228114  
229−2. **Integration Tests:**
115+- **Issues**: [GitHub Issues](https://github.com/enuno/unifi-mcp-server/issues)
116+- **Documentation**: See `API.md` for complete tool reference
117+- **Examples**: Check `docs/examples/` for AI assistant prompts
230118  
231− ```python
232− import pytest
119+## Key Principles
233120  
234− @pytest.mark.integration
235− async def test_get_devices_from_real_api():
236− """Test fetching devices from real UniFi Cloud API."""
237− # This test requires UNIFI_API_KEY environment variable
238− client = UniFiClient.from_env()
239− devices = await client.get_devices()
240− assert isinstance(devices, list)
241− ```
121+1. **Safety First**: Never perform destructive operations without confirmation
122+2. **Quality Over Speed**: Maintain high test coverage and code quality
123+3. **Clarity**: Write self-documenting code with clear docstrings
124+4. **Consistency**: Follow existing patterns and conventions
125+5. **Security**: Never commit credentials, validate all inputs
242126  
243−3. **Mock Tests:**
127+## Additional Resources
244128  
245− ```python
246− from unittest.mock import AsyncMock, patch
129+- [CONTRIBUTING.md](CONTRIBUTING.md) - Contribution guidelines
130+- [SECURITY.md](SECURITY.md) - Security policy and best practices
131+- [AGENTS.md](AGENTS.md) - Detailed AI agent guidelines
132+- [TESTING_PLAN.md](docs/archive/TESTING_PLAN.md) - Testing strategy
133+- [DEVELOPMENT_PLAN.md](DEVELOPMENT_PLAN.md) - Complete roadmap
247134  
248− @pytest.mark.unit
249− async def test_get_devices_handles_error():
250− """Test error handling when API fails."""
251− with patch('src.api.client.httpx.AsyncClient.get') as mock_get:
252− mock_get.side_effect = httpx.HTTPError("Connection failed")
253− client = UniFiClient(
254− api_key="test-key",
255− host="api.ui.com",
256− api_type="cloud"
257− )
258− with pytest.raises(APIError):
259− await client.get_devices()
260− ```
261− 
262−### Running Tests
263− 
264−```bash
265−# Run all tests
266−pytest
267− 
268−# Run with coverage
269−pytest --cov=src --cov-report=html --cov-report=term-missing
270− 
271−# Run only unit tests
272−pytest -m unit
273− 
274−# Run only integration tests (requires UniFi controller)
275−pytest -m integration
276− 
277−# Run specific test file
278−pytest tests/unit/test_client.py
279− 
280−# Run tests matching pattern
281−pytest -k "test_device"
282−```
283− 
284−## Security Guardrails
285− 
286−### Credential Management
287− 
288−**NEVER include API keys or credentials in code:**
289− 
290−```python
291−# ❌ BAD - Hardcoded API key
292−client = UniFiClient(
293− api_key="abc123def456ghi789...",
294− host="api.ui.com"
295−)
296− 
297−# ✅ GOOD - Load from environment
298−from src.config.settings import Settings
299− 
300−settings = Settings() # Loads from environment
301−client = UniFiClient(
302− api_key=settings.unifi_api_key,
303− host=settings.unifi_host,
304− api_type=settings.unifi_api_type
305−)
306−```
307− 
308−### Input Validation
309− 
310−Always validate and sanitize inputs:
311− 
312−```python
313−from pydantic import BaseModel, Field, validator
314− 
315−class NetworkConfig(BaseModel):
316− name: str = Field(..., min_length=1, max_length=32)
317− vlan_id: int = Field(..., ge=1, le=4094)
318− subnet: str
319− 
320− @validator('subnet')
321− def validate_subnet(cls, v):
322− import ipaddress
323− try:
324− ipaddress.ip_network(v)
325− except ValueError:
326− raise ValueError('Invalid subnet format')
327− return v
328−```
329− 
330−### Error Handling
331− 
332−Don't expose sensitive information in errors:
333− 
334−```python
335−# ❌ BAD - Exposes API key in logs
336−logging.error(f"Auth failed with API key: {api_key}")
337− 
338−# ✅ GOOD - Safe error message
339−logging.error(f"Authentication failed for host '{host}' (API key: {api_key[:8]}...)")
340− 
341−# ✅ EVEN BETTER - No key exposure
342−logging.error(f"Authentication failed for host '{host}'. Check your UNIFI_API_KEY.")
343−```
344− 
345−### Secret Detection
346− 
347−Pre-commit hooks will prevent committing secrets:
348− 
349−```bash
350−# Initialize pre-commit
351−pre-commit install
352− 
353−# Manually check for secrets
354−detect-secrets scan
355−```
356− 
357−## UniFi API Guidelines
358− 
359−### Authentication with API Keys
360− 
361−This project uses the **official UniFi Cloud API** with API key authentication. All AI agents must follow these guidelines:
362− 
363−**Authentication Method:**
364− 
365−- Use `UNIFI_API_KEY` environment variable for authentication
366−- API key is passed via the `X-API-Key` HTTP header
367−- No session management or cookies required (stateless authentication)
368− 
369−**NEVER hardcode API keys:**
370− 
371−```python
372−# ❌ BAD - Hardcoded API key
373−headers = {
374− "X-API-Key": "abc123def456..."
375−}
376− 
377−# ✅ GOOD - Load from environment
378−from src.config.settings import Settings
379− 
380−settings = Settings()
381−headers = {
382− "X-API-Key": settings.unifi_api_key
383−}
384−```
385− 
386−### API Access Modes
387− 
388−Support both cloud and local gateway access modes:
389− 
390−**Cloud API (Default):**
391− 
392−```python
393−# Base URL: https://api.ui.com/v1/
394−settings.unifi_api_type = "cloud"
395−settings.unifi_host = "api.ui.com"
396−settings.unifi_port = 443
397−```
398− 
399−**Local Gateway Proxy:**
400− 
401−```python
402−# Base URL: https://{gateway-ip}/proxy/network/integration/v1/
403−settings.unifi_api_type = "local"
404−settings.unifi_host = "192.168.2.1"
405−settings.unifi_port = 443
406−```
407− 
408−### Read-Only Limitation
409− 
410−**IMPORTANT:** The Early Access API is currently **read-only**.
411− 
412−```python
413−# ✅ ALLOWED - Read operations
414−async def list_devices(site_id: str):
415− """List all devices - read operation."""
416− devices = await client.get(f"/v1/sites/{site_id}/devices")
417− return devices
418− 
419−# ❌ NOT AVAILABLE - Write operations (will fail)
420−async def create_network(name: str, vlan_id: int):
421− """Create network - not yet supported in EA API."""
422− # This will return 403 Forbidden in current API version
423− raise NotImplementedError(
424− "Write operations are not available in the Early Access API. "
425− "This feature will be available in v1 Stable release."
426− )
427−```
428− 
429−**Handling write requests:**
430− 
431−- Document that write operations are not yet available
432−- Return clear error messages to users
433−- Consider implementing a "preview" mode that shows what would be created
434−- Monitor UniFi API release notes for v1 Stable availability
435− 
436−### Rate Limiting Considerations
437− 
438−Implement proper rate limiting to respect API limits:
439− 
440−**Current Limits:**
441− 
442−- Early Access: 100 requests/minute
443−- v1 Stable (future): 10,000 requests/minute
444− 
445−**Implementation Example:**
446− 
447−```python
448−import asyncio
449−from collections import deque
450−from datetime import datetime, timedelta
451− 
452−class UniFiRateLimiter:
453− """Rate limiter for UniFi API requests."""
454− 
455− def __init__(self, max_requests: int = 100, window_seconds: int = 60):
456− self.max_requests = max_requests
457− self.window = timedelta(seconds=window_seconds)
458− self.requests = deque()
459− 
460− async def acquire(self):
461− """Wait if necessary to respect rate limits."""
462− now = datetime.now()
463− 
464− # Remove old requests outside the window
465− while self.requests and self.requests[0] < now - self.window:
466− self.requests.popleft()
467− 
468− # Wait if at limit
469− if len(self.requests) >= self.max_requests:
470− sleep_time = (self.requests[0] + self.window - now).total_seconds()
471− if sleep_time > 0:
472− await asyncio.sleep(sleep_time)
473− 
474− self.requests.append(now)
475−```
476− 
477−**Best Practices:**
478− 
479−- Cache frequently accessed data (devices, sites, networks)
480−- Batch operations when possible
481−- Implement exponential backoff for 429 errors
482−- Use configurable rate limits via `UNIFI_RATE_LIMIT` environment variable
483−- Log rate limit warnings for monitoring
484− 
485−### API Error Handling
486− 
487−Handle UniFi API-specific errors gracefully:
488− 
489−```python
490−import httpx
491−from typing import Dict, Any
492− 
493−class UniFiAPIError(Exception):
494− """Base exception for UniFi API errors."""
495− pass
496− 
497−class UniFiAuthenticationError(UniFiAPIError):
498− """Authentication failed - invalid API key."""
499− pass
500− 
501−class UniFiRateLimitError(UniFiAPIError):
502− """Rate limit exceeded."""
503− pass
504− 
505−async def safe_api_request(
506− client: httpx.AsyncClient,
507− method: str,
508− endpoint: str,
509− **kwargs
510−) -> Dict[str, Any]:
511− """
512− Make a safe API request with proper error handling.
513− 
514− Args:
515− client: HTTP client
516− method: HTTP method (GET, POST, etc.)
517− endpoint: API endpoint
518− **kwargs: Additional request parameters
519− 
520− Returns:
521− Response data as dictionary
522− 
523− Raises:
524− UniFiAuthenticationError: Invalid API key
525− UniFiRateLimitError: Rate limit exceeded
526− UniFiAPIError: Other API errors
527− """
528− try:
529− response = await client.request(method, endpoint, **kwargs)
530− response.raise_for_status()
531− return response.json()
532− 
533− except httpx.HTTPStatusError as e:
534− if e.response.status_code == 401:
535− raise UniFiAuthenticationError(
536− "Invalid API key. Please check your UNIFI_API_KEY."
537− )
538− elif e.response.status_code == 429:
539− retry_after = e.response.headers.get("Retry-After", 60)
540− raise UniFiRateLimitError(
541− f"Rate limit exceeded. Retry after {retry_after} seconds."
542− )
543− else:
544− raise UniFiAPIError(f"API error: {e.response.status_code}")
545− 
546− except httpx.RequestError as e:
547− raise UniFiAPIError(f"Request failed: {str(e)}")
548−```
549− 
550−### Official API Documentation
551− 
552−Always reference the official UniFi API documentation:
553− 
554−**Primary Resources:**
555− 
556−- **Getting Started**: [https://developer.ui.com/site-manager-api/gettingstarted](https://developer.ui.com/site-manager-api/gettingstarted)
557−- **Project Reference**: `docs/UNIFI_API.md` (comprehensive guide)
558−- **API Tutorial**: [https://www.makewithdata.tech/p/build-a-mcp-server-for-ai-access](https://www.makewithdata.tech/p/build-a-mcp-server-for-ai-access)
559− 
560−**When implementing new features:**
561− 
562−1. Review official API documentation first
563−2. Check `docs/UNIFI_API.md` for project-specific guidance
564−3. Ensure endpoint paths match official specifications
565−4. Test against real UniFi Cloud API or gateway proxy
566−5. Document any API limitations or quirks discovered
567− 
568−### API Key Security Checklist
569− 
570−Before committing code, verify:
571− 
572−- [ ] No hardcoded API keys in source code
573−- [ ] API key loaded from environment variables
574−- [ ] No API keys in log messages (even debug logs)
575−- [ ] API keys redacted in error messages
576−- [ ] `.env` file in `.gitignore`
577−- [ ] `.env.example` has placeholder, not real key
578−- [ ] Pre-commit hooks detect-secrets passing
579−- [ ] Documentation mentions API key security
580− 
581−## Code Quality Standards
582− 
583−### Type Hints
584− 
585−All functions must have type hints:
586− 
587−```python
588−from typing import List, Dict, Optional
589−import httpx
590− 
591−async def get_devices(
592− client: httpx.AsyncClient,
593− site_id: str = "default"
594−) -> List[Dict[str, Any]]:
595− """Fetch devices from UniFi controller."""
596− response = await client.get(f"/api/s/{site_id}/stat/device")
597− return response.json()["data"]
598−```
599− 
600−### Docstrings
601− 
602−Use Google-style docstrings:
603− 
604−```python
605−def calculate_network_capacity(
606− bandwidth_mbps: int,
607− devices: int,
608− overhead_percent: float = 0.2
609−) -> float:
610− """
611− Calculate available bandwidth per device.
612− 
613− Args:
614− bandwidth_mbps: Total bandwidth in Mbps
615− devices: Number of connected devices
616− overhead_percent: Network overhead as decimal (default: 0.2 for 20%)
617− 
618− Returns:
619− Available bandwidth per device in Mbps
620− 
621− Raises:
622− ValueError: If bandwidth or devices is less than 1
623− 
624− Example:
625− >>> calculate_network_capacity(100, 10)
626− 8.0
627− """
628− if bandwidth_mbps < 1 or devices < 1:
629− raise ValueError("Bandwidth and devices must be positive")
630− 
631− available = bandwidth_mbps * (1 - overhead_percent)
632− return available / devices
633−```
634− 
635−### Code Formatting
636− 
637−Code is automatically formatted by pre-commit hooks:
638− 
639−```bash
640−# Format code
641−black src/ tests/
642− 
643−# Sort imports
644−isort src/ tests/
645− 
646−# Lint code
647−ruff check src/ tests/ --fix
648−```
649− 
650−## Documentation Requirements
651− 
652−### Code Documentation
653− 
654−- **All public functions:** Require docstrings
655−- **Complex logic:** Add inline comments
656−- **Type hints:** Required for all functions
657−- **Examples:** Include in docstrings when helpful
658− 
659−### Project Documentation
660− 
661−Update relevant documentation files:
662− 
663−- `README.md` - For user-facing changes
664−- `API.md` - For new MCP tools or resources
665−- `CONTRIBUTING.md` - For workflow changes
666−- `SECURITY.md` - For security-related changes
667− 
668−### API Documentation
669− 
670−When adding new MCP tools, document in `API.md`:
671− 
672−```markdown
673−### get_device
674− 
675−Retrieve information about a specific UniFi device.
676− 
677−**Parameters:**
678−- `mac_address` (string, required): Device MAC address
679−- `site_id` (string, optional): Site identifier (default: "default")
680− 
681−**Returns:**
682−Object containing device information
683− 
684−**Example:**
685−\`\`\`python
686−result = await mcp.call_tool("get_device", {
687− "mac_address": "aa:bb:cc:dd:ee:ff",
688− "site_id": "default"
689−})
690−\`\`\`
691−```
692− 
693−## Approval and Merge Policies
694− 
695−### Auto-Merge Restrictions
696− 
697−AI agents **MUST NOT**:
698− 
699−- Automatically merge pull requests
700−- Bypass code review requirements
701−- Push directly to the `main` branch
702−- Override branch protection rules
703−- Disable or skip CI/CD checks
704− 
705−### Required Approvals
706− 
707−All AI-generated code requires:
708− 
709−- At least one human reviewer approval
710−- All CI/CD checks passing
711−- No unresolved review comments
712−- Up-to-date with the `main` branch
713− 
714−### Human-in-the-Loop
715− 
716−Critical changes require additional human review:
717− 
718−- Security-related code
719−- Authentication/authorization logic
720−- Data deletion or modification
721−- API contract changes
722−- Database schema changes
723−- Configuration changes affecting production
724− 
725−### Tagging AI Contributions
726− 
727−Mark AI-assisted PRs in the description:
728− 
729−```markdown
730−## AI Assistance
731− 
732−This PR was created with assistance from Claude Code.
733− 
734−**Human Review Status:** ✅ Reviewed and approved by @username
735−**Test Coverage:** 95%
736−**Security Review:** Completed
737−```
738− 
739−## Special Considerations
740− 
741−### MCP-Specific Guidelines
742− 
743−When implementing MCP tools and resources:
744− 
745−```python
746−from fastmcp import FastMCP
747− 
748−mcp = FastMCP("UniFi Network")
749− 
750−@mcp.tool()
751−async def get_devices(site_id: str = "default") -> list:
752− """
753− Get all devices for a site.
754− 
755− Args:
756− site_id: Site identifier (default: "default")
757− 
758− Returns:
759− List of device objects
760− """
761− # Implementation
762− pass
763− 
764−@mcp.resource("sites://{site_id}/devices")
765−async def list_site_devices(site_id: str) -> str:
766− """List all devices in a site."""
767− # Return JSON string of devices
768− pass
769−```
770− 
771−### UniFi API Integration
772− 
773−Centralize API calls in dedicated modules:
774− 
775−```python
776−# src/api/client.py
777−class UniFiClient:
778− async def request(
779− self,
780− method: str,
781− endpoint: str,
782− **kwargs
783− ) -> Dict[str, Any]:
784− """
785− Make authenticated request to UniFi API.
786− 
787− Handles authentication, retries, and error handling.
788− """
789− # Centralized implementation
790− pass
791−```
792− 
793−## Conclusion
794− 
795−By following these guidelines, AI agents can contribute effectively to the UniFi MCP Server project while maintaining high standards of quality, security, and maintainability.
796− 
797−**Remember:** When in doubt, ask for human guidance. It's better to request clarification than to make assumptions that could introduce bugs or security issues.
798− 
799135 ---
800136  
801−**Last Updated:** 2025-10-17
802− 
803−For additional guidance, see:
804− 
805−- `AI_CODING_ASSISTANT.md` - Project-specific AI guidelines
806−- `AI_GIT_PRACTICES.md` - AI-specific Git practices
807−- `CONTRIBUTING.md` - General contribution guidelines
808−- `SECURITY.md` - Security policies
137+**Last Updated**: 2026-02-18
138+**Maintained By**: Development Team
809139  

Also from Kynth Studios

Built for the same person as RuleStack

ToolDrift

What the AI coding tools changed last night

tooldrift.kynth.studio

StillShipping

Which agent tools have stopped shipping

stillshipping.kynth.studio

BlockDex

Search inside every shadcn registry

blockdex.kynth.studio

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack