Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,18 @@
"Bash(mv /c/Users/antjs/uds-renderer/create_plan.js /c/Users/antjs/uds-renderer/create_plan.cjs)",
"Bash(node create_plan.cjs)",
"Bash(git pull:*)",
"Bash(PYTHONIOENCODING=utf-8 python packages/pm-data-tools/scripts/generate_synthetic_data.py --verify)"
"Bash(PYTHONIOENCODING=utf-8 python packages/pm-data-tools/scripts/generate_synthetic_data.py --verify)",
"Bash(git worktree:*)",
"mcp__c1fc4002-5f49-5f9d-a4e5-93c4ef5d6a75__google_drive_search",
"WebSearch",
"WebFetch(domain:www.gov.uk)",
"WebFetch(domain:www.instituteforgovernment.org.uk)",
"WebFetch(domain:www.newcivilengineer.com)",
"WebFetch(domain:publications.parliament.uk)",
"WebFetch(domain:www.constructionnews.co.uk)",
"WebFetch(domain:www.productivity.ac.uk)",
"WebFetch(domain:www.reinforcementproductsonline.co.uk)",
"Bash(2)"
]
}
}
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,24 @@ Thumbs.db
.env
.env.local
*.local

# SQLite databases (demo/debug)
*.db
*.sqlite

# Claude worktrees
.claude/worktrees/

# Temp/debug files
*_debug.db
demo_*.json

# Internal docs (not for public repo)
ASSUMPTION_DRIFT_PROMPT.md

# Office temp files
~$*
*.docx
*.pdf
*.pptx
PROJ-MPA-HACK-005-dashboard.html
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ AI reliability framework with confidence extraction and outlier mining.

### pm-mcp-servers
MCP servers enabling Claude to interact with PM data.
- **Servers**: pm-data, pm-validate, pm-analyse, pm-benchmark
- **Unified server**: `pda-platform-server` exposes all 41 tools through a single endpoint
- **Modules**: pm-data (6 tools), pm-analyse (6), pm-validate (4), pm-nista (5), pm-assure (20)
- **Remote access**: `pda-platform-remote` adds SSE transport for use with Claude.ai
- **Install**: `pip install pm-mcp-servers`

## Specifications
Expand All @@ -78,7 +80,7 @@ All specifications are in the `specs/` directory:
| Spec | Description |
|------|-------------|
| [Canonical Model](specs/canonical-model/) | 12-entity JSON Schema for PM data |
| [MCP Servers](specs/mcp-servers/) | 4 servers, 19 tools for AI integration |
| [MCP Servers](specs/mcp-servers/) | 5 modules, 41 tools for AI integration |
| [Benchmarks](specs/benchmarks/) | 5 evaluation tasks for PM AI |
| [Synthetic Data](specs/synthetic-data/) | Privacy-preserving data generation |

Expand Down
39 changes: 17 additions & 22 deletions docs/architecture-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,33 +191,28 @@ openai # Optional: GPT integration
└──────────────────────────┘
```

#### Server Types
#### Unified Server

**1. pm-data-server**
- Tools: `read_project`, `list_tasks`, `get_resource`, `export_project`
- Purpose: Basic CRUD operations on PM data
The **`pda-platform-server`** is a single MCP endpoint that aggregates all 41 tools
from 5 modules. Each module exports a `registry.py` with its tool definitions and a
`dispatch()` function. The unified server imports and combines them at startup.

**2. pm-validate-server**
- Tools: `validate_nista`, `validate_structure`, `check_compliance`
- Purpose: Data quality and compliance checking
For remote access (e.g., from Claude.ai), **`pda-platform-remote`** wraps the unified
server in an SSE transport layer using Starlette and uvicorn.

**3. pm-analyse-server**
- Tools: `analyze_schedule`, `find_critical_path`, `identify_risks`, `calculate_metrics`
- Purpose: Advanced analytics and insights
#### Server Modules

**4. pm-benchmark-server**
- Tools: `compare_projects`, `benchmark_performance`, `generate_report`
- Purpose: Cross-project comparison
| Module | Tools | Purpose |
|--------|-------|---------|
| **pm-data** | 6 | Project data loading, querying, critical path, conversion |
| **pm-analyse** | 6 | AI-powered risk identification, forecasting, health assessment |
| **pm-validate** | 4 | Structural, semantic, and NISTA compliance validation |
| **pm-nista** | 5 | GMPP reporting, AI narratives, NISTA API integration |
| **pm-assure** | 20 | Assurance lifecycle: assumptions, compliance, findings, scheduling, overrides, lessons, overhead, workflows, domain classification |
| **Total** | **41** | |

**5. pm-nista-server**
- Tools: `nista_export`, `nista_validate`, `nista_transform`
- Purpose: NISTA-specific operations

**6. pm-assure-server**
- Tools: 16 tools across P1–P10 (see [docs/assurance.md](./assurance.md))
- Purpose: Full assurance quality lifecycle — artefact currency, compliance trends,
review action tracking, confidence monitoring, adaptive scheduling, override logging,
lessons learned, overhead optimisation, workflow orchestration, domain classification
Individual servers (`pm-data-server`, `pm-assure-server`, etc.) remain available for
use cases where only a subset of tools is needed.

**Design Decisions**:
- **Stateless**: Each request is independent
Expand Down
18 changes: 3 additions & 15 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,25 +208,13 @@ pip install pm-mcp-servers
# or %APPDATA%/Claude/claude_desktop_config.json (Windows)
```

Add to your Claude config:
Add the **unified server** to your Claude config (recommended — gives access to all 41 tools):

```json
{
"mcpServers": {
"pm-data": {
"command": "pm-data-server",
"args": []
},
"pm-validate": {
"command": "pm-validate-server",
"args": []
},
"pm-analyse": {
"command": "pm-analyse-server",
"args": []
},
"pm-assure": {
"command": "pm-assure-server",
"pda-platform": {
"command": "pda-platform-server",
"args": [],
"env": { "ANTHROPIC_API_KEY": "sk-ant-..." }
}
Expand Down
5 changes: 2 additions & 3 deletions packages/agent-task-planning/examples/02_multi_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@

import asyncio
import os
from typing import Optional

from agent_planning import TodoListPlanner, GuardrailConfig
from agent_planning import GuardrailConfig, TodoListPlanner
from agent_planning.providers.base import BaseProvider


def get_provider(name: str) -> Optional[BaseProvider]:
def get_provider(name: str) -> BaseProvider | None:
"""Get a provider by name."""
if name == "anthropic":
from agent_planning.providers import AnthropicProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import asyncio
import os

from agent_planning import TodoListPlanner, GuardrailConfig
from agent_planning import GuardrailConfig, TodoListPlanner
from agent_planning.providers import AnthropicProvider


Expand Down
9 changes: 5 additions & 4 deletions packages/agent-task-planning/examples/04_temporal_hybrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
# For actual use, install temporalio and configure a Temporal server.

try:
from temporalio import workflow, activity
from temporalio import activity, workflow
from temporalio.client import Client
from temporalio.worker import Worker
from temporalio.worker import Worker # noqa: F401
TEMPORAL_AVAILABLE = True
except ImportError:
TEMPORAL_AVAILABLE = False
Expand Down Expand Up @@ -67,9 +67,10 @@ async def agent_analyse(sources: list[str], topic: str) -> dict:
This is where the LLM-based planning happens, wrapped in
a deterministic activity with timeout and retry policies.
"""
import os

from agent_planning import TodoListPlanner
from agent_planning.providers import AnthropicProvider
import os

provider = AnthropicProvider(api_key=os.getenv("ANTHROPIC_API_KEY"))
planner = TodoListPlanner(provider=provider)
Expand Down Expand Up @@ -164,7 +165,7 @@ async def main():
task_queue="research-queue",
)

print(f"Research complete!")
print("Research complete!")
print(f"Summary: {result.summary[:200]}...")
print(f"Confidence: {result.confidence}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import asyncio
import os

from agent_planning import ConfidenceExtractor, SchemaType
from agent_planning.providers import AnthropicProvider
from agent_planning.guardrails import GuardrailConfig
from agent_planning.providers import AnthropicProvider


async def main():
Expand Down
4 changes: 2 additions & 2 deletions packages/agent-task-planning/examples/06_pm_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import asyncio
import os

from agent_planning.confidence import (
ConfidenceExtractor,
SchemaType,
ReviewLevel,
SchemaType,
)
from agent_planning.providers import AnthropicProvider


PROJECT_CONTEXT = """
Project: Legacy System Migration
Duration: 18 months
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

import asyncio
import os

from agent_planning.confidence import (
ConfidenceExtractor,
SchemaType,
confidence_extract_batch,
)
from agent_planning.providers import AnthropicProvider


CONTEXT = """
Project: Digital Transformation Initiative
Budget: £5M over 2 years
Expand Down Expand Up @@ -70,7 +69,7 @@ async def main():
progress_callback=progress,
)

print(f"\nBatch complete!")
print("\nBatch complete!")
print(f"Succeeded: {result.queries_succeeded}")
print(f"Failed: {result.queries_failed}")
print(f"Total cost: ${result.total_cost_usd:.4f}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import asyncio
import os
from dataclasses import dataclass

from agent_planning.confidence import (
ConfidenceExtractor,
CustomSchema,
Expand Down
3 changes: 2 additions & 1 deletion packages/agent-task-planning/examples/09_basic_mining.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import asyncio
import os
from agent_planning.mining import OutlierMiner, MiningConfig

from agent_planning.confidence import SchemaType
from agent_planning.mining import MiningConfig, OutlierMiner
from agent_planning.providers import AnthropicProvider


Expand Down
4 changes: 2 additions & 2 deletions packages/agent-task-planning/examples/10_risk_mining.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import asyncio
import os
from agent_planning.mining import OutlierMiner, MiningConfig

from agent_planning.confidence import SchemaType
from agent_planning.mining import MiningConfig, OutlierMiner
from agent_planning.providers import AnthropicProvider


PROJECT_CONTEXT = """
Project: Cloud Migration Programme
Budget: £5.2M
Expand Down
3 changes: 2 additions & 1 deletion packages/agent-task-planning/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,12 @@ testpaths = ["tests"]
asyncio_mode = "auto"

[tool.ruff]
line-length = 88
line-length = 120
target-version = "py310"

[tool.ruff.lint]
select = ["E", "F", "I", "N", "W", "UP"]
ignore = ["E501", "E722", "N818", "N806", "F821"]

[tool.mypy]
python_version = "3.10"
Expand Down
5 changes: 3 additions & 2 deletions packages/agent-task-planning/scripts/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# Add src to path for development
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))

from agent_planning import TodoListPlanner, GuardrailConfig
from agent_planning import GuardrailConfig, TodoListPlanner


def get_provider(provider_name: str, model: str | None = None):
Expand Down Expand Up @@ -73,8 +73,9 @@ async def main():

# Setup logging if verbose
if args.verbose:
import structlog
import logging

import structlog
structlog.configure(
wrapper_class=structlog.make_filtering_bound_logger(logging.DEBUG),
)
Expand Down
20 changes: 10 additions & 10 deletions packages/agent-task-planning/src/agent_planning/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@
result = await planner.execute("Your complex task here")
"""

from agent_planning.core.task import Task, TaskStatus
from agent_planning.core.state import TaskState, ExecutionResult
from agent_planning.core.planner import BasePlanner
from agent_planning.planners.todo_list import TodoListPlanner
from agent_planning.guardrails.limits import GuardrailConfig
from agent_planning.confidence import (
ConfidenceExtractor,
confidence_extract,
confidence_extract_batch,
ConfidenceResult,
SchemaType,
ReviewLevel,
SchemaType,
confidence_extract,
confidence_extract_batch,
)
from agent_planning.core.planner import BasePlanner
from agent_planning.core.state import ExecutionResult, TaskState
from agent_planning.core.task import Task, TaskStatus
from agent_planning.guardrails.limits import GuardrailConfig
from agent_planning.mining import (
MiningConfig,
MiningResult,
OutlierMiner,
mine,
mine_batch,
MiningConfig,
MiningResult,
)
from agent_planning.planners.todo_list import TodoListPlanner

__version__ = "0.1.0"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
confidence_extract_batch,
)
from .models import (
ConfidenceResult,
BatchConfidenceResult,
ConfidenceResult,
EstimateMode,
OutlierReport,
ReviewLevel,
EstimateMode,
)
from .schemas import (
SchemaType,
BarrierItem,
CustomSchema,
RiskItem,
EstimateItem,
RecommendationItem,
MilestoneItem,
BarrierItem,
OutcomeMeasureItem,
RecommendationItem,
RiskItem,
SchemaType,
StakeholderImpactItem,
)

Expand Down
Loading
Loading