feat: v3.0.0 architecture overhaul
- Rename marketplace to lm-claude-plugins - Move MCP servers to root with symlinks - Add 6 PR tools to Gitea MCP (list_pull_requests, get_pull_request, get_pr_diff, get_pr_comments, create_pr_review, add_pr_comment) - Add clarity-assist plugin (prompt optimization with ND accommodations) - Add git-flow plugin (workflow automation) - Add pr-review plugin (multi-agent review with confidence scoring) - Centralize configuration docs - Update all documentation for v3.0.0 BREAKING CHANGE: MCP server paths changed, marketplace renamed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
281
mcp-servers/netbox/mcp_server/tools/tenancy.py
Normal file
281
mcp-servers/netbox/mcp_server/tools/tenancy.py
Normal file
@@ -0,0 +1,281 @@
|
||||
"""
|
||||
Tenancy tools for NetBox MCP Server.
|
||||
|
||||
Covers: Tenants, Tenant Groups, Contacts, Contact Groups, and Contact Roles.
|
||||
"""
|
||||
import logging
|
||||
from typing import List, Dict, Optional, Any
|
||||
from ..netbox_client import NetBoxClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TenancyTools:
|
||||
"""Tools for Tenancy operations in NetBox"""
|
||||
|
||||
def __init__(self, client: NetBoxClient):
|
||||
self.client = client
|
||||
self.base_endpoint = 'tenancy'
|
||||
|
||||
# ==================== Tenant Groups ====================
|
||||
|
||||
async def list_tenant_groups(
|
||||
self,
|
||||
name: Optional[str] = None,
|
||||
slug: Optional[str] = None,
|
||||
parent_id: Optional[int] = None,
|
||||
**kwargs
|
||||
) -> List[Dict]:
|
||||
"""List all tenant groups."""
|
||||
params = {k: v for k, v in {
|
||||
'name': name, 'slug': slug, 'parent_id': parent_id, **kwargs
|
||||
}.items() if v is not None}
|
||||
return self.client.list(f'{self.base_endpoint}/tenant-groups', params=params)
|
||||
|
||||
async def get_tenant_group(self, id: int) -> Dict:
|
||||
"""Get a specific tenant group by ID."""
|
||||
return self.client.get(f'{self.base_endpoint}/tenant-groups', id)
|
||||
|
||||
async def create_tenant_group(
|
||||
self,
|
||||
name: str,
|
||||
slug: str,
|
||||
parent: Optional[int] = None,
|
||||
description: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> Dict:
|
||||
"""Create a new tenant group."""
|
||||
data = {'name': name, 'slug': slug, **kwargs}
|
||||
if parent:
|
||||
data['parent'] = parent
|
||||
if description:
|
||||
data['description'] = description
|
||||
return self.client.create(f'{self.base_endpoint}/tenant-groups', data)
|
||||
|
||||
async def update_tenant_group(self, id: int, **kwargs) -> Dict:
|
||||
"""Update a tenant group."""
|
||||
return self.client.patch(f'{self.base_endpoint}/tenant-groups', id, kwargs)
|
||||
|
||||
async def delete_tenant_group(self, id: int) -> None:
|
||||
"""Delete a tenant group."""
|
||||
self.client.delete(f'{self.base_endpoint}/tenant-groups', id)
|
||||
|
||||
# ==================== Tenants ====================
|
||||
|
||||
async def list_tenants(
|
||||
self,
|
||||
name: Optional[str] = None,
|
||||
slug: Optional[str] = None,
|
||||
group_id: Optional[int] = None,
|
||||
**kwargs
|
||||
) -> List[Dict]:
|
||||
"""List all tenants with optional filtering."""
|
||||
params = {k: v for k, v in {
|
||||
'name': name, 'slug': slug, 'group_id': group_id, **kwargs
|
||||
}.items() if v is not None}
|
||||
return self.client.list(f'{self.base_endpoint}/tenants', params=params)
|
||||
|
||||
async def get_tenant(self, id: int) -> Dict:
|
||||
"""Get a specific tenant by ID."""
|
||||
return self.client.get(f'{self.base_endpoint}/tenants', id)
|
||||
|
||||
async def create_tenant(
|
||||
self,
|
||||
name: str,
|
||||
slug: str,
|
||||
group: Optional[int] = None,
|
||||
description: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> Dict:
|
||||
"""Create a new tenant."""
|
||||
data = {'name': name, 'slug': slug, **kwargs}
|
||||
if group:
|
||||
data['group'] = group
|
||||
if description:
|
||||
data['description'] = description
|
||||
return self.client.create(f'{self.base_endpoint}/tenants', data)
|
||||
|
||||
async def update_tenant(self, id: int, **kwargs) -> Dict:
|
||||
"""Update a tenant."""
|
||||
return self.client.patch(f'{self.base_endpoint}/tenants', id, kwargs)
|
||||
|
||||
async def delete_tenant(self, id: int) -> None:
|
||||
"""Delete a tenant."""
|
||||
self.client.delete(f'{self.base_endpoint}/tenants', id)
|
||||
|
||||
# ==================== Contact Groups ====================
|
||||
|
||||
async def list_contact_groups(
|
||||
self,
|
||||
name: Optional[str] = None,
|
||||
slug: Optional[str] = None,
|
||||
parent_id: Optional[int] = None,
|
||||
**kwargs
|
||||
) -> List[Dict]:
|
||||
"""List all contact groups."""
|
||||
params = {k: v for k, v in {
|
||||
'name': name, 'slug': slug, 'parent_id': parent_id, **kwargs
|
||||
}.items() if v is not None}
|
||||
return self.client.list(f'{self.base_endpoint}/contact-groups', params=params)
|
||||
|
||||
async def get_contact_group(self, id: int) -> Dict:
|
||||
"""Get a specific contact group by ID."""
|
||||
return self.client.get(f'{self.base_endpoint}/contact-groups', id)
|
||||
|
||||
async def create_contact_group(
|
||||
self,
|
||||
name: str,
|
||||
slug: str,
|
||||
parent: Optional[int] = None,
|
||||
description: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> Dict:
|
||||
"""Create a new contact group."""
|
||||
data = {'name': name, 'slug': slug, **kwargs}
|
||||
if parent:
|
||||
data['parent'] = parent
|
||||
if description:
|
||||
data['description'] = description
|
||||
return self.client.create(f'{self.base_endpoint}/contact-groups', data)
|
||||
|
||||
async def update_contact_group(self, id: int, **kwargs) -> Dict:
|
||||
"""Update a contact group."""
|
||||
return self.client.patch(f'{self.base_endpoint}/contact-groups', id, kwargs)
|
||||
|
||||
async def delete_contact_group(self, id: int) -> None:
|
||||
"""Delete a contact group."""
|
||||
self.client.delete(f'{self.base_endpoint}/contact-groups', id)
|
||||
|
||||
# ==================== Contact Roles ====================
|
||||
|
||||
async def list_contact_roles(
|
||||
self,
|
||||
name: Optional[str] = None,
|
||||
slug: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> List[Dict]:
|
||||
"""List all contact roles."""
|
||||
params = {k: v for k, v in {'name': name, 'slug': slug, **kwargs}.items() if v is not None}
|
||||
return self.client.list(f'{self.base_endpoint}/contact-roles', params=params)
|
||||
|
||||
async def get_contact_role(self, id: int) -> Dict:
|
||||
"""Get a specific contact role by ID."""
|
||||
return self.client.get(f'{self.base_endpoint}/contact-roles', id)
|
||||
|
||||
async def create_contact_role(
|
||||
self,
|
||||
name: str,
|
||||
slug: str,
|
||||
description: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> Dict:
|
||||
"""Create a new contact role."""
|
||||
data = {'name': name, 'slug': slug, **kwargs}
|
||||
if description:
|
||||
data['description'] = description
|
||||
return self.client.create(f'{self.base_endpoint}/contact-roles', data)
|
||||
|
||||
async def update_contact_role(self, id: int, **kwargs) -> Dict:
|
||||
"""Update a contact role."""
|
||||
return self.client.patch(f'{self.base_endpoint}/contact-roles', id, kwargs)
|
||||
|
||||
async def delete_contact_role(self, id: int) -> None:
|
||||
"""Delete a contact role."""
|
||||
self.client.delete(f'{self.base_endpoint}/contact-roles', id)
|
||||
|
||||
# ==================== Contacts ====================
|
||||
|
||||
async def list_contacts(
|
||||
self,
|
||||
name: Optional[str] = None,
|
||||
group_id: Optional[int] = None,
|
||||
email: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> List[Dict]:
|
||||
"""List all contacts with optional filtering."""
|
||||
params = {k: v for k, v in {
|
||||
'name': name, 'group_id': group_id, 'email': email, **kwargs
|
||||
}.items() if v is not None}
|
||||
return self.client.list(f'{self.base_endpoint}/contacts', params=params)
|
||||
|
||||
async def get_contact(self, id: int) -> Dict:
|
||||
"""Get a specific contact by ID."""
|
||||
return self.client.get(f'{self.base_endpoint}/contacts', id)
|
||||
|
||||
async def create_contact(
|
||||
self,
|
||||
name: str,
|
||||
group: Optional[int] = None,
|
||||
title: Optional[str] = None,
|
||||
phone: Optional[str] = None,
|
||||
email: Optional[str] = None,
|
||||
address: Optional[str] = None,
|
||||
link: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> Dict:
|
||||
"""Create a new contact."""
|
||||
data = {'name': name, **kwargs}
|
||||
for key, val in [
|
||||
('group', group), ('title', title), ('phone', phone),
|
||||
('email', email), ('address', address), ('link', link),
|
||||
('description', description)
|
||||
]:
|
||||
if val is not None:
|
||||
data[key] = val
|
||||
return self.client.create(f'{self.base_endpoint}/contacts', data)
|
||||
|
||||
async def update_contact(self, id: int, **kwargs) -> Dict:
|
||||
"""Update a contact."""
|
||||
return self.client.patch(f'{self.base_endpoint}/contacts', id, kwargs)
|
||||
|
||||
async def delete_contact(self, id: int) -> None:
|
||||
"""Delete a contact."""
|
||||
self.client.delete(f'{self.base_endpoint}/contacts', id)
|
||||
|
||||
# ==================== Contact Assignments ====================
|
||||
|
||||
async def list_contact_assignments(
|
||||
self,
|
||||
contact_id: Optional[int] = None,
|
||||
role_id: Optional[int] = None,
|
||||
object_type: Optional[str] = None,
|
||||
object_id: Optional[int] = None,
|
||||
**kwargs
|
||||
) -> List[Dict]:
|
||||
"""List all contact assignments."""
|
||||
params = {k: v for k, v in {
|
||||
'contact_id': contact_id, 'role_id': role_id,
|
||||
'object_type': object_type, 'object_id': object_id, **kwargs
|
||||
}.items() if v is not None}
|
||||
return self.client.list(f'{self.base_endpoint}/contact-assignments', params=params)
|
||||
|
||||
async def get_contact_assignment(self, id: int) -> Dict:
|
||||
"""Get a specific contact assignment by ID."""
|
||||
return self.client.get(f'{self.base_endpoint}/contact-assignments', id)
|
||||
|
||||
async def create_contact_assignment(
|
||||
self,
|
||||
contact: int,
|
||||
role: int,
|
||||
object_type: str,
|
||||
object_id: int,
|
||||
priority: Optional[str] = None,
|
||||
**kwargs
|
||||
) -> Dict:
|
||||
"""Create a new contact assignment."""
|
||||
data = {
|
||||
'contact': contact, 'role': role,
|
||||
'object_type': object_type, 'object_id': object_id, **kwargs
|
||||
}
|
||||
if priority:
|
||||
data['priority'] = priority
|
||||
return self.client.create(f'{self.base_endpoint}/contact-assignments', data)
|
||||
|
||||
async def update_contact_assignment(self, id: int, **kwargs) -> Dict:
|
||||
"""Update a contact assignment."""
|
||||
return self.client.patch(f'{self.base_endpoint}/contact-assignments', id, kwargs)
|
||||
|
||||
async def delete_contact_assignment(self, id: int) -> None:
|
||||
"""Delete a contact assignment."""
|
||||
self.client.delete(f'{self.base_endpoint}/contact-assignments', id)
|
||||
Reference in New Issue
Block a user