DevPulse PM Agent

DevPulse PM Agent

MCP server providing tools for product management decision-making including backlog prioritization, feedback analysis, capacity assessment, and dependency mapping.

Category
访问服务器

README

DevPulse PM Agent — MCP Server

An MCP server that gives Asha four tools for grounded PM decision-making, backed by the real DevPulse datasets.

Quick Start

cd devpulse-pm-agent
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python server.py

Connect to Claude Code

claude mcp add pm-agent python /absolute/path/to/server.py

Data Path Contract

The server reads from PM_AGENT_DATA env var, falling back to ./data:

DATA_DIR = Path(os.environ.get("PM_AGENT_DATA", Path(__file__).parent / "data"))

Tools

Tool Purpose Data source
prioritize_backlog Score & rank items (RICE/weighted/FIFO) product_backlog + customer_feedback
analyze_feedback Extract themes, detect biases customer_feedback
assess_capacity Real sprint capacity per engineer team_roster (oracle-discovered rules)
map_dependencies Trace chains, detect cycles dependency_map (oracle-discovered graph)

Approach Summary (Technical Decision Log)

1. Schema Rationale

prioritize_backlog takes a method enum to let Asha switch scoring approaches without rewording her question — RICE for data-driven prioritization, FIFO when chronological ordering matters, weighted for a simpler BV/confidence ratio. Flags are discrete booleans on each item rather than a separate list, so Claude can directly say "BP-126 is flagged unestimated and no_customer_signal." The deprioritize_blocked toggle separates "surfacing blocked items" from "penalizing them" — Asha might want to see blocked items at the top precisely so she can unblock them.

I considered a top_n parameter but rejected it — Claude can filter; a parameter cap just hides information.

analyze_feedback returns structured theme objects (not raw text) so Claude synthesizes, not recites. The group_by="customer" switch addresses the common query "what does CUST-01 keep asking for?" — a different grouping axis than theme. Bias warnings are always-on and surfaced as a first-class field, not buried in metadata.

I considered keyword embedding (sentence-transformers) for theme detection but rejected it — it adds a large dependency, fails in sandboxed grading environments, and the fixed keyword approach is fully auditable and sufficient for 9 known themes.

assess_capacity exposes every intermediate calculation (effective, after_pto, available) so Claude can explain the number, not just report it. planned_items is an optional list so Asha can ask "given these items, do we have the right skills?" in one call.

map_dependencies returns both direct and transitive deps in a tree structure per item, plus a separate critical_path field. The tree structure lets Claude reason about depth; the critical path field lets it directly answer "what's the riskiest chain?"

2. Investigation & Trap Handling

Capacity oracle investigation strategy:

The oracle exposes capacity_oracle(engineer_id) returning inputs + available_points. I designed a systematic probe:

  • Baseline: queried an engineer with 100% allocation, 0 PTO, 0 carry-over → expected 21 points → confirmed total_capacity_points = 21.
  • Isolation — allocation: queried 50% allocation, 0 PTO, 0 carry-over → expected 10.5 → confirmed effective = 21 * (allocation/100).
  • Isolation — PTO: 100% allocation, 2 PTO days, 0 carry-over → expected 21 * (1 - 2/10) = 16.8 → confirmed PTO is pro-rated over the 10-day sprint, not a flat deduction.
  • Isolation — carry-over: 100% allocation, 0 PTO, 5 carry-over → expected 21 - 5 = 16 → confirmed carry-over is subtracted after PTO.
  • Zero allocation edge: queried 0% engineer → expected 0, confirmed contributes nothing to squad totals. This is important: a shared engineer doesn't "gift" capacity they can't actually give.
  • Floor check: carry-over larger than capacity → expected 0 (not negative) → confirmed max(0, ...) floor.

The formula is:

effective = 21 * (allocation / 100)
after_pto = effective * (1 - pto_days / 10)
available = max(0, after_pto - carry_over_points)

Dependency oracle investigation:

  • Queried known item IDs from the backlog and followed returned target_ids to trace the graph.
  • Found that type distinguishes hard blockers (blocks) from optional ordering (soft) from cross-team dependencies (external).
  • External deps with external_eta = "TBD" or null are a key risk signal — no committed delivery date means unknown blocking time.
  • Soft dependencies get the same graph traversal as hard ones (critical path logic is the same) but are excluded from "blocks" warnings.

Data anomalies found in the given files:

  • BP-126: effort_points = 0 — unestimated item, cannot compute reliable RICE score. Flagged as unestimated.
  • BP-131 Executive dashboard: business_value_score = 2 but priority = P1 and has executive-priority tag — classic stakeholder override. Tool flags it and applies a 20% boost rather than ignoring it, since ignoring it would cause Claude to give Asha advice that conflicts with executive expectations she has to manage.
  • BP-112 GraphQL migration depends on BP-118, which itself depends on BP-125, which depends on BP-112 — a potential cycle. The map_dependencies tool detects and reports this cycle.
  • NovaBuild (CUST-07) has 10 feedback entries — 11% of the corpus — but is churned. Volume bias detection fires, and churned signal is flagged separately.
  • Two BP-127 / BP-119 items both titled "Notification digest system" from different requesters with different effort estimates — a near-duplicate backlog item anomaly. The prioritize tool doesn't deduplicate these (that would require PM judgment) but the analyze_feedback near-duplicate check helps surface it.

3. Tool Description Craft

Tool descriptions are written to answer two questions Claude is implicitly asking: "Should I call this?" and "What should I pass?". Each description leads with example Asha questions ("What are customers actually asking for?") because Claude pattern-matches user intent to descriptions.

Example where the description shaped behavior: map_dependencies says "at least one ID is required" and lists the format BP-NNN. Without this, Claude would call the tool with fuzzy item names like "API redesign" instead of BP-112, causing a miss. Adding "Use backlog IDs (BP-NNN) as they appear in the dependency map" caused Claude to first call prioritize_backlog to find the ID, then map_dependencies with the correct format.

The assess_capacity description includes the formula verbatim — not to teach Claude math, but so Claude can explain the number to Asha without hallucinating an alternate explanation.

4. Failure Modes

  • Bad input IDs in map_dependencies: If an item_id has no edges in the graph, the tool returns direct_deps: [] and chain_depth: 0 — informative, not a crash.
  • Empty item_ids: Returns {"error": "item_ids must contain at least one item ID."} with a clear message.
  • Cycle in dependency graph: Detected via DFS with path tracking. Returns the full cycle path (BP-112 -> BP-118 -> BP-125 -> BP-112) so Asha can see exactly what's circular. The tool does not crash — it flags and continues tracing the rest of the graph.
  • Broken chain (target references unknown item): _trace_chain simply returns no transitive deps for an unknown target — doesn't crash, doesn't recurse into nothing. The _detect_cycle function uses a visited set to prevent infinite loops.
  • Missing data files: load_json raises FileNotFoundError with a clear message about PM_AGENT_DATA. The roster and dependency map loaders try the canonical filename first, then fall back to the sample file — allows local dev without the grading harness.
  • Unestimated items in RICE: Effort = 0 causes division by zero. The code uses max(effort, 1) and also flags the item as unestimated so Asha knows the score is unreliable.

5. Custom Insight: Designing Tools for AI vs. Human UI

The key insight: AI tools need to surface judgment inputs, not conclusions. A human dashboard shows a score; an AI tool should expose the components of that score (reach, impact, confidence, effort) so the AI can reason about tradeoffs, not just read a number.

The second insight: tool descriptions are API contracts with the AI. Every example question in the description is a routing hint. When Claude sees "What's blocking the API redesign?" it needs to know that's a map_dependencies call, not a prioritize_backlog call. The description does that work.

The third: flags matter more than scores. A dependency_conflict flag changes Asha's action (unblock first) even if the item scored first. Scores rank; flags route.

6. Production Scaling

Data layer: Replace file-based JSON with a read API that accepts a team_id. Each tool call would pass team_id as context so the same server can serve 6 product teams. Add a caching layer (Redis, 5-min TTL) — feedback and backlog data doesn't change mid-conversation.

Schema changes: Add team_id to all tool inputs. Add as_of_date parameter to assess_capacity so Asha can query future sprints. Add a confidence_interval output to assess_capacity based on historical velocity variance from sprint_history.

Error handling: Switch from raise FileNotFoundError to structured error responses ({"error": "...", "error_code": "data_unavailable"}) so the AI can explain the failure gracefully rather than receiving a crash.

New tools I'd add:

  • sprint_fit_check(item_ids) — combines capacity + dependencies to answer "can we fit these specific items?" in one call
  • churn_risk_signal(customer_id) — cross-reference feedback sentiment trend with ARR to give Asha early churn warnings
  • velocity_forecast(sprint_count) — projects future capacity from historical sprint data

What I'd explicitly NOT automate: Sprint commitment decisions (which items go in), capacity reallocation between engineers, and executive priority overrides. These require human negotiation, context beyond the data, and accountability. The tools should inform these decisions, not make them. An AI that auto-commits the sprint or auto-reassigns engineers creates false precision and removes the PM's ability to surface organizational context the data doesn't capture.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选