feat: implement XER MCP Server with 9 schedule query tools
Implement complete MCP server for parsing Primavera P6 XER files and exposing schedule data through MCP tools. All 4 user stories complete. Tools implemented: - load_xer: Parse XER files into SQLite database - list_activities: Query activities with pagination and filtering - get_activity: Get activity details by ID - list_relationships: Query activity dependencies - get_predecessors/get_successors: Query activity relationships - get_project_summary: Project overview with counts - list_milestones: Query milestone activities - get_critical_path: Query driving path activities Features: - Tab-delimited XER format parsing with pluggable table handlers - In-memory SQLite database for fast queries - Pagination with 100-item default limit - Multi-project file support with project selection - ISO8601 date formatting - NO_FILE_LOADED error handling for all query tools Test coverage: 81 tests (contract, integration, unit)
This commit is contained in:
38
src/xer_mcp/parser/table_handlers/project.py
Normal file
38
src/xer_mcp/parser/table_handlers/project.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""PROJECT table handler."""
|
||||
|
||||
from xer_mcp.parser.table_handlers.base import TableHandler
|
||||
|
||||
|
||||
def convert_date(date_str: str | None) -> str | None:
|
||||
"""Convert XER date format to ISO8601.
|
||||
|
||||
XER format: "YYYY-MM-DD HH:MM"
|
||||
ISO8601 format: "YYYY-MM-DDTHH:MM:SS"
|
||||
"""
|
||||
if not date_str or date_str.strip() == "":
|
||||
return None
|
||||
# Replace space with T and add seconds
|
||||
return date_str.replace(" ", "T") + ":00"
|
||||
|
||||
|
||||
class ProjectHandler(TableHandler):
|
||||
"""Handler for PROJECT table in XER files."""
|
||||
|
||||
@property
|
||||
def table_name(self) -> str:
|
||||
return "PROJECT"
|
||||
|
||||
def parse_row(self, fields: list[str], values: list[str]) -> dict | None:
|
||||
"""Parse a PROJECT row."""
|
||||
if len(values) < len(fields):
|
||||
# Pad with empty strings if needed
|
||||
values = values + [""] * (len(fields) - len(values))
|
||||
|
||||
data = dict(zip(fields, values, strict=False))
|
||||
|
||||
return {
|
||||
"proj_id": data.get("proj_id", ""),
|
||||
"proj_short_name": data.get("proj_short_name", ""),
|
||||
"plan_start_date": convert_date(data.get("plan_start_date")),
|
||||
"plan_end_date": convert_date(data.get("plan_end_date")),
|
||||
}
|
||||
Reference in New Issue
Block a user