initial setup: planning documents updated

This commit is contained in:
2025-11-06 08:29:41 -05:00
parent 817cc3d7bf
commit eebfd0e2f9
8 changed files with 4500 additions and 1709 deletions

226
CLAUDE.md
View File

@@ -7,9 +7,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
This repository contains development of two Claude Code plugins for project management: This repository contains development of two Claude Code plugins for project management:
1. **`projman`** - Single-repository project management plugin (build first) 1. **`projman`** - Single-repository project management plugin (build first)
2. **`pmo`** - Multi-project PMO coordination plugin (build second) 2. **`projman-pmo`** - Multi-project PMO coordination plugin (build second)
These plugins transform a proven 15-sprint workflow into reusable, distributable tools for managing software development with Claude Code, Gitea, and agile methodologies. These plugins transform a proven 15-sprint workflow into reusable, distributable tools for managing software development with Claude Code, Gitea, Wiki.js, and agile methodologies.
**Status:** Planning phase complete, ready for implementation (Phase 1)
## Core Architecture ## Core Architecture
@@ -41,9 +43,9 @@ The plugins implement a three-agent architecture that mirrors the proven workflo
### MCP Server Integration ### MCP Server Integration
Both plugins use a Gitea MCP server (`mcp-server/`) to expose Gitea API as tools: Both plugins use **two shared MCP servers** at repository root level (`mcp-servers/`):
**Core Tools:** **1. Gitea MCP Server** (Python)
- `list_issues` - Query issues with filters - `list_issues` - Query issues with filters
- `get_issue` - Fetch single issue details - `get_issue` - Fetch single issue details
- `create_issue` - Create new issue with labels - `create_issue` - Create new issue with labels
@@ -52,7 +54,21 @@ Both plugins use a Gitea MCP server (`mcp-server/`) to expose Gitea API as tools
- `get_labels` - Fetch org + repo label taxonomy - `get_labels` - Fetch org + repo label taxonomy
- `suggest_labels` - Analyze context and suggest appropriate labels - `suggest_labels` - Analyze context and suggest appropriate labels
Configuration lives in `.mcp.json` and uses environment variables for Gitea credentials. **2. Wiki.js MCP Server** (Python, GraphQL)
- `search_pages` - Search Wiki.js pages by keywords/tags
- `get_page` - Fetch specific page content
- `create_page` - Create new Wiki page
- `update_page` - Modify existing page
- `list_pages` - List pages in a path
- `create_lesson` - Create lessons learned document
- `search_lessons` - Search past lessons by tags
- `tag_lesson` - Add tags to lessons learned
**Key Architecture Points:**
- MCP servers are **shared** by both plugins at `mcp-servers/gitea` and `mcp-servers/wikijs`
- Each MCP server detects its mode (project-scoped vs company-wide) based on environment variables
- Configuration uses hybrid approach (system-level + project-level)
- Both plugins reference `../mcp-servers/` in their `.mcp.json` files
## Branch-Aware Security Model ## Branch-Aware Security Model
@@ -100,20 +116,37 @@ The label system includes:
**Critical Feature:** After 15 sprints without lesson capture, repeated mistakes occurred (e.g., Claude Code infinite loops on similar issues 2-3 times). **Critical Feature:** After 15 sprints without lesson capture, repeated mistakes occurred (e.g., Claude Code infinite loops on similar issues 2-3 times).
**Structure:** **Wiki.js Structure:**
``` ```
docs/lessons-learned/ Wiki.js: https://wiki.hyperhivelabs.com
── INDEX.md # Master index with searchable tags ── /hyper-hive-labs/
├── sprints/ # Per-sprint lessons ├── projects/ # Project-specific documentation
├── patterns/ # Recurring patterns (deployment, architecture, Claude issues) ├── cuisineflow/
└── templates/ # Lesson template ├── lessons-learned/
│ │ │ ├── sprints/
│ │ │ ├── patterns/
│ │ │ └── INDEX.md
│ │ └── documentation/
│ ├── cuisineflow-site/
│ ├── intuit-engine/
│ └── hhl-site/
├── company/ # Company-wide documentation
│ ├── processes/
│ ├── standards/
│ └── tools/
└── shared/ # Cross-project resources
├── architecture-patterns/
├── best-practices/
└── tech-stack/
``` ```
**Workflow:** **Workflow:**
- Orchestrator captures lessons at sprint close - Orchestrator captures lessons at sprint close via Wiki.js MCP
- Planner searches relevant lessons at sprint start - Planner searches relevant lessons at sprint start using GraphQL search
- INDEX.md maintained automatically - INDEX.md maintained automatically via Wiki.js API
- Tags enable cross-project lesson discovery
- Focus on preventable repetitions, not every detail - Focus on preventable repetitions, not every detail
- Web interface for team review and editing
## Development Workflow ## Development Workflow
@@ -125,48 +158,93 @@ docs/lessons-learned/
See [docs/reference-material/projman-implementation-plan.md](docs/reference-material/projman-implementation-plan.md) for the complete 12-phase implementation plan. See [docs/reference-material/projman-implementation-plan.md](docs/reference-material/projman-implementation-plan.md) for the complete 12-phase implementation plan.
### Plugin Structure ### Repository Structure (DEFINITIVE)
⚠️ **See `docs/CORRECT-ARCHITECTURE.md` for the authoritative structure reference**
``` ```
projman/ hyperhivelabs/claude-plugins/
├── .claude-plugin/ ├── .claude-plugin/
│ └── plugin.json # Plugin manifest │ └── marketplace.json
├── commands/ # Slash commands (user entry points) ├── mcp-servers/ # ← SHARED BY BOTH PLUGINS
│ ├── sprint-plan.md │ ├── gitea/
│ ├── sprint-start.md │ ├── .venv/
│ ├── sprint-status.md │ ├── requirements.txt # Python dependencies
│ ├── sprint-close.md │ ├── mcp_server/
├── issue-create.md │ │ ├── __init__.py
├── issue-list.md │ │ ├── server.py
├── labels-sync.md │ │ ├── config.py # Mode detection (project/company)
└── deploy-check.md │ │ ├── gitea_client.py
├── agents/ # Agent personalities and workflows └── tools/
├── planner.md │ │ ├── issues.py
├── orchestrator.md │ │ └── labels.py
│ └── executor.md │ └── tests/
├── skills/ # Supporting knowledge (not orchestrators) │ └── wikijs/
├── gitea-api/ ├── .venv/
├── label-taxonomy/ ├── requirements.txt # Python + GraphQL dependencies
├── lessons-learned/ ├── mcp_server/
├── agile-pm/ │ ├── __init__.py
└── branch-strategy/ │ ├── server.py
├── hooks/ # Automation (post-task sync, staging guards) ├── config.py # Mode detection (project/company)
└── hooks.json │ ├── wikijs_client.py # GraphQL client
├── .mcp.json # MCP server configuration └── tools/
├── mcp-server/ # Gitea API integration ├── pages.py
├── package.json │ ├── lessons_learned.py
├── tsconfig.json │ └── documentation.py
└── src/ └── tests/
── README.md ── projman/ # ← PROJECT PLUGIN
│ ├── .claude-plugin/
│ │ └── plugin.json
│ ├── .mcp.json # Points to ../mcp-servers/
│ ├── commands/
│ │ ├── sprint-plan.md
│ │ ├── sprint-start.md
│ │ ├── sprint-status.md
│ │ ├── sprint-close.md
│ │ └── labels-sync.md
│ ├── agents/
│ │ ├── planner.md
│ │ ├── orchestrator.md
│ │ └── executor.md
│ ├── skills/
│ │ └── label-taxonomy/
│ │ └── labels-reference.md
│ ├── README.md
│ └── CONFIGURATION.md
└── projman-pmo/ # ← PMO PLUGIN
├── .claude-plugin/
│ └── plugin.json
├── .mcp.json # Points to ../mcp-servers/
├── commands/
│ ├── pmo-status.md
│ ├── pmo-priorities.md
│ ├── pmo-dependencies.md
│ └── pmo-schedule.md
├── agents/
│ └── pmo-coordinator.md
└── README.md
``` ```
### Key Design Decisions ### Key Design Decisions
**MCP vs Direct API:** **Two MCP Servers (Shared Architecture):**
- Use MCP Server for Gitea integration - **Gitea MCP**: Issues, labels, repository management
- Allows agents to use tools naturally in conversation - **Wiki.js MCP**: Documentation, lessons learned, knowledge base
- Easier to test independently - Servers are **shared** between both plugins at repository root
- Future-proof for additional integrations - Mode detection based on environment variables (project vs company-wide)
- Benefits: Single source of truth, fix bugs once, professional architecture
**Python Implementation:**
- Python chosen over Node.js for MCP servers
- Better suited for configuration management and modular code
- Easier to maintain and extend
- Virtual environment (.venv) per MCP server
**Hybrid Configuration:**
- **System-level**: `~/.config/claude/gitea.env` and `wikijs.env` (credentials)
- **Project-level**: `project-root/.env` (repository and path specification)
- Merge strategy: project overrides system
- Benefits: Single token per service, easy multi-project setup
**Skills as Knowledge, Not Orchestrators:** **Skills as Knowledge, Not Orchestrators:**
- Skills provide supporting knowledge loaded when relevant - Skills provide supporting knowledge loaded when relevant
@@ -188,18 +266,24 @@ projman/
## Multi-Project Context (PMO Plugin) ## Multi-Project Context (PMO Plugin)
The `pmo` plugin will coordinate interdependent projects: The `projman-pmo` plugin will coordinate interdependent projects:
- **CuisineFlow** - Main product - **CuisineFlow** - Main product
- **CuisineFlow-Site** - Demo sync + customer gateway - **CuisineFlow-Site** - Demo sync + customer gateway
- **Intuit Engine Service** - API aggregator extraction (imminent) - **Intuit Engine Service** - API aggregator extraction (imminent)
- **HHL-Site** - Company presence - **HHL-Site** - Company presence
PMO plugin adds: PMO plugin adds:
- Cross-project issue aggregation - Cross-project issue aggregation (all repos in organization)
- Dependency tracking and visualization - Dependency tracking and visualization
- Resource allocation across projects - Resource allocation across projects
- Deployment coordination - Deployment coordination
- Multi-project prioritization - Multi-project prioritization
- Company-wide lessons learned search
**Configuration Difference:**
- PMO operates at company level (no `GITEA_REPO` or `WIKIJS_PROJECT`)
- Accesses entire `/hyper-hive-labs` Wiki.js namespace
- Queries all repositories in organization
Build PMO plugin AFTER projman is working and validated. Build PMO plugin AFTER projman is working and validated.
@@ -231,3 +315,43 @@ Test in real CuisineFlow repository with actual Gitea instance before distributi
- **Lessons learned is critical** - Prevents repeated mistakes (e.g., Claude infinite loops) - **Lessons learned is critical** - Prevents repeated mistakes (e.g., Claude infinite loops)
- **Type/Refactor label** - Newly implemented at org level for architectural work - **Type/Refactor label** - Newly implemented at org level for architectural work
- **Branch detection must be 100% reliable** - Prevents production accidents - **Branch detection must be 100% reliable** - Prevents production accidents
- **Python for MCP servers** - Use Python 3.8+ with virtual environments
- **Wiki.js structure** - All HHL content under `/hyper-hive-labs` namespace
## Documentation Index
This repository contains comprehensive planning documentation:
- **`docs/CORRECT-ARCHITECTURE.md`** - ⚠️ DEFINITIVE repository structure reference
- **`docs/DOCUMENT-INDEX.md`** - Complete guide to all planning documents
- **`docs/projman-implementation-plan-updated.md`** - Full 12-phase implementation plan
- **`docs/projman-python-quickstart.md`** - Python-specific implementation guide
- **`docs/two-mcp-architecture-guide.md`** - Deep dive into two-MCP architecture
**Start with:** `docs/DOCUMENT-INDEX.md` for navigation guidance
## Recent Updates (Updated: 2025-06-11)
### Planning Phase Complete
- Comprehensive 12-phase implementation plan finalized
- Architecture decisions documented and validated
- Two-MCP-server approach confirmed (Gitea + Wiki.js)
- Python selected for MCP server implementation
- Hybrid configuration strategy defined (system + project level)
- Wiki.js structure planned at `/hyper-hive-labs`
- Repository structure designed with shared MCP servers
- `claude-plugin-developer` skill added to project
### Key Architectural Decisions Made
1. **Shared MCP Servers**: Both plugins use the same MCP codebase at `mcp-servers/`
2. **Mode Detection**: MCP servers detect project vs company-wide mode via environment variables
3. **Python Implementation**: MCP servers written in Python (not Node.js) for better configuration handling
4. **Wiki.js Integration**: Lessons learned and documentation moved to Wiki.js for better collaboration
5. **Hybrid Config**: System-level credentials + project-level paths for flexibility
### Next Steps
- Begin Phase 1.1a: Gitea MCP Server implementation
- Set up Python virtual environments
- Create configuration loaders
- Implement core Gitea tools (issues, labels)
- Write integration tests

File diff suppressed because it is too large Load Diff

View File

@@ -1,636 +0,0 @@
# ProjMan Plugin: Analysis & Design
## Executive Summary
Leo has built a sophisticated, working project management system over 15 sprints using:
- **Skills** for behavioral guidance
- **Python scripts** for Gitea API interaction
- **CLAUDE.md** for branch-aware permission control
**Goal:** Transform this proven system into a reusable, distributable plugin called `projman`.
## Current System Analysis
### What's Working Well
**1. Three-Chat Architecture**
- **Chat 0** (Claude Web): Planning & architecture → generates sprint documents
- **Chat 1** (Claude Code): Orchestration → manages branches, generates prompts, tracks progress
- **Chat 2+** (Claude Code): Execution → implements features according to prompts
**2. Branch-Aware Security**
```
development → Full access
feat/* → Full access
staging → Read-only code, can modify .env, creates issues
main → Read-only code, emergency .env only, creates issues
```
**3. Gitea Integration**
- Two Python scripts: `create_gitea_issue.py` and `list_gitea_issues.py`
- Proper API authentication via environment variables
- Structured issue creation with labels, priority, affected files
**4. Skills System**
- `sprint-workflow.md` - Planning phase (Chat 0)
- `sprint-orchestrator.md` - Coordination phase (Chat 1)
- `sprint-executor.md` - Implementation phase (Chat 2+)
- `post-task-doc-sync.md` - Documentation updates
- `incident-reporter.md` - Issue creation from staging/prod
### What Feels Messy
Leo identified these friction points:
**1. Skills vs Agents Confusion**
> "I don't think skill would be the best way of handling an Agent"
Current state: Using skills to guide behavior that should be agent personalities
**2. Manual Script Invocation**
Scripts exist but require manual execution:
```bash
python ops/scripts/create_gitea_issue.py --title "..." --problem "..." ...
python ops/scripts/list_gitea_issues.py
```
**3. Mode Detection Redundancy**
Branch detection logic is duplicated across:
- CLAUDE.md
- Each skill file
- Manual checks in workflows
**4. Context Switching Overhead**
User must manually:
- Switch between chats
- Remember which skill to load where
- Copy/paste completion reports between chats
## Plugin Architecture Design
### Core Insight: The 3-Agent Model
Transform the three chats into three distinct agents:
```
projman/
├── agents/
│ ├── planner.md # Chat 0 → Planning Agent
│ ├── orchestrator.md # Chat 1 → PM Agent
│ └── executor.md # Chat 2+ → Implementation Agent
```
### Component Breakdown
#### 1. MCP Server: `gitea-mcp`
**Purpose:** Provide Gitea API access as tools that agents can use
**Tools to expose:**
```typescript
{
"list_issues": {
state: "open" | "closed" | "all",
labels: string[],
assignee: string
},
"create_issue": {
title: string,
body: string,
labels: string[],
assignee: string,
priority: "critical" | "high" | "medium" | "low"
},
"update_issue": {
number: number,
state: "open" | "closed",
body: string,
labels: string[]
},
"get_issue": {
number: number
},
"add_comment": {
number: number,
body: string
},
"get_labels": {
// Fetches all org + repo labels with metadata
include_org: boolean,
include_repo: boolean
},
"suggest_labels": {
// Analyzes context and suggests appropriate labels
issue_body: string,
context: {
branch: string,
files_changed: string[],
is_bug: boolean,
components: string[]
}
}
}
```
**Configuration:** `.mcp.json`
```json
{
"mcpServers": {
"gitea": {
"command": "node",
"args": ["mcp-server/gitea-server.js"],
"env": {
"GITEA_URL": "${GITEA_URL}",
"GITEA_OWNER": "${GITEA_OWNER}",
"GITEA_REPO": "${GITEA_REPO}",
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}"
}
}
}
}
```
#### 2. Slash Commands
**Primary commands for user interaction:**
```markdown
commands/
├── sprint-plan.md # /sprint-plan - Start planning a new sprint
├── sprint-start.md # /sprint-start - Begin sprint execution
├── sprint-status.md # /sprint-status - Check current sprint progress
├── sprint-close.md # /sprint-close - Complete sprint, capture lessons learned
├── issue-create.md # /issue-create - Quick issue creation
├── issue-list.md # /issue-list - List issues with filters
├── labels-sync.md # /labels-sync - Sync label taxonomy from Gitea
└── deploy-check.md # /deploy-check - Staging/prod environment validation
```
**Example: `/labels-sync`**
```markdown
---
name: labels-sync
description: Sync label taxonomy from Gitea and review changes
agent: planner
---
You are updating the plugin's label reference from Gitea.
**Workflow:**
1. Fetch current labels from Gitea (org + repo)
2. Compare with local reference (skills/label-taxonomy/labels-reference.md)
3. Show user a diff of changes:
- New labels added
- Labels removed
- Description/color changes
4. Discuss impact: "The new Type/Refactor label means we should update suggestion logic for architectural changes"
5. After approval, update local reference
6. Update label suggestion rules if needed
This ensures the plugin stays in sync with your evolving label system.
```
#### 3. Agents
**Agent: `planner.md`**
```markdown
---
name: planner
description: Architecture analysis and sprint planning expert
---
You are the Planning Agent for project management.
**Your Role:**
- Analyze business requirements
- Make architectural decisions
- Break work into implementation steps
- Generate sprint planning documents
- Create Gitea issues for approved plans
**Your Personality:**
- Ask clarifying questions upfront
- Think through edge cases
- Consider architectural fit
- Document risks explicitly
- Never rush to implementation
**Your Tools:**
- gitea.create_issue - Create issues after approval
- gitea.list_issues - Check for similar existing issues
**Branch Awareness:**
${BRANCH_DETECTION_LOGIC}
**Workflow:**
[... rest of sprint-workflow.md content ...]
```
**Agent: `orchestrator.md`**
```markdown
---
name: orchestrator
description: Sprint execution coordinator and progress tracker
---
You are the Orchestrator Agent for project management.
**Your Role:**
- Manage sprint execution
- Generate lean execution prompts
- Track progress and update documentation
- Handle Git operations (commit, merge, cleanup)
- Coordinate task dependencies
**Your Personality:**
- Concise and action-oriented
- Track details meticulously
- Signal next steps clearly
- Never write application code yourself
**Your Tools:**
- gitea.get_issue - Read issue details
- gitea.update_issue - Update issue status
- gitea.add_comment - Add progress notes
**Branch Awareness:**
${BRANCH_DETECTION_LOGIC}
**Workflow:**
[... rest of sprint-orchestrator.md content ...]
```
**Agent: `executor.md`**
```markdown
---
name: executor
description: Feature implementation and code execution specialist
---
You are the Executor Agent for project management.
**Your Role:**
- Implement features according to execution prompts
- Write clean, tested code
- Follow architectural decisions from planning
- Generate completion reports for orchestrator
**Your Personality:**
- Implementation-focused
- Follow specs precisely
- Test as you build
- Report blockers immediately
**Your Tools:**
- None (uses standard code tools)
**Branch Awareness:**
${BRANCH_DETECTION_LOGIC}
**Workflow:**
[... rest of sprint-executor.md content ...]
```
#### 4. Skills
Skills become **supporting knowledge** rather than primary orchestrators:
```markdown
skills/
├── gitea-api/
│ └── SKILL.md # How to use Gitea MCP server effectively
├── agile-pm/
│ └── SKILL.md # Agile/PMP best practices
└── branch-strategy/
└── SKILL.MD # Git branching workflow
```
#### 5. Hooks
Automate repetitive actions:
```json
{
"hooks": [
{
"name": "post-task-sync",
"event": "task_completed",
"action": "run_command",
"command": "update-docs",
"description": "Sync documentation after task completion"
},
{
"name": "staging-incident",
"event": "file_changed",
"filter": {
"branch": "staging",
"paths": ["src/**/*.py", "src/**/*.js"]
},
"action": "warn",
"message": "⚠️ Code changes on staging branch. Consider creating issue instead."
}
]
}
```
### Environment-Aware Behavior
**Key Design Decision:** Plugin behavior adapts to Git branch
```typescript
// Branch detection in plugin
const CURRENT_BRANCH = getCurrentBranch();
const MODE = detectMode(CURRENT_BRANCH);
// Modify agent permissions based on mode
switch (MODE) {
case 'DEVELOPMENT':
// Full access
agents.planner.allowGiteaAPI = true;
agents.orchestrator.allowFileWrite = true;
break;
case 'STAGING':
// Read-only code, can modify .env, can create issues
agents.planner.allowGiteaAPI = true;
agents.orchestrator.allowFileWrite = false;
agents.orchestrator.allowEnvWrite = true;
break;
case 'PRODUCTION':
// Emergency mode only
agents.planner.allowGiteaAPI = true; // Create incidents
agents.orchestrator.allowFileWrite = false;
agents.orchestrator.allowEnvWrite = true; // Emergency only
break;
}
```
## Migration Strategy
### Phase 1: MCP Server (Week 1)
**Goal:** Replace Python scripts with MCP server
**Tasks:**
1. Build `gitea-mcp` server in Node.js/TypeScript
2. Implement 5 core tools (list, create, update, get, comment)
3. Test with environment variables from CuisineFlow
4. Verify equivalent functionality to existing scripts
**Success Criteria:**
- MCP server can create issues identical to `create_gitea_issue.py`
- MCP server can list issues identical to `list_gitea_issues.py`
- No regression in functionality
### Phase 2: Agents (Week 2)
**Goal:** Convert skills to agents
**Tasks:**
1. Create `agents/planner.md` from `sprint-workflow.md`
2. Create `agents/orchestrator.md` from `sprint-orchestrator.md`
3. Create `agents/executor.md` from `sprint-executor.md`
4. Add agent-specific tool permissions
5. Test agent invocation via commands
**Success Criteria:**
- `/sprint-plan` invokes planner agent correctly
- `/sprint-start` invokes orchestrator agent correctly
- Agents have distinct personalities and tool access
### Phase 3: Commands (Week 2-3)
**Goal:** Create user-facing slash commands
**Tasks:**
1. Build 6 core commands (plan, start, status, issue-create, issue-list, deploy-check)
2. Connect commands to agents
3. Add branch detection to command behavior
4. Test command flow end-to-end
**Success Criteria:**
- Commands invoke correct agents
- Branch restrictions work automatically
- User workflow feels natural
### Phase 4: Hooks (Week 3)
**Goal:** Automate repetitive tasks
**Tasks:**
1. Implement post-task documentation sync
2. Add staging/production code change warnings
3. Auto-update issue status on merge
4. Test hook reliability
**Success Criteria:**
- Hooks trigger at correct moments
- No false positives
- Improve workflow efficiency
### Phase 5: Skills Refactor (Week 4)
**Goal:** Convert orchestration skills to supporting knowledge
**Tasks:**
1. Extract Gitea API patterns → `skills/gitea-api/SKILL.md`
2. Extract PM best practices → `skills/agile-pm/SKILL.md`
3. Extract Git workflows → `skills/branch-strategy/SKILL.md`
4. Remove duplication from agent prompts
**Success Criteria:**
- Skills are referenced by agents, not primary orchestrators
- Less token usage per interaction
- Knowledge is reusable across agents
### Phase 6: Local Testing (Week 4)
**Goal:** Validate entire plugin in CuisineFlow
**Tasks:**
1. Create local marketplace for testing
2. Install plugin in CuisineFlow project
3. Run through complete sprint cycle
4. Compare to current workflow
5. Fix issues and iterate
**Success Criteria:**
- Plugin performs equivalently to current system
- Workflow feels smoother, not worse
- No major regressions
### Phase 7: Distribution (Week 5)
**Goal:** Package for others to use
**Tasks:**
1. Write comprehensive README
2. Add installation instructions
3. Document configuration requirements
4. Create example `.env` template
5. Publish to plugin marketplace
**Success Criteria:**
- Someone else can install and use it
- Clear documentation
- Configuration is straightforward
## Directory Structure
```
projman/
├── .claude-plugin/
│ └── plugin.json
├── commands/
│ ├── sprint-plan.md
│ ├── sprint-start.md
│ ├── sprint-status.md
│ ├── issue-create.md
│ ├── issue-list.md
│ └── deploy-check.md
├── agents/
│ ├── planner.md
│ ├── orchestrator.md
│ └── executor.md
├── skills/
│ ├── gitea-api/
│ │ └── SKILL.md
│ ├── agile-pm/
│ │ └── SKILL.md
│ └── branch-strategy/
│ └── SKILL.md
├── hooks/
│ └── hooks.json
├── .mcp.json
├── mcp-server/
│ ├── package.json
│ ├── tsconfig.json
│ ├── gitea-server.ts
│ └── types.ts
├── README.md
├── LICENSE
└── CHANGELOG.md
```
## Key Decisions
### Decision 1: MCP vs Direct API Calls in Commands
**Choice:** Use MCP Server
**Rationale:**
- Agents can use tools naturally in conversation
- Easier to test MCP server independently
- Future-proof for adding more integrations (Asana, Linear)
- Follows Claude Code best practices
### Decision 2: Three Agents vs One Agent with Modes
**Choice:** Three Distinct Agents
**Rationale:**
- Clear separation of concerns matches Leo's three-chat workflow
- Each agent has distinct personality and tool access
- User knows exactly which agent they're talking to
- Prevents mode confusion
### Decision 3: Branch Detection in Plugin vs CLAUDE.md
**Choice:** Both
**Rationale:**
- CLAUDE.md provides base-level permissions (file access)
- Plugin agents adapt behavior based on branch (tool usage)
- Defense in depth - two layers of protection
- Plugin works with or without CLAUDE.md
### Decision 4: Skills as Orchestrators vs Knowledge
**Choice:** Skills as Supporting Knowledge
**Rationale:**
- Agents are the primary interface
- Skills reduce token usage (loaded only when relevant)
- Skills can be shared across agents
- Follows Anthropic's Agent Skills spec
## Validated Requirements from Leo
**Q1: Asana Integration**
- ✅ Build Gitea-only first, add Asana as separate MCP server later
**Q2: Agent Invocation**
- ✅ Via commands only (`/sprint-plan` → planner agent)
**Q3: Multi-Project Support**
- ✅ Two plugins needed:
- `projman`: Single-repo project management (build first)
- `projman-pmo`: Multi-project orchestration (build second)
- **Context:** Leo manages interdependent projects:
- CuisineFlow (main product)
- CuisineFlow-Site (demo sync + customer gateway)
- Intuit Engine Service (API aggregator extraction - imminent)
- HHL-Site (company presence)
- These have real deployment dependencies and require coordination
**Q4: Deployment Environment**
- ✅ Same plugin on laptop + VPS servers, branch-aware behavior handles differences
**Q5: Label System**
- ✅ Leo has sophisticated 43-label taxonomy at org level (enforced consistency)
- ✅ Include label suggestion in v1
- ✅ Plugin maintains local reference, syncs from Gitea with agent review
**Q6: Lessons Learned**
- ✅ Wiki-based implementation in v1 (NOT v2)
- **Critical pain point:** 15 sprints with no lesson capture causing repeated mistakes
- **Real example:** Claude Code infinite loops on same issues 2-3 times
- Must capture at sprint close, reference at sprint start
## Success Metrics
**Technical:**
- ✅ MCP server passes all integration tests
- ✅ Agents invoke correctly via commands
- ✅ Branch detection works 100% reliably
- ✅ No token usage increase vs current system
**User Experience:**
- ✅ Leo completes sprint cycle faster than before
- ✅ Less context switching between chats
- ✅ Fewer manual script invocations
- ✅ Clearer agent personalities
**Distribution:**
- ✅ Another PM can install and use it
- ✅ Documentation is clear enough
- ✅ Configuration takes <10 minutes
## Next Steps
**Immediate (Today):**
1. Leo reviews this analysis
2. Answer open questions (Q1-Q4)
3. Decide: build MCP server first or start with agents?
**Short-term (This Week):**
1. Begin Phase 1 (MCP server) OR Phase 2 (agents)
2. Set up local marketplace for testing
3. Create `plugin.json` manifest
**Medium-term (Next 2 Weeks):**
1. Complete Phases 1-4 (MCP, agents, commands, hooks)
2. Test in real CuisineFlow sprint
3. Iterate based on friction points
## Anti-Over-Engineering Checklist
Before building anything, verify:
- [ ] Have we done this manually 3+ times? ✅ (15 sprints)
- [ ] Is current system actually broken? ✅ (messy, but Leo identified pain points)
- [ ] Will plugin reduce friction? ✅ (fewer manual steps, clearer roles)
- [ ] Can we build incrementally? ✅ (7-phase plan)
- [ ] Is scope contained? ✅ (Gitea only, not all possible features)
**Verdict:** This plugin is justified. Proceed with confidence.

View File

@@ -0,0 +1,325 @@
# DEFINITIVE ARCHITECTURE - FINAL CORRECT VERSION
## ⚠️ THIS IS THE ONLY CORRECT STRUCTURE ⚠️
If you see ANY other structure in ANY other document, **THIS ONE IS CORRECT**.
---
## Repository Structure (FINAL)
```
your-gitea/hyperhivelabs/claude-plugins/
├── .claude-plugin/
│ └── marketplace.json
├── mcp-servers/ # ← SHARED BY BOTH PLUGINS
│ ├── gitea/
│ │ ├── .venv/
│ │ ├── requirements.txt
│ │ ├── mcp_server/
│ │ │ ├── __init__.py
│ │ │ ├── server.py
│ │ │ ├── config.py
│ │ │ ├── gitea_client.py
│ │ │ └── tools/
│ │ │ ├── __init__.py
│ │ │ ├── issues.py
│ │ │ └── labels.py
│ │ └── tests/
│ │ ├── test_config.py
│ │ ├── test_gitea_client.py
│ │ └── test_tools.py
│ └── wikijs/
│ ├── .venv/
│ ├── requirements.txt
│ ├── mcp_server/
│ │ ├── __init__.py
│ │ ├── server.py
│ │ ├── config.py
│ │ ├── wikijs_client.py
│ │ └── tools/
│ │ ├── __init__.py
│ │ ├── pages.py
│ │ ├── lessons_learned.py
│ │ └── documentation.py
│ └── tests/
│ ├── test_config.py
│ ├── test_wikijs_client.py
│ └── test_tools.py
├── projman/ # ← PROJECT PLUGIN
│ ├── .claude-plugin/
│ │ └── plugin.json
│ ├── .mcp.json # Points to ../mcp-servers/
│ ├── commands/
│ │ ├── sprint-plan.md
│ │ ├── sprint-start.md
│ │ ├── sprint-status.md
│ │ ├── sprint-close.md
│ │ └── labels-sync.md
│ ├── agents/
│ │ ├── planner.md
│ │ ├── orchestrator.md
│ │ └── executor.md
│ ├── skills/
│ │ └── label-taxonomy/
│ │ └── labels-reference.md
│ ├── README.md
│ └── CONFIGURATION.md
└── projman-pmo/ # ← PMO PLUGIN
├── .claude-plugin/
│ └── plugin.json
├── .mcp.json # Points to ../mcp-servers/
├── commands/
│ ├── pmo-status.md
│ ├── pmo-priorities.md
│ ├── pmo-dependencies.md
│ └── pmo-schedule.md
├── agents/
│ └── pmo-coordinator.md
└── README.md
```
---
## Key Points
### 1. MCP Servers Are SHARED
- Location: `mcp-servers/` at repository root
- NOT inside `projman/` or `projman-pmo/`
- Built ONCE, used by BOTH plugins
### 2. Plugins Reference MCP Servers
- Both plugins use `.mcp.json` to point to `../mcp-servers/`
- No MCP code inside plugin directories
- Only commands, agents, and skills in plugin directories
### 3. Mode Detection
- MCP servers detect mode based on environment variables
- Project mode: When `GITEA_REPO` and `WIKIJS_PROJECT` present
- Company mode: When those variables absent (PMO)
---
## Configuration Files
### projman/.mcp.json
```json
{
"mcpServers": {
"gitea-projman": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"GITEA_API_URL": "${GITEA_API_URL}",
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
"GITEA_OWNER": "${GITEA_OWNER}",
"GITEA_REPO": "${GITEA_REPO}"
}
},
"wikijs-projman": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}",
"WIKIJS_PROJECT": "${WIKIJS_PROJECT}"
}
}
}
}
```
### projman-pmo/.mcp.json
```json
{
"mcpServers": {
"gitea-pmo": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"GITEA_API_URL": "${GITEA_API_URL}",
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
"GITEA_OWNER": "${GITEA_OWNER}"
}
},
"wikijs-pmo": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}"
}
}
}
}
```
**Critical:** Both plugins point to `../mcp-servers/` using relative paths.
---
## Setup Instructions
### 1. System Configuration
```bash
# Create config directory
mkdir -p ~/.config/claude
# Gitea config
cat > ~/.config/claude/gitea.env << EOF
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
GITEA_API_TOKEN=your_token
GITEA_OWNER=hyperhivelabs
EOF
# Wiki.js config
cat > ~/.config/claude/wikijs.env << EOF
WIKIJS_API_URL=https://wiki.hyperhivelabs.com/graphql
WIKIJS_API_TOKEN=your_token
WIKIJS_BASE_PATH=/hyper-hive-labs
EOF
# Secure files
chmod 600 ~/.config/claude/*.env
```
### 2. Project Configuration
```bash
# In each project root
cat > .env << EOF
GITEA_REPO=cuisineflow
WIKIJS_PROJECT=projects/cuisineflow
EOF
# Add to .gitignore
echo ".env" >> .gitignore
```
### 3. Install MCP Servers (ONE TIME)
```bash
# Gitea MCP Server
cd /path/to/claude-plugins/mcp-servers/gitea
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Wiki.js MCP Server
cd /path/to/claude-plugins/mcp-servers/wikijs
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
---
## What Makes This Work
### Mode Detection in config.py
```python
# mcp-servers/gitea/mcp_server/config.py
def load(self):
# ... load configs ...
self.repo = os.getenv('GITEA_REPO') # Optional
if self.repo:
self.mode = 'project'
logger.info(f"Running in project mode: {self.repo}")
else:
self.mode = 'company'
logger.info("Running in company-wide mode (PMO)")
return {
'api_url': self.api_url,
'api_token': self.api_token,
'owner': self.owner,
'repo': self.repo,
'mode': self.mode
}
```
### Same MCP Code, Different Behavior
The SAME MCP server code runs differently based on environment variables:
**When projman calls it:**
- Has `GITEA_REPO` → operates on single repository
- Has `WIKIJS_PROJECT` → operates on single project path
**When projman-pmo calls it:**
- No `GITEA_REPO` → operates on all repositories
- No `WIKIJS_PROJECT` → operates on entire company namespace
---
## Visual Path Flow
### projman Plugin Flow
```
projman/.mcp.json
↓ (cwd: ../mcp-servers/gitea)
mcp-servers/gitea/mcp_server/server.py
↓ (loads config)
mcp-servers/gitea/mcp_server/config.py
↓ (detects GITEA_REPO present)
→ PROJECT MODE
```
### projman-pmo Plugin Flow
```
projman-pmo/.mcp.json
↓ (cwd: ../mcp-servers/gitea)
mcp-servers/gitea/mcp_server/server.py
↓ (loads config)
mcp-servers/gitea/mcp_server/config.py
↓ (detects NO GITEA_REPO)
→ COMPANY MODE
```
---
## File Paths Quick Reference
### Gitea MCP Server Files
- Config loader: `mcp-servers/gitea/mcp_server/config.py`
- API client: `mcp-servers/gitea/mcp_server/gitea_client.py`
- Server entry: `mcp-servers/gitea/mcp_server/server.py`
- Issue tools: `mcp-servers/gitea/mcp_server/tools/issues.py`
- Label tools: `mcp-servers/gitea/mcp_server/tools/labels.py`
### Wiki.js MCP Server Files
- Config loader: `mcp-servers/wikijs/mcp_server/config.py`
- API client: `mcp-servers/wikijs/mcp_server/wikijs_client.py`
- Server entry: `mcp-servers/wikijs/mcp_server/server.py`
- Page tools: `mcp-servers/wikijs/mcp_server/tools/pages.py`
- Lessons tools: `mcp-servers/wikijs/mcp_server/tools/lessons_learned.py`
### Plugin Files
- projman config: `projman/.mcp.json`
- projman-pmo config: `projman-pmo/.mcp.json`
---
## This Is The Truth
**If ANY other document shows MCP servers inside plugin directories, that document is WRONG.**
**THIS document shows the CORRECT, FINAL architecture.**
Use this as your reference. Period.

View File

@@ -0,0 +1,241 @@
# ProjMan Implementation - Document Index
All documentation for building the projman and projman-pmo plugins.
---
## ⚠️ START HERE - CORRECT ARCHITECTURE
### [CORRECT-ARCHITECTURE.md](./CORRECT-ARCHITECTURE.md)
**⚠️ THIS IS THE DEFINITIVE REFERENCE ⚠️**
**Use when:** You need to verify the correct repository structure
**Contains:**
- THE ONLY CORRECT repository structure
- MCP servers are SHARED at root level (`mcp-servers/` directory)
- Configuration file examples
- Setup instructions
- Path references
- Mode detection implementation
**If any other document conflicts with this, THIS ONE IS CORRECT.**
---
## 📚 Core Implementation Documents
### [projman-implementation-plan-updated.md](./projman-implementation-plan-updated.md)
**Purpose:** Complete, detailed implementation plan
**Use when:** Actually building the plugins (your main reference)
**Contains:**
- 12 detailed implementation phases
- Configuration architecture
- Complete code examples
- Success criteria per phase
- Testing strategies
- No timelines - work at your pace
- **Length:** Comprehensive (2000+ lines)
---
## 🐍 Python-Specific Guides
### [projman-python-quickstart.md](./projman-python-quickstart.md)
**Purpose:** Python-specific implementation guide
**Use when:** Setting up Python environment, writing code
**Contains:**
- Python project structure
- Virtual environment setup
- Requirements.txt examples
- Configuration loader code
- Modular code patterns
- Testing with pytest
- Debugging tips
---
## 🏗️ Architecture Documentation
### [two-mcp-architecture-guide.md](./two-mcp-architecture-guide.md)
**Purpose:** Deep dive into two-MCP-server architecture
**Use when:** Understanding the MCP server design
**Contains:**
- Wiki.js structure at `/hyper-hive-labs`
- Complete Gitea MCP server code
- Complete Wiki.js MCP server code (GraphQL)
- Configuration examples
- Mode detection implementation
- Setup instructions
- Migration guidance
---
## 🎯 How to Use These Documents
### Phase 1: Planning & Setup
1. Read **CORRECT-ARCHITECTURE.md** to understand the definitive repository structure
2. Review **projman-implementation-plan-updated.md** Phase 1 for setup overview
3. Set up your Gitea and Wiki.js instances
4. Create system-level configuration files
### Phase 2: Starting Implementation
1. Open **projman-implementation-plan-updated.md** (your main reference for all 12 phases)
2. Start with Phase 1.1a (Gitea MCP Server)
3. Reference **projman-python-quickstart.md** for Python patterns and virtual environment setup
4. Reference **two-mcp-architecture-guide.md** for detailed MCP server code examples
### Phase 3: During Development
1. **Main reference:** projman-implementation-plan-updated.md (follow phase by phase)
2. **Structure reference:** CORRECT-ARCHITECTURE.md (when in doubt about paths)
3. **Code patterns:** projman-python-quickstart.md
4. **Architecture deep dive:** two-mcp-architecture-guide.md
### Phase 4: Troubleshooting
1. Check **CORRECT-ARCHITECTURE.md** for definitive path references
2. Review configuration examples in **two-mcp-architecture-guide.md**
3. Check Python-specific debugging in **projman-python-quickstart.md**
4. Verify setup instructions in **projman-implementation-plan-updated.md** Phase 1.3
---
## 📖 Document Relationships
```
CORRECT-ARCHITECTURE.md (definitive structure)
↓ (referenced by)
├── projman-implementation-plan-updated.md (main implementation guide)
│ ↓ (uses Python patterns from)
│ ├── projman-python-quickstart.md
│ ↓ (references architecture from)
│ └── two-mcp-architecture-guide.md
└── DOCUMENT-INDEX.md (this file - navigation)
```
---
## 🎨 Quick Reference by Topic
### Repository Structure
- **Definitive reference:** CORRECT-ARCHITECTURE.md (lines 9-80)
- **Key point:** MCP servers are SHARED at `mcp-servers/` directory (not inside plugins)
### Configuration
- **Setup instructions:** CORRECT-ARCHITECTURE.md (lines 172-229)
- **Implementation details:** projman-implementation-plan-updated.md (Phase 1.3)
- **Python code examples:** projman-python-quickstart.md (lines 140-214)
- **Config loader:** two-mcp-architecture-guide.md (lines 281-358)
### MCP Servers
- **Architecture overview:** CORRECT-ARCHITECTURE.md (Key Points section)
- **Gitea MCP:** projman-implementation-plan-updated.md (Phase 1.1a)
- **Wiki.js MCP:** projman-implementation-plan-updated.md (Phase 1.1b)
- **Complete implementation:** two-mcp-architecture-guide.md (lines 277-680)
### Wiki.js Structure
- **Full structure:** two-mcp-architecture-guide.md (lines 13-70)
- **Path resolution:** projman-implementation-plan-updated.md (lines 110-115)
- **Integration:** projman-implementation-plan-updated.md (Phase 4.1)
### Python Patterns
- **Setup & dependencies:** projman-python-quickstart.md (lines 15-111)
- **Modular code structure:** projman-python-quickstart.md (lines 511-575)
- **Virtual environment:** projman-python-quickstart.md (lines 579-616)
### Sprint Workflow
- **Commands:** projman-implementation-plan-updated.md (Phase 2)
- **Agents:** projman-implementation-plan-updated.md (Phase 3)
- **Lessons Learned:** projman-implementation-plan-updated.md (Phase 4)
### PMO Plugin
- **Requirements:** projman-implementation-plan-updated.md (Phase 9)
- **Implementation:** projman-implementation-plan-updated.md (Phase 10-11)
- **Multi-project methods:** two-mcp-architecture-guide.md (lines 639-679)
---
## 🚀 Suggested Reading Order
### First Time (Understanding the Project)
1. **CORRECT-ARCHITECTURE.md** (15 minutes)
- Understand the definitive repository structure
- See MCP server placement (shared at root)
- Review configuration approach
2. **projman-python-quickstart.md** (30 minutes)
- Understand Python setup
- See code patterns
- Virtual environment setup
3. **projman-implementation-plan-updated.md** (2-3 hours)
- Read Phase 1 in detail
- Skim Phases 2-12 to understand the flow
- This is your main implementation guide
4. **two-mcp-architecture-guide.md** (1 hour)
- Deep dive into MCP server architecture
- Complete code examples
- Wiki.js structure and integration
### During Implementation
- Keep **projman-implementation-plan-updated.md** open (your main reference)
- Reference **CORRECT-ARCHITECTURE.md** when unsure about paths
- Use **projman-python-quickstart.md** for Python-specific code
- Use **two-mcp-architecture-guide.md** for detailed MCP implementation
### When You Need Quick Answers
- **"What's the correct repository structure?"** → CORRECT-ARCHITECTURE.md
- **"How do I set up Python?"** → projman-python-quickstart.md
- **"How does configuration work?"** → CORRECT-ARCHITECTURE.md or two-mcp-architecture-guide.md
- **"What's the full MCP server code?"** → two-mcp-architecture-guide.md
- **"What do I build in Phase X?"** → projman-implementation-plan-updated.md
---
## 📊 Document Statistics
| Document | Lines | Focus | Primary Use |
|----------|-------|-------|-------------|
| CORRECT-ARCHITECTURE.md | 325 | Definitive Structure | Reference (paths, config) |
| projman-implementation-plan-updated.md | 2081 | Complete Implementation | Main guide (building) |
| projman-python-quickstart.md | 727 | Python Patterns | Code patterns & setup |
| two-mcp-architecture-guide.md | 941 | Architecture Deep Dive | MCP implementation |
**Total:** ~4,074 lines of comprehensive documentation
---
## ✅ Pre-Implementation Checklist
Before starting Phase 1, verify you have:
- [ ] Read CORRECT-ARCHITECTURE.md (understand structure)
- [ ] Understand the two-MCP-server architecture (Gitea + Wiki.js)
- [ ] Understand shared MCP codebase at `mcp-servers/` (not in plugin dirs)
- [ ] Understand Wiki.js structure at `/hyper-hive-labs`
- [ ] Understand hybrid configuration (system + project levels)
- [ ] Python 3.11+ installed
- [ ] Access to Gitea instance
- [ ] Access to Wiki.js instance
- [ ] API tokens for both services
---
## 🎯 Key Architectural Decisions
These are the final decisions documented across all files:
1. **Two MCP Servers** - Separate Gitea and Wiki.js servers for better maintainability
2. **Shared MCP Codebase** - Located at `mcp-servers/` (root level), used by both plugins
3. **Python Implementation** - MCP servers written in Python 3.11+
4. **Hybrid Configuration** - System-level tokens + project-level paths
5. **Wiki.js for Lessons** - Superior to Git-based Wiki for documentation and search
6. **Mode Detection** - MCP servers detect project vs company-wide mode via environment variables
7. **Build Order** - projman first (Phases 1-8), then projman-pmo (Phases 9-12)
---
## 🎉 You're Ready!
You have everything you need to build the projman and projman-pmo plugins. All architectural decisions are finalized and documented.
**Start here:** [projman-implementation-plan-updated.md](./projman-implementation-plan-updated.md) - Phase 1.1a
Good luck with the build!

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,729 @@
# ProjMan Plugins - Python Quick Start
This guide provides Python-specific setup and development information for the projman and projman-pmo plugins.
> **⚠️ IMPORTANT:** For the definitive repository structure, refer to [CORRECT-ARCHITECTURE.md](./CORRECT-ARCHITECTURE.md). This guide shows Python-specific patterns and setup.
---
## Technology Stack
- **MCP Server:** Python 3.11+
- **Commands:** Markdown files
- **Agents:** Markdown files
- **Dependencies:** pip with requirements.txt
- **Virtual Environment:** .venv (per plugin)
---
## Initial Setup
### 1. System Requirements
```bash
# Python 3.11 or higher
python --version
# pip (latest)
pip --version
# git
git --version
```
### 2. System-Level Configuration
```bash
# Create config directory
mkdir -p ~/.config/claude
# Create gitea.env with your credentials
cat > ~/.config/claude/gitea.env << EOF
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
GITEA_API_TOKEN=your_token_here
GITEA_OWNER=hyperhivelabs
EOF
# Secure the file
chmod 600 ~/.config/claude/gitea.env
```
### 3. Project-Level Configuration
```bash
# In each repository root
echo "GITEA_REPO=cuisineflow" > .env
# Add to .gitignore
echo ".env" >> .gitignore
```
---
## MCP Server Structure
```
hyperhivelabs/claude-plugins/
├── mcp-servers/ # SHARED by both plugins
│ ├── gitea/
│ │ ├── .venv/
│ │ ├── requirements.txt
│ │ ├── mcp_server/
│ │ │ ├── __init__.py
│ │ │ ├── server.py
│ │ │ ├── config.py
│ │ │ ├── gitea_client.py
│ │ │ └── tools/
│ │ └── tests/
│ └── wikijs/
│ ├── .venv/
│ ├── requirements.txt
│ ├── mcp_server/
│ │ ├── __init__.py
│ │ ├── server.py
│ │ ├── config.py
│ │ └── wikijs_client.py
│ └── tests/
├── projman/
│ ├── .mcp.json # Points to ../mcp-servers/
│ ├── commands/
│ └── agents/
└── projman-pmo/
├── .mcp.json # Points to ../mcp-servers/
└── commands/
```
---
## Dependencies (requirements.txt)
```txt
# anthropic-sdk==0.18.0 # MCP SDK
anthropic-sdk>=0.18.0
# python-dotenv==1.0.0 # Environment variable loading
python-dotenv>=1.0.0
# requests==2.31.0 # HTTP client for Gitea API
requests>=2.31.0
# pydantic==2.5.0 # Data validation
pydantic>=2.5.0
# pytest==7.4.3 # Testing framework
pytest>=7.4.3
# pytest-asyncio==0.23.0 # Async testing support
pytest-asyncio>=0.23.0
```
**Note:** Following your coding preferences, library versions are specified with comments showing the exact version being used.
---
## Development Workflow
### Initial MCP Server Setup
```bash
# Navigate to MCP servers directory
cd /path/to/claude-plugins/mcp-servers/gitea
# Create virtual environment
python -m venv .venv
# Activate virtual environment
source .venv/bin/activate # Linux/Mac
# or
.venv\Scripts\activate # Windows
# Install dependencies
pip install -r requirements.txt
# Verify installation
python -c "import anthropic; print('SDK installed')"
```
### Configuration Loader (config.py)
```python
# mcp-servers/gitea/mcp_server/config.py
from pathlib import Path
from dotenv import load_dotenv
import os
from typing import Dict, Optional
class Config:
"""Hybrid configuration loader for projman plugins"""
def __init__(self):
self.api_url: Optional[str] = None
self.api_token: Optional[str] = None
self.owner: Optional[str] = None
self.repo: Optional[str] = None
def load(self) -> Dict[str, str]:
"""
Load configuration from system and project levels.
Project-level configuration overrides system-level.
"""
# Load system config
system_config = Path.home() / '.config' / 'claude' / 'gitea.env'
if system_config.exists():
load_dotenv(system_config)
else:
raise FileNotFoundError(
f"System config not found: {system_config}\n"
"Create it with: mkdir -p ~/.config/claude && "
"cat > ~/.config/claude/gitea.env"
)
# Load project config (overrides system)
project_config = Path.cwd() / '.env'
if project_config.exists():
load_dotenv(project_config, override=True)
# Extract values
self.api_url = os.getenv('GITEA_API_URL')
self.api_token = os.getenv('GITEA_API_TOKEN')
self.owner = os.getenv('GITEA_OWNER')
self.repo = os.getenv('GITEA_REPO') # Optional for PMO
# Validate required variables
self._validate()
return {
'api_url': self.api_url,
'api_token': self.api_token,
'owner': self.owner,
'repo': self.repo
}
def _validate(self) -> None:
"""Validate that required configuration is present"""
required = {
'GITEA_API_URL': self.api_url,
'GITEA_API_TOKEN': self.api_token,
'GITEA_OWNER': self.owner
}
missing = [key for key, value in required.items() if not value]
if missing:
raise ValueError(
f"Missing required configuration: {', '.join(missing)}\n"
"Check your ~/.config/claude/gitea.env file"
)
# Usage
config = Config()
config_dict = config.load()
```
### Gitea API Client (gitea_client.py)
```python
# mcp-servers/gitea/mcp_server/gitea_client.py
import requests
from typing import List, Dict, Optional
from .config import Config
class GiteaClient:
"""Client for interacting with Gitea API"""
def __init__(self):
config = Config()
config_dict = config.load()
self.base_url = config_dict['api_url']
self.token = config_dict['api_token']
self.owner = config_dict['owner']
self.repo = config_dict.get('repo') # Optional
self.session = requests.Session()
self.session.headers.update({
'Authorization': f'token {self.token}',
'Content-Type': 'application/json'
})
def list_issues(
self,
state: str = 'open',
labels: Optional[List[str]] = None,
repo: Optional[str] = None
) -> List[Dict]:
"""
List issues from Gitea repository.
Args:
state: Issue state (open, closed, all)
labels: Filter by labels
repo: Override configured repo (for PMO multi-repo)
"""
target_repo = repo or self.repo
if not target_repo:
raise ValueError("Repository not specified")
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues"
params = {'state': state}
if labels:
params['labels'] = ','.join(labels)
response = self.session.get(url, params=params)
response.raise_for_status()
return response.json()
def create_issue(
self,
title: str,
body: str,
labels: Optional[List[str]] = None,
repo: Optional[str] = None
) -> Dict:
"""Create a new issue in Gitea"""
target_repo = repo or self.repo
if not target_repo:
raise ValueError("Repository not specified")
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/issues"
data = {
'title': title,
'body': body
}
if labels:
data['labels'] = labels
response = self.session.post(url, json=data)
response.raise_for_status()
return response.json()
def get_labels(
self,
repo: Optional[str] = None
) -> List[Dict]:
"""Get all labels from repository"""
target_repo = repo or self.repo
if not target_repo:
raise ValueError("Repository not specified")
url = f"{self.base_url}/repos/{self.owner}/{target_repo}/labels"
response = self.session.get(url)
response.raise_for_status()
return response.json()
```
### MCP Server Entry Point (server.py)
```python
# mcp-servers/gitea/mcp_server/server.py
from anthropic import Anthropic
from .gitea_client import GiteaClient
from .tools import IssueTools, LabelTools, WikiTools
class ProjManMCPServer:
"""Main MCP server for projman plugin"""
def __init__(self):
self.gitea = GiteaClient()
self.issue_tools = IssueTools(self.gitea)
self.label_tools = LabelTools(self.gitea)
self.wiki_tools = WikiTools(self.gitea)
def register_tools(self):
"""Register all available MCP tools"""
return [
# Issue tools
self.issue_tools.list_issues,
self.issue_tools.get_issue,
self.issue_tools.create_issue,
self.issue_tools.update_issue,
self.issue_tools.add_comment,
# Label tools
self.label_tools.get_labels,
self.label_tools.suggest_labels,
# Wiki tools
self.wiki_tools.search_wiki,
self.wiki_tools.get_wiki_page,
self.wiki_tools.create_wiki_page
]
if __name__ == '__main__':
server = ProjManMCPServer()
# MCP server startup logic here
```
---
## Testing
### Unit Tests
```python
# tests/test_config.py
import pytest
from pathlib import Path
from mcp_server.config import Config
def test_load_system_config(tmp_path):
"""Test loading system-level configuration"""
# Create mock system config
config_dir = tmp_path / '.config' / 'claude'
config_dir.mkdir(parents=True)
config_file = config_dir / 'gitea.env'
config_file.write_text(
"GITEA_API_URL=https://test.com/api/v1\n"
"GITEA_API_TOKEN=test_token\n"
"GITEA_OWNER=test_owner\n"
)
# Test config loading
config = Config()
# ... test assertions
def test_project_config_override(tmp_path):
"""Test that project config overrides system config"""
# ... test implementation
def test_missing_required_config():
"""Test error handling for missing configuration"""
with pytest.raises(ValueError):
config = Config()
config.load()
```
### Integration Tests
```python
# tests/test_gitea_client.py
import pytest
from mcp_server.gitea_client import GiteaClient
@pytest.fixture
def gitea_client():
"""Fixture providing configured Gitea client"""
return GiteaClient()
def test_list_issues(gitea_client):
"""Test listing issues from Gitea"""
issues = gitea_client.list_issues(state='open')
assert isinstance(issues, list)
def test_create_issue(gitea_client):
"""Test creating an issue in Gitea"""
issue = gitea_client.create_issue(
title="Test Issue",
body="Test body",
labels=["Type/Bug"]
)
assert issue['title'] == "Test Issue"
assert "Type/Bug" in [label['name'] for label in issue['labels']]
```
### Running Tests
```bash
# Activate virtual environment
source .venv/bin/activate
# Run all tests
pytest
# Run with coverage
pytest --cov=mcp_server --cov-report=html
# Run specific test file
pytest tests/test_config.py
# Run with verbose output
pytest -v
```
---
## .mcp.json Configuration
### projman (Repository-Specific)
```json
{
"mcpServers": {
"gitea-projman": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"GITEA_API_URL": "${GITEA_API_URL}",
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
"GITEA_OWNER": "${GITEA_OWNER}",
"GITEA_REPO": "${GITEA_REPO}"
}
},
"wikijs-projman": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}",
"WIKIJS_PROJECT": "${WIKIJS_PROJECT}"
}
}
}
}
```
### projman-pmo (Multi-Project)
```json
{
"mcpServers": {
"gitea-pmo": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"GITEA_API_URL": "${GITEA_API_URL}",
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
"GITEA_OWNER": "${GITEA_OWNER}"
}
},
"wikijs-pmo": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}"
}
}
}
}
```
**Note:** Both plugins reference `../mcp-servers/` (shared location). PMO doesn't use `GITEA_REPO` since it operates across all repositories.
---
## Modular Code Structure (Following Your Preferences)
### Single Responsibility Functions
```python
def validate_configuration(config: Dict[str, str]) -> None:
"""
Validate that all required configuration values are present.
Raises ValueError if any required values are missing.
"""
required_keys = ['api_url', 'api_token', 'owner']
missing = [key for key in required_keys if not config.get(key)]
if missing:
raise ValueError(f"Missing configuration: {', '.join(missing)}")
def load_system_config() -> Dict[str, str]:
"""
Load configuration from system-level gitea.env file.
Returns dictionary of configuration values.
"""
config_path = Path.home() / '.config' / 'claude' / 'gitea.env'
if not config_path.exists():
raise FileNotFoundError(f"System config not found: {config_path}")
load_dotenv(config_path)
return {
'api_url': os.getenv('GITEA_API_URL'),
'api_token': os.getenv('GITEA_API_TOKEN'),
'owner': os.getenv('GITEA_OWNER')
}
def load_project_config() -> Dict[str, Optional[str]]:
"""
Load project-specific configuration from local .env file.
Returns dictionary with 'repo' key, value may be None if not configured.
"""
project_env = Path.cwd() / '.env'
if project_env.exists():
load_dotenv(project_env, override=True)
return {
'repo': os.getenv('GITEA_REPO')
}
def merge_configurations(system: Dict, project: Dict) -> Dict[str, str]:
"""
Merge system and project configurations.
Project values override system values where present.
"""
merged = system.copy()
merged.update({k: v for k, v in project.items() if v is not None})
return merged
def main():
"""Main entry point that orchestrates configuration loading"""
system_config = load_system_config()
project_config = load_project_config()
final_config = merge_configurations(system_config, project_config)
validate_configuration(final_config)
return final_config
```
---
## Virtual Environment Management
### Creation
```bash
# In plugin mcp-server directory
python -m venv .venv
```
### Activation
```bash
# Linux/Mac
source .venv/bin/activate
# Windows
.venv\Scripts\activate
```
### Deactivation
```bash
deactivate
```
### Cleanup & Rebuild
```bash
# Remove old virtual environment
rm -rf .venv
# Create fresh virtual environment
python -m venv .venv
# Activate and reinstall
source .venv/bin/activate
pip install -r requirements.txt
```
---
## Debugging
### Enable Debug Logging
```python
# Add to server.py
import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
```
### Common Issues
**Issue:** Module not found
```bash
# Solution: Ensure PYTHONPATH is set in .mcp.json
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/mcp-server"
}
```
**Issue:** Configuration not loading
```bash
# Solution: Check file permissions
chmod 600 ~/.config/claude/gitea.env
# Verify file exists
cat ~/.config/claude/gitea.env
```
**Issue:** API authentication failing
```bash
# Solution: Test token manually
curl -H "Authorization: token YOUR_TOKEN" \
https://your-gitea.com/api/v1/user
```
---
## Performance Optimization
### Caching with functools
```python
from functools import lru_cache
@lru_cache(maxsize=128)
def get_labels_cached(repo: str) -> List[Dict]:
"""Cached label retrieval to reduce API calls"""
return self.gitea.get_labels(repo)
```
### Async Operations
```python
import asyncio
import aiohttp
async def fetch_multiple_repos(repos: List[str]) -> List[Dict]:
"""Fetch data from multiple repositories concurrently"""
async with aiohttp.ClientSession() as session:
tasks = [fetch_repo_data(session, repo) for repo in repos]
return await asyncio.gather(*tasks)
```
---
## Next Steps
1. **Set up system configuration** as shown above
2. **Create project configuration** in your first repository
3. **Navigate to Phase 1.1** of the implementation plan
4. **Build the MCP server** following the structure above
5. **Write tests** as you implement each component
6. **Test with real Gitea instance** early and often
---
## Key Differences from Node.js Approach
| Aspect | Node.js | Python (Your Choice) |
|--------|---------|---------------------|
| Dependencies | package.json | requirements.txt |
| Package Manager | npm/yarn | pip |
| Isolation | node_modules | .venv |
| Module System | ES6 imports | Python imports |
| Async | async/await | async/await |
| Type Checking | TypeScript | Type hints + Pydantic |
| Testing | Jest | pytest |
---
## Resources
- **Anthropic MCP SDK (Python):** https://github.com/anthropics/anthropic-sdk-python
- **Python Requests:** https://docs.python-requests.org/
- **Pydantic:** https://docs.pydantic.dev/
- **pytest:** https://docs.pytest.org/
- **Gitea API Docs:** https://docs.gitea.com/api/
---
Ready to build! 🚀

View File

@@ -0,0 +1,944 @@
# Two MCP Server Architecture - Implementation Guide
## Overview
The projman plugin now uses **two separate MCP servers**:
1. **Gitea MCP Server** - Issues, labels, repository management
2. **Wiki.js MCP Server** - Documentation, lessons learned, knowledge base
This separation provides better maintainability, independent configuration, and leverages Wiki.js's superior documentation features.
> **⚠️ IMPORTANT:** For the definitive repository structure and configuration paths, refer to [CORRECT-ARCHITECTURE.md](./CORRECT-ARCHITECTURE.md). This guide provides detailed implementation examples and architectural deep-dive.
---
## Wiki.js Structure at Hyper Hive Labs
### Company-Wide Organization
```
Wiki.js Instance: https://wiki.hyperhivelabs.com
└── /hyper-hive-labs/ # Base path for all HHL content
├── projects/ # Project-specific documentation
│ ├── cuisineflow/
│ │ ├── lessons-learned/
│ │ │ ├── sprints/
│ │ │ │ ├── sprint-01-auth.md
│ │ │ │ ├── sprint-02-api.md
│ │ │ │ └── ...
│ │ │ ├── patterns/
│ │ │ │ ├── service-extraction.md
│ │ │ │ └── database-migration.md
│ │ │ └── INDEX.md
│ │ └── documentation/
│ │ ├── architecture/
│ │ ├── api/
│ │ └── deployment/
│ ├── cuisineflow-site/
│ │ ├── lessons-learned/
│ │ └── documentation/
│ ├── intuit-engine/
│ │ ├── lessons-learned/
│ │ └── documentation/
│ └── hhl-site/
│ ├── lessons-learned/
│ └── documentation/
├── company/ # Company-wide documentation
│ ├── processes/
│ │ ├── onboarding.md
│ │ ├── deployment.md
│ │ └── code-review.md
│ ├── standards/
│ │ ├── python-style-guide.md
│ │ ├── api-design.md
│ │ └── security.md
│ └── tools/
│ ├── gitea-guide.md
│ ├── wikijs-guide.md
│ └── claude-plugins.md
└── shared/ # Cross-project resources
├── architecture-patterns/
│ ├── microservices.md
│ ├── api-gateway.md
│ └── database-per-service.md
├── best-practices/
│ ├── error-handling.md
│ ├── logging.md
│ └── testing.md
└── tech-stack/
├── python-ecosystem.md
├── docker.md
└── ci-cd.md
```
---
## Configuration Architecture
### System-Level Configuration
**File: `~/.config/claude/gitea.env`**
```bash
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
GITEA_API_TOKEN=your_gitea_token_here
GITEA_OWNER=hyperhivelabs
```
**File: `~/.config/claude/wikijs.env`**
```bash
WIKIJS_API_URL=https://wiki.hyperhivelabs.com/graphql
WIKIJS_API_TOKEN=your_wikijs_token_here
WIKIJS_BASE_PATH=/hyper-hive-labs
```
**Why separate files?**
- Different services, different authentication
- Can update one without affecting the other
- Clear separation of concerns
- Easier to revoke/rotate tokens per service
### Project-Level Configuration
**File: `project-root/.env`**
```bash
# Gitea repository name
GITEA_REPO=cuisineflow
# Wiki.js project path (relative to /hyper-hive-labs)
WIKIJS_PROJECT=projects/cuisineflow
```
**Path Resolution:**
- Full Wiki.js path = `{WIKIJS_BASE_PATH}/{WIKIJS_PROJECT}`
- For cuisineflow: `/hyper-hive-labs/projects/cuisineflow`
- For intuit-engine: `/hyper-hive-labs/projects/intuit-engine`
### PMO Configuration (No Project Scope)
**PMO operates at company level:**
- **Gitea**: No `GITEA_REPO` → accesses all repos
- **Wiki.js**: No `WIKIJS_PROJECT` → accesses entire `/hyper-hive-labs` namespace
---
## Plugin Structure
### Repository Structure (CORRECT)
```
hyperhivelabs/claude-plugins/
├── mcp-servers/ # SHARED by both plugins
│ ├── gitea/
│ │ ├── .venv/
│ │ ├── requirements.txt
│ │ │ # anthropic-sdk>=0.18.0
│ │ │ # python-dotenv>=1.0.0
│ │ │ # requests>=2.31.0
│ │ │ # pydantic>=2.5.0
│ │ ├── .env.example
│ │ ├── mcp_server/
│ │ │ ├── __init__.py
│ │ │ ├── server.py
│ │ │ ├── config.py
│ │ │ ├── gitea_client.py
│ │ │ └── tools/
│ │ │ ├── issues.py
│ │ │ └── labels.py
│ │ └── tests/
│ │ ├── test_config.py
│ │ ├── test_gitea_client.py
│ │ └── test_tools.py
│ └── wikijs/
│ ├── .venv/
│ ├── requirements.txt
│ │ # anthropic-sdk>=0.18.0
│ │ # python-dotenv>=1.0.0
│ │ # gql>=3.4.0
│ │ # aiohttp>=3.9.0
│ │ # pydantic>=2.5.0
│ ├── .env.example
│ ├── mcp_server/
│ │ ├── __init__.py
│ │ ├── server.py
│ │ ├── config.py
│ │ ├── wikijs_client.py
│ │ └── tools/
│ │ ├── pages.py
│ │ ├── lessons_learned.py
│ │ └── documentation.py
│ └── tests/
│ ├── test_config.py
│ ├── test_wikijs_client.py
│ └── test_tools.py
├── projman/ # Project plugin
│ ├── .claude-plugin/
│ │ └── plugin.json
│ ├── .mcp.json # Points to ../mcp-servers/
│ ├── commands/
│ │ ├── sprint-plan.md
│ │ ├── sprint-start.md
│ │ ├── sprint-status.md
│ │ ├── sprint-close.md
│ │ └── labels-sync.md
│ ├── agents/
│ │ ├── planner.md
│ │ ├── orchestrator.md
│ │ └── executor.md
│ ├── skills/
│ │ └── label-taxonomy/
│ │ └── labels-reference.md
│ ├── README.md
│ └── CONFIGURATION.md
└── projman-pmo/ # PMO plugin
├── .claude-plugin/
│ └── plugin.json
├── .mcp.json # Points to ../mcp-servers/
├── commands/
│ ├── pmo-status.md
│ ├── pmo-priorities.md
│ ├── pmo-dependencies.md
│ └── pmo-schedule.md
├── agents/
│ └── pmo-coordinator.md
└── README.md
```
---
## MCP Configuration Files
### projman .mcp.json (Project-Scoped)
```json
{
"mcpServers": {
"gitea-projman": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"GITEA_API_URL": "${GITEA_API_URL}",
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
"GITEA_OWNER": "${GITEA_OWNER}",
"GITEA_REPO": "${GITEA_REPO}"
}
},
"wikijs-projman": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}",
"WIKIJS_PROJECT": "${WIKIJS_PROJECT}"
}
}
}
}
```
### projman-pmo .mcp.json (Company-Wide)
```json
{
"mcpServers": {
"gitea-pmo": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/gitea",
"GITEA_API_URL": "${GITEA_API_URL}",
"GITEA_API_TOKEN": "${GITEA_API_TOKEN}",
"GITEA_OWNER": "${GITEA_OWNER}"
}
},
"wikijs-pmo": {
"command": "python",
"args": ["-m", "mcp_server.server"],
"cwd": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/../mcp-servers/wikijs",
"WIKIJS_API_URL": "${WIKIJS_API_URL}",
"WIKIJS_API_TOKEN": "${WIKIJS_API_TOKEN}",
"WIKIJS_BASE_PATH": "${WIKIJS_BASE_PATH}"
}
}
}
}
```
**Critical Notes:**
- Both plugins reference `../mcp-servers/` (shared location at repository root)
- **projman**: Includes `GITEA_REPO` and `WIKIJS_PROJECT` for project-scoped operations
- **projman-pmo**: Omits project-specific variables for company-wide operations
---
## Wiki.js MCP Server Implementation
### Configuration Loader
```python
# mcp-wikijs/mcp_server/config.py
from pathlib import Path
from dotenv import load_dotenv
import os
from typing import Dict, Optional
class WikiJSConfig:
"""Hybrid configuration loader for Wiki.js"""
def __init__(self):
self.api_url: Optional[str] = None
self.api_token: Optional[str] = None
self.base_path: Optional[str] = None
self.project_path: Optional[str] = None
self.full_path: Optional[str] = None
def load(self) -> Dict[str, str]:
"""
Load Wiki.js configuration from system and project levels.
Composes full path from base_path + project_path.
"""
# Load system config
system_config = Path.home() / '.config' / 'claude' / 'wikijs.env'
if system_config.exists():
load_dotenv(system_config)
else:
raise FileNotFoundError(
f"System config not found: {system_config}\n"
"Create it with: cat > ~/.config/claude/wikijs.env"
)
# Load project config (if exists, optional for PMO)
project_config = Path.cwd() / '.env'
if project_config.exists():
load_dotenv(project_config, override=True)
# Extract values
self.api_url = os.getenv('WIKIJS_API_URL')
self.api_token = os.getenv('WIKIJS_API_TOKEN')
self.base_path = os.getenv('WIKIJS_BASE_PATH') # /hyper-hive-labs
self.project_path = os.getenv('WIKIJS_PROJECT') # projects/cuisineflow (optional)
# Compose full path
if self.project_path:
self.full_path = f"{self.base_path}/{self.project_path}"
else:
# PMO mode - entire company namespace
self.full_path = self.base_path
# Validate required variables
self._validate()
return {
'api_url': self.api_url,
'api_token': self.api_token,
'base_path': self.base_path,
'project_path': self.project_path,
'full_path': self.full_path
}
def _validate(self) -> None:
"""Validate that required configuration is present"""
required = {
'WIKIJS_API_URL': self.api_url,
'WIKIJS_API_TOKEN': self.api_token,
'WIKIJS_BASE_PATH': self.base_path
}
missing = [key for key, value in required.items() if not value]
if missing:
raise ValueError(
f"Missing required configuration: {', '.join(missing)}\n"
"Check your ~/.config/claude/wikijs.env file"
)
```
### GraphQL Client
```python
# mcp-wikijs/mcp_server/wikijs_client.py
from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport
from typing import List, Dict, Optional
from .config import WikiJSConfig
class WikiJSClient:
"""Client for interacting with Wiki.js GraphQL API"""
def __init__(self):
config = WikiJSConfig()
config_dict = config.load()
self.api_url = config_dict['api_url']
self.api_token = config_dict['api_token']
self.base_path = config_dict['base_path']
self.project_path = config_dict.get('project_path')
self.full_path = config_dict['full_path']
# Set up GraphQL client
transport = AIOHTTPTransport(
url=self.api_url,
headers={'Authorization': f'Bearer {self.api_token}'}
)
self.client = Client(
transport=transport,
fetch_schema_from_transport=True
)
async def search_pages(
self,
query: str,
path: Optional[str] = None,
tags: Optional[List[str]] = None
) -> List[Dict]:
"""
Search pages in Wiki.js within a specific path.
Args:
query: Search query string
path: Optional path to search within (defaults to full_path)
tags: Optional list of tags to filter by
"""
search_path = path or self.full_path
gql_query = gql("""
query SearchPages($query: String!, $path: String) {
pages {
search(query: $query, path: $path) {
results {
id
path
title
description
tags
updatedAt
}
}
}
}
""")
result = await self.client.execute(
gql_query,
variable_values={'query': query, 'path': search_path}
)
pages = result['pages']['search']['results']
# Filter by tags if specified
if tags:
pages = [
p for p in pages
if any(tag in p['tags'] for tag in tags)
]
return pages
async def get_page(self, path: str) -> Dict:
"""Fetch a specific page by path"""
gql_query = gql("""
query GetPage($path: String!) {
pages {
single(path: $path) {
id
path
title
description
content
tags
createdAt
updatedAt
}
}
}
""")
result = await self.client.execute(
gql_query,
variable_values={'path': path}
)
return result['pages']['single']
async def create_page(
self,
path: str,
title: str,
content: str,
tags: List[str],
description: str = ""
) -> Dict:
"""
Create a new page in Wiki.js.
Args:
path: Full path for the page (e.g., /hyper-hive-labs/projects/cuisineflow/lessons-learned/sprints/sprint-01)
title: Page title
content: Page content (markdown)
tags: List of tags
description: Optional description
"""
gql_mutation = gql("""
mutation CreatePage(
$path: String!,
$title: String!,
$content: String!,
$tags: [String]!,
$description: String
) {
pages {
create(
path: $path,
title: $title,
content: $content,
tags: $tags,
description: $description,
isPublished: true,
editor: "markdown"
) {
responseResult {
succeeded
errorCode
message
}
page {
id
path
title
}
}
}
}
""")
result = await self.client.execute(
gql_mutation,
variable_values={
'path': path,
'title': title,
'content': content,
'tags': tags,
'description': description
}
)
return result['pages']['create']
async def update_page(
self,
page_id: int,
content: str,
tags: Optional[List[str]] = None
) -> Dict:
"""Update existing page"""
variables = {
'id': page_id,
'content': content
}
if tags is not None:
variables['tags'] = tags
gql_mutation = gql("""
mutation UpdatePage(
$id: Int!,
$content: String!,
$tags: [String]
) {
pages {
update(
id: $id,
content: $content,
tags: $tags
) {
responseResult {
succeeded
errorCode
message
}
}
}
}
""")
result = await self.client.execute(gql_mutation, variable_values=variables)
return result['pages']['update']
async def list_pages(self, path: str) -> List[Dict]:
"""List all pages within a path"""
gql_query = gql("""
query ListPages($path: String!) {
pages {
list(path: $path, orderBy: TITLE) {
id
path
title
description
tags
updatedAt
}
}
}
""")
result = await self.client.execute(
gql_query,
variable_values={'path': path}
)
return result['pages']['list']
# Lessons Learned Specific Methods
async def create_lesson(
self,
sprint_name: str,
lesson_content: str,
tags: List[str]
) -> Dict:
"""
Create a lessons learned document for a sprint.
Args:
sprint_name: Sprint identifier (e.g., "sprint-16-intuit-engine")
lesson_content: Full lesson markdown content
tags: Tags for categorization
"""
# Compose path within project's lessons-learned/sprints/
lesson_path = f"{self.full_path}/lessons-learned/sprints/{sprint_name}"
title = f"Sprint {sprint_name.split('-')[1]}: {' '.join(sprint_name.split('-')[2:]).title()}"
return await self.create_page(
path=lesson_path,
title=title,
content=lesson_content,
tags=tags,
description=f"Lessons learned from {sprint_name}"
)
async def search_lessons(
self,
query: str,
tags: Optional[List[str]] = None
) -> List[Dict]:
"""
Search lessons learned within the current project.
Args:
query: Search keywords
tags: Optional tags to filter by
"""
lessons_path = f"{self.full_path}/lessons-learned"
return await self.search_pages(
query=query,
path=lessons_path,
tags=tags
)
# PMO Multi-Project Methods
async def search_all_projects(
self,
query: str,
tags: Optional[List[str]] = None
) -> Dict[str, List[Dict]]:
"""
Search lessons across all projects (PMO mode).
Returns results grouped by project.
"""
all_projects_path = f"{self.base_path}/projects"
results = await self.search_pages(
query=query,
path=all_projects_path,
tags=tags
)
# Group by project
by_project = {}
for result in results:
# Extract project name from path
# e.g., "/hyper-hive-labs/projects/cuisineflow/..." -> "cuisineflow"
path_parts = result['path'].split('/')
if len(path_parts) >= 4:
project = path_parts[3]
if project not in by_project:
by_project[project] = []
by_project[project].append(result)
return by_project
async def get_shared_docs(self, category: str) -> List[Dict]:
"""
Access company-wide shared documentation.
Args:
category: Category within shared/ (e.g., "architecture-patterns", "best-practices")
"""
shared_path = f"{self.base_path}/shared/{category}"
return await self.list_pages(path=shared_path)
```
---
## MCP Tools Structure
### Gitea MCP Tools
```python
# mcp-gitea/mcp_server/tools/issues.py
class IssueTools:
def __init__(self, gitea_client):
self.gitea = gitea_client
async def list_issues(self, state='open', labels=None):
"""List issues in current repository"""
return await self.gitea.list_issues(state=state, labels=labels)
async def get_issue(self, issue_number):
"""Get specific issue details"""
return await self.gitea.get_issue(issue_number)
async def create_issue(self, title, body, labels=None):
"""Create new issue"""
return await self.gitea.create_issue(title, body, labels)
# ... other issue tools
# mcp-gitea/mcp_server/tools/labels.py
class LabelTools:
def __init__(self, gitea_client):
self.gitea = gitea_client
async def get_labels(self):
"""Get all labels from repository"""
return await self.gitea.get_labels()
async def suggest_labels(self, context):
"""Suggest appropriate labels based on context"""
# Label suggestion logic using taxonomy
pass
```
### Wiki.js MCP Tools
```python
# mcp-wikijs/mcp_server/tools/pages.py
class PageTools:
def __init__(self, wikijs_client):
self.wikijs = wikijs_client
async def search_pages(self, query, path=None, tags=None):
"""Search Wiki.js pages"""
return await self.wikijs.search_pages(query, path, tags)
async def get_page(self, path):
"""Get specific page"""
return await self.wikijs.get_page(path)
async def create_page(self, path, title, content, tags):
"""Create new page"""
return await self.wikijs.create_page(path, title, content, tags)
# ... other page tools
# mcp-wikijs/mcp_server/tools/lessons_learned.py
class LessonsLearnedTools:
def __init__(self, wikijs_client):
self.wikijs = wikijs_client
async def create_lesson(self, sprint_name, content, tags):
"""Create lessons learned document"""
return await self.wikijs.create_lesson(sprint_name, content, tags)
async def search_lessons(self, query, tags=None):
"""Search past lessons"""
return await self.wikijs.search_lessons(query, tags)
async def search_all_projects(self, query, tags=None):
"""Search lessons across all projects (PMO)"""
return await self.wikijs.search_all_projects(query, tags)
```
---
## Setup Instructions
### 1. System Configuration
```bash
# Create config directory
mkdir -p ~/.config/claude
# Create Gitea config
cat > ~/.config/claude/gitea.env << EOF
GITEA_API_URL=https://gitea.hyperhivelabs.com/api/v1
GITEA_API_TOKEN=your_gitea_token
GITEA_OWNER=hyperhivelabs
EOF
# Create Wiki.js config
cat > ~/.config/claude/wikijs.env << EOF
WIKIJS_API_URL=https://wiki.hyperhivelabs.com/graphql
WIKIJS_API_TOKEN=your_wikijs_token
WIKIJS_BASE_PATH=/hyper-hive-labs
EOF
# Secure config files
chmod 600 ~/.config/claude/*.env
```
### 2. Project Configuration
```bash
# In each project root
cat > .env << EOF
GITEA_REPO=cuisineflow
WIKIJS_PROJECT=projects/cuisineflow
EOF
# Add to .gitignore
echo ".env" >> .gitignore
```
### 3. Install MCP Servers
```bash
# Gitea MCP Server
cd /path/to/claude-plugins/mcp-servers/gitea
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Wiki.js MCP Server
cd /path/to/claude-plugins/mcp-servers/wikijs
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
### 4. Initialize Wiki.js Structure
Create the base structure in Wiki.js web interface:
1. Navigate to https://wiki.hyperhivelabs.com
2. Create `/hyper-hive-labs` page
3. Create `/hyper-hive-labs/projects` page
4. Create `/hyper-hive-labs/company` page
5. Create `/hyper-hive-labs/shared` page
Or use the Wiki.js API:
```python
# One-time setup script
import asyncio
from wikijs_client import WikiJSClient
async def initialize_wiki_structure():
client = WikiJSClient()
# Create base pages
await client.create_page(
path="/hyper-hive-labs",
title="Hyper Hive Labs",
content="# Hyper Hive Labs Documentation",
tags=["company"]
)
await client.create_page(
path="/hyper-hive-labs/projects",
title="Projects",
content="# Project Documentation",
tags=["projects"]
)
# ... create other base pages
asyncio.run(initialize_wiki_structure())
```
---
## Benefits of This Architecture
### 1. Separation of Concerns
- **Gitea MCP**: Project tracking, issues, labels
- **Wiki.js MCP**: Knowledge management, documentation
### 2. Independent Configuration
- Update Gitea credentials without affecting Wiki.js
- Different token expiration policies
- Independent service availability
### 3. Better Documentation Features
- Wiki.js rich editor
- Built-in search and indexing
- Tag system
- Version history
- Access control
- Web-based review and editing
### 4. Company-Wide Knowledge Base
- Shared documentation accessible to all projects
- Cross-project lesson learning
- Best practices repository
- Onboarding materials
- Technical standards
### 5. Scalability
- Add new projects easily
- Grow company documentation organically
- PMO has visibility across everything
- Individual projects stay focused
---
## Migration from Single MCP
If you have existing Wiki content in Git:
```python
# Migration script
import asyncio
from wikijs_client import WikiJSClient
from pathlib import Path
async def migrate_lessons_to_wikijs():
"""Migrate existing lessons learned from Git to Wiki.js"""
client = WikiJSClient()
# Read existing markdown files
lessons_dir = Path("wiki/lessons-learned/sprints")
for lesson_file in lessons_dir.glob("*.md"):
content = lesson_file.read_text()
sprint_name = lesson_file.stem
# Extract tags from content (e.g., from frontmatter or hashtags)
tags = extract_tags(content)
# Create in Wiki.js
await client.create_lesson(
sprint_name=sprint_name,
lesson_content=content,
tags=tags
)
print(f"Migrated: {sprint_name}")
asyncio.run(migrate_lessons_to_wikijs())
```
---
## Next Steps
1. **Set up Wiki.js instance** if not already done
2. **Create base structure** in Wiki.js
3. **Implement both MCP servers** (Phase 1.1a and 1.1b)
4. **Test configuration** with both services
5. **Migrate existing lessons** (if applicable)
6. **Start using with next sprint**
The two-MCP-server architecture provides a solid foundation for both project-level and company-wide knowledge management!