pm-agent
README.md
# PM Agent — MCP Server
An MCP server that gives Claude the tools to help a product manager make sprint decisions grounded in real data. Built for DevPulse's PM Asha: four tools that answer the questions she spends 60% of her week answering manually.
## Tools
| Tool | Purpose |
|------|---------|
| `prioritize_backlog` | Score and rank backlog items by RICE, customer signal, or a combined method. Flags stale, unestimated, blocked, and anomalous items. |
| `analyze_feedback` | Extract themes from customer feedback with ARR weighting and bias warnings (over-represented customers, churned signal, segment skew). |
| `assess_capacity` | Compute per-engineer available capacity for the sprint, accounting for allocation %, PTO, and carry-over work. |
| `map_dependencies` | Trace dependency chains, detect cycles, and flag external blockers and long chains for a set of backlog items. |
## Prerequisites
- Python 3.10+
- `uv` (recommended) or `pip`
## Setup
```bash
cd mcp_starter
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```
Place the five data files in `./data/`:
```
data/
product_backlog.json
customer_feedback.json
team_roster.json
dependency_map.json
sprint_history.json
```
## Running
```bash
python server.py
```
The server uses **stdio** transport (what Claude Desktop and Claude Code expect). It will not print anything to stdout on startup — that's normal.
## DATA PATH CONTRACT
The server reads its dataset from the `PM_AGENT_DATA` environment variable, falling back to `./data` for local development:
```python
DATA_DIR = Path(os.environ.get("PM_AGENT_DATA", Path(__file__).parent / "data"))
```
At grading time the evaluation harness mounts a different dataset at `PM_AGENT_DATA`. No IDs, names, or numbers are hardcoded — all tools compute from whatever is mounted.
## Connecting to Claude Desktop
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
```json
{
"mcpServers": {
"pm-agent": {
"command": "python",
"args": ["/absolute/path/to/mcp_starter/server.py"],
"env": { "PM_AGENT_DATA": "/absolute/path/to/data" }
}
}
}
```
Use absolute paths. Restart Claude Desktop after editing.
## Connecting via Claude Code
```bash
claude mcp add pm-agent python /absolute/path/to/mcp_starter/server.py
```
## Tool Reference
### `prioritize_backlog`
Score and rank backlog items by one of three methods.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `method` | string | `"combined"` | `"rice"`, `"customer_signal"`, or `"combined"` |
| `squad` | string | `null` | Filter to `"platform"` or `"growth"` |
| `status_filter` | list | `null` | e.g. `["planned", "proposed"]` |
| `include_dependency_check` | bool | `true` | Flag and penalize blocked items |
| `limit` | int | `20` | Max items returned |
**Flags:** `STALE`, `UNESTIMATED`, `NO_CUSTOMER_SIGNAL`, `BLOCKED`, `EXECUTIVE_PRIORITY_ANOMALY`, `LOW_CONFIDENCE`, `DUPLICATE_TITLE`
---
### `analyze_feedback`
Extract themes from customer feedback with bias detection.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `theme_limit` | int | `5` | Number of top themes |
| `group_by` | string | `"theme"` | `"theme"` or `"customer"` |
| `customer_status` | string | `null` | Filter: `"active"`, `"churned"`, `"trial"` |
| `customer_tier` | string | `null` | Filter: `"enterprise"`, `"mid_market"`, `"startup"` |
**Bias warnings:** `OVER_REPRESENTED_CUSTOMER`, `CHURNED_CUSTOMER_SIGNAL`, `SEGMENT_SKEW`, `ARR_CONCENTRATION`
---
### `assess_capacity`
Per-engineer sprint capacity with three tiers: total → effective (after allocation/PTO) → available (after carry-over).
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `squad` | string | `null` | Filter to `"platform"` or `"growth"` |
| `required_skills` | list | `null` | e.g. `["backend", "security"]` |
Formula: `effective = 21 × (allocation%/100) × ((10 - pto_days)/10)` · `available = effective - carry_over_points`
---
### `map_dependencies`
Trace dependency chains and surface risks.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `item_ids` | list | required | e.g. `["BP-112", "BP-117"]` |
| `max_depth` | int | `3` | Hops to follow |
| `include_soft` | bool | `true` | Include non-blocking soft deps |
**Risk flags:** `CYCLE`, `EXTERNAL_NO_ETA`, `EXTERNAL_WITH_ETA`, `LONG_CHAIN`
## Repo Structure
```
mcp_starter/
├── server.py # MCP entry point
├── requirements.txt
├── olympics.json # run contract
├── README.md
├── TDL.md # Technical Decision Log
├── tools/
│ ├── __init__.py
│ ├── prioritize_backlog.py
│ ├── analyze_feedback.py
│ ├── assess_capacity.py
│ └── map_dependencies.py
└── data/ # sample data for local dev (not committed)
```
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues