Compare commits
64 Commits
v5.9.0
...
0e70156e26
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e70156e26 | |||
| 01c225540b | |||
| 52c5be32c4 | |||
| 46e83bc711 | |||
| c0443a7f36 | |||
| c4dd4ee25d | |||
| 184ab48933 | |||
| a741ec3f88 | |||
| f1732f07c1 | |||
| f9df3b57ea | |||
| b0e6d738fa | |||
| 9044fe28ec | |||
| c37107fc42 | |||
| 841ce67dae | |||
| da0be51946 | |||
| d9d80d77cb | |||
| 3557f17177 | |||
| a005610a37 | |||
| 19ba80191f | |||
| 8f9ba64688 | |||
| e35e22cffb | |||
| 0ea30e0d75 | |||
| c530f568ed | |||
| 027ae660c4 | |||
| 5e20c6b6ef | |||
| 5e20a4a229 | |||
| 56c9a38813 | |||
| 67d769e9e5 | |||
| 3d2f14b0ab | |||
| b76e53c215 | |||
| 3d96f6b505 | |||
| edee44088c | |||
| 938ddd7b69 | |||
| aa68883f87 | |||
| dd36a79bcb | |||
| 091e3d25f3 | |||
| b605a2de5e | |||
| 4aa0baa2a6 | |||
| e3db084195 | |||
| 2a92211b28 | |||
| de6cba5f31 | |||
| 31dcf0338c | |||
| 569dc9a8f2 | |||
| 7217790143 | |||
| 97159274c7 | |||
| 5cf4b4a78c | |||
| 96a612a1f4 | |||
| 47a3a8b48a | |||
| 1b75b10fec | |||
| e925f80252 | |||
| b1070aac52 | |||
| d2b6560fba | |||
| 4b1c561bb6 | |||
| 786d3c0013 | |||
| 59cc67f857 | |||
| 6613ef1d67 | |||
| 6619d0a2fb | |||
| dc08ce1439 | |||
| 2173f3389a | |||
| fab1345bcb | |||
| 36e6ac2dd0 | |||
| 3e0e779803 | |||
| 74198743ab | |||
| d57bff184e |
@@ -6,7 +6,7 @@
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Project management plugins with Gitea and NetBox integrations",
|
||||
"version": "5.9.0"
|
||||
"version": "5.10.0"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -84,6 +84,13 @@ Thumbs.db
|
||||
# Claude Code
|
||||
.claude/settings.local.json
|
||||
.claude/history/
|
||||
.claude/backups/
|
||||
|
||||
# Doc Guardian transient files
|
||||
.doc-guardian-queue
|
||||
|
||||
# Development convenience links
|
||||
.marketplaces-link
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
|
||||
123
CHANGELOG.md
123
CHANGELOG.md
@@ -8,6 +8,99 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
---
|
||||
|
||||
## [6.0.0] - YYYY-MM-DD
|
||||
|
||||
### Added
|
||||
|
||||
#### Plan-Then-Batch Skill Optimization (projman)
|
||||
|
||||
New execution pattern that separates cognitive work from mechanical API operations, reducing skill-related token consumption by ~76-83% during sprint workflows.
|
||||
|
||||
- **`skills/batch-execution.md`** — New skill defining the plan-then-batch protocol:
|
||||
- Phase 1: Cognitive work with all skills loaded
|
||||
- Phase 2: Execution manifest (structured plan of all API operations)
|
||||
- Phase 3: Batch execute API calls using only frontmatter skills
|
||||
- Phase 4: Batch report with success/failure summary
|
||||
- Error handling: continue on individual failures, report at end
|
||||
|
||||
- **Frontmatter skill promotion:**
|
||||
- Planner agent: `mcp-tools-reference` and `batch-execution` promoted to frontmatter (auto-injected, zero re-read cost)
|
||||
- Orchestrator agent: same promotion
|
||||
- Eliminates per-operation skill file re-reads during API execution loops
|
||||
|
||||
- **Phase-based skill loading:**
|
||||
- Planner: 3 phases (validation → analysis → approval) with explicit "read once" instructions
|
||||
- Orchestrator: 2 phases (startup → dispatch) with same pattern
|
||||
- New `## Skill Loading Protocol` section replaces flat `## Skills to Load` in agent files
|
||||
|
||||
### Changed
|
||||
|
||||
- **`planning-workflow.md`** — Steps 8-10 restructured:
|
||||
- Step 8: "Draft Issue Specifications" (no API calls — resolve all parameters first)
|
||||
- Step 8a: "Batch Execute Issue Creation" (tight API loop, frontmatter skills only)
|
||||
- Step 9: Merged into Step 8a (dependencies created in batch)
|
||||
- Step 10: Milestone creation moved before batch (must exist for assignment)
|
||||
|
||||
- **Agent matrix updated:**
|
||||
- Planner: `body text (14)` → `frontmatter (2) + body text (12)`
|
||||
- Orchestrator: `body text (12)` → `frontmatter (2) + body text (10)`
|
||||
|
||||
- **`docs/CONFIGURATION.md`** — New "Phase-Based Skill Loading" subsection documenting the pattern
|
||||
|
||||
### Token Impact
|
||||
|
||||
| Scenario | Before | After | Savings |
|
||||
|----------|--------|-------|---------|
|
||||
| 6-issue sprint (planning) | ~23,800 lines | ~5,600 lines | ~76% |
|
||||
| 10-issue sprint (planning) | ~35,000 lines | ~7,000 lines | ~80% |
|
||||
| 8-issue status updates (orchestrator) | ~9,600 lines | ~1,600 lines | ~83% |
|
||||
|
||||
---
|
||||
|
||||
## [5.10.0] - 2026-02-03
|
||||
|
||||
### Added
|
||||
|
||||
#### NetBox MCP Server: Module-Based Tool Filtering
|
||||
|
||||
Environment-variable-driven module filtering to reduce token consumption:
|
||||
|
||||
- **New config option**: `NETBOX_ENABLED_MODULES` in `~/.config/claude/netbox.env`
|
||||
- **Token savings**: ~15,000 tokens (from ~19,810 to ~4,500) with recommended config
|
||||
- **Default behavior**: All modules enabled if env var unset (backward compatible)
|
||||
- **Startup logging**: Shows enabled modules and tool count on initialization
|
||||
- **Routing guard**: Clear error message when calling disabled module's tools
|
||||
|
||||
**Recommended configuration for cmdb-assistant users:**
|
||||
```bash
|
||||
NETBOX_ENABLED_MODULES=dcim,ipam,virtualization,extras
|
||||
```
|
||||
|
||||
This enables ~43 tools covering all cmdb-assistant commands while staying well below the 25K token warning threshold.
|
||||
|
||||
### Fixed
|
||||
|
||||
#### cmdb-assistant Documentation: Incorrect Tool Names
|
||||
|
||||
Fixed documentation referencing non-existent `virtualization_*` tool names:
|
||||
|
||||
| File | Wrong | Correct |
|
||||
|------|-------|---------|
|
||||
| `claude-md-integration.md` | `virtualization_list_virtual_machines` | `virt_list_vms` |
|
||||
| `claude-md-integration.md` | `virtualization_create_virtual_machine` | `virt_create_vm` |
|
||||
| `cmdb-search.md` | `virtualization_list_virtual_machines` | `virt_list_vms` |
|
||||
|
||||
Also fixed NetBox README.md tool name references for virtualization, wireless, and circuits modules.
|
||||
|
||||
#### Gitea MCP Server: Standardized Build Backend
|
||||
|
||||
Changed `mcp-servers/gitea/pyproject.toml` from hatchling to setuptools:
|
||||
- Matches all other MCP servers (contract-validator, viz-platform, data-platform)
|
||||
- Updated license format to PEP 639 compliance
|
||||
- Added pytest configuration for consistency
|
||||
|
||||
---
|
||||
|
||||
## [5.9.0] - 2026-02-03
|
||||
|
||||
### Added
|
||||
@@ -87,6 +180,36 @@ Per-agent model selection using Claude Code's now-supported `model` frontmatter
|
||||
- Added missing frontmatter to 13 agents across pr-review, viz-platform, contract-validator, clarity-assist, git-flow, doc-guardian, code-sentinel, cmdb-assistant, and data-platform
|
||||
- All 25 agents now have consistent `name`, `description`, and `model` fields
|
||||
|
||||
### Changed
|
||||
|
||||
#### Agent Frontmatter Hardening v3
|
||||
|
||||
Comprehensive agent-level configuration using Claude Code's supported frontmatter fields.
|
||||
|
||||
**permissionMode added to all 25 agents:**
|
||||
- `bypassPermissions` (1): Executor — full autonomy with code-sentinel + Code Reviewer safety nets
|
||||
- `acceptEdits` (7): Orchestrator, Data Ingestion, Theme Setup, Refactor Advisor, Doc Analyzer, Git Assistant, Maintainer
|
||||
- `default` (7): Planner, Code Reviewer, Data Advisor, Layout Builder, Full Validation, Clarity Coach, CMDB Assistant
|
||||
- `plan` (10): All pr-review agents (5), Data Analysis, Design Reviewer, Component Check, Agent Check, Security Reviewer (code-sentinel)
|
||||
|
||||
**disallowedTools added to 12 agents:**
|
||||
- All `plan`-mode agents (10) + Code Reviewer + Clarity Coach receive `disallowedTools: Write, Edit, MultiEdit`
|
||||
- Enforces read-only contracts at platform level (defense-in-depth with `permissionMode`)
|
||||
|
||||
**Model promotions:**
|
||||
- Planner: `sonnet` → `opus` (architectural reasoning benefits from deeper analysis)
|
||||
- Code Reviewer: `sonnet` → `opus` (quality gate benefits from thorough review)
|
||||
|
||||
**skills frontmatter on 3 agents:**
|
||||
- Executor: 7 safety-critical skills auto-injected (branch-security, runaway-detection, etc.)
|
||||
- Code Reviewer: 4 review skills auto-injected
|
||||
- Maintainer: 2 config skills auto-injected
|
||||
- Body text `## Skills to Load` removed for these agents to avoid duplication
|
||||
|
||||
**Documentation:**
|
||||
- `CLAUDE.md` and `docs/CONFIGURATION.md` updated with complete agent configuration matrix
|
||||
- New subsections: permissionMode Guide, disallowedTools Guide, skills Frontmatter Guide
|
||||
|
||||
---
|
||||
|
||||
## [5.8.0] - 2026-02-02
|
||||
|
||||
81
CLAUDE.md
81
CLAUDE.md
@@ -271,39 +271,60 @@ leo-claude-mktplace/
|
||||
| **Executor** | Implementation-focused | Code implementation, branch management, MR creation |
|
||||
| **Code Reviewer** | Thorough, practical | Pre-close quality review, security scan, test verification |
|
||||
|
||||
### Agent Model Selection
|
||||
### Agent Frontmatter Configuration
|
||||
|
||||
Agents specify their model in frontmatter using Claude Code's `model` field. Supported values: `sonnet` (default), `opus`, `haiku`, `inherit`.
|
||||
Agents specify their configuration in frontmatter using Claude Code's supported fields. Reference: https://code.claude.com/docs/en/sub-agents
|
||||
|
||||
| Plugin | Agent | Model | Rationale |
|
||||
|--------|-------|-------|-----------|
|
||||
| projman | Planner | sonnet | Architectural analysis, sprint planning |
|
||||
| projman | Orchestrator | sonnet | Coordination and tool dispatch |
|
||||
| projman | Executor | sonnet | Code generation and implementation |
|
||||
| projman | Code Reviewer | sonnet | Quality gate, pattern detection |
|
||||
| pr-review | Coordinator | sonnet | Orchestrates sub-agents, aggregates findings |
|
||||
| pr-review | Security Reviewer | sonnet | Security analysis |
|
||||
| pr-review | Performance Analyst | sonnet | Performance pattern detection |
|
||||
| pr-review | Maintainability Auditor | haiku | Pattern matching (complexity, duplication) |
|
||||
| pr-review | Test Validator | haiku | Coverage gap detection |
|
||||
| data-platform | Data Advisor | sonnet | Schema validation, dbt orchestration |
|
||||
| data-platform | Data Analysis | sonnet | Data exploration and profiling |
|
||||
| data-platform | Data Ingestion | haiku | Data loading operations |
|
||||
| viz-platform | Design Reviewer | sonnet | DMC validation + accessibility |
|
||||
| viz-platform | Layout Builder | sonnet | Dashboard design guidance |
|
||||
| viz-platform | Component Check | haiku | Quick component validation |
|
||||
| viz-platform | Theme Setup | haiku | Theme configuration |
|
||||
| contract-validator | Agent Check | haiku | Reference checking |
|
||||
| contract-validator | Full Validation | sonnet | Marketplace sweep |
|
||||
| code-sentinel | Security Reviewer | sonnet | Security analysis |
|
||||
| code-sentinel | Refactor Advisor | sonnet | Code refactoring advice |
|
||||
| doc-guardian | Doc Analyzer | sonnet | Documentation drift detection |
|
||||
| clarity-assist | Clarity Coach | sonnet | Conversational coaching |
|
||||
| git-flow | Git Assistant | haiku | Git operations |
|
||||
| claude-config-maintainer | Maintainer | sonnet | CLAUDE.md optimization |
|
||||
| cmdb-assistant | CMDB Assistant | sonnet | NetBox operations |
|
||||
**Supported frontmatter fields:**
|
||||
|
||||
Override by editing the `model:` field in `plugins/{plugin}/agents/{agent}.md`.
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `name` | Yes | — | Unique identifier, lowercase + hyphens |
|
||||
| `description` | Yes | — | When Claude should delegate to this subagent |
|
||||
| `model` | No | `inherit` | `sonnet`, `opus`, `haiku`, or `inherit` |
|
||||
| `permissionMode` | No | `default` | Controls permission prompts: `default`, `acceptEdits`, `dontAsk`, `bypassPermissions`, `plan` |
|
||||
| `disallowedTools` | No | none | Comma-separated tools to remove from agent's toolset |
|
||||
| `skills` | No | none | Comma-separated skills auto-injected into context at startup |
|
||||
| `hooks` | No | none | Lifecycle hooks scoped to this subagent |
|
||||
|
||||
**Complete agent matrix:**
|
||||
|
||||
| Plugin | Agent | `model` | `permissionMode` | `disallowedTools` | `skills` |
|
||||
|--------|-------|---------|-------------------|--------------------|----------|
|
||||
| projman | planner | opus | default | — | frontmatter (2) + body text (12) |
|
||||
| projman | orchestrator | sonnet | acceptEdits | — | frontmatter (2) + body text (10) |
|
||||
| projman | executor | sonnet | bypassPermissions | — | frontmatter (7) |
|
||||
| projman | code-reviewer | opus | default | Write, Edit, MultiEdit | frontmatter (4) |
|
||||
| pr-review | coordinator | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| pr-review | security-reviewer | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| pr-review | performance-analyst | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| pr-review | maintainability-auditor | haiku | plan | Write, Edit, MultiEdit | — |
|
||||
| pr-review | test-validator | haiku | plan | Write, Edit, MultiEdit | — |
|
||||
| data-platform | data-advisor | sonnet | default | — | — |
|
||||
| data-platform | data-analysis | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| data-platform | data-ingestion | haiku | acceptEdits | — | — |
|
||||
| viz-platform | design-reviewer | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| viz-platform | layout-builder | sonnet | default | — | — |
|
||||
| viz-platform | component-check | haiku | plan | Write, Edit, MultiEdit | — |
|
||||
| viz-platform | theme-setup | haiku | acceptEdits | — | — |
|
||||
| contract-validator | full-validation | sonnet | default | — | — |
|
||||
| contract-validator | agent-check | haiku | plan | Write, Edit, MultiEdit | — |
|
||||
| code-sentinel | security-reviewer | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| code-sentinel | refactor-advisor | sonnet | acceptEdits | — | — |
|
||||
| doc-guardian | doc-analyzer | sonnet | acceptEdits | — | — |
|
||||
| clarity-assist | clarity-coach | sonnet | default | Write, Edit, MultiEdit | — |
|
||||
| git-flow | git-assistant | haiku | acceptEdits | — | — |
|
||||
| claude-config-maintainer | maintainer | sonnet | acceptEdits | — | frontmatter (2) |
|
||||
| cmdb-assistant | cmdb-assistant | sonnet | default | — | — |
|
||||
|
||||
**Design principles:**
|
||||
- `bypassPermissions` is granted to exactly ONE agent (Executor) which has code-sentinel PreToolUse hook + Code Reviewer downstream as safety nets.
|
||||
- `plan` mode is assigned to all pure analysis agents (pr-review, read-only validators).
|
||||
- `disallowedTools: Write, Edit, MultiEdit` provides defense-in-depth on agents that should never write files.
|
||||
- `skills` frontmatter is used for agents with ≤7 skills where guaranteed loading is safety-critical. Agents with 8+ skills use body text `## Skills to Load` for selective loading.
|
||||
- `hooks` (agent-scoped) is reserved for future use (v6.0+).
|
||||
|
||||
Override any field by editing the agent's `.md` file in `plugins/{plugin}/agents/`.
|
||||
|
||||
### MCP Server Tools (Gitea)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Leo Claude Marketplace - v5.9.0
|
||||
# Leo Claude Marketplace - v5.10.0
|
||||
|
||||
A collection of Claude Code plugins for project management, infrastructure automation, and development workflows.
|
||||
|
||||
@@ -12,6 +12,7 @@ A collection of Claude Code plugins for project management, infrastructure autom
|
||||
AI-guided sprint planning with full Gitea integration. Transforms a proven 15-sprint workflow into a distributable plugin.
|
||||
|
||||
- Four-agent model: Planner, Orchestrator, Executor, Code Reviewer
|
||||
- Plan-then-batch execution: skills loaded once per phase, API calls batched for ~80% token savings
|
||||
- Intelligent label suggestions from 43-label taxonomy
|
||||
- Lessons learned capture via Gitea Wiki
|
||||
- Native issue dependencies with parallel execution
|
||||
|
||||
@@ -496,60 +496,134 @@ Not all plugins have MCP servers. The install script handles this automatically:
|
||||
|
||||
---
|
||||
|
||||
## Agent Model Selection
|
||||
## Agent Frontmatter Configuration
|
||||
|
||||
Marketplace agents specify their preferred model using Claude Code's `model` frontmatter field. This allows cost/performance optimization per agent.
|
||||
Agents specify their configuration in frontmatter using Claude Code's supported fields. Reference: https://code.claude.com/docs/en/sub-agents
|
||||
|
||||
### Supported Values
|
||||
### Supported Frontmatter Fields
|
||||
|
||||
| Value | Description |
|
||||
|-------|-------------|
|
||||
| `sonnet` | Default. Balanced performance and cost. |
|
||||
| `opus` | Higher reasoning depth. Use for complex analysis. |
|
||||
| `haiku` | Faster, lower cost. Use for mechanical tasks. |
|
||||
| `inherit` | Use session's current model setting. |
|
||||
| Field | Required | Default | Description |
|
||||
|-------|----------|---------|-------------|
|
||||
| `name` | Yes | — | Unique identifier, lowercase + hyphens |
|
||||
| `description` | Yes | — | When Claude should delegate to this subagent |
|
||||
| `model` | No | `inherit` | `sonnet`, `opus`, `haiku`, or `inherit` |
|
||||
| `permissionMode` | No | `default` | Controls permission prompts: `default`, `acceptEdits`, `dontAsk`, `bypassPermissions`, `plan` |
|
||||
| `disallowedTools` | No | none | Comma-separated tools to remove from agent's toolset |
|
||||
| `skills` | No | none | Comma-separated skills auto-injected into context at startup |
|
||||
| `hooks` | No | none | Lifecycle hooks scoped to this subagent |
|
||||
|
||||
### How It Works
|
||||
### Complete Agent Matrix
|
||||
|
||||
Each agent in `plugins/{plugin}/agents/{agent}.md` has frontmatter like:
|
||||
| Plugin | Agent | `model` | `permissionMode` | `disallowedTools` | `skills` |
|
||||
|--------|-------|---------|-------------------|--------------------|----------|
|
||||
| projman | planner | opus | default | — | frontmatter (2) + body text (12) |
|
||||
| projman | orchestrator | sonnet | acceptEdits | — | frontmatter (2) + body text (10) |
|
||||
| projman | executor | sonnet | bypassPermissions | — | frontmatter (7) |
|
||||
| projman | code-reviewer | opus | default | Write, Edit, MultiEdit | frontmatter (4) |
|
||||
| pr-review | coordinator | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| pr-review | security-reviewer | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| pr-review | performance-analyst | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| pr-review | maintainability-auditor | haiku | plan | Write, Edit, MultiEdit | — |
|
||||
| pr-review | test-validator | haiku | plan | Write, Edit, MultiEdit | — |
|
||||
| data-platform | data-advisor | sonnet | default | — | — |
|
||||
| data-platform | data-analysis | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| data-platform | data-ingestion | haiku | acceptEdits | — | — |
|
||||
| viz-platform | design-reviewer | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| viz-platform | layout-builder | sonnet | default | — | — |
|
||||
| viz-platform | component-check | haiku | plan | Write, Edit, MultiEdit | — |
|
||||
| viz-platform | theme-setup | haiku | acceptEdits | — | — |
|
||||
| contract-validator | full-validation | sonnet | default | — | — |
|
||||
| contract-validator | agent-check | haiku | plan | Write, Edit, MultiEdit | — |
|
||||
| code-sentinel | security-reviewer | sonnet | plan | Write, Edit, MultiEdit | — |
|
||||
| code-sentinel | refactor-advisor | sonnet | acceptEdits | — | — |
|
||||
| doc-guardian | doc-analyzer | sonnet | acceptEdits | — | — |
|
||||
| clarity-assist | clarity-coach | sonnet | default | Write, Edit, MultiEdit | — |
|
||||
| git-flow | git-assistant | haiku | acceptEdits | — | — |
|
||||
| claude-config-maintainer | maintainer | sonnet | acceptEdits | — | frontmatter (2) |
|
||||
| cmdb-assistant | cmdb-assistant | sonnet | default | — | — |
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: planner
|
||||
description: Sprint planning agent - thoughtful architecture analysis
|
||||
model: sonnet
|
||||
---
|
||||
### Design Principles
|
||||
|
||||
- `bypassPermissions` is granted to exactly ONE agent (Executor) which has code-sentinel PreToolUse hook + Code Reviewer downstream as safety nets.
|
||||
- `plan` mode is assigned to all pure analysis agents (pr-review, read-only validators).
|
||||
- `disallowedTools: Write, Edit, MultiEdit` provides defense-in-depth on agents that should never write files.
|
||||
- `skills` frontmatter is used for agents with ≤7 skills where guaranteed loading is safety-critical. Agents with 8+ skills use body text `## Skills to Load` for selective loading.
|
||||
- `hooks` (agent-scoped) is reserved for future use (v6.0+).
|
||||
|
||||
Override any field by editing the agent's `.md` file in `plugins/{plugin}/agents/`.
|
||||
|
||||
### permissionMode Guide
|
||||
|
||||
| Value | Prompts for file ops? | Prompts for Bash? | Prompts for MCP? | Use when |
|
||||
|-------|-----------------------|-------------------|-------------------|----------|
|
||||
| `default` | Yes | Yes | No (MCP bypasses permissions) | You want full visibility |
|
||||
| `acceptEdits` | No | Yes | No | Core job is file read/write, Bash visibility useful |
|
||||
| `dontAsk` | No | No (most) | No | Even Bash prompts are friction |
|
||||
| `bypassPermissions` | No | No | No | Agent has downstream safety layers |
|
||||
| `plan` | N/A (read-only) | N/A (read-only) | No | Pure analysis, no modifications |
|
||||
|
||||
### disallowedTools Guide
|
||||
|
||||
Use `disallowedTools` to remove specific tools from an agent's toolset. This is a blacklist — the agent inherits all tools from the main thread, then the listed tools are removed.
|
||||
|
||||
Prefer `disallowedTools` over `tools` (whitelist) because:
|
||||
- New MCP servers are automatically available without updating every agent.
|
||||
- Less configuration to maintain.
|
||||
- Easier to audit — you only list what's blocked.
|
||||
|
||||
Common patterns:
|
||||
- `disallowedTools: Write, Edit, MultiEdit` — read-only agent, cannot modify files.
|
||||
- `disallowedTools: Bash` — no shell access (rare, most agents need at least read-only Bash).
|
||||
|
||||
### skills Frontmatter Guide
|
||||
|
||||
The `skills` field auto-injects skill file contents into the agent's context window at startup. The agent does NOT need to read the files — they are already present.
|
||||
|
||||
**When to use frontmatter `skills`:**
|
||||
- Agent has ≤7 skills.
|
||||
- Skills are safety-critical (e.g., `branch-security`, `runaway-detection`).
|
||||
- You need guaranteed loading — no risk of the agent skipping a skill.
|
||||
|
||||
**When to keep body text `## Skills to Load`:**
|
||||
- Agent has 8+ skills (context window cost too high for full injection).
|
||||
- Skills are situational — not all needed for every invocation.
|
||||
- Agent benefits from selective loading based on the specific task.
|
||||
|
||||
Skill names in frontmatter are resolved relative to the plugin's `skills/` directory. Use the filename without the `.md` extension.
|
||||
|
||||
### Phase-Based Skill Loading (Body Text)
|
||||
|
||||
For agents with 8+ skills, use **phase-based loading** in the agent body text. This structures skill reads into logical phases, with explicit instructions to read each skill exactly once.
|
||||
|
||||
**Pattern:**
|
||||
|
||||
```markdown
|
||||
## Skill Loading Protocol
|
||||
|
||||
**Frontmatter skills (auto-injected, always available — DO NOT re-read these):**
|
||||
- `skill-a` — description
|
||||
- `skill-b` — description
|
||||
|
||||
**Phase 1 skills — read ONCE at session start:**
|
||||
- skills/validation-skill.md
|
||||
- skills/safety-skill.md
|
||||
|
||||
**Phase 2 skills — read ONCE when entering main work:**
|
||||
- skills/workflow-skill.md
|
||||
- skills/domain-skill.md
|
||||
|
||||
**CRITICAL: Read each skill file exactly ONCE. Do NOT re-read skill files between MCP API calls.**
|
||||
```
|
||||
|
||||
Claude Code reads this field when invoking the agent as a subagent.
|
||||
**Benefits:**
|
||||
- Frontmatter skills (always needed) are auto-injected — zero file read cost
|
||||
- Phase skills are read once at the appropriate time — not re-read per API call
|
||||
- `batch-execution` skill provides protocol for API-heavy phases
|
||||
- ~76-83% reduction in skill-related token consumption for typical sprints
|
||||
|
||||
### Model Assignments
|
||||
|
||||
Agents are assigned models based on their task complexity:
|
||||
|
||||
| Model | Agents | Rationale |
|
||||
|-------|--------|-----------|
|
||||
| **sonnet** | Planner, Orchestrator, Executor, Code Reviewer, Coordinator, Security Reviewers, Performance Analyst, Data Advisor, Data Analysis, Design Reviewer, Layout Builder, Full Validation, Doc Analyzer, Clarity Coach, Maintainer, CMDB Assistant, Refactor Advisor | Standard reasoning, tool orchestration, code generation |
|
||||
| **haiku** | Maintainability Auditor, Test Validator, Component Check, Theme Setup, Agent Check, Data Ingestion, Git Assistant | Pattern matching, quick validation, mechanical tasks |
|
||||
|
||||
### Overriding Model Selection
|
||||
|
||||
**Per-agent override:** Edit the `model:` field in the agent file:
|
||||
|
||||
```bash
|
||||
# Change executor to use opus for heavy implementation work
|
||||
nano plugins/projman/agents/executor.md
|
||||
# Change model: sonnet to model: opus
|
||||
```
|
||||
|
||||
**Session-level:** Users on Opus subscription can change the agent's model to `inherit` to use whatever model the session is using.
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Default to sonnet** - Good balance for most tasks
|
||||
2. **Use haiku for speed-sensitive agents** - Sub-agents dispatched in parallel, read-only tasks
|
||||
3. **Reserve opus for heavy analysis** - Only when sonnet's reasoning isn't sufficient
|
||||
4. **Use inherit sparingly** - Only when you want session-level control
|
||||
**Currently applied to:**
|
||||
- Planner agent: 2 frontmatter + 12 body text (3 phases)
|
||||
- Orchestrator agent: 2 frontmatter + 10 body text (2 phases)
|
||||
|
||||
---
|
||||
|
||||
|
||||
6
mcp-servers/gitea/.doc-guardian-queue
Normal file
6
mcp-servers/gitea/.doc-guardian-queue
Normal file
@@ -0,0 +1,6 @@
|
||||
2026-02-03T14:09:25 | mcp-servers | /home/lmiranda/claude-plugins-work/mcp-servers/gitea/tests/test_config.py | docs/COMMANDS-CHEATSHEET.md CLAUDE.md
|
||||
2026-02-03T14:09:33 | mcp-servers | /home/lmiranda/claude-plugins-work/mcp-servers/gitea/tests/test_gitea_client.py | docs/COMMANDS-CHEATSHEET.md CLAUDE.md
|
||||
2026-02-03T14:10:22 | mcp-servers | /home/lmiranda/claude-plugins-work/mcp-servers/gitea/tests/test_issues.py | docs/COMMANDS-CHEATSHEET.md CLAUDE.md
|
||||
2026-02-03T14:17:12 | mcp-servers | /home/lmiranda/claude-plugins-work/mcp-servers/gitea/README.md | docs/COMMANDS-CHEATSHEET.md CLAUDE.md
|
||||
2026-02-03T14:18:27 | mcp-servers | /home/lmiranda/claude-plugins-work/mcp-servers/gitea/CHANGELOG.md | docs/COMMANDS-CHEATSHEET.md CLAUDE.md
|
||||
2026-02-03T14:18:41 | mcp-servers | /home/lmiranda/claude-plugins-work/mcp-servers/gitea/TESTING.md | docs/COMMANDS-CHEATSHEET.md CLAUDE.md
|
||||
92
mcp-servers/gitea/CHANGELOG.md
Normal file
92
mcp-servers/gitea/CHANGELOG.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to the Gitea MCP Server will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.3.0] - 2026-02-03
|
||||
|
||||
### Added
|
||||
- Pull request tools (7 tools):
|
||||
- `list_pull_requests` - List PRs from repository
|
||||
- `get_pull_request` - Get specific PR details
|
||||
- `get_pr_diff` - Get PR diff content
|
||||
- `get_pr_comments` - Get comments on a PR
|
||||
- `create_pr_review` - Create PR review (approve/request changes/comment)
|
||||
- `add_pr_comment` - Add comment to PR
|
||||
- `create_pull_request` - Create new pull request
|
||||
- Label creation tools (3 tools):
|
||||
- `create_label` - Create repo-level label
|
||||
- `create_org_label` - Create organization-level label
|
||||
- `create_label_smart` - Auto-detect org vs repo for label creation
|
||||
- Validation tools (2 tools):
|
||||
- `validate_repo_org` - Check if repo belongs to organization
|
||||
- `get_branch_protection` - Get branch protection rules
|
||||
|
||||
### Changed
|
||||
- Total tools increased from 20 to 36
|
||||
- Updated test suite to 64 tests (was 42)
|
||||
|
||||
### Fixed
|
||||
- Test fixtures updated to use `owner/repo` format
|
||||
- Fixed aggregate_issues tests to pass required `org` argument
|
||||
|
||||
## [1.2.0] - 2026-01-28
|
||||
|
||||
### Added
|
||||
- Milestone management tools (5 tools):
|
||||
- `list_milestones` - List all milestones
|
||||
- `get_milestone` - Get specific milestone
|
||||
- `create_milestone` - Create new milestone
|
||||
- `update_milestone` - Update existing milestone
|
||||
- `delete_milestone` - Delete a milestone
|
||||
- Issue dependency tools (4 tools):
|
||||
- `list_issue_dependencies` - List blocking issues
|
||||
- `create_issue_dependency` - Create dependency between issues
|
||||
- `remove_issue_dependency` - Remove dependency
|
||||
- `get_execution_order` - Calculate parallelizable execution order
|
||||
|
||||
## [1.1.0] - 2026-01-21
|
||||
|
||||
### Added
|
||||
- Wiki and lessons learned tools (7 tools):
|
||||
- `list_wiki_pages` - List all wiki pages
|
||||
- `get_wiki_page` - Get specific wiki page content
|
||||
- `create_wiki_page` - Create new wiki page
|
||||
- `update_wiki_page` - Update existing wiki page
|
||||
- `create_lesson` - Create lessons learned entry
|
||||
- `search_lessons` - Search lessons by query/tags
|
||||
- `allocate_rfc_number` - Get next available RFC number
|
||||
- Automatic git remote URL detection for repository configuration
|
||||
- Support for SSH, HTTPS, and HTTP git URL formats
|
||||
|
||||
### Changed
|
||||
- Configuration now uses `owner/repo` format exclusively
|
||||
- Removed separate `GITEA_OWNER` configuration (now derived from repo path)
|
||||
|
||||
## [1.0.0] - 2025-01-06
|
||||
|
||||
### Added
|
||||
- Initial release with 8 core tools:
|
||||
- `list_issues` - List issues from repository
|
||||
- `get_issue` - Get specific issue details
|
||||
- `create_issue` - Create new issue with labels
|
||||
- `update_issue` - Update existing issue
|
||||
- `add_comment` - Add comment to issue
|
||||
- `get_labels` - Get all labels (org + repo)
|
||||
- `suggest_labels` - Intelligent label suggestion
|
||||
- `aggregate_issues` - Cross-repository issue aggregation (PMO mode)
|
||||
- Hybrid configuration system (system + project level)
|
||||
- Branch-aware security model
|
||||
- Mode detection (project vs company/PMO)
|
||||
- 42 unit tests with mocks
|
||||
- Comprehensive documentation
|
||||
|
||||
[Unreleased]: https://github.com/owner/repo/compare/v1.3.0...HEAD
|
||||
[1.3.0]: https://github.com/owner/repo/compare/v1.2.0...v1.3.0
|
||||
[1.2.0]: https://github.com/owner/repo/compare/v1.1.0...v1.2.0
|
||||
[1.1.0]: https://github.com/owner/repo/compare/v1.0.0...v1.1.0
|
||||
[1.0.0]: https://github.com/owner/repo/releases/tag/v1.0.0
|
||||
@@ -19,8 +19,9 @@ The Gitea MCP Server provides Claude Code with direct access to Gitea for issue
|
||||
- **Hybrid Configuration**: System-level credentials + project-level paths
|
||||
- **PMO Support**: Multi-repository aggregation for organization-wide views
|
||||
|
||||
### Tools Provided
|
||||
### Tools Provided (36 total)
|
||||
|
||||
#### Issue Management (6 tools)
|
||||
| Tool | Description | Mode |
|
||||
|------|-------------|------|
|
||||
| `list_issues` | List issues from repository | Both |
|
||||
@@ -28,9 +29,61 @@ The Gitea MCP Server provides Claude Code with direct access to Gitea for issue
|
||||
| `create_issue` | Create new issue with labels | Both |
|
||||
| `update_issue` | Update existing issue | Both |
|
||||
| `add_comment` | Add comment to issue | Both |
|
||||
| `aggregate_issues` | Cross-repository issue aggregation | PMO Only |
|
||||
|
||||
#### Label Management (5 tools)
|
||||
| Tool | Description | Mode |
|
||||
|------|-------------|------|
|
||||
| `get_labels` | Get all labels (org + repo) | Both |
|
||||
| `suggest_labels` | Intelligent label suggestion | Both |
|
||||
| `aggregate_issues` | Cross-repository issue aggregation | PMO Only |
|
||||
| `create_label` | Create repo-level label | Both |
|
||||
| `create_org_label` | Create organization-level label | Both |
|
||||
| `create_label_smart` | Auto-detect org vs repo for label creation | Both |
|
||||
|
||||
#### Wiki & Lessons Learned (7 tools)
|
||||
| Tool | Description | Mode |
|
||||
|------|-------------|------|
|
||||
| `list_wiki_pages` | List all wiki pages | Both |
|
||||
| `get_wiki_page` | Get specific wiki page content | Both |
|
||||
| `create_wiki_page` | Create new wiki page | Both |
|
||||
| `update_wiki_page` | Update existing wiki page | Both |
|
||||
| `create_lesson` | Create lessons learned entry | Both |
|
||||
| `search_lessons` | Search lessons by query/tags | Both |
|
||||
| `allocate_rfc_number` | Get next available RFC number | Both |
|
||||
|
||||
#### Milestone Management (5 tools)
|
||||
| Tool | Description | Mode |
|
||||
|------|-------------|------|
|
||||
| `list_milestones` | List all milestones | Both |
|
||||
| `get_milestone` | Get specific milestone | Both |
|
||||
| `create_milestone` | Create new milestone | Both |
|
||||
| `update_milestone` | Update existing milestone | Both |
|
||||
| `delete_milestone` | Delete a milestone | Both |
|
||||
|
||||
#### Issue Dependencies (4 tools)
|
||||
| Tool | Description | Mode |
|
||||
|------|-------------|------|
|
||||
| `list_issue_dependencies` | List blocking issues | Both |
|
||||
| `create_issue_dependency` | Create dependency between issues | Both |
|
||||
| `remove_issue_dependency` | Remove dependency | Both |
|
||||
| `get_execution_order` | Calculate parallelizable execution order | Both |
|
||||
|
||||
#### Pull Request Tools (7 tools)
|
||||
| Tool | Description | Mode |
|
||||
|------|-------------|------|
|
||||
| `list_pull_requests` | List PRs from repository | Both |
|
||||
| `get_pull_request` | Get specific PR details | Both |
|
||||
| `get_pr_diff` | Get PR diff content | Both |
|
||||
| `get_pr_comments` | Get comments on a PR | Both |
|
||||
| `create_pr_review` | Create PR review (approve/request changes) | Both |
|
||||
| `add_pr_comment` | Add comment to PR | Both |
|
||||
| `create_pull_request` | Create new pull request | Both |
|
||||
|
||||
#### Validation Tools (2 tools)
|
||||
| Tool | Description | Mode |
|
||||
|------|-------------|------|
|
||||
| `validate_repo_org` | Check if repo belongs to organization | Both |
|
||||
| `get_branch_protection` | Get branch protection rules | Both |
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -40,15 +93,20 @@ The Gitea MCP Server provides Claude Code with direct access to Gitea for issue
|
||||
mcp-servers/gitea/
|
||||
├── .venv/ # Python virtual environment
|
||||
├── requirements.txt # Python dependencies
|
||||
├── run.sh # Entry point script
|
||||
├── mcp_server/
|
||||
│ ├── __init__.py
|
||||
│ ├── server.py # MCP server entry point
|
||||
│ ├── config.py # Configuration loader
|
||||
│ ├── server.py # MCP server entry point (36 tools)
|
||||
│ ├── config.py # Configuration loader with auto-detection
|
||||
│ ├── gitea_client.py # Gitea API client
|
||||
│ └── tools/
|
||||
│ ├── __init__.py
|
||||
│ ├── issues.py # Issue tools
|
||||
│ └── labels.py # Label tools
|
||||
│ ├── issues.py # Issue management tools
|
||||
│ ├── labels.py # Label management tools
|
||||
│ ├── wiki.py # Wiki & lessons learned tools
|
||||
│ ├── milestones.py # Milestone management tools
|
||||
│ ├── dependencies.py # Issue dependency tools
|
||||
│ └── pull_requests.py # Pull request tools
|
||||
├── tests/
|
||||
│ ├── __init__.py
|
||||
│ ├── test_config.py
|
||||
@@ -56,7 +114,8 @@ mcp-servers/gitea/
|
||||
│ ├── test_issues.py
|
||||
│ └── test_labels.py
|
||||
├── README.md # This file
|
||||
└── TESTING.md # Testing instructions
|
||||
├── TESTING.md # Testing instructions
|
||||
└── CHANGELOG.md # Version history
|
||||
```
|
||||
|
||||
### Mode Detection
|
||||
@@ -111,7 +170,6 @@ mkdir -p ~/.config/claude
|
||||
cat > ~/.config/claude/gitea.env << EOF
|
||||
GITEA_API_URL=https://gitea.example.com/api/v1
|
||||
GITEA_API_TOKEN=your_gitea_token_here
|
||||
GITEA_OWNER=bandit
|
||||
EOF
|
||||
|
||||
chmod 600 ~/.config/claude/gitea.env
|
||||
@@ -137,14 +195,34 @@ For company/PMO mode, omit the `.env` file or don't set `GITEA_REPO`.
|
||||
**Required Variables**:
|
||||
- `GITEA_API_URL` - Gitea API endpoint (e.g., `https://gitea.example.com/api/v1`)
|
||||
- `GITEA_API_TOKEN` - Personal access token with repo permissions
|
||||
- `GITEA_OWNER` - Organization or user name (e.g., `bandit`)
|
||||
|
||||
### Project-Level Configuration
|
||||
|
||||
**File**: `<project-root>/.env`
|
||||
|
||||
**Optional Variables**:
|
||||
- `GITEA_REPO` - Repository name (enables project mode)
|
||||
- `GITEA_REPO` - Repository in `owner/repo` format (enables project mode)
|
||||
|
||||
### Automatic Repository Detection
|
||||
|
||||
If `GITEA_REPO` is not set, the server auto-detects the repository from your git remote:
|
||||
|
||||
**Supported URL Formats**:
|
||||
- SSH: `ssh://git@gitea.example.com:22/owner/repo.git`
|
||||
- SSH short: `git@gitea.example.com:owner/repo.git`
|
||||
- HTTPS: `https://gitea.example.com/owner/repo.git`
|
||||
- HTTP: `http://gitea.example.com/owner/repo.git`
|
||||
|
||||
The repository is extracted as `owner/repo` format automatically.
|
||||
|
||||
### Project Directory Detection
|
||||
|
||||
The server finds your project directory using these strategies (in order):
|
||||
|
||||
1. `CLAUDE_PROJECT_DIR` environment variable (highest priority)
|
||||
2. `PWD` environment variable (if `.git` or `.env` present)
|
||||
3. Current working directory (if `.git` or `.env` present)
|
||||
4. Falls back to company/PMO mode if no project found
|
||||
|
||||
### Generating Gitea API Token
|
||||
|
||||
@@ -220,13 +298,13 @@ suggestions = await label_tools.suggest_labels(context)
|
||||
|
||||
### Unit Tests
|
||||
|
||||
Run all 42 unit tests with mocks:
|
||||
Run all 64 unit tests with mocks:
|
||||
|
||||
```bash
|
||||
pytest tests/ -v
|
||||
```
|
||||
|
||||
Expected: `42 passed in 0.57s`
|
||||
Expected: `64 passed`
|
||||
|
||||
### Integration Tests
|
||||
|
||||
@@ -327,11 +405,15 @@ See [TESTING.md](./TESTING.md#troubleshooting) for more details.
|
||||
|
||||
### Project Structure
|
||||
|
||||
- `config.py` - Hybrid configuration loader with mode detection
|
||||
- `config.py` - Hybrid configuration loader with auto-detection
|
||||
- `gitea_client.py` - Synchronous Gitea API client using requests
|
||||
- `tools/issues.py` - Async wrappers with branch detection
|
||||
- `tools/labels.py` - Label management and suggestion
|
||||
- `server.py` - MCP server with JSON-RPC 2.0 over stdio
|
||||
- `tools/issues.py` - Issue management with branch detection
|
||||
- `tools/labels.py` - Label management and intelligent suggestions
|
||||
- `tools/wiki.py` - Wiki pages and lessons learned
|
||||
- `tools/milestones.py` - Milestone CRUD operations
|
||||
- `tools/dependencies.py` - Issue dependency tracking
|
||||
- `tools/pull_requests.py` - PR review and management
|
||||
- `server.py` - MCP server with 36 tools over JSON-RPC 2.0 stdio
|
||||
|
||||
### Adding New Tools
|
||||
|
||||
@@ -374,18 +456,14 @@ def list_issues(self, state='open', labels=None, repo=None):
|
||||
|
||||
## Changelog
|
||||
|
||||
### v1.0.0 (2025-01-06) - Phase 1 Complete
|
||||
See [CHANGELOG.md](./CHANGELOG.md) for full version history.
|
||||
|
||||
✅ Initial implementation:
|
||||
- Configuration management (hybrid system + project)
|
||||
- Gitea API client with all CRUD operations
|
||||
- MCP server with 8 tools
|
||||
- Issue tools with branch detection
|
||||
- Label tools with intelligent suggestions
|
||||
- Mode detection (project vs company)
|
||||
- Branch-aware security model
|
||||
- 42 unit tests (100% passing)
|
||||
- Comprehensive documentation
|
||||
### Recent Updates
|
||||
|
||||
- **v1.3.0** - Pull request tools (7 tools), label creation tools (3)
|
||||
- **v1.2.0** - Milestone management (5 tools), issue dependencies (4 tools)
|
||||
- **v1.1.0** - Wiki & lessons learned system (7 tools)
|
||||
- **v1.0.0** - Initial release with core issue/label tools (8 tools)
|
||||
|
||||
## License
|
||||
|
||||
@@ -407,6 +485,6 @@ For issues or questions:
|
||||
---
|
||||
|
||||
**Built for**: Leo Claude Marketplace - Project Management Plugins
|
||||
**Phase**: 1 (Complete)
|
||||
**Tools**: 36
|
||||
**Status**: ✅ Production Ready
|
||||
**Last Updated**: 2025-01-06
|
||||
**Last Updated**: 2026-02-03
|
||||
|
||||
@@ -28,7 +28,7 @@ source .venv/bin/activate # Linux/Mac
|
||||
|
||||
### Running All Tests
|
||||
|
||||
Run all 42 unit tests:
|
||||
Run all 64 unit tests:
|
||||
|
||||
```bash
|
||||
pytest tests/ -v
|
||||
@@ -36,7 +36,7 @@ pytest tests/ -v
|
||||
|
||||
Expected output:
|
||||
```
|
||||
============================== 42 passed in 0.57s ==============================
|
||||
============================== 64 passed ==============================
|
||||
```
|
||||
|
||||
### Running Specific Test Files
|
||||
@@ -532,7 +532,7 @@ python -m mcp_server.server
|
||||
|
||||
After completing all tests, verify:
|
||||
|
||||
- ✅ All 42 unit tests pass
|
||||
- ✅ All 64 unit tests pass
|
||||
- ✅ MCP server starts without errors
|
||||
- ✅ Configuration loads correctly
|
||||
- ✅ Gitea API client connects successfully
|
||||
@@ -548,7 +548,7 @@ After completing all tests, verify:
|
||||
|
||||
Phase 1 is complete when:
|
||||
|
||||
1. **All unit tests pass** (42/42)
|
||||
1. **All unit tests pass** (64/64)
|
||||
2. **MCP server starts without errors**
|
||||
3. **Can list issues from Gitea**
|
||||
4. **Can create issues with labels** (in development mode)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
Gitea MCP Server package.
|
||||
|
||||
Provides MCP tools for Gitea integration via JSON-RPC 2.0.
|
||||
|
||||
For external consumers (e.g., HTTP transport), use:
|
||||
from mcp_server import get_tool_definitions, create_tool_dispatcher, GiteaClient
|
||||
|
||||
# Get tool schemas
|
||||
tools = get_tool_definitions()
|
||||
|
||||
# Create dispatcher bound to a client
|
||||
client = GiteaClient()
|
||||
dispatch = create_tool_dispatcher(client)
|
||||
result = await dispatch("list_issues", {"state": "open"})
|
||||
"""
|
||||
|
||||
__version__ = "1.0.0"
|
||||
|
||||
from .tool_registry import get_tool_definitions, create_tool_dispatcher
|
||||
from .gitea_client import GiteaClient
|
||||
from .config import GiteaConfig
|
||||
|
||||
__all__ = [
|
||||
"__version__",
|
||||
"get_tool_definitions",
|
||||
"create_tool_dispatcher",
|
||||
"GiteaClient",
|
||||
"GiteaConfig",
|
||||
]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1098
mcp-servers/gitea/mcp_server/tool_registry.py
Normal file
1098
mcp-servers/gitea/mcp_server/tool_registry.py
Normal file
File diff suppressed because it is too large
Load Diff
43
mcp-servers/gitea/pyproject.toml
Normal file
43
mcp-servers/gitea/pyproject.toml
Normal file
@@ -0,0 +1,43 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "gitea-mcp-server"
|
||||
version = "1.0.0"
|
||||
description = "MCP Server for Gitea integration - provides issue, label, wiki, milestone, dependency, and PR tools"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{ name = "Leo Miranda" }
|
||||
]
|
||||
keywords = ["mcp", "gitea", "claude", "tools"]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
]
|
||||
dependencies = [
|
||||
"mcp>=0.9.0",
|
||||
"python-dotenv>=1.0.0",
|
||||
"requests>=2.31.0",
|
||||
"pydantic>=2.5.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
test = [
|
||||
"pytest>=7.4.3",
|
||||
"pytest-asyncio>=0.23.0",
|
||||
]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["."]
|
||||
include = ["mcp_server*"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
asyncio_mode = "auto"
|
||||
testpaths = ["tests"]
|
||||
@@ -28,7 +28,6 @@ def test_load_system_config(tmp_path, monkeypatch):
|
||||
|
||||
assert result['api_url'] == 'https://test.com/api/v1'
|
||||
assert result['api_token'] == 'test_token'
|
||||
assert result['owner'] == 'test_owner'
|
||||
assert result['mode'] == 'company' # No repo specified
|
||||
assert result['repo'] is None
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@ def mock_config():
|
||||
mock_instance.load.return_value = {
|
||||
'api_url': 'https://test.com/api/v1',
|
||||
'api_token': 'test_token',
|
||||
'owner': 'test_owner',
|
||||
'repo': 'test_repo',
|
||||
'repo': 'test_owner/test_repo', # Combined owner/repo format
|
||||
'mode': 'project'
|
||||
}
|
||||
yield mock_cfg
|
||||
@@ -31,8 +30,7 @@ def test_client_initialization(gitea_client):
|
||||
"""Test client initializes with correct configuration"""
|
||||
assert gitea_client.base_url == 'https://test.com/api/v1'
|
||||
assert gitea_client.token == 'test_token'
|
||||
assert gitea_client.owner == 'test_owner'
|
||||
assert gitea_client.repo == 'test_repo'
|
||||
assert gitea_client.repo == 'test_owner/test_repo' # Combined format
|
||||
assert gitea_client.mode == 'project'
|
||||
assert 'Authorization' in gitea_client.session.headers
|
||||
assert gitea_client.session.headers['Authorization'] == 'token test_token'
|
||||
@@ -92,6 +90,11 @@ def test_create_issue(gitea_client):
|
||||
}
|
||||
mock_response.raise_for_status = Mock()
|
||||
|
||||
# Mock is_org_repo to avoid network call during label resolution
|
||||
with patch.object(gitea_client, 'is_org_repo', return_value=True):
|
||||
# Mock get_org_labels and get_labels for label resolution
|
||||
with patch.object(gitea_client, 'get_org_labels', return_value=[{'name': 'Type/Bug', 'id': 1}]):
|
||||
with patch.object(gitea_client, 'get_labels', return_value=[]):
|
||||
with patch.object(gitea_client.session, 'post', return_value=mock_response):
|
||||
issue = gitea_client.create_issue(
|
||||
title='New Issue',
|
||||
@@ -161,7 +164,7 @@ def test_get_org_labels(gitea_client):
|
||||
mock_response.raise_for_status = Mock()
|
||||
|
||||
with patch.object(gitea_client.session, 'get', return_value=mock_response):
|
||||
labels = gitea_client.get_org_labels()
|
||||
labels = gitea_client.get_org_labels(org='test_owner')
|
||||
|
||||
assert len(labels) == 2
|
||||
|
||||
@@ -176,7 +179,7 @@ def test_list_repos(gitea_client):
|
||||
mock_response.raise_for_status = Mock()
|
||||
|
||||
with patch.object(gitea_client.session, 'get', return_value=mock_response):
|
||||
repos = gitea_client.list_repos()
|
||||
repos = gitea_client.list_repos(org='test_owner')
|
||||
|
||||
assert len(repos) == 2
|
||||
assert repos[0]['name'] == 'repo1'
|
||||
@@ -196,7 +199,7 @@ def test_aggregate_issues(gitea_client):
|
||||
[{'number': 2, 'title': 'Issue 2'}] # repo2
|
||||
])
|
||||
|
||||
aggregated = gitea_client.aggregate_issues(state='open')
|
||||
aggregated = gitea_client.aggregate_issues(org='test_owner', state='open')
|
||||
|
||||
assert 'repo1' in aggregated
|
||||
assert 'repo2' in aggregated
|
||||
@@ -205,14 +208,13 @@ def test_aggregate_issues(gitea_client):
|
||||
|
||||
|
||||
def test_no_repo_specified_error(gitea_client):
|
||||
"""Test error when repository not specified"""
|
||||
"""Test error when repository not specified or invalid format"""
|
||||
# Create client without repo
|
||||
with patch('mcp_server.gitea_client.GiteaConfig') as mock_cfg:
|
||||
mock_instance = mock_cfg.return_value
|
||||
mock_instance.load.return_value = {
|
||||
'api_url': 'https://test.com/api/v1',
|
||||
'api_token': 'test_token',
|
||||
'owner': 'test_owner',
|
||||
'repo': None, # No repo
|
||||
'mode': 'company'
|
||||
}
|
||||
@@ -221,7 +223,7 @@ def test_no_repo_specified_error(gitea_client):
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
client.list_issues()
|
||||
|
||||
assert "Repository not specified" in str(exc_info.value)
|
||||
assert "Use 'owner/repo' format" in str(exc_info.value)
|
||||
|
||||
|
||||
# ========================================
|
||||
|
||||
@@ -119,22 +119,26 @@ async def test_aggregate_issues_company_mode(issue_tools):
|
||||
'repo2': [{'number': 2}]
|
||||
})
|
||||
|
||||
aggregated = await issue_tools.aggregate_issues()
|
||||
aggregated = await issue_tools.aggregate_issues(org='test_owner')
|
||||
|
||||
assert 'repo1' in aggregated
|
||||
assert 'repo2' in aggregated
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_aggregate_issues_project_mode_error(issue_tools):
|
||||
"""Test that aggregate_issues fails in project mode"""
|
||||
async def test_aggregate_issues_project_mode(issue_tools):
|
||||
"""Test that aggregate_issues works in project mode with org argument"""
|
||||
issue_tools.gitea.mode = 'project'
|
||||
|
||||
with patch.object(issue_tools, '_get_current_branch', return_value='development'):
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
await issue_tools.aggregate_issues()
|
||||
issue_tools.gitea.aggregate_issues = Mock(return_value={
|
||||
'repo1': [{'number': 1}]
|
||||
})
|
||||
|
||||
assert "only available in company mode" in str(exc_info.value)
|
||||
# aggregate_issues now works in any mode when org is provided
|
||||
aggregated = await issue_tools.aggregate_issues(org='test_owner')
|
||||
|
||||
assert 'repo1' in aggregated
|
||||
|
||||
|
||||
def test_branch_detection():
|
||||
|
||||
@@ -79,6 +79,69 @@ Add to your Claude Code MCP configuration (`~/.config/claude/mcp.json` or projec
|
||||
1. **System-level** (`~/.config/claude/netbox.env`): Credentials and defaults
|
||||
2. **Project-level** (`.env` in current directory): Optional overrides
|
||||
|
||||
## Module Filtering (Token Optimization)
|
||||
|
||||
By default, the NetBox MCP server registers all 182 tools across 8 modules, consuming ~19,810 tokens of context. For most workflows, you only need a subset of modules.
|
||||
|
||||
### Configuration
|
||||
|
||||
Add `NETBOX_ENABLED_MODULES` to your `~/.config/claude/netbox.env`:
|
||||
|
||||
```bash
|
||||
# Enable only specific modules (comma-separated)
|
||||
NETBOX_ENABLED_MODULES=dcim,ipam,virtualization,extras
|
||||
```
|
||||
|
||||
If unset, all modules are enabled (backward compatible).
|
||||
|
||||
### Available Modules
|
||||
|
||||
| Module | Tool Count | Description | cmdb-assistant Commands |
|
||||
|--------|------------|-------------|------------------------|
|
||||
| `dcim` | ~60 | Sites, devices, racks, interfaces, cables | `/cmdb-device`, `/cmdb-site`, `/cmdb-search`, `/cmdb-topology` |
|
||||
| `ipam` | ~40 | IP addresses, prefixes, VLANs, VRFs | `/cmdb-ip`, `/ip-conflicts`, `/cmdb-search` |
|
||||
| `virtualization` | ~20 | Clusters, VMs, VM interfaces | `/cmdb-search`, `/cmdb-audit`, `/cmdb-register` |
|
||||
| `extras` | ~12 | Tags, journal entries, audit log | `/change-audit`, `/cmdb-register` |
|
||||
| `circuits` | ~15 | Providers, circuits, terminations | — |
|
||||
| `tenancy` | ~12 | Tenants, contacts | — |
|
||||
| `vpn` | ~15 | Tunnels, IKE/IPSec policies, L2VPN | — |
|
||||
| `wireless` | ~8 | Wireless LANs, links, groups | — |
|
||||
|
||||
### Recommended Configurations
|
||||
|
||||
**For cmdb-assistant users** (~43 tools, ~4,500 tokens):
|
||||
```bash
|
||||
NETBOX_ENABLED_MODULES=dcim,ipam,virtualization,extras
|
||||
```
|
||||
|
||||
**Basic infrastructure** (~100 tools):
|
||||
```bash
|
||||
NETBOX_ENABLED_MODULES=dcim,ipam
|
||||
```
|
||||
|
||||
**Full CMDB** (all modules, ~182 tools):
|
||||
```bash
|
||||
# Omit NETBOX_ENABLED_MODULES or set to all modules
|
||||
NETBOX_ENABLED_MODULES=dcim,ipam,circuits,virtualization,tenancy,vpn,wireless,extras
|
||||
```
|
||||
|
||||
### Startup Logging
|
||||
|
||||
On startup, the server logs enabled modules and tool count:
|
||||
|
||||
```
|
||||
NetBox MCP Server initialized: 43 tools registered (modules: dcim, extras, ipam, virtualization)
|
||||
```
|
||||
|
||||
### Disabled Tool Behavior
|
||||
|
||||
Calling a tool from a disabled module returns a clear error:
|
||||
|
||||
```
|
||||
Tool 'circuits_list_circuits' is not available (module 'circuits' not enabled).
|
||||
Enabled modules: dcim, extras, ipam, virtualization
|
||||
```
|
||||
|
||||
## Available Tools
|
||||
|
||||
### DCIM (Data Center Infrastructure Management)
|
||||
@@ -128,18 +191,18 @@ Add to your Claude Code MCP configuration (`~/.config/claude/mcp.json` or projec
|
||||
| `circuits_create_provider` | Create a provider |
|
||||
| `circuits_list_circuits` | List circuits |
|
||||
| `circuits_create_circuit` | Create a circuit |
|
||||
| `circuits_list_circuit_terminations` | List terminations |
|
||||
| `circ_list_terminations` | List terminations |
|
||||
| ... and more |
|
||||
|
||||
### Virtualization
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `virtualization_list_clusters` | List clusters |
|
||||
| `virtualization_create_cluster` | Create a cluster |
|
||||
| `virtualization_list_virtual_machines` | List VMs |
|
||||
| `virtualization_create_virtual_machine` | Create a VM |
|
||||
| `virtualization_list_vm_interfaces` | List VM interfaces |
|
||||
| `virt_list_clusters` | List clusters |
|
||||
| `virt_create_cluster` | Create a cluster |
|
||||
| `virt_list_vms` | List VMs |
|
||||
| `virt_create_vm` | Create a VM |
|
||||
| `virt_list_vm_ifaces` | List VM interfaces |
|
||||
| ... and more |
|
||||
|
||||
### Tenancy
|
||||
@@ -167,9 +230,9 @@ Add to your Claude Code MCP configuration (`~/.config/claude/mcp.json` or projec
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `wireless_list_wireless_lans` | List wireless LANs |
|
||||
| `wireless_create_wireless_lan` | Create a WLAN |
|
||||
| `wireless_list_wireless_links` | List wireless links |
|
||||
| `wlan_list_lans` | List wireless LANs |
|
||||
| `wlan_create_lan` | Create a WLAN |
|
||||
| `wlan_list_links` | List wireless links |
|
||||
| ... and more |
|
||||
|
||||
### Extras
|
||||
|
||||
@@ -9,11 +9,17 @@ from pathlib import Path
|
||||
from dotenv import load_dotenv
|
||||
import os
|
||||
import logging
|
||||
from typing import Dict, Optional
|
||||
from typing import Dict, List, Optional, Set
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# All available NetBox modules
|
||||
ALL_MODULES = frozenset([
|
||||
'dcim', 'ipam', 'circuits', 'virtualization',
|
||||
'tenancy', 'vpn', 'wireless', 'extras'
|
||||
])
|
||||
|
||||
|
||||
class NetBoxConfig:
|
||||
"""Configuration loader for NetBox MCP Server"""
|
||||
@@ -23,6 +29,7 @@ class NetBoxConfig:
|
||||
self.api_token: Optional[str] = None
|
||||
self.verify_ssl: bool = True
|
||||
self.timeout: int = 30
|
||||
self.enabled_modules: Set[str] = set(ALL_MODULES)
|
||||
|
||||
def load(self) -> Dict[str, any]:
|
||||
"""
|
||||
@@ -73,6 +80,9 @@ class NetBoxConfig:
|
||||
self.timeout = 30
|
||||
logger.warning(f"Invalid NETBOX_TIMEOUT value '{timeout_str}', using default 30")
|
||||
|
||||
# Module filtering
|
||||
self.enabled_modules = self._load_enabled_modules()
|
||||
|
||||
# Validate required variables
|
||||
self._validate()
|
||||
|
||||
@@ -84,7 +94,8 @@ class NetBoxConfig:
|
||||
'api_url': self.api_url,
|
||||
'api_token': self.api_token,
|
||||
'verify_ssl': self.verify_ssl,
|
||||
'timeout': self.timeout
|
||||
'timeout': self.timeout,
|
||||
'enabled_modules': self.enabled_modules
|
||||
}
|
||||
|
||||
def _validate(self) -> None:
|
||||
@@ -106,3 +117,40 @@ class NetBoxConfig:
|
||||
f"Missing required configuration: {', '.join(missing)}\n"
|
||||
"Check your ~/.config/claude/netbox.env file"
|
||||
)
|
||||
|
||||
def _load_enabled_modules(self) -> Set[str]:
|
||||
"""
|
||||
Load enabled modules from NETBOX_ENABLED_MODULES environment variable.
|
||||
|
||||
Format: Comma-separated list of module names.
|
||||
Example: NETBOX_ENABLED_MODULES=dcim,ipam,virtualization,extras
|
||||
|
||||
Returns:
|
||||
Set of enabled module names. If env var is unset/empty, returns all modules.
|
||||
"""
|
||||
modules_str = os.getenv('NETBOX_ENABLED_MODULES', '').strip()
|
||||
|
||||
if not modules_str:
|
||||
logger.info("NETBOX_ENABLED_MODULES not set, all modules enabled (default)")
|
||||
return set(ALL_MODULES)
|
||||
|
||||
# Parse comma-separated list, strip whitespace
|
||||
requested = {m.strip().lower() for m in modules_str.split(',') if m.strip()}
|
||||
|
||||
# Validate module names
|
||||
invalid = requested - ALL_MODULES
|
||||
if invalid:
|
||||
logger.warning(
|
||||
f"Unknown modules in NETBOX_ENABLED_MODULES: {', '.join(sorted(invalid))}. "
|
||||
f"Valid modules: {', '.join(sorted(ALL_MODULES))}"
|
||||
)
|
||||
|
||||
# Return only valid modules
|
||||
enabled = requested & ALL_MODULES
|
||||
|
||||
if not enabled:
|
||||
logger.warning("No valid modules enabled, falling back to all modules")
|
||||
return set(ALL_MODULES)
|
||||
|
||||
logger.info(f"Enabled modules: {', '.join(sorted(enabled))}")
|
||||
return enabled
|
||||
|
||||
@@ -8,11 +8,12 @@ Tenancy, VPN, Wireless, and Extras.
|
||||
import asyncio
|
||||
import logging
|
||||
import json
|
||||
from typing import Optional, Set
|
||||
from mcp.server import Server
|
||||
from mcp.server.stdio import stdio_server
|
||||
from mcp.types import Tool, TextContent
|
||||
|
||||
from .config import NetBoxConfig
|
||||
from .config import NetBoxConfig, ALL_MODULES
|
||||
from .netbox_client import NetBoxClient
|
||||
from .tools.dcim import DCIMTools
|
||||
from .tools.ipam import IPAMTools
|
||||
@@ -1453,6 +1454,49 @@ TOOL_NAME_MAP = {
|
||||
}
|
||||
|
||||
|
||||
# Map tool name prefixes to module names.
|
||||
# This handles both full prefixes and shortened prefixes used in TOOL_NAME_MAP.
|
||||
PREFIX_TO_MODULE = {
|
||||
'dcim': 'dcim',
|
||||
'ipam': 'ipam',
|
||||
'circuits': 'circuits',
|
||||
'circ': 'circuits', # Shortened prefix
|
||||
'virtualization': 'virtualization',
|
||||
'virt': 'virtualization', # Shortened prefix
|
||||
'tenancy': 'tenancy',
|
||||
'vpn': 'vpn',
|
||||
'wireless': 'wireless',
|
||||
'wlan': 'wireless', # Shortened prefix
|
||||
'extras': 'extras',
|
||||
}
|
||||
|
||||
|
||||
def _get_tool_module(tool_name: str) -> Optional[str]:
|
||||
"""
|
||||
Determine which module a tool belongs to.
|
||||
|
||||
Checks TOOL_NAME_MAP first for shortened names, then falls back to prefix extraction.
|
||||
|
||||
Args:
|
||||
tool_name: The tool name (e.g., 'dcim_list_devices', 'virt_list_vms')
|
||||
|
||||
Returns:
|
||||
Module name (e.g., 'dcim', 'virtualization') or None if unknown
|
||||
"""
|
||||
# Check mapped short names first
|
||||
if tool_name in TOOL_NAME_MAP:
|
||||
category, _ = TOOL_NAME_MAP[tool_name]
|
||||
return category
|
||||
|
||||
# Fall back to prefix extraction
|
||||
parts = tool_name.split('_', 1)
|
||||
if len(parts) < 2:
|
||||
return None
|
||||
|
||||
prefix = parts[0]
|
||||
return PREFIX_TO_MODULE.get(prefix)
|
||||
|
||||
|
||||
class NetBoxMCPServer:
|
||||
"""MCP Server for NetBox integration"""
|
||||
|
||||
@@ -1460,6 +1504,8 @@ class NetBoxMCPServer:
|
||||
self.server = Server("netbox-mcp")
|
||||
self.config = None
|
||||
self.client = None
|
||||
self.enabled_modules: Set[str] = set(ALL_MODULES)
|
||||
# Tool instances - only instantiated for enabled modules
|
||||
self.dcim_tools = None
|
||||
self.ipam_tools = None
|
||||
self.circuits_tools = None
|
||||
@@ -1474,18 +1520,39 @@ class NetBoxMCPServer:
|
||||
try:
|
||||
config_loader = NetBoxConfig()
|
||||
self.config = config_loader.load()
|
||||
self.enabled_modules = self.config['enabled_modules']
|
||||
|
||||
self.client = NetBoxClient()
|
||||
|
||||
# Conditionally instantiate tool classes for enabled modules only
|
||||
if 'dcim' in self.enabled_modules:
|
||||
self.dcim_tools = DCIMTools(self.client)
|
||||
if 'ipam' in self.enabled_modules:
|
||||
self.ipam_tools = IPAMTools(self.client)
|
||||
if 'circuits' in self.enabled_modules:
|
||||
self.circuits_tools = CircuitsTools(self.client)
|
||||
if 'virtualization' in self.enabled_modules:
|
||||
self.virtualization_tools = VirtualizationTools(self.client)
|
||||
if 'tenancy' in self.enabled_modules:
|
||||
self.tenancy_tools = TenancyTools(self.client)
|
||||
if 'vpn' in self.enabled_modules:
|
||||
self.vpn_tools = VPNTools(self.client)
|
||||
if 'wireless' in self.enabled_modules:
|
||||
self.wireless_tools = WirelessTools(self.client)
|
||||
if 'extras' in self.enabled_modules:
|
||||
self.extras_tools = ExtrasTools(self.client)
|
||||
|
||||
logger.info(f"NetBox MCP Server initialized for {self.config['api_url']}")
|
||||
# Count tools that will be registered
|
||||
tool_count = sum(
|
||||
1 for name in TOOL_DEFINITIONS
|
||||
if _get_tool_module(name) in self.enabled_modules
|
||||
)
|
||||
|
||||
modules_str = ', '.join(sorted(self.enabled_modules))
|
||||
logger.info(
|
||||
f"NetBox MCP Server initialized: {tool_count} tools registered "
|
||||
f"(modules: {modules_str})"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to initialize: {e}")
|
||||
raise
|
||||
@@ -1495,9 +1562,14 @@ class NetBoxMCPServer:
|
||||
|
||||
@self.server.list_tools()
|
||||
async def list_tools() -> list[Tool]:
|
||||
"""Return list of available tools"""
|
||||
"""Return list of available tools, filtered by enabled modules"""
|
||||
tools = []
|
||||
for name, definition in TOOL_DEFINITIONS.items():
|
||||
# Filter tools by enabled modules
|
||||
module = _get_tool_module(name)
|
||||
if module not in self.enabled_modules:
|
||||
continue
|
||||
|
||||
tools.append(Tool(
|
||||
name=name,
|
||||
description=definition['description'],
|
||||
@@ -1532,6 +1604,14 @@ class NetBoxMCPServer:
|
||||
'virtualization_list_virtual_machines') to meet the 28-character
|
||||
limit. TOOL_NAME_MAP handles the translation to actual method names.
|
||||
"""
|
||||
# Check module is enabled (routing guard)
|
||||
module = _get_tool_module(name)
|
||||
if module and module not in self.enabled_modules:
|
||||
raise ValueError(
|
||||
f"Tool '{name}' is not available (module '{module}' not enabled). "
|
||||
f"Enabled modules: {', '.join(sorted(self.enabled_modules))}"
|
||||
)
|
||||
|
||||
# Check if this is a mapped short name
|
||||
if name in TOOL_NAME_MAP:
|
||||
category, method_name = TOOL_NAME_MAP[name]
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: clarity-coach
|
||||
description: Patient, structured coach helping users articulate requirements clearly. Uses neurodivergent-friendly communication patterns.
|
||||
model: sonnet
|
||||
permissionMode: default
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Clarity Coach Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: maintainer
|
||||
description: CLAUDE.md optimization and maintenance agent
|
||||
model: sonnet
|
||||
permissionMode: acceptEdits
|
||||
skills: visual-header, settings-optimization
|
||||
---
|
||||
|
||||
# CLAUDE.md Maintainer Agent
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: cmdb-assistant
|
||||
description: Infrastructure management assistant specialized in NetBox CMDB operations. Use for device management, IP addressing, and infrastructure queries.
|
||||
model: sonnet
|
||||
permissionMode: default
|
||||
---
|
||||
|
||||
# CMDB Assistant Agent
|
||||
|
||||
@@ -32,9 +32,9 @@ The following NetBox MCP tools are available for infrastructure management:
|
||||
- `ipam_list_available_ips`, `ipam_create_available_ip` - IP allocation
|
||||
|
||||
**Virtualization:**
|
||||
- `virtualization_list_virtual_machines`, `virtualization_create_virtual_machine` - VM management
|
||||
- `virtualization_list_clusters`, `virtualization_create_cluster` - Cluster management
|
||||
- `virtualization_list_vm_interfaces` - VM interface management
|
||||
- `virt_list_vms`, `virt_create_vm`, `virt_update_vm`, `virt_delete_vm` - VM management
|
||||
- `virt_list_clusters`, `virt_create_cluster`, `virt_update_cluster`, `virt_delete_cluster` - Cluster management
|
||||
- `virt_list_vm_ifaces`, `virt_create_vm_iface` - VM interface management
|
||||
|
||||
**Circuits:**
|
||||
- `circuits_list_circuits`, `circuits_create_circuit` - Circuit management
|
||||
|
||||
@@ -31,7 +31,7 @@ When the user provides a search query, determine the best approach:
|
||||
3. **Site search**: Use `dcim_list_sites` with name filter
|
||||
4. **Prefix search**: Use `ipam_list_prefixes` with prefix or within filter
|
||||
5. **VLAN search**: Use `ipam_list_vlans` with vid or name filter
|
||||
6. **VM search**: Use `virtualization_list_virtual_machines` with name filter
|
||||
6. **VM search**: Use `virt_list_vms` with name filter
|
||||
|
||||
For broad searches, query multiple endpoints and consolidate results.
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: refactor-advisor
|
||||
description: Code structure and refactoring specialist. Use when analyzing code quality, design patterns, or planning refactoring work.
|
||||
model: sonnet
|
||||
permissionMode: acceptEdits
|
||||
---
|
||||
|
||||
# Refactor Advisor Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: security-reviewer
|
||||
description: Security-focused code review agent
|
||||
model: sonnet
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Security Reviewer Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: agent-check
|
||||
description: Agent definition validator for quick verification
|
||||
model: haiku
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Agent Check Agent
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: full-validation
|
||||
description: Contract validation specialist for comprehensive cross-plugin compatibility validation of the entire marketplace.
|
||||
model: sonnet
|
||||
permissionMode: default
|
||||
---
|
||||
|
||||
# Full Validation Agent
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: data-advisor
|
||||
description: Reviews code for data integrity, schema validity, and dbt compliance using data-platform MCP tools. Use when validating database operations or data pipelines.
|
||||
model: sonnet
|
||||
permissionMode: default
|
||||
---
|
||||
|
||||
# Data Advisor Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: data-analysis
|
||||
description: Data analysis specialist for exploration and profiling
|
||||
model: sonnet
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Data Analysis Agent
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: data-ingestion
|
||||
description: Data ingestion specialist for loading, transforming, and preparing data for analysis.
|
||||
model: haiku
|
||||
permissionMode: acceptEdits
|
||||
---
|
||||
|
||||
# Data Ingestion Agent
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: doc-analyzer
|
||||
description: Specialized agent for documentation analysis and drift detection. Use when detecting or fixing discrepancies between code and documentation.
|
||||
model: sonnet
|
||||
permissionMode: acceptEdits
|
||||
---
|
||||
|
||||
# Documentation Analyzer Agent
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: git-assistant
|
||||
description: Git workflow assistant for complex git operations, conflict resolution, and repository history management.
|
||||
model: haiku
|
||||
permissionMode: acceptEdits
|
||||
---
|
||||
|
||||
# Git Assistant Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: coordinator
|
||||
description: Review coordinator that orchestrates the multi-agent PR review process. Dispatches to specialized reviewers, aggregates findings, and produces the final review report. Use proactively after code changes.
|
||||
model: sonnet
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Coordinator Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: maintainability-auditor
|
||||
description: Identifies code complexity, duplication, naming issues, and architecture concerns in PR changes.
|
||||
model: haiku
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Maintainability Auditor Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: performance-analyst
|
||||
description: Performance-focused code reviewer that identifies performance issues, inefficiencies, and optimization opportunities.
|
||||
model: sonnet
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Performance Analyst Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: security-reviewer
|
||||
description: Security-focused code reviewer for PR analysis
|
||||
model: sonnet
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Security Reviewer Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: test-validator
|
||||
description: Test quality reviewer that validates test coverage, test quality, and testing practices in PR changes.
|
||||
model: haiku
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Test Validator Agent
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
---
|
||||
name: code-reviewer
|
||||
description: Pre-sprint code quality review agent
|
||||
model: sonnet
|
||||
model: opus
|
||||
permissionMode: default
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
skills: review-checklist, test-standards, sprint-lifecycle, visual-output
|
||||
---
|
||||
|
||||
# Code Reviewer Agent
|
||||
|
||||
You are the **Code Reviewer Agent** - a thorough, practical reviewer who ensures code quality before sprint close.
|
||||
|
||||
## Skills to Load
|
||||
|
||||
- skills/review-checklist.md
|
||||
- skills/test-standards.md
|
||||
- skills/sprint-lifecycle.md
|
||||
- skills/visual-output.md
|
||||
|
||||
## Your Personality
|
||||
|
||||
**Thorough but Practical:**
|
||||
|
||||
@@ -2,22 +2,14 @@
|
||||
name: executor
|
||||
description: Implementation executor agent - precise implementation guidance and code quality
|
||||
model: sonnet
|
||||
permissionMode: bypassPermissions
|
||||
skills: mcp-tools-reference, branch-security, git-workflow, progress-tracking, runaway-detection, lessons-learned, visual-output
|
||||
---
|
||||
|
||||
# Implementation Executor Agent
|
||||
|
||||
You are the **Executor Agent** - an implementation-focused specialist who writes clean code and ensures quality.
|
||||
|
||||
## Skills to Load
|
||||
|
||||
- skills/mcp-tools-reference.md
|
||||
- skills/branch-security.md
|
||||
- skills/git-workflow.md
|
||||
- skills/progress-tracking.md
|
||||
- skills/runaway-detection.md
|
||||
- skills/lessons-learned.md
|
||||
- skills/visual-output.md
|
||||
|
||||
## Your Personality
|
||||
|
||||
**Implementation-Focused:**
|
||||
|
||||
@@ -2,26 +2,36 @@
|
||||
name: orchestrator
|
||||
description: Sprint orchestration agent - coordinates execution and tracks progress
|
||||
model: sonnet
|
||||
permissionMode: acceptEdits
|
||||
skills: mcp-tools-reference, batch-execution
|
||||
---
|
||||
|
||||
# Sprint Orchestration Agent
|
||||
|
||||
You are the **Orchestrator Agent** - a concise, action-oriented coordinator who keeps sprints on track.
|
||||
|
||||
## Skills to Load
|
||||
## Skill Loading Protocol
|
||||
|
||||
- skills/mcp-tools-reference.md
|
||||
**Frontmatter skills (auto-injected, always available — DO NOT re-read these):**
|
||||
- `mcp-tools-reference` — MCP tool signatures for all Gitea operations
|
||||
- `batch-execution` — Plan-then-batch protocol for API execution
|
||||
|
||||
**Phase 1 skills — read ONCE at session start, before any work begins:**
|
||||
- skills/branch-security.md
|
||||
- skills/sprint-approval.md
|
||||
- skills/sprint-lifecycle.md
|
||||
- skills/visual-output.md
|
||||
- skills/runaway-detection.md
|
||||
|
||||
**Phase 2 skills — read ONCE when sequencing and dispatching work:**
|
||||
- skills/dependency-management.md
|
||||
- skills/lessons-learned.md
|
||||
- skills/git-workflow.md
|
||||
- skills/progress-tracking.md
|
||||
- skills/runaway-detection.md
|
||||
- skills/wiki-conventions.md
|
||||
- skills/domain-consultation.md
|
||||
- skills/sprint-lifecycle.md
|
||||
- skills/visual-output.md
|
||||
|
||||
**CRITICAL: Read each skill file exactly ONCE. Do NOT re-read skill files between MCP API calls. When posting status updates, label changes, or comments across multiple issues, use the batch-execution protocol — queue all operations, execute in a loop using only frontmatter skills.**
|
||||
|
||||
## Your Personality
|
||||
|
||||
|
||||
@@ -1,29 +1,41 @@
|
||||
---
|
||||
name: planner
|
||||
description: Sprint planning agent - thoughtful architecture analysis and issue creation
|
||||
model: sonnet
|
||||
model: opus
|
||||
permissionMode: default
|
||||
skills: mcp-tools-reference, batch-execution
|
||||
---
|
||||
|
||||
# Sprint Planning Agent
|
||||
|
||||
You are the **Planner Agent** - a methodical architect who thoroughly analyzes requirements before creating well-structured plans.
|
||||
|
||||
## Skills to Load
|
||||
## Skill Loading Protocol
|
||||
|
||||
- skills/mcp-tools-reference.md
|
||||
**Frontmatter skills (auto-injected, always available — DO NOT re-read these):**
|
||||
- `mcp-tools-reference` — MCP tool signatures for all Gitea operations
|
||||
- `batch-execution` — Plan-then-batch protocol for API execution
|
||||
|
||||
**Phase 1 skills — read ONCE at session start, before any work begins:**
|
||||
- skills/branch-security.md
|
||||
- skills/repo-validation.md
|
||||
- skills/sprint-lifecycle.md
|
||||
- skills/visual-output.md
|
||||
|
||||
**Phase 2 skills — read ONCE when entering analysis/planning work:**
|
||||
- skills/input-detection.md
|
||||
- skills/lessons-learned.md
|
||||
- skills/wiki-conventions.md
|
||||
- skills/task-sizing.md
|
||||
- skills/issue-conventions.md
|
||||
- skills/sprint-approval.md
|
||||
- skills/planning-workflow.md
|
||||
- skills/label-taxonomy/labels-reference.md
|
||||
- skills/domain-consultation.md
|
||||
- skills/sprint-lifecycle.md
|
||||
- skills/visual-output.md
|
||||
|
||||
**Phase 3 skills — read ONCE before requesting approval:**
|
||||
- skills/sprint-approval.md
|
||||
|
||||
**CRITICAL: Read each skill file exactly ONCE. Do NOT re-read skill files between MCP API calls. During batch execution (Step 8a of planning-workflow.md), use ONLY the frontmatter skills — no file reads.**
|
||||
|
||||
## Your Personality
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ agent: planner
|
||||
|
||||
## Skills Required
|
||||
|
||||
- skills/mcp-tools-reference.md
|
||||
- skills/mcp-tools-reference.md (frontmatter — auto-injected)
|
||||
- skills/batch-execution.md (frontmatter — auto-injected)
|
||||
- skills/branch-security.md
|
||||
- skills/repo-validation.md
|
||||
- skills/input-detection.md
|
||||
|
||||
@@ -7,7 +7,8 @@ agent: orchestrator
|
||||
|
||||
## Skills Required
|
||||
|
||||
- skills/mcp-tools-reference.md
|
||||
- skills/mcp-tools-reference.md (frontmatter — auto-injected)
|
||||
- skills/batch-execution.md (frontmatter — auto-injected)
|
||||
- skills/branch-security.md
|
||||
- skills/sprint-approval.md
|
||||
- skills/dependency-management.md
|
||||
|
||||
116
plugins/projman/skills/batch-execution.md
Normal file
116
plugins/projman/skills/batch-execution.md
Normal file
@@ -0,0 +1,116 @@
|
||||
---
|
||||
name: batch-execution
|
||||
description: Batch MCP API execution to eliminate redundant skill reloading between repetitive operations
|
||||
---
|
||||
|
||||
# Batch Execution Pattern
|
||||
|
||||
## Purpose
|
||||
|
||||
Separate cognitive work (analysis, planning, decision-making) from mechanical API execution (issue creation, dependency setup, status updates). Think once with all skills loaded, then execute repetitive API calls in a tight loop with only `mcp-tools-reference.md` needed.
|
||||
|
||||
## When to Use
|
||||
|
||||
- **Planner agent**: After drafting all issues, before calling `create_issue`
|
||||
- **Orchestrator agent**: When posting status updates, label changes, or comments across multiple issues
|
||||
- **Any agent**: When making 3+ similar MCP API calls in sequence
|
||||
|
||||
## Protocol
|
||||
|
||||
### Phase 1: Cognitive Work (all skills loaded)
|
||||
|
||||
During analysis, architecture, and planning — use every skill you need. Read files, think deeply, ask questions, resolve ambiguity. This is where the full skill set pays for itself.
|
||||
|
||||
**Output of this phase:** A complete, structured execution plan listing every API operation with all parameters fully resolved. No ambiguity, no placeholders that require re-analysis.
|
||||
|
||||
### Phase 2: Execution Manifest
|
||||
|
||||
Before entering batch mode, produce a structured manifest. This serves as both the execution plan AND a checkpoint for user visibility. Format:
|
||||
|
||||
```
|
||||
## Execution Manifest
|
||||
|
||||
### Issue Creation (N items)
|
||||
1. `create_issue` — title: "[Sprint XX] feat: ..." | labels: [...] | milestone: N
|
||||
2. `create_issue` — title: "[Sprint XX] fix: ..." | labels: [...] | milestone: N
|
||||
...
|
||||
|
||||
### Dependency Setup (N items)
|
||||
1. `create_issue_dependency` — issue: $1 depends_on: $2
|
||||
...
|
||||
|
||||
### Milestone Assignment (N items)
|
||||
1. `update_issue` — issue: $1 milestone: N
|
||||
...
|
||||
|
||||
### Status/Label Updates (N items)
|
||||
1. `update_issue` — issue: #N labels: [add "Status/In-Progress"]
|
||||
...
|
||||
```
|
||||
|
||||
Variable references (`$1`, `$2`) resolve to outputs from prior batch operations (e.g., `$1` = issue number returned by first `create_issue`).
|
||||
|
||||
### Phase 3: Batch Execute
|
||||
|
||||
Execute the manifest items in order, grouped by operation type:
|
||||
|
||||
1. **All `create_issue` calls** — collect returned issue numbers
|
||||
2. **Resolve variable references** — map `$1` → actual issue #45, `$2` → #46, etc.
|
||||
3. **All `create_issue_dependency` calls** — using resolved numbers
|
||||
4. **All milestone assignments** — if not done during creation
|
||||
5. **All status/label updates** — using resolved numbers
|
||||
|
||||
**Rules during batch execution:**
|
||||
- Do NOT re-read any skill files between calls
|
||||
- Do NOT re-analyze or second-guess the plan — it was finalized in Phase 1
|
||||
- Do NOT add commentary between individual API calls — batch them silently
|
||||
- DO track success/failure per operation
|
||||
- DO continue on individual failures (log and report at end)
|
||||
- DO post a progress summary after each batch group completes
|
||||
|
||||
### Phase 4: Batch Report
|
||||
|
||||
After all operations complete, report results:
|
||||
|
||||
```
|
||||
## Batch Execution Complete
|
||||
|
||||
### Issue Creation: 6/6 ✓
|
||||
- #45: [Sprint 19] feat: JWT generation
|
||||
- #46: [Sprint 19] feat: Login endpoint
|
||||
- #47: [Sprint 19] feat: Token refresh
|
||||
- #48: [Sprint 19] test: Auth unit tests
|
||||
- #49: [Sprint 19] docs: API documentation
|
||||
- #50: [Sprint 19] chore: CI pipeline
|
||||
|
||||
### Dependencies: 4/4 ✓
|
||||
- #46 depends on #45
|
||||
- #47 depends on #45
|
||||
- #48 depends on #46, #47
|
||||
- #49 depends on #46
|
||||
|
||||
### Milestone Assignment: 6/6 ✓
|
||||
- All issues assigned to Sprint 19
|
||||
|
||||
### Failures: 0
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | Action |
|
||||
|-------|--------|
|
||||
| Single API call fails | Log error, continue with next item |
|
||||
| Dependency target missing (prior create failed) | Skip dependency, log as blocked |
|
||||
| All creates fail | STOP batch, report connection/auth issue |
|
||||
| Partial milestone assignment | Report which issues weren't assigned |
|
||||
|
||||
After batch completes, if any failures: present failure summary and ask user whether to retry failed operations or continue.
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
| Wrong | Why | Right |
|
||||
|-------|-----|-------|
|
||||
| Re-reading `mcp-tools-reference.md` before each API call | Wastes tokens; you already know the tool signatures | Read once, execute many |
|
||||
| Interleaving analysis with API calls | Forces full context per call | Finish ALL analysis first, THEN batch execute |
|
||||
| Calling create_issue one at a time with commentary between | Token overhead per turn | Queue all creates, execute in tight loop |
|
||||
| Stopping the batch to ask user about individual items | Defeats batching purpose | Complete batch, report results, ask about failures |
|
||||
@@ -84,21 +84,38 @@ Think through:
|
||||
- What dependencies exist?
|
||||
- What are potential risks?
|
||||
|
||||
### 8. Create Gitea Issues
|
||||
### 8. Draft Issue Specifications (DO NOT create yet)
|
||||
|
||||
Follow `skills/issue-conventions.md` and `skills/task-sizing.md`:
|
||||
- Use proper title format: `[Sprint XX] <type>: <description>`
|
||||
- Include wiki implementation reference
|
||||
- Apply appropriate labels using `suggest_labels`
|
||||
- **Refuse to create L/XL tasks without breakdown**
|
||||
Follow `skills/issue-conventions.md` and `skills/task-sizing.md` to prepare the complete specification for ALL issues. **Do NOT call `create_issue` yet.**
|
||||
|
||||
### 9. Set Up Dependencies
|
||||
For each issue, resolve completely:
|
||||
- Title: `[Sprint XX] <type>: <description>`
|
||||
- Body: Full description with wiki reference, acceptance criteria, technical notes
|
||||
- Labels: Use `suggest_labels` to determine, then finalize the list
|
||||
- Milestone: The sprint milestone (create first if needed)
|
||||
- Dependencies: Which issues depend on which (by draft order index)
|
||||
|
||||
```python
|
||||
create_issue_dependency(repo="org/repo", issue_number=46, depends_on=45)
|
||||
```
|
||||
**Refuse to create L/XL tasks without breakdown.**
|
||||
|
||||
### 10. Create or Select Milestone
|
||||
Output: A complete execution manifest per `skills/batch-execution.md` Phase 2 format.
|
||||
|
||||
### 8a. Batch Execute Issue Creation
|
||||
|
||||
Follow `skills/batch-execution.md` Phase 3:
|
||||
1. Execute all `create_issue` calls — collect returned issue numbers
|
||||
2. Execute all `create_issue_dependency` calls — using collected numbers
|
||||
3. Assign all issues to milestone
|
||||
4. Report batch results per Phase 4 format
|
||||
|
||||
**Only `skills/mcp-tools-reference.md` is needed for this step.** Do NOT re-read other skill files.
|
||||
|
||||
### 9. (Merged into Step 8a)
|
||||
|
||||
Dependencies are now created as part of the batch execution in Step 8a. No separate step needed.
|
||||
|
||||
### 10. Create or Select Milestone (before batch)
|
||||
|
||||
**This step runs BEFORE Step 8a** — the milestone must exist before batch issue creation can assign to it.
|
||||
|
||||
```python
|
||||
create_milestone(
|
||||
@@ -109,7 +126,7 @@ create_milestone(
|
||||
)
|
||||
```
|
||||
|
||||
Assign issues to the milestone.
|
||||
If milestone already exists, select it. Record the milestone ID for use in the batch manifest.
|
||||
|
||||
### 11. Request Sprint Approval
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: component-check
|
||||
description: DMC component validation specialist
|
||||
model: haiku
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Component Check Agent
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
name: design-reviewer
|
||||
description: Reviews code for design system compliance using viz-platform MCP tools. Use when validating DMC components, theme tokens, or accessibility standards.
|
||||
model: sonnet
|
||||
permissionMode: plan
|
||||
disallowedTools: Write, Edit, MultiEdit
|
||||
---
|
||||
|
||||
# Design Reviewer Agent
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: layout-builder
|
||||
description: Practical dashboard layout specialist for creating well-structured layouts with filtering, grid systems, and responsive design.
|
||||
model: sonnet
|
||||
permissionMode: default
|
||||
---
|
||||
|
||||
# Layout Builder Agent
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name: theme-setup
|
||||
description: Design-focused theme setup specialist for creating consistent, brand-aligned themes for Dash Mantine Components applications.
|
||||
model: haiku
|
||||
permissionMode: acceptEdits
|
||||
---
|
||||
|
||||
# Theme Setup Agent
|
||||
|
||||
Reference in New Issue
Block a user