Skip to main content
Glama
jackhendon

PM Context MCP Server

by jackhendon
README.md
# PM Context MCP Server

A Python MCP server that gives Claude access to PM workflow data (sprints, roadmap, blockers, workload) so you can ask it questions a PM actually needs answered.

**No API keys required.** Runs entirely on synthetic fixture data representing a fictional product team ("Petal & Co"). Designed to be forked and connected to a real Linear or Jira workspace privately.

<img src="Demo-mcp.jpg" alt="Demo of Claude answering a sprint question using the MCP server" width="50%">

---

## The Problem

PMs spend a disproportionate amount of time context-switching: checking Linear for sprint status, Confluence for the roadmap, Slack for who's blocked. Each lookup is a tab, a search, a few seconds of reorientation.

The bigger problem is that the *questions* PMs ask are aggregate and cross-cutting ("what should I focus on today?", "who's overloaded?", "what's actually blocking us?") but the tools expose raw CRUD. You have to do the aggregation yourself.

This MCP server exposes PM-oriented tools to Claude so those questions get answered in one place, with actual data behind them.

---

## Architecture

```
Claude (Desktop or CLI)
        │
        │  MCP (stdio transport)
        ▼
pm-mcp-server (FastMCP)
        │
        │  loads
        ▼
data/fixture.json          ← synthetic Petal & Co dataset
(or real Linear / Jira API in a private fork)
```

The server runs as a local subprocess. Claude calls tools over stdio; no network, no auth for the demo.

---

## Tools

| Tool | What Claude can ask |
|------|---------------------|
| `get_current_sprint_tool` | "What's in the current sprint?" / "How close are we to done?" |
| `get_my_issues_tool` | "What's on Priya's plate right now?" |
| `get_blockers_tool` | "What's blocking the team?" / "What should we unblock first?" |
| `search_issues_tool` | "Find all issues related to payments" |
| `get_roadmap_tool` | "How far along are we on each epic?" |
| `get_team_workload_tool` | "Who has the most issues assigned?" / "Show me the Growth team's workload" |
| `get_velocity_tool` | "What's our sprint velocity trend?" |

---

## How to Run

**Requirements:** Python 3.10+, [uv](https://docs.astral.sh/uv/)

```bash
# Clone and enter the repo
git clone https://github.com/jackhendon/pm-mcp-server
cd pm-mcp-server

# Install dependencies
uv sync

# Test a tool directly
uv run python -c "from tools.sprints import get_current_sprint; import json; print(json.dumps(get_current_sprint(), indent=2))"

# Run the MCP inspector (requires mcp[cli])
uv run mcp dev server.py
```

### Connect to Claude Desktop

Add this to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "pm-context": {
      "command": "/Users/yourname/.local/bin/uv",
      "args": ["--directory", "/path/to/pm-mcp-server", "run", "python", "server.py"]
    }
  }
}
```

> **Note:** Claude Desktop on macOS doesn't inherit your shell PATH, so `uv` must be an absolute path. Run `which uv` in your terminal to find it.

Config location:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

Restart Claude Desktop. You should see `pm-context` listed under connected tools.

### Connect to Claude Code (CLI)

```bash
claude mcp add pm-context uv run python server.py --cwd /path/to/pm-mcp-server
```

### Try these prompts

- "What's in the current sprint and how close are we to finishing?"
- "Who has the most work on their plate right now?"
- "What's blocking the team and what should we unblock first?"
- "How has our sprint velocity trended over the last few sprints?"
- "What's the roadmap looking like across all epics?"
- "Find all issues related to API authentication"

---

## Fixture Data: Petal & Co

The synthetic dataset represents a fictional gift-card startup's product team:

- **6 team members** across 2 teams (Growth, Core)
- **3 projects**: Checkout Redesign, API Platform v2, Gifting Suite
- **3 epics** at different stages of completion
- **17 issues** in the active sprint (Sprint 14) with realistic statuses and blockers
- **4 completed sprints** for velocity calculation

The data is rich enough that all 7 tools return genuinely interesting and differentiated results.

---

## Real API Mode

This repo is designed to be forked privately and connected to a real Linear or Jira workspace.

1. Fork the repo
2. Copy `.env.example` to `.env` and add your credentials
3. Implement `tools/integrations/linear.py` or `tools/integrations/jira.py` that returns data in the same shape as the fixture
4. Update `tools/__init__.py` to route to the real integration based on `DATA_SOURCE` env var

The tool signatures and return shapes stay the same. Claude doesn't know or care whether the data comes from a fixture or a live API.

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation5/5

Each tool targets a distinct aspect of PM context: current sprint, assignee issues, blockers, keyword search, roadmap, workload, and velocity. There is no overlap that would cause an agent to select the wrong tool for a given query.

Naming Consistency5/5

All tools follow a consistent [verb]_[noun]_tool pattern using snake_case. The only non-get verb is 'search', but it still fits the same structure, making the naming predictable and uniform.

Tool Count5/5

With 7 tools, the server is well-scoped for its purpose of providing PM context. Each tool covers a distinct read-only query without unnecessary redundancy or bloat.

Completeness4/5

The server covers core PM context areas like sprint status, issues, blockers, roadmap, workload, and velocity. However, it lacks a direct way to fetch all issues for a specific sprint or retrieve a single issue by ID, requiring search instead. These are minor gaps but not fatal.

Maintenance

ActivityInactive
ResponsivenessNo issues