Add missing create_pull_request tool to Gitea MCP server. This completes
the PR lifecycle - previously only had list/get/review/comment tools.
- Add create_pull_request to GiteaClient
- Add async wrapper to PullRequestTools with branch permissions
- Register tool in server.py with proper schema
- Parameters: title, body, head, base, labels (optional)
- Branch-aware security: only allowed on development/feature branches
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes#160: update_wiki_page was renaming pages to "unnamed"
Root causes:
1. page_name wasn't URL-encoded, breaking pages with special chars like ':'
2. PATCH request was missing 'title' field, causing Gitea to use default name
Changes:
- Add URL encoding (urllib.parse.quote) to get_wiki_page, update_wiki_page, delete_wiki_page
- Add 'title': page_name to update_wiki_page payload to preserve page name
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes multiple issues from diagnostic #123:
1. create_label_smart type safety (labels.py)
- Add isinstance(result, dict) checks after API calls
- Return structured error dict if API returns unexpected type
- Prevents "list indices must be integers" crash
2. debug-report always uses curl with labels
- Remove MCP option - always use curl for marketplace issues
- Add label ID fetching step (Source/Diagnostic, Type/Bug)
- Include labels in curl POST payload
- Avoids branch protection restrictions on main branch
Fixes#123
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
create_label_smart now checks if label already exists before creating.
- Checks both org and repo labels
- Handles format variations (Type/Bug vs Type: Bug)
- Returns {skipped: true} if label already exists
- Prevents duplicate label creation errors
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The suggest_labels tool accepted a repo parameter in the implementation
but didn't expose it in the MCP tool schema, causing it to always rely
on auto-detection which failed in some contexts.
Fixes#94
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The suggest_labels function now dynamically detects the label naming convention
used in the repository (slash format like Type/Bug or colon-space format like
Type: Bug) instead of hardcoding slash format.
Changes:
- Added _build_label_lookup() to parse and normalize label formats
- Added _find_label() to find actual labels from the lookup
- Updated suggest_labels() to accept optional repo parameter
- Labels are fetched first, then suggestions match actual names
- Supports Efforts/Effort normalization (handles singular/plural)
Fixes issue #73 sub-issue 3: label format mismatch
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The MCP server runs with cwd set to the plugin directory, not the
user's project directory. This caused git remote auto-detection to
fail because it was looking at the wrong directory.
Changes:
- Added _find_project_directory() method with multiple strategies:
1. CLAUDE_PROJECT_DIR environment variable
2. PWD environment variable (if it has .git or .env)
3. Current working directory (if it has .git or .env)
- Updated _detect_repo_from_git() to accept project_dir parameter
- Added 3 new tests for project directory detection
Fixes#70
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1. Repo Auto-Detection (config.py):
- Added _detect_repo_from_git() to parse git remote URL
- Supports SSH, SSH short, HTTPS, HTTP URL formats
- Falls back to git remote when GITEA_REPO not set
2. Organization Validation (gitea_client.py):
- Changed is_org_repo() to use /orgs/{owner} endpoint
- Added _is_organization() method for reliable org detection
- Fixes issue where owner.type was null in Gitea API
3. Tests:
- Added 6 tests for git URL parsing
- Added 3 tests for org detection
Fixes#64
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The get_labels tool was failing with 404 for user-owned repositories
because it always queried /api/v1/orgs/{owner}/labels, which only
works for organizations.
Changes:
- labels.py: Check is_org_repo() before fetching org labels
- gitea_client.py: Same fix in _resolve_label_ids()
- test_labels.py: Added tests for both org and user-owned repos
Fixes#61
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Claude Code only caches the plugin directory when installed from a
marketplace, not parent directories. This broke the shared mcp-servers/
architecture because relative paths like ../../mcp-servers/ resolved
to non-existent locations in the cache.
Changes:
- Move gitea and wikijs MCP servers into plugins/projman/mcp-servers/
- Move netbox MCP server into plugins/cmdb-assistant/mcp-servers/
- Update .mcp.json files to use ${CLAUDE_PLUGIN_ROOT}/mcp-servers/
- Update setup.sh to handle new bundled structure
- Add netbox.env config template to setup.sh
- Update CLAUDE.md and CANONICAL-PATHS.md documentation
This ensures plugins work correctly when installed and cached.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove separate GITEA_OWNER config, use owner/repo format everywhere
- Add _parse_repo() helper to extract owner and repo from combined string
- Update plugin.json schema: file -> source, author as object
- Remove redundant configuration section from cmdb-assistant plugin
- Simplify gitea_client.py by removing excessive docstrings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Problem:
- Gitea API expects label IDs (integers), not label names (strings)
- Previous implementation passed label names directly, causing 422 errors
Solution:
- Added _resolve_label_ids() method to convert names to IDs
- Fetches all labels (org + repo) and builds name->ID mapping
- Automatically resolves IDs before creating issues
Testing:
- Created test issue #4 with 4 labels (manual verification)
- Created test issue #5 with 11 labels (automated testing)
- All labels applied correctly in Gitea
Also updated:
- projman/skills/label-taxonomy/labels-reference.md with current taxonomy
- Status updated to "Synced with Gitea" (43 labels total)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>