myco:extend-unifi-api

Implements new UniFi resource types end-to-end across manager, tool, and API layers.

777|101|Updated Apr 21, 2025
One-click install
npx skills add https://github.com/sirkirby/unifi-network-mcp --skill myco-extend-unifi-api
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: myco:extend-unifi-api
Source: https://github.com/sirkirby/unifi-network-mcp/tree/main/.agents/skills/extend-unifi-api
Command: npx skills add https://github.com/sirkirby/unifi-network-mcp --skill myco-extend-unifi-api

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Adding a new UniFi resource type to this monorepo requires coordinated changes across many layers — manager classes, MCP tool modules, Pydantic domain models, tests, REST/GraphQL API exposure, and the action dispatcher — and missing any one surface causes silent failures or CI merge blocks. This Skill encodes the complete, battle-tested procedure so nothing is missed.

Core Features & Use Cases

  • End-to-end resource implementation: Step-by-step coverage of manager CRUD (including 405 list-and-filter workarounds), V2 response normalization, domain Pydantic models with MUTABLE_FIELDS validation, tool modules with preview/confirm flow, and typed action input models.
  • API layer integration: Strawberry GraphQL type registration, cursor-based pagination, serializer registration, DISPATCH_ARG_TRANSLATORS wiring, render hints, and HTTP error contracts (409 for capability mismatch).
  • Field-symmetry migration and update safety: Procedures for auditing list/create/update field parity, the fetch-merge-put update pattern with deepcopy, delta previews, and write-verification classification of persisted/dropped/coerced fields.
  • Use Case: When asked to add support for a new UniFi resource (e.g., a new firewall or alarm resource), apply this Skill to produce the manager, tools, models, tests, GraphQL type, REST route, dispatcher translator, and regenerated manifests in one CI-passing change.

Quick Start

Apply the extend-unifi-api skill to implement a new UniFi resource type end-to-end across the manager, tool, and API layers.

Frequently Asked Questions about myco:extend-unifi-api

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I add a new UniFi resource type to the MCP server?

Create a manager class in unifi-core, define a Pydantic domain model with MUTABLE_FIELDS, add a tool module with preview/confirm flow, write manager and tool tests, then run make generate to update the manifest. The API layer also needs a Strawberry type, REST route, serializer, and dispatcher translator.

How do I handle UniFi endpoints that return 405 on GET by ID?

Implement get_{resource} via list-and-filter instead of a direct GET-by-ID call: fetch the full list, match on the _id field, and raise a not-found error if absent. This pattern applies to DNS records, AP groups, ACL rules, and filtering rules.

Why does my UniFi update tool silently drop fields?

Silent drops happen when update tools skip the fetch-merge-put pattern or omit additionalProperties: false on the input schema. Always fetch current state, deepcopy it, merge the caller's partial dict, and PUT the fully merged object so omitted fields are preserved.

What is the difference between UniFi V2 ObjectID and Integration UUID?

The V2 API _id is a controller-local ObjectID valid only within that controller's database, while the Integration UUID is used for cross-controller queries. Sending an ObjectID to a different controller fails silently with 404 or empty results.

Why is my UniFi API PR blocked by CI after adding a new tool?

The multi-surface Phase 8 gate requires all surfaces complete: GraphQL type and query field, REST route, action dispatcher entry, serializer registration, regenerated GraphQL docs, skill references artifact, and committed openapi.json. Incomplete PRs are merge-blocked.

When should a Protect list tool use kind=list versus a DETAIL wrapper?

Use kind=list with automatic _coerce_list_result normalization when the manager returns a consistent single-key envelope. Use a DETAIL wrapper with a normalizing from_manager_output classmethod when firmware versions return either a bare list or an {items, count} dict.