Skip to main content
Glama
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)
```

Maintenance

ActivitySlowing
ResponsivenessNo issues