devhive 0.1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
devhive-0.1.6/PKG-INFO ADDED
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.4
2
+ Name: devhive
3
+ Version: 0.1.6
4
+ Summary: DevHive MCP Server
5
+ Requires-Python: >=3.10
@@ -0,0 +1,224 @@
1
+ # DevHive MCP Server
2
+
3
+ [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
4
+ [![MCP Protocol](https://img.shields.io/badge/MCP-1.0-green)](https://modelcontextprotocol.io/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ **DevHive** is a powerful **Model Context Protocol (MCP)** server that orchestrates an autonomous AI software development team. It transforms a single LLM session into a sequential, multi-agent pipeline capable of handling complex software engineering tasksβ€”from initial requirements analysis to final code archiving.
8
+
9
+ Designed to integrate seamlessly with **OpenCode** and **GitHub Copilot**, DevHive provides the tooling and state management necessary for AI agents to work continuously on large projects without losing context.
10
+
11
+ ---
12
+
13
+ ## πŸš€ Key Features
14
+
15
+ * **8-Stage Agent Pipeline:** A structured workflow guiding development through specialized roles:
16
+ 1. **Explorer:** Analyzes requirements and feasibility.
17
+ 2. **Proposal:** Creates detailed feature proposals.
18
+ 3. **Architect:** Designs technical architecture and system diagrams.
19
+ 4. **TaskPlanner:** Breaks down work into actionable developer tasks.
20
+ 5. **Developer:** Implements code and writes files.
21
+ 6. **QA:** Generates and executes test suites.
22
+ 7. **Auditor:** Verifies consistency against architecture and requirements.
23
+ 8. **Archivist:** Finalizes and archives the project state.
24
+ * **Persistent State Management:** Tracks project progress, artifacts, and file generation across sessions.
25
+ * **Context Optimization (RAG):** Built-in memory system using TF-IDF to retrieve relevant context from previous steps, reducing token usage and hallucination.
26
+ * **Cross-Platform CLI:** Easy-to-use command-line interface for configuration and server management.
27
+ * **Universal Compatibility:** Works as a local MCP server for OpenCode, Claude Desktop, or any MCP-compliant client.
28
+
29
+ ---
30
+
31
+ ## πŸ›  Architecture
32
+
33
+ DevHive operates on a strictly sequential pipeline model. Each agent produces a specific **Artifact** (JSON document) that serves as the input for the next agent.
34
+
35
+ ```mermaid
36
+ graph LR
37
+ User[User Request] --> Explorer
38
+ Explorer --> Proposal
39
+ Proposal --> Architect
40
+ Architect --> TaskPlanner
41
+ TaskPlanner --> Developer
42
+ Developer --> QA
43
+ QA --> Auditor
44
+ Auditor --> Archivist
45
+ Archivist --> Done((Project Complete))
46
+ ```
47
+
48
+ ### Core Components
49
+
50
+ * **`mcp_server`**: The main Python package containing the server logic.
51
+ * **`TaskOrchestrator`**: Manages the transition between agents and validates outputs.
52
+ * **`MemoryStore`**: A local vector-lite store (TF-IDF) for semantic search over project history.
53
+ * **`ProjectStateManager`**: Persists project status to `project_state.json`.
54
+
55
+ ---
56
+
57
+ ## πŸ“¦ Installation
58
+
59
+ ### Prerequisites
60
+
61
+ * Python 3.10 or higher
62
+ * `pip`
63
+
64
+ ### Install from Source
65
+
66
+ Clone the repository and install the package in editable mode:
67
+
68
+ ```bash
69
+ git clone https://github.com/yourusername/devhive.git
70
+ cd devhive
71
+ pip install -e .
72
+ ```
73
+
74
+ This installs the `devhive` CLI tool globally in your environment.
75
+
76
+ ---
77
+
78
+ ## βš™οΈ Configuration
79
+
80
+ DevHive includes a smart configuration tool that sets up your environment automatically.
81
+
82
+ ### 1. Run the Setup Wizard
83
+
84
+ ```bash
85
+ devhive configure
86
+ ```
87
+
88
+ The wizard will ask:
89
+ * **Client Selection:** OpenCode, GitHub Copilot (VS Code), or both.
90
+ * **MCP Server Registration:** For OpenCode users, it can automatically add the DevHive server to your `config.json`.
91
+ * **VS Code Integration:** For Copilot users, it injects the agent system prompts directly into your global VS Code settings (`github.copilot.chat.codeGeneration.instructions`).
92
+
93
+ ### 2. Manual Configuration (Optional)
94
+
95
+ If you prefer manual setup:
96
+
97
+ **OpenCode (`~/.config/opencode/opencode.json`):**
98
+ ```json
99
+ {
100
+ "mcp": {
101
+ "devhive": {
102
+ "type": "local",
103
+ "command": ["python3", "-m", "mcp_server.server"],
104
+ "enabled": true,
105
+ "env": { "PYTHONUNBUFFERED": "1" }
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ **VS Code (`settings.json`):**
112
+ ```json
113
+ "github.copilot.chat.codeGeneration.instructions": [
114
+ {
115
+ "file": "/path/to/devhive/DEVHIVE_AGENT.md"
116
+ }
117
+ ]
118
+ ```
119
+
120
+ ---
121
+
122
+ ## πŸ–₯ Usage
123
+
124
+ ### Starting the Server
125
+
126
+ To start the MCP server locally (useful for debugging or manual connection):
127
+
128
+ ```bash
129
+ devhive start
130
+ ```
131
+
132
+ *Note: If configured correctly in OpenCode, the server starts automatically in the background.*
133
+
134
+ ### Workflow with AI Clients
135
+
136
+ 1. **Open your AI Client** (OpenCode or VS Code Copilot).
137
+ 2. **Initialize a Project:**
138
+ Ask the agent: *"Start a new pipeline for a CSV export feature."*
139
+
140
+ The agent will use `devhive_start_pipeline`.
141
+ 3. **Follow the Steps:**
142
+ The AI will automatically assume the role of the **Explorer**.
143
+ * It will analyze the request.
144
+ * It will submit its findings using `devhive_submit_result`.
145
+ 4. **Iterate:**
146
+ DevHive will return the prompt for the next agent (Proposal). The AI client will switch roles and continue until the **Archivist** declares the project complete.
147
+
148
+ ---
149
+
150
+ ## πŸ“š API / Tool Reference
151
+
152
+ The server exposes the following MCP tools to the AI agent:
153
+
154
+ | Tool | Description |
155
+ |------|-------------|
156
+ | `devhive_start_pipeline` | Initializes a project and retrieves the first task (Explorer). |
157
+ | `devhive_submit_result` | Submits work from the current agent, saves artifacts, and retrieves the next task. |
158
+ | `devhive_search_memory` | Searches project history/context using semantic query. |
159
+ | `devhive_get_recent_memories` | Retrieves the most recent interactions for context refreshment. |
160
+ | `devhive_get_memory_stats` | Returns usage statistics for the project memory. |
161
+ | `list_workspace_files` | Lists files in the current working directory. |
162
+ | `read_workspace_file` | Reads content of a specific file. |
163
+
164
+ ---
165
+
166
+ ## πŸ“‚ Project Structure
167
+
168
+ ```text
169
+ devhive/
170
+ β”œβ”€β”€ DEVHIVE_AGENT.md # The "Brain" - System prompt for the AI agent
171
+ β”œβ”€β”€ AGENTS.md # Documentation for agent roles
172
+ β”œβ”€β”€ pyproject.toml # Python project configuration
173
+ β”œβ”€β”€ setup.py # Legacy setup support
174
+ β”œβ”€β”€ mcp_server/ # Source code
175
+ β”‚ β”œβ”€β”€ agents/ # Logic for individual agents (Explorer, Developer, etc.)
176
+ β”‚ β”œβ”€β”€ core/ # Core infrastructure (LLM, Memory, State)
177
+ β”‚ β”œβ”€β”€ utils/ # Filesystem and validation utilities
178
+ β”‚ β”œβ”€β”€ cli.py # CLI implementation (devhive command)
179
+ β”‚ └── server.py # FastMCP server entry point
180
+ └── tests/ # Test suite
181
+ ```
182
+
183
+ ---
184
+
185
+ ## πŸ§ͺ Development
186
+
187
+ ### Running Tests
188
+
189
+ DevHive uses `pytest` for testing.
190
+
191
+ ```bash
192
+ # Install test dependencies
193
+ pip install pytest
194
+
195
+ # Run all tests
196
+ pytest
197
+ ```
198
+
199
+ ### Adding a New Agent
200
+
201
+ 1. Create a new class in `mcp_server/agents/` inheriting from `BaseAgent`.
202
+ 2. Define the agent's specific validation logic in `mcp_server/utils/validation.py`.
203
+ 3. Register the agent in `mcp_server/server.py` and `mcp_server/core/task_orchestrator.py`.
204
+ 4. Update `DEVHIVE_AGENT.md` to include the new role in the pipeline instructions.
205
+
206
+ ---
207
+
208
+ ## 🀝 Contributing
209
+
210
+ Contributions are welcome! Please follow these steps:
211
+
212
+ 1. Fork the repository.
213
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`).
214
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`).
215
+ 4. Push to the branch (`git push origin feature/amazing-feature`).
216
+ 5. Open a Pull Request.
217
+
218
+ Please ensure all tests pass and your code follows the existing style conventions (Python 3.10+ type hinting).
219
+
220
+ ---
221
+
222
+ ## πŸ“„ License
223
+
224
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.4
2
+ Name: devhive
3
+ Version: 0.1.6
4
+ Summary: DevHive MCP Server
5
+ Requires-Python: >=3.10
@@ -0,0 +1,22 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ devhive.egg-info/PKG-INFO
5
+ devhive.egg-info/SOURCES.txt
6
+ devhive.egg-info/dependency_links.txt
7
+ devhive.egg-info/entry_points.txt
8
+ devhive.egg-info/top_level.txt
9
+ mcp_server/__init__.py
10
+ mcp_server/cli.py
11
+ mcp_server/server.py
12
+ mcp_server/agents/__init__.py
13
+ mcp_server/agents/architect.py
14
+ mcp_server/agents/archivist.py
15
+ mcp_server/agents/auditor.py
16
+ mcp_server/agents/base_agent.py
17
+ mcp_server/agents/ceo.py
18
+ mcp_server/agents/developer.py
19
+ mcp_server/agents/explorer.py
20
+ mcp_server/agents/proposal.py
21
+ mcp_server/agents/qa.py
22
+ mcp_server/agents/task_agent.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ devhive = mcp_server.cli:main
3
+ devhive_mcp = mcp_server.server:main
@@ -0,0 +1 @@
1
+ mcp_server
@@ -0,0 +1 @@
1
+ # MCP Server Package
@@ -0,0 +1,10 @@
1
+ from mcp_server.agents.base_agent import BaseAgent
2
+ from mcp_server.agents.explorer import ExplorerAgent
3
+ from mcp_server.agents.proposal import ProposalAgent
4
+ from mcp_server.agents.architect import ArchitectAgent
5
+ from mcp_server.agents.task_agent import TaskAgent
6
+ from mcp_server.agents.developer import DeveloperAgent
7
+ from mcp_server.agents.qa import QAAgent
8
+ from mcp_server.agents.auditor import AuditorAgent
9
+ from mcp_server.agents.archivist import ArchivistAgent
10
+ from mcp_server.agents.ceo import CEOAgent
@@ -0,0 +1,28 @@
1
+ import json
2
+ from typing import Dict, Any
3
+ from mcp.server.fastmcp import Context
4
+ from mcp_server.agents.base_agent import BaseAgent
5
+
6
+ class ArchitectAgent(BaseAgent):
7
+ role = "Architect"
8
+
9
+ async def execute(self, ctx: Context, **kwargs) -> str:
10
+ context = self.get_context()
11
+ sys_prompt = "You are the Tech Lead. Output JSON only."
12
+ user_prompt = f"""Design architecture.
13
+ Context: {json.dumps(context, default=str)}
14
+ Return JSON with keys: architecture_pattern, components, data_models, apis."""
15
+
16
+ resp = await self._call_llm(ctx, sys_prompt, user_prompt)
17
+ data = self._parse_json(resp)
18
+ return self.save_artifact("architecture", data)
19
+
20
+ def generate_summary(self, data: Dict[str, Any]) -> str:
21
+ """Generate executive summary for Architect agent."""
22
+ components_count = len(data.get("components", []))
23
+ apis_count = len(data.get("apis", []))
24
+ pattern = data.get("architecture_pattern", "N/A")
25
+ return (
26
+ f"Designed architecture using {pattern} pattern "
27
+ f"with {components_count} components and {apis_count} APIs."
28
+ )
@@ -0,0 +1,19 @@
1
+ import json
2
+ from typing import Dict, Any
3
+ from mcp.server.fastmcp import Context
4
+ from mcp_server.agents.base_agent import BaseAgent
5
+
6
+ class ArchivistAgent(BaseAgent):
7
+ role = "Archivist"
8
+ async def execute(self, ctx: Context, **kwargs) -> str:
9
+ state = self.state_manager.get_state()
10
+ state["status"] = "completed"
11
+ if "artifacts" not in state: state["artifacts"] = {}
12
+ state["artifacts"]["archive"] = "archived"
13
+ self.state_manager.update_state(state)
14
+ return "Project Archived Successfully"
15
+
16
+ def generate_summary(self, data: Dict[str, Any]) -> str:
17
+ """Generate executive summary for Archivist agent."""
18
+ # Archivist doesn't use structured data, just returns success message
19
+ return "Project archived successfully. All artifacts and state preserved."
@@ -0,0 +1,28 @@
1
+ import json
2
+ from typing import Dict, Any
3
+ from mcp.server.fastmcp import Context
4
+ from mcp_server.agents.base_agent import BaseAgent
5
+
6
+ class AuditorAgent(BaseAgent):
7
+ role = "Auditor"
8
+ async def execute(self, ctx: Context, **kwargs) -> str:
9
+ context = self.get_context()
10
+ sys_prompt = "You are the Auditor. Output JSON only."
11
+ user_prompt = f"""Verify the project.
12
+ Context: {json.dumps(context, default=str)}
13
+ Return JSON with keys: architecture_consistency (bool), missing_pieces (list), security_risks (list)."""
14
+
15
+ resp = await self._call_llm(ctx, sys_prompt, user_prompt)
16
+ data = self._parse_json(resp)
17
+ return self.save_artifact("verification", data)
18
+
19
+ def generate_summary(self, data: Dict[str, Any]) -> str:
20
+ """Generate executive summary for Auditor agent."""
21
+ consistent = data.get("architecture_consistency", False)
22
+ missing_count = len(data.get("missing_pieces", []))
23
+ security_count = len(data.get("security_risks", []))
24
+ status = "βœ“ Passed" if consistent and missing_count == 0 else "⚠ Issues Found"
25
+ return (
26
+ f"{status}. Missing pieces: {missing_count}, "
27
+ f"Security risks: {security_count}"
28
+ )
@@ -0,0 +1,104 @@
1
+ import json
2
+ import logging
3
+ from typing import Dict, Any, Optional
4
+ from mcp.types import SamplingMessage, TextContent
5
+ from mcp.server.fastmcp import Context
6
+ from mcp_server.core.project_state_manager import ProjectStateManager
7
+ from mcp_server.core.artifact_manager import ArtifactManager
8
+ from mcp_server.core.context_router import ContextRouter
9
+ from mcp_server.core.llm import LLM
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ class BaseAgent:
14
+ role: str = "Base"
15
+
16
+ def __init__(self, project_name: str):
17
+ self.project_name = project_name
18
+ self.state_manager = ProjectStateManager(project_name)
19
+ self.artifact_manager = ArtifactManager(project_name)
20
+ self.context_router = ContextRouter(self.state_manager, self.artifact_manager)
21
+
22
+ def get_context(self) -> Dict[str, Any]:
23
+ return self.context_router.get_context(self.role)
24
+
25
+ def save_artifact(self, step_name: str, content: Dict[str, Any]) -> str:
26
+ aid = self.artifact_manager.save_artifact(step_name, content)
27
+ self.state_manager.update_artifact(step_name, aid)
28
+ return aid
29
+
30
+ def generate_summary(self, data: Dict[str, Any]) -> str:
31
+ """
32
+ Generate a 1-3 sentence executive summary of the agent's work.
33
+
34
+ This default implementation provides a basic summary. Subclasses should
35
+ override this method to provide more specific summaries based on their
36
+ role and the data they produce.
37
+
38
+ Args:
39
+ data: The artifact data produced by the agent
40
+
41
+ Returns:
42
+ A concise 1-3 sentence summary suitable for orchestrator context
43
+ """
44
+ return f"{self.role} completed successfully."
45
+
46
+ async def _call_llm(self, ctx: Context, system_prompt: str, user_prompt: str, max_tokens: int = 2000)-> str:
47
+ decision = await LLM.generate_json(
48
+ ctx,
49
+ system_prompt,
50
+ user_prompt
51
+ )
52
+ return json.dumps(decision)
53
+
54
+
55
+ async def _call_llm_old(self, ctx: Context, system_prompt: str, user_prompt: str, max_tokens: int = 2000) -> str:
56
+ """Helper to call LLM via Sampling."""
57
+ try:
58
+ messages = [
59
+ {"role": "user", "content": { "type": "text", "text": f"{system_prompt}\n\n{user_prompt}" }}
60
+ ]
61
+
62
+ # Using create_message which is standard
63
+ if hasattr(ctx.session, 'create_message'):
64
+ try:
65
+ result = await ctx.session.create_message(
66
+ messages=messages,
67
+ max_tokens=max_tokens,
68
+ system_prompt=system_prompt
69
+ )
70
+ except:
71
+ # Retry with just user prompt if system prompt arg fails
72
+ result = await ctx.session.create_message(
73
+ messages=messages,
74
+ max_tokens=max_tokens
75
+ )
76
+
77
+ if hasattr(result, 'content') and hasattr(result.content, 'text'):
78
+ return result.content.text
79
+ return str(result)
80
+
81
+ # Fallback
82
+ if hasattr(ctx.session, 'sample'):
83
+ return str(await ctx.session.sample(messages=messages, max_tokens=max_tokens))
84
+
85
+ return '{"error": "No sampling capability found on session"}'
86
+
87
+ except Exception as e:
88
+ logger.error(f"LLM Call failed: {e}")
89
+ return json.dumps({"error": str(e)})
90
+
91
+ def _parse_json(self, text: str) -> Dict[str, Any]:
92
+ """ Robust JSON parser """
93
+ text = text.strip()
94
+ if "```json" in text:
95
+ text = text.split("```json")[1].split("```")[0]
96
+ elif "```" in text:
97
+ text = text.split("```")[1].split("```")[0]
98
+ try:
99
+ return json.loads(text)
100
+ except:
101
+ return {"raw_text": text}
102
+
103
+ async def execute(self, ctx: Context, **kwargs) -> Any:
104
+ raise NotImplementedError
@@ -0,0 +1,171 @@
1
+ import json
2
+ from typing import Dict, Any
3
+ from mcp.server.fastmcp import Context
4
+ from mcp_server.agents.base_agent import BaseAgent
5
+ from mcp_server.core.project_state_manager import ProjectStateManager
6
+
7
+ class CEOAgent(BaseAgent):
8
+ role = "CEO"
9
+
10
+ def get_next_agent_deterministic(self) -> Dict[str, Any]:
11
+ """
12
+ Determine next agent to run based on current state (no LLM needed).
13
+ This is a rule-based decision making process following the strict pipeline sequence.
14
+
15
+ Pipeline order:
16
+ 1. Explorer
17
+ 2. Proposal
18
+ 3. Architect
19
+ 4. TaskPlanner
20
+ 5. Developer
21
+ 6. QA
22
+ 7. Auditor
23
+ 8. Archivist
24
+
25
+ Returns:
26
+ Dict with 'agent' (role name) and 'reason' (explanation)
27
+ """
28
+ state = self.state_manager.get_state()
29
+ artifacts = state.get("artifacts", {})
30
+
31
+ # Check each stage in order
32
+ if artifacts.get("exploration") is None:
33
+ return {
34
+ "agent": "Explorer",
35
+ "reason": "Need initial feature analysis and exploration"
36
+ }
37
+
38
+ # Determine complexity from exploration artifact
39
+ complexity = "high" # Default to high safety
40
+ try:
41
+ expl_id = artifacts.get("exploration")
42
+ if expl_id:
43
+ expl_data = self.artifact_manager.load_artifact(expl_id)
44
+ complexity = expl_data.get("complexity", "high").lower()
45
+ except Exception:
46
+ pass # Fallback to high complexity on error
47
+
48
+ # Dynamic Routing based on Complexity
49
+ # Low: Explorer -> Developer -> QA -> Archivist
50
+ # Medium: Explorer -> Proposal -> Developer -> QA -> Archivist
51
+ # High: Full Suite
52
+
53
+ if artifacts.get("proposal") is None:
54
+ if complexity == "low":
55
+ pass # Skip Proposal
56
+ else:
57
+ return {
58
+ "agent": "Proposal",
59
+ "reason": "Exploration complete, need feature proposal"
60
+ }
61
+
62
+ if artifacts.get("architecture") is None:
63
+ if complexity in ["low", "medium"]:
64
+ pass # Skip Architecture
65
+ else:
66
+ return {
67
+ "agent": "Architect",
68
+ "reason": "Proposal complete, need technical architecture design"
69
+ }
70
+
71
+ if artifacts.get("tasks") is None:
72
+ if complexity in ["low", "medium"]:
73
+ pass # Skip Task Planning
74
+ else:
75
+ return {
76
+ "agent": "TaskPlanner",
77
+ "reason": "Architecture complete, need task breakdown"
78
+ }
79
+
80
+ if artifacts.get("implementation") is None:
81
+ return {
82
+ "agent": "Developer",
83
+ "reason": "Ready for implementation"
84
+ }
85
+
86
+ if artifacts.get("tests") is None:
87
+ return {
88
+ "agent": "QA",
89
+ "reason": "Implementation complete, need tests"
90
+ }
91
+
92
+ if artifacts.get("verification") is None:
93
+ if complexity in ["low", "medium"]:
94
+ pass # Skip Auditor
95
+ else:
96
+ return {
97
+ "agent": "Auditor",
98
+ "reason": "Tests complete, need final verification"
99
+ }
100
+
101
+ if artifacts.get("archive") is None:
102
+ return {
103
+ "agent": "Archivist",
104
+ "reason": "All stages complete, ready to archive project"
105
+ }
106
+
107
+ # All done
108
+ return {
109
+ "agent": "Complete",
110
+ "reason": "All pipeline stages finished, project is complete"
111
+ }
112
+
113
+ async def execute(self, ctx: Context, **kwargs) -> Dict[str, Any]:
114
+ """
115
+ Original LLM-based decision making (requires sampling support).
116
+ Currently not used in manual workflow.
117
+ """
118
+ state_manager = ProjectStateManager(self.project_name)
119
+ state = state_manager.get_state()
120
+
121
+ context = {
122
+ "project_status": state.get('status'),
123
+ "artifacts_summary": state.get("artifacts", {})
124
+ }
125
+
126
+ sys_prompt = """
127
+ You are the CEO orchestrating an AI software development pipeline.
128
+
129
+ The pipeline is strictly sequential:
130
+
131
+ 1 Explorer
132
+ 2 Proposal
133
+ 3 Architect
134
+ 4 TaskPlanner
135
+ 5 Developer
136
+ 6 QA
137
+ 7 Auditor
138
+ 8 Archivist
139
+
140
+ Rules:
141
+
142
+ - NEVER return Wait unless the pipeline is finished
143
+ - ALWAYS select the next missing role
144
+ - Each role produces an artifact
145
+
146
+ Explorer β†’ exploration
147
+ Proposal β†’ proposal
148
+ Architect β†’ architecture
149
+ TaskPlanner β†’ tasks
150
+ Developer β†’ implementation
151
+ QA β†’ tests
152
+ Auditor β†’ verification
153
+ Archivist β†’ archived
154
+
155
+ Return JSON only:
156
+ { "decision": "Run <Role>", "reason": "..." }
157
+ """
158
+ user_prompt = f"""Decide next step.
159
+
160
+ Project: {context.get('project_name')}
161
+ Status: {context.get('project_status')}
162
+ Stage: {context.get('stage')}
163
+ Artifacts: {json.dumps(context.get('artifacts_summary', {}), indent=2)}
164
+
165
+ Available Roles: Explorer, Proposal, Architect, TaskPlanner, Developer, QA, Auditor, Archivist.
166
+ Return JSON: {{ "decision": "Run <Role>", "reason": "..." }}
167
+ If finished, "Run Archivist".
168
+ If stage is "initialization", "Run Explorer"
169
+ """
170
+ resp = await self._call_llm(ctx, sys_prompt, user_prompt)
171
+ return self._parse_json(resp)
@@ -0,0 +1,44 @@
1
+ import json
2
+ from typing import Dict, Any
3
+ from mcp.server.fastmcp import Context
4
+ from mcp_server.agents.base_agent import BaseAgent
5
+
6
+ class DeveloperAgent(BaseAgent):
7
+ role = "Developer"
8
+
9
+ def write_files(self, data: Dict[str, Any]) -> list[str]:
10
+ """Write implementation files to disk. Returns list of file paths."""
11
+ files = data.get("files", [])
12
+ from mcp_server.utils.filesystem import write_file
13
+ file_paths = []
14
+ for f in files:
15
+ if isinstance(f, dict) and "path" in f and "content" in f:
16
+ write_file(f["path"], f["content"])
17
+ file_paths.append(f["path"])
18
+ return file_paths
19
+
20
+ async def execute(self, ctx: Context, **kwargs) -> str:
21
+ context = self.get_context()
22
+ sys_prompt = "You are the Developer. Output JSON only."
23
+ user_prompt = f"""Implement the feature.
24
+ Context: {json.dumps(context, default=str)}
25
+ Return JSON with keys: implementation_strategy, file_structure, pseudocode, files (list of {{path, content}})."""
26
+
27
+ resp = await self._call_llm(ctx, sys_prompt, user_prompt, max_tokens=4000)
28
+ data = self._parse_json(resp)
29
+
30
+ # Write files (using extracted method)
31
+ file_paths = self.write_files(data)
32
+ self.state_manager.add_files(file_paths)
33
+ return self.save_artifact("implementation", data)
34
+
35
+ def generate_summary(self, data: Dict[str, Any]) -> str:
36
+ """Generate executive summary for Developer agent."""
37
+ files_count = len(data.get("files", []))
38
+ strategy = data.get("implementation_strategy", "N/A")
39
+ # Truncate if too long
40
+ if len(strategy) > 80:
41
+ strategy = strategy[:80] + "..."
42
+ return (
43
+ f"Implemented {files_count} files using strategy: {strategy}"
44
+ )