diff --git a/CLAUDE.md b/CLAUDE.md
index b2c1383..ad2e51b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1,10 +1,10 @@
# CLAUDE.md
-This file provides guidance to Claude Code (claude.ai/code) when working with the MCP Office Tools codebase.
+This file provides guidance to Claude Code (claude.ai/code) when working with the mcwaddams codebase.
## Project Overview
-MCP Office Tools is a FastMCP server that provides comprehensive Microsoft Office document processing capabilities including text extraction, image extraction, metadata extraction, and format detection. The server supports Word (.docx, .doc), Excel (.xlsx, .xls), PowerPoint (.pptx, .ppt), and CSV files with intelligent method selection and automatic fallbacks.
+mcwaddams is a FastMCP server that provides comprehensive Microsoft Office document processing capabilities including text extraction, image extraction, metadata extraction, and format detection. The server supports Word (.docx, .doc), Excel (.xlsx, .xls), PowerPoint (.pptx, .ppt), and CSV files with intelligent method selection and automatic fallbacks.
## Development Commands
@@ -23,7 +23,7 @@ uv sync --dev
uv run pytest
# Run with coverage
-uv run pytest --cov=mcp_office_tools
+uv run pytest --cov=mcwaddams
# Run specific test file
uv run pytest tests/test_server.py
@@ -47,10 +47,10 @@ uv run mypy src/
### Running the Server
```bash
# Run MCP server directly
-uv run mcp-office-tools
+uv run mcwaddams
# Run with Python module
-uv run python -m mcp_office_tools.server
+uv run python -m mcwaddams.server
# Test with sample documents
uv run python examples/test_office_tools.py /path/to/test.docx
@@ -69,8 +69,8 @@ uv publish
### Core Components
-- **`src/mcp_office_tools/server.py`**: Main server implementation with all Office processing tools
-- **`src/mcp_office_tools/utils/`**: Utility modules for validation, caching, and file detection
+- **`src/mcwaddams/server.py`**: Main server implementation with all Office processing tools
+- **`src/mcwaddams/utils/`**: Utility modules for validation, caching, and file detection
- **FastMCP Framework**: Uses FastMCP for MCP protocol implementation
- **Multi-library approach**: Integrates python-docx, openpyxl, python-pptx, pandas, and legacy format handlers
@@ -165,8 +165,8 @@ Tools are registered using FastMCP decorators and follow MCP protocol standards
## Project Structure
```
-mcp-office-tools/
-├── src/mcp_office_tools/
+mcwaddams/
+├── src/mcwaddams/
│ ├── __init__.py # Package initialization
│ ├── server.py # Main FastMCP server with tools
│ ├── utils/ # Utility modules
@@ -218,7 +218,7 @@ The project uses pytest with:
## Relationship to MCP PDF Tools
-MCP Office Tools is designed as a companion to MCP PDF Tools:
+mcwaddams is designed as a companion to MCP PDF Tools:
- Consistent API design patterns
- Similar caching and URL handling
- Parallel tool organization
diff --git a/IMPLEMENTATION_STATUS.md b/IMPLEMENTATION_STATUS.md
index e27ed95..202bbb0 100644
--- a/IMPLEMENTATION_STATUS.md
+++ b/IMPLEMENTATION_STATUS.md
@@ -151,10 +151,10 @@ except OfficeFileError as e:
### **Server Status: OPERATIONAL ✅**
```bash
-$ uv run mcp-office-tools --version
+$ uv run mcwaddams --version
MCP Office Tools v0.1.0
-$ uv run mcp-office-tools
+$ uv run mcwaddams
[Server starts successfully with FastMCP banner]
```
@@ -178,8 +178,8 @@ $ uv run mcp-office-tools
```json
{
"mcpServers": {
- "mcp-office-tools": {
- "command": "mcp-office-tools"
+ "mcwaddams": {
+ "command": "mcwaddams"
}
}
}
diff --git a/Makefile b/Makefile
index 99cbabd..d6516ff 100644
--- a/Makefile
+++ b/Makefile
@@ -97,13 +97,13 @@ quick-test:
# Coverage report
coverage:
@echo "📊 Generating coverage report..."
- @uv run pytest --cov=mcp_office_tools --cov-report=html --cov-report=term
+ @uv run pytest --cov=mcwaddams --cov-report=html --cov-report=term
@echo "✅ Coverage report generated at htmlcov/index.html"
# Run server in development mode
dev:
@echo "🚀 Starting MCP Office Tools server..."
- @uv run mcp-office-tools
+ @uv run mcwaddams
# Build distribution packages
build:
@@ -116,7 +116,7 @@ info:
@echo "MCP Office Tools - Project Information"
@echo "======================================="
@echo ""
- @echo "Project: mcp-office-tools"
+ @echo "Project: mcwaddams"
@echo "Version: $(shell grep '^version' pyproject.toml | cut -d'"' -f2)"
@echo "Python: $(shell python --version)"
@echo "UV: $(shell uv --version 2>/dev/null || echo 'not installed')"
diff --git a/README.md b/README.md
index fb3ce60..ad07f90 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,15 @@
-# 📊 MCP Office Tools
+# 📎 mcwaddams
-**MCP server for extracting text, tables, images, and data from Microsoft Office files**
+**MCP server for Microsoft Office document processing**
[](https://www.python.org/downloads/)
[](https://gofastmcp.com)
[](https://opensource.org/licenses/MIT)
[](https://modelcontextprotocol.io)
-*Word, Excel, PowerPoint, CSV — all the formats your AI agent needs to read but can't*
+*"I was told there would be document extraction."*
[Installation](#-installation) • [Tools](#-available-tools) • [Examples](#-usage-examples) • [Testing](#-testing)
@@ -17,14 +17,22 @@
---
+## The Backstory
+
+Milton Waddams was relocated to the basement. They took his stapler. But down there, surrounded by boxes of `.doc` files from 1997 and `.xls` spreadsheets that predate Unicode, he became something else entirely: a document processing expert.
+
+This MCP server channels that energy. It handles the legacy formats nobody else wants to touch. It extracts text from files that should have been migrated to Google Docs a decade ago. It reads the TPS reports.
+
+---
+
## ✨ Features
- **Universal extraction** — Pull text, images, and metadata from any Office format
- **Format-specific tools** — Deep analysis for Word (tables, structure), Excel (formulas, charts), PowerPoint
- **Automatic pagination** — Large documents get chunked so they don't blow up your context window
-- **Fallback processing** — When one library chokes on a weird file, we try another. No silent failures.
+- **Fallback processing** — When one library chokes on a weird file, we try another
- **URL support** — Pass a URL instead of a file path; we'll download and cache it
-- **Legacy formats** — Yes, even those .doc and .xls files from 2003 still work
+- **Legacy formats** — Yes, even those `.doc` and `.xls` files from the basement
---
@@ -32,11 +40,11 @@
```bash
# Quick install with uvx (recommended)
-uvx mcp-office-tools
+uvx mcwaddams
# Or install with uv/pip
-uv add mcp-office-tools
-pip install mcp-office-tools
+uv add mcwaddams
+pip install mcwaddams
```
### Claude Desktop Configuration
@@ -46,9 +54,9 @@ Add to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
- "office-tools": {
+ "mcwaddams": {
"command": "uvx",
- "args": ["mcp-office-tools"]
+ "args": ["mcwaddams"]
}
}
}
@@ -57,7 +65,7 @@ Add to your `claude_desktop_config.json`:
### Claude Code Configuration
```bash
-claude mcp add office-tools "uvx mcp-office-tools"
+claude mcp add mcwaddams "uvx mcwaddams"
```
---
@@ -183,7 +191,7 @@ Use `text_patterns_only=True` to skip heading style detection for documents with
## 🎯 MCP Prompts
-Pre-built workflows that chain multiple tools together. Use these as starting points:
+Pre-built workflows that chain multiple tools together:
| Prompt | Level | Description |
|--------|-------|-------------|
@@ -245,99 +253,7 @@ result = await analyze_excel_data(
check_data_quality=True
)
-# Returns per-column analysis
-# {
-# "analysis": {
-# "Sheet1": {
-# "dimensions": {"rows": 1000, "columns": 12},
-# "column_info": {
-# "Revenue": {
-# "data_type": "float64",
-# "null_percentage": 2.3,
-# "statistics": {"mean": 45000, "median": 42000, ...},
-# "quality_issues": ["5 potential outliers"]
-# }
-# },
-# "data_quality": {
-# "completeness_percentage": 97.8,
-# "duplicate_rows": 12
-# }
-# }
-# }
-# }
-```
-
-### Extract Excel Formulas
-
-```python
-result = await extract_excel_formulas(
- file_path="financial-model.xlsx",
- analyze_dependencies=True
-)
-
-# Returns formula details with dependency mapping
-# {
-# "formulas": {
-# "Sheet1": [
-# {
-# "cell": "D2",
-# "formula": "=B2*C2",
-# "value": 1500.00,
-# "dependencies": ["B2", "C2"]
-# }
-# ]
-# }
-# }
-```
-
-### Generate Chart Data
-
-```python
-result = await create_excel_chart_data(
- file_path="quarterly-revenue.xlsx",
- chart_type="line",
- output_format="chartjs"
-)
-
-# Returns ready-to-use Chart.js configuration
-# {
-# "chartjs": {
-# "type": "line",
-# "data": {
-# "labels": ["Q1", "Q2", "Q3", "Q4"],
-# "datasets": [{"label": "Revenue", "data": [100, 120, 115, 140]}]
-# }
-# }
-# }
-```
-
-### Extract Word Tables
-
-```python
-result = await extract_word_tables(
- file_path="contract.docx",
- output_format="markdown"
-)
-
-# Returns tables with optional format conversion
-# {
-# "tables": [
-# {
-# "table_index": 0,
-# "dimensions": {"rows": 5, "columns": 3},
-# "converted_output": "| Name | Role | Department |\n|---|---|---|\n..."
-# }
-# ]
-# }
-```
-
-### Process Documents from URLs
-
-```python
-# Documents are downloaded and cached automatically
-result = await extract_text("https://example.com/report.docx")
-
-# Cache expires after 1 hour by default
+# Returns per-column analysis with quality issues
```
### Index Document for On-Demand Resource Fetching
@@ -351,8 +267,7 @@ result = await index_document("novel.docx")
# "doc_id": "56036b0f171a",
# "resources": {
# "chapter": [
-# {"id": "1", "title": "Chapter 1: The Beginning", "uri": "chapter://56036b0f171a/1"},
-# {"id": "2", "title": "Chapter 2: Rising Action", "uri": "chapter://56036b0f171a/2"},
+# {"id": "1", "title": "Chapter 1", "uri": "chapter://56036b0f171a/1"},
# ...
# ],
# "image": [
@@ -362,63 +277,47 @@ result = await index_document("novel.docx")
# }
# }
-# Now fetch specific content via MCP resources:
+# Fetch specific content via MCP resources:
# - chapter://56036b0f171a/1 → Chapter 1 as markdown
# - chapter://56036b0f171a/1.txt → Chapter 1 as plain text
# - chapters://56036b0f171a/1-3 → Chapters 1-3 combined
-# - image://56036b0f171a/0 → First embedded image
-
-# Works with Excel and PowerPoint too:
-await index_document("data.xlsx")
-# → sheet://abc123/Revenue, sheet://abc123/Expenses, ...
-
-await index_document("presentation.pptx")
-# → slide://def456/1, slide://def456/2, ...
```
---
## 🧪 Testing
-We built a visual test dashboard because staring at pytest output gets old. Run `make test` and you get an HTML report with pass/fail stats, detailed I/O for each test, and expandable tracebacks when things break.
-
```bash
# Run tests and generate the dashboard
make test
-# Just pytest, no dashboard
+# Just pytest
make test-pytest
-# Open existing dashboard
+# Open dashboard
make view-dashboard
```
-The dashboard has an MS Office-inspired theme (Word blue, Excel green, PowerPoint orange) and groups tests by category so you can see what's working at a glance.
-
---
## 🏗 Architecture
-The mixin pattern keeps things modular — universal tools work on everything, format-specific tools go deeper. When the primary library can't handle something (corrupted files, weird formatting), we fall back to alternatives.
+The mixin pattern keeps things modular — universal tools work on everything, format-specific tools go deeper.
```
-mcp-office-tools/
-├── src/mcp_office_tools/
+mcwaddams/
+├── src/mcwaddams/
│ ├── server.py # FastMCP server + resource templates
│ ├── resources.py # Resource store for on-demand content
│ ├── mixins/
-│ │ ├── universal.py # Format-agnostic tools (incl. index_document)
+│ │ ├── universal.py # Format-agnostic tools
│ │ ├── word.py # Word-specific tools
│ │ ├── excel.py # Excel-specific tools
-│ │ └── powerpoint.py # PowerPoint tools (WIP)
-│ ├── utils/
-│ │ ├── validation.py # File validation
-│ │ ├── file_detection.py # Format detection
-│ │ ├── caching.py # URL caching
-│ │ └── decorators.py # Error handling, defaults
+│ │ └── powerpoint.py # PowerPoint tools
+│ ├── utils/ # Validation, caching, detection
│ └── pagination.py # Large document pagination
-├── tests/ # pytest test suite
-└── reports/ # Test dashboard output
+├── tests/
+└── reports/
```
### Processing Libraries
@@ -436,57 +335,17 @@ mcp-office-tools/
## 🔧 Development
```bash
-# Clone and install
-git clone https://github.com/yourusername/mcp-office-tools.git
-cd mcp-office-tools
+git clone https://github.com/ryanmalloy/mcwaddams.git
+cd mcwaddams
uv sync --dev
-# Run tests
uv run pytest
-
-# Format and lint
uv run black src/ tests/
uv run ruff check src/ tests/
-
-# Type check
-uv run mypy src/
```
---
-## 📦 Dependencies
-
-**Core:**
-- `fastmcp` - MCP server framework
-- `python-docx` - Word document processing
-- `openpyxl` - Excel spreadsheet processing
-- `python-pptx` - PowerPoint processing
-- `pandas` - Data analysis and CSV handling
-- `mammoth` - Word to HTML/Markdown conversion
-- `olefile` - Legacy OLE format support
-- `xlrd` - Legacy Excel support
-- `pillow` - Image processing
-- `aiohttp` / `aiofiles` - Async HTTP and file I/O
-
-**Optional:**
-- `python-magic` - Enhanced MIME type detection
-- `msoffcrypto-tool` - Encrypted file detection
-
----
-
-## 🤝 Related Projects
-
-- **[MCP PDF Tools](https://github.com/yourusername/mcp-pdf-tools)** - Companion server for PDF processing
-- **[FastMCP](https://gofastmcp.com)** - The framework powering this server
-
-## 📝 Behind the Scenes
-
-This README was rewritten during a human-AI collaboration session. The process raised questions about discernment, voice, and what makes documentation actually land:
-
-- **[AI Isn't New. Your Discernment Is What Matters.](https://ryanmalloy.com/blog/ai-discernment)** — Ryan's take on 40 years of writing code and why discernment matters more than the tools
-
----
-
## 📜 License
MIT License - see [LICENSE](LICENSE) for details.
@@ -495,6 +354,8 @@ MIT License - see [LICENSE](LICENSE) for details.
+*Named for Milton Waddams, who was relocated to the basement with the legacy documents.*
+
**Built with [FastMCP](https://gofastmcp.com) and the [Model Context Protocol](https://modelcontextprotocol.io)**
diff --git a/TESTING_STRATEGY.md b/TESTING_STRATEGY.md
index 403c085..de42ee8 100644
--- a/TESTING_STRATEGY.md
+++ b/TESTING_STRATEGY.md
@@ -59,7 +59,7 @@ async def test_tool_functionality():
mixin = UniversalMixin(app)
# Mock dependencies
- with patch('mcp_office_tools.utils.validation.validate_office_file'):
+ with patch('mcwaddams.utils.validation.validate_office_file'):
# Test tool directly through mixin
result = await mixin.extract_text("/test.csv")
assert "text" in result
@@ -185,13 +185,13 @@ uv run pytest
uv run pytest tests/test_universal_mixin.py -v
# With coverage
-uv run pytest --cov=mcp_office_tools
+uv run pytest --cov=mcwaddams
```
### Continuous Integration
```bash
# All tests with coverage reporting
-uv run pytest --cov=mcp_office_tools --cov-report=xml --cov-report=html
+uv run pytest --cov=mcwaddams --cov-report=xml --cov-report=html
```
## Key Testing Fixtures
diff --git a/docs/DOCX_PROCESSING_FIXES.md b/docs/DOCX_PROCESSING_FIXES.md
index ae2dc2f..ce42fc4 100644
--- a/docs/DOCX_PROCESSING_FIXES.md
+++ b/docs/DOCX_PROCESSING_FIXES.md
@@ -17,7 +17,7 @@ This document captures critical bugs discovered and fixed while processing compl
## 1. FastMCP Banner Corruption
-**File:** `src/mcp_office_tools/server.py`
+**File:** `src/mcwaddams/server.py`
**Symptom:** MCP connection fails with `Invalid JSON: EOF while parsing`
@@ -35,7 +35,7 @@ def main():
## 2. Page Range Cap Bug
-**File:** `src/mcp_office_tools/utils/word_processing.py`
+**File:** `src/mcwaddams/utils/word_processing.py`
**Symptom:** Requesting pages 1-5 returns truncated content, but pages 195-200 returns everything.
@@ -57,7 +57,7 @@ max_chars = num_pages_requested * 50000
## 3. Heading Scan Limit Bug
-**File:** `src/mcp_office_tools/utils/word_processing.py`
+**File:** `src/mcwaddams/utils/word_processing.py`
**Symptom:** `_get_available_headings()` returns empty list for documents with chapters beyond the first few pages.
@@ -81,7 +81,7 @@ for element in doc.element.body: # Scan ALL elements
## 4. Short-Text Fallback Logic Bug
-**File:** `src/mcp_office_tools/utils/word_processing.py`
+**File:** `src/mcwaddams/utils/word_processing.py`
**Symptom:** Chapter search fails even when chapter text exists and is under 100 characters.
@@ -115,7 +115,7 @@ if is_heading_style or len(text_content.strip()) < 100:
## 5. Critical xpath API Mismatch (ROOT CAUSE)
-**File:** `src/mcp_office_tools/utils/word_processing.py`
+**File:** `src/mcwaddams/utils/word_processing.py`
**Symptom:** Chapter search always returns "not found" even for chapters that clearly exist.
@@ -152,7 +152,7 @@ if pPr is not None:
## 6. Image Mode Default
-**File:** `src/mcp_office_tools/mixins/word.py`
+**File:** `src/mcwaddams/mixins/word.py`
**Symptom:** Responses exceed token limits when documents contain images.
diff --git a/examples/test_office_tools.py b/examples/test_office_tools.py
index 6f242ff..4552e91 100644
--- a/examples/test_office_tools.py
+++ b/examples/test_office_tools.py
@@ -10,7 +10,7 @@ from pathlib import Path
# Add the package to Python path for local testing
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
-from mcp_office_tools.server import (
+from mcwaddams.server import (
extract_text,
extract_images,
extract_metadata,
diff --git a/examples/verify_installation.py b/examples/verify_installation.py
index a51f0c9..092a70e 100644
--- a/examples/verify_installation.py
+++ b/examples/verify_installation.py
@@ -29,15 +29,15 @@ def test_import():
print("🔍 Testing package import...")
try:
- import mcp_office_tools
- print(f"✅ Package imported successfully - Version: {mcp_office_tools.__version__}")
+ import mcwaddams
+ print(f"✅ Package imported successfully - Version: {mcwaddams.__version__}")
# Test server import
- from mcp_office_tools.server import app
+ from mcwaddams.server import app
print("✅ Server module imported successfully")
# Test utils import
- from mcp_office_tools.utils import OfficeFileError, get_supported_extensions
+ from mcwaddams.utils import OfficeFileError, get_supported_extensions
print("✅ Utils module imported successfully")
# Test supported extensions
@@ -58,7 +58,7 @@ async def test_utils():
print("\n🔧 Testing utility functions...")
try:
- from mcp_office_tools.utils import (
+ from mcwaddams.utils import (
detect_file_format,
validate_office_path,
OfficeFileError
@@ -103,7 +103,7 @@ def test_server_structure():
print("\n🖥️ Testing server structure...")
try:
- from mcp_office_tools.server import app
+ from mcwaddams.server import app
# Check that app has tools
if hasattr(app, '_tools'):
@@ -134,7 +134,7 @@ async def test_caching():
print("\n📦 Testing caching functionality...")
try:
- from mcp_office_tools.utils.caching import OfficeFileCache, get_cache
+ from mcwaddams.utils.caching import OfficeFileCache, get_cache
# Test cache creation
cache = get_cache()
@@ -145,7 +145,7 @@ async def test_caching():
print(f"✅ Cache stats: {stats['total_files']} files, {stats['total_size_mb']} MB")
# Test URL validation
- from mcp_office_tools.utils.validation import is_url
+ from mcwaddams.utils.validation import is_url
assert is_url("https://example.com/file.docx")
assert not is_url("/local/path/file.docx")
@@ -243,7 +243,7 @@ async def main():
print("🎉 Installation verified successfully!")
print("✅ MCP Office Tools is ready to use.")
print("\n🚀 Next steps:")
- print(" 1. Run the MCP server: uv run mcp-office-tools")
+ print(" 1. Run the MCP server: uv run mcwaddams")
print(" 2. Add to Claude Desktop config")
print(" 3. Test with Office documents")
return 0
diff --git a/pyproject.toml b/pyproject.toml
index 556fdde..b7f14e3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,12 +1,12 @@
[project]
-name = "mcp-office-tools"
+name = "mcwaddams"
version = "0.1.0"
-description = "MCP server for comprehensive Microsoft Office document processing"
-authors = [{name = "MCP Office Tools", email = "contact@mcpofficetools.dev"}]
+description = "MCP server for Microsoft Office document processing. Named for Milton Waddams, who was relocated to the basement with boxes of legacy documents."
+authors = [{name = "Ryan Malloy", email = "ryan@supported.systems"}]
readme = "README.md"
license = {text = "MIT"}
requires-python = ">=3.11"
-keywords = ["mcp", "office", "docx", "xlsx", "pptx", "word", "excel", "powerpoint", "document", "processing"]
+keywords = ["mcp", "office", "docx", "xlsx", "pptx", "word", "excel", "powerpoint", "document", "processing", "milton", "legacy"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
@@ -64,20 +64,19 @@ enhanced = [
]
[project.urls]
-Homepage = "https://github.com/mcp-office-tools/mcp-office-tools"
-Documentation = "https://mcp-office-tools.readthedocs.io"
-Repository = "https://github.com/mcp-office-tools/mcp-office-tools"
-Issues = "https://github.com/mcp-office-tools/mcp-office-tools/issues"
+Homepage = "https://github.com/ryanmalloy/mcwaddams"
+Repository = "https://github.com/ryanmalloy/mcwaddams"
+Issues = "https://github.com/ryanmalloy/mcwaddams/issues"
[project.scripts]
-mcp-office-tools = "mcp_office_tools.server:main"
+mcwaddams = "mcwaddams.server:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
-packages = ["src/mcp_office_tools"]
+packages = ["src/mcwaddams"]
[tool.hatch.build.targets.sdist]
include = [
@@ -145,7 +144,7 @@ minversion = "7.0"
addopts = [
"--strict-markers",
"--strict-config",
- "--cov=mcp_office_tools",
+ "--cov=mcwaddams",
"--cov-report=term-missing",
"--cov-report=html",
"--cov-report=xml",
@@ -161,7 +160,7 @@ markers = [
]
[tool.coverage.run]
-source = ["src/mcp_office_tools"]
+source = ["src/mcwaddams"]
omit = [
"*/tests/*",
"*/test_*",
diff --git a/reports/test_results.json b/reports/test_results.json
index 17f47cb..6c847f2 100644
--- a/reports/test_results.json
+++ b/reports/test_results.json
@@ -1,9 +1,9 @@
{
"metadata": {
- "start_time": "2026-01-11T09:40:29.164041",
+ "start_time": "2026-01-11T11:35:12.792077",
"pytest_version": "9.0.2",
- "end_time": "2026-01-11T09:40:30.048909",
- "duration": 0.8848621845245361,
+ "end_time": "2026-01-11T11:35:14.191660",
+ "duration": 1.399580955505371,
"exit_status": 0
},
"summary": {
diff --git a/src/mcp_office_tools/__init__.py b/src/mcwaddams/__init__.py
similarity index 100%
rename from src/mcp_office_tools/__init__.py
rename to src/mcwaddams/__init__.py
diff --git a/src/mcp_office_tools/mixins/__init__.py b/src/mcwaddams/mixins/__init__.py
similarity index 100%
rename from src/mcp_office_tools/mixins/__init__.py
rename to src/mcwaddams/mixins/__init__.py
diff --git a/src/mcp_office_tools/mixins/excel.py b/src/mcwaddams/mixins/excel.py
similarity index 100%
rename from src/mcp_office_tools/mixins/excel.py
rename to src/mcwaddams/mixins/excel.py
diff --git a/src/mcp_office_tools/mixins/powerpoint.py b/src/mcwaddams/mixins/powerpoint.py
similarity index 100%
rename from src/mcp_office_tools/mixins/powerpoint.py
rename to src/mcwaddams/mixins/powerpoint.py
diff --git a/src/mcp_office_tools/mixins/universal.py b/src/mcwaddams/mixins/universal.py
similarity index 100%
rename from src/mcp_office_tools/mixins/universal.py
rename to src/mcwaddams/mixins/universal.py
diff --git a/src/mcp_office_tools/mixins/word.py b/src/mcwaddams/mixins/word.py
similarity index 100%
rename from src/mcp_office_tools/mixins/word.py
rename to src/mcwaddams/mixins/word.py
diff --git a/src/mcp_office_tools/pagination.py b/src/mcwaddams/pagination.py
similarity index 100%
rename from src/mcp_office_tools/pagination.py
rename to src/mcwaddams/pagination.py
diff --git a/src/mcp_office_tools/processors/__init__.py b/src/mcwaddams/processors/__init__.py
similarity index 100%
rename from src/mcp_office_tools/processors/__init__.py
rename to src/mcwaddams/processors/__init__.py
diff --git a/src/mcp_office_tools/resources.py b/src/mcwaddams/resources.py
similarity index 100%
rename from src/mcp_office_tools/resources.py
rename to src/mcwaddams/resources.py
diff --git a/src/mcp_office_tools/server.py b/src/mcwaddams/server.py
similarity index 100%
rename from src/mcp_office_tools/server.py
rename to src/mcwaddams/server.py
diff --git a/src/mcp_office_tools/utils/__init__.py b/src/mcwaddams/utils/__init__.py
similarity index 100%
rename from src/mcp_office_tools/utils/__init__.py
rename to src/mcwaddams/utils/__init__.py
diff --git a/src/mcp_office_tools/utils/caching.py b/src/mcwaddams/utils/caching.py
similarity index 100%
rename from src/mcp_office_tools/utils/caching.py
rename to src/mcwaddams/utils/caching.py
diff --git a/src/mcp_office_tools/utils/decorators.py b/src/mcwaddams/utils/decorators.py
similarity index 100%
rename from src/mcp_office_tools/utils/decorators.py
rename to src/mcwaddams/utils/decorators.py
diff --git a/src/mcp_office_tools/utils/excel_processing.py b/src/mcwaddams/utils/excel_processing.py
similarity index 100%
rename from src/mcp_office_tools/utils/excel_processing.py
rename to src/mcwaddams/utils/excel_processing.py
diff --git a/src/mcp_office_tools/utils/file_detection.py b/src/mcwaddams/utils/file_detection.py
similarity index 100%
rename from src/mcp_office_tools/utils/file_detection.py
rename to src/mcwaddams/utils/file_detection.py
diff --git a/src/mcp_office_tools/utils/powerpoint_processing.py b/src/mcwaddams/utils/powerpoint_processing.py
similarity index 100%
rename from src/mcp_office_tools/utils/powerpoint_processing.py
rename to src/mcwaddams/utils/powerpoint_processing.py
diff --git a/src/mcp_office_tools/utils/processing.py b/src/mcwaddams/utils/processing.py
similarity index 100%
rename from src/mcp_office_tools/utils/processing.py
rename to src/mcwaddams/utils/processing.py
diff --git a/src/mcp_office_tools/utils/validation.py b/src/mcwaddams/utils/validation.py
similarity index 100%
rename from src/mcp_office_tools/utils/validation.py
rename to src/mcwaddams/utils/validation.py
diff --git a/src/mcp_office_tools/utils/word_processing.py b/src/mcwaddams/utils/word_processing.py
similarity index 100%
rename from src/mcp_office_tools/utils/word_processing.py
rename to src/mcwaddams/utils/word_processing.py
diff --git a/test_mcp_tools.py b/test_mcp_tools.py
index 185b08b..d37c7e4 100644
--- a/test_mcp_tools.py
+++ b/test_mcp_tools.py
@@ -39,7 +39,7 @@ async def test_mcp_server():
try:
# Import the server components
- from mcp_office_tools.mixins import UniversalMixin
+ from mcwaddams.mixins import UniversalMixin
# Test the Universal Mixin directly
universal = UniversalMixin()
diff --git a/test_pagination.py b/test_pagination.py
index ec63ae1..0f7355c 100644
--- a/test_pagination.py
+++ b/test_pagination.py
@@ -12,9 +12,9 @@ def test_pagination():
try:
# Import the server components
- from mcp_office_tools.server import app
- from mcp_office_tools.mixins.word import WordMixin
- from mcp_office_tools.pagination import DocumentPaginationManager, paginate_document_conversion
+ from mcwaddams.server import app
+ from mcwaddams.mixins.word import WordMixin
+ from mcwaddams.pagination import DocumentPaginationManager, paginate_document_conversion
print("✅ Successfully imported all pagination components:")
print(" • DocumentPaginationManager")
diff --git a/tests/conftest.py b/tests/conftest.py
index 407f354..17708a0 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -14,7 +14,7 @@ from typing import Dict, Any
from fastmcp import FastMCP
# FastMCP testing utilities are created manually
-from mcp_office_tools.mixins import UniversalMixin, WordMixin, ExcelMixin, PowerPointMixin
+from mcwaddams.mixins import UniversalMixin, WordMixin, ExcelMixin, PowerPointMixin
@pytest.fixture
@@ -211,23 +211,23 @@ class MockValidationContext:
self.patches = []
def __enter__(self):
- import mcp_office_tools.utils.validation
- import mcp_office_tools.utils.file_detection
+ import mcwaddams.utils.validation
+ import mcwaddams.utils.file_detection
from unittest.mock import patch
if self.resolve_path:
- p1 = patch('mcp_office_tools.utils.validation.resolve_office_file_path',
+ p1 = patch('mcwaddams.utils.validation.resolve_office_file_path',
return_value=self.resolve_path)
self.patches.append(p1)
p1.start()
- p2 = patch('mcp_office_tools.utils.validation.validate_office_file',
+ p2 = patch('mcwaddams.utils.validation.validate_office_file',
return_value=self.validation_result)
self.patches.append(p2)
p2.start()
- p3 = patch('mcp_office_tools.utils.file_detection.detect_format',
+ p3 = patch('mcwaddams.utils.file_detection.detect_format',
return_value=self.format_detection)
self.patches.append(p3)
p3.start()
diff --git a/tests/test_mixins.py b/tests/test_mixins.py
index cd47f3b..9b9af4b 100644
--- a/tests/test_mixins.py
+++ b/tests/test_mixins.py
@@ -20,8 +20,8 @@ from typing import Dict, Any
from fastmcp import FastMCP
# FastMCP testing - using direct tool access
-from mcp_office_tools.mixins import UniversalMixin, WordMixin, ExcelMixin, PowerPointMixin
-from mcp_office_tools.utils import OfficeFileError
+from mcwaddams.mixins import UniversalMixin, WordMixin, ExcelMixin, PowerPointMixin
+from mcwaddams.utils import OfficeFileError
class TestMixinArchitecture:
@@ -131,9 +131,9 @@ class TestUniversalMixinUnit:
await universal_mixin.extract_text("/nonexistent/file.docx")
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.universal.validate_office_file')
- @patch('mcp_office_tools.mixins.universal.detect_format')
- @patch('mcp_office_tools.mixins.universal.resolve_office_file_path')
+ @patch('mcwaddams.mixins.universal.validate_office_file')
+ @patch('mcwaddams.mixins.universal.detect_format')
+ @patch('mcwaddams.mixins.universal.resolve_office_file_path')
async def test_extract_text_csv_success(self, mock_resolve, mock_detect, mock_validate, universal_mixin, mock_csv_file):
"""Test successful CSV text extraction with proper mocking."""
# Setup mocks
@@ -200,9 +200,9 @@ class TestWordMixinUnit:
await word_mixin.convert_to_markdown("/nonexistent/file.docx")
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.word.validate_office_file')
- @patch('mcp_office_tools.mixins.word.detect_format')
- @patch('mcp_office_tools.mixins.word.resolve_office_file_path')
+ @patch('mcwaddams.mixins.word.validate_office_file')
+ @patch('mcwaddams.mixins.word.detect_format')
+ @patch('mcwaddams.mixins.word.resolve_office_file_path')
async def test_convert_to_markdown_non_word_document(self, mock_resolve, mock_detect, mock_validate, word_mixin):
"""Test that non-Word documents are rejected for markdown conversion."""
# Setup mocks for a non-Word document
@@ -287,9 +287,9 @@ class TestMockingStrategies:
}
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.universal.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.universal.validate_office_file')
- @patch('mcp_office_tools.mixins.universal.detect_format')
+ @patch('mcwaddams.mixins.universal.resolve_office_file_path')
+ @patch('mcwaddams.mixins.universal.validate_office_file')
+ @patch('mcwaddams.mixins.universal.detect_format')
async def test_comprehensive_mocking_pattern(self, mock_detect, mock_validate, mock_resolve, mock_office_file):
"""Demonstrate comprehensive mocking pattern for tool testing."""
app = FastMCP("Test App")
@@ -347,8 +347,8 @@ class TestFileOperationMocking:
universal.register_all(app)
# Mock only the validation/detection layers
- with patch('mcp_office_tools.utils.validation.validate_office_file') as mock_validate:
- with patch('mcp_office_tools.utils.file_detection.detect_format') as mock_detect:
+ with patch('mcwaddams.utils.validation.validate_office_file') as mock_validate:
+ with patch('mcwaddams.utils.file_detection.detect_format') as mock_detect:
mock_validate.return_value = {"is_valid": True, "errors": []}
mock_detect.return_value = {
"category": "data",
@@ -375,9 +375,9 @@ class TestAsyncPatterns:
universal.register_all(app)
# Mock all async dependencies
- with patch('mcp_office_tools.mixins.universal.resolve_office_file_path') as mock_resolve:
- with patch('mcp_office_tools.mixins.universal.validate_office_file') as mock_validate:
- with patch('mcp_office_tools.mixins.universal.detect_format') as mock_detect:
+ with patch('mcwaddams.mixins.universal.resolve_office_file_path') as mock_resolve:
+ with patch('mcwaddams.mixins.universal.validate_office_file') as mock_validate:
+ with patch('mcwaddams.mixins.universal.detect_format') as mock_detect:
# Make mocks properly async
mock_resolve.return_value = "/test.csv"
mock_validate.return_value = {"is_valid": True, "errors": []}
diff --git a/tests/test_server.py b/tests/test_server.py
index c40880b..2401646 100644
--- a/tests/test_server.py
+++ b/tests/test_server.py
@@ -8,8 +8,8 @@ from unittest.mock import patch, MagicMock
# FastMCP testing - using direct tool access
-from mcp_office_tools.server import app
-from mcp_office_tools.utils import OfficeFileError
+from mcwaddams.server import app
+from mcwaddams.utils import OfficeFileError
class TestServerInitialization:
@@ -54,7 +54,7 @@ class TestServerInitialization:
def test_mixin_composition_works(self):
"""Test that mixin composition created the expected server structure."""
# Import the server module to ensure all mixins are initialized
- import mcp_office_tools.server as server_module
+ import mcwaddams.server as server_module
# Verify the mixins were created
assert hasattr(server_module, 'universal_mixin')
@@ -63,7 +63,7 @@ class TestServerInitialization:
assert hasattr(server_module, 'powerpoint_mixin')
# Verify mixin instances are correct types
- from mcp_office_tools.mixins import UniversalMixin, WordMixin, ExcelMixin, PowerPointMixin
+ from mcwaddams.mixins import UniversalMixin, WordMixin, ExcelMixin, PowerPointMixin
assert isinstance(server_module.universal_mixin, UniversalMixin)
assert isinstance(server_module.word_mixin, WordMixin)
assert isinstance(server_module.excel_mixin, ExcelMixin)
diff --git a/tests/test_universal_mixin.py b/tests/test_universal_mixin.py
index 1092069..2033ede 100644
--- a/tests/test_universal_mixin.py
+++ b/tests/test_universal_mixin.py
@@ -16,8 +16,8 @@ from pathlib import Path
from fastmcp import FastMCP
# FastMCP testing - using direct tool access
-from mcp_office_tools.mixins.universal import UniversalMixin
-from mcp_office_tools.utils import OfficeFileError
+from mcwaddams.mixins.universal import UniversalMixin
+from mcwaddams.utils import OfficeFileError
class TestUniversalMixinRegistration:
@@ -69,9 +69,9 @@ class TestExtractText:
await mixin.extract_text("/nonexistent/file.docx")
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.universal.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.universal.validate_office_file')
- @patch('mcp_office_tools.mixins.universal.detect_format')
+ @patch('mcwaddams.mixins.universal.resolve_office_file_path')
+ @patch('mcwaddams.mixins.universal.validate_office_file')
+ @patch('mcwaddams.mixins.universal.detect_format')
async def test_extract_text_validation_failure(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test extract_text with validation failure."""
mock_resolve.return_value = "/test.docx"
@@ -84,9 +84,9 @@ class TestExtractText:
await mixin.extract_text("/test.docx")
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.universal.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.universal.validate_office_file')
- @patch('mcp_office_tools.mixins.universal.detect_format')
+ @patch('mcwaddams.mixins.universal.resolve_office_file_path')
+ @patch('mcwaddams.mixins.universal.validate_office_file')
+ @patch('mcwaddams.mixins.universal.detect_format')
async def test_extract_text_csv_success(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test successful CSV text extraction."""
# Setup mocks
@@ -126,9 +126,9 @@ class TestExtractText:
async def test_extract_text_parameter_handling(self, mixin):
"""Test extract_text parameter validation and handling."""
# Mock all dependencies for parameter testing
- with patch('mcp_office_tools.mixins.universal.resolve_office_file_path') as mock_resolve:
- with patch('mcp_office_tools.mixins.universal.validate_office_file') as mock_validate:
- with patch('mcp_office_tools.mixins.universal.detect_format') as mock_detect:
+ with patch('mcwaddams.mixins.universal.resolve_office_file_path') as mock_resolve:
+ with patch('mcwaddams.mixins.universal.validate_office_file') as mock_validate:
+ with patch('mcwaddams.mixins.universal.detect_format') as mock_detect:
mock_resolve.return_value = "/test.docx"
mock_validate.return_value = {"is_valid": True, "errors": []}
mock_detect.return_value = {"category": "word", "extension": ".docx", "format_name": "Word"}
@@ -174,9 +174,9 @@ class TestExtractImages:
await mixin.extract_images("/nonexistent/file.docx")
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.universal.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.universal.validate_office_file')
- @patch('mcp_office_tools.mixins.universal.detect_format')
+ @patch('mcwaddams.mixins.universal.resolve_office_file_path')
+ @patch('mcwaddams.mixins.universal.validate_office_file')
+ @patch('mcwaddams.mixins.universal.detect_format')
async def test_extract_images_unsupported_format(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test extract_images with unsupported format (CSV) returns empty list."""
mock_resolve.return_value = "/test.csv"
@@ -263,9 +263,9 @@ class TestDocumentHealth:
return mixin
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.universal.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.universal.validate_office_file')
- @patch('mcp_office_tools.mixins.universal.detect_format')
+ @patch('mcwaddams.mixins.universal.resolve_office_file_path')
+ @patch('mcwaddams.mixins.universal.validate_office_file')
+ @patch('mcwaddams.mixins.universal.detect_format')
async def test_analyze_document_health_success(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test successful document health analysis."""
mock_resolve.return_value = "/test.docx"
@@ -343,9 +343,9 @@ class TestMockingPatterns:
async def test_comprehensive_mocking_pattern(self, mixin):
"""Demonstrate comprehensive mocking for complex tool testing."""
# Mock all external dependencies
- with patch('mcp_office_tools.mixins.universal.resolve_office_file_path') as mock_resolve:
- with patch('mcp_office_tools.mixins.universal.validate_office_file') as mock_validate:
- with patch('mcp_office_tools.mixins.universal.detect_format') as mock_detect:
+ with patch('mcwaddams.mixins.universal.resolve_office_file_path') as mock_resolve:
+ with patch('mcwaddams.mixins.universal.validate_office_file') as mock_validate:
+ with patch('mcwaddams.mixins.universal.detect_format') as mock_detect:
# Setup realistic mock responses
mock_resolve.return_value = "/realistic/path/document.docx"
diff --git a/tests/test_word_mixin.py b/tests/test_word_mixin.py
index 24c3835..7188153 100644
--- a/tests/test_word_mixin.py
+++ b/tests/test_word_mixin.py
@@ -14,8 +14,8 @@ from pathlib import Path
from fastmcp import FastMCP
# FastMCP testing - using direct tool access
-from mcp_office_tools.mixins.word import WordMixin
-from mcp_office_tools.utils import OfficeFileError
+from mcwaddams.mixins.word import WordMixin
+from mcwaddams.utils import OfficeFileError
class TestWordMixinRegistration:
@@ -58,9 +58,9 @@ class TestConvertToMarkdown:
await mixin.convert_to_markdown("/nonexistent/file.docx")
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.word.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.word.validate_office_file')
- @patch('mcp_office_tools.mixins.word.detect_format')
+ @patch('mcwaddams.mixins.word.resolve_office_file_path')
+ @patch('mcwaddams.mixins.word.validate_office_file')
+ @patch('mcwaddams.mixins.word.detect_format')
async def test_convert_to_markdown_validation_failure(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test convert_to_markdown with validation failure."""
mock_resolve.return_value = "/test.docx"
@@ -73,9 +73,9 @@ class TestConvertToMarkdown:
await mixin.convert_to_markdown("/test.docx")
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.word.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.word.validate_office_file')
- @patch('mcp_office_tools.mixins.word.detect_format')
+ @patch('mcwaddams.mixins.word.resolve_office_file_path')
+ @patch('mcwaddams.mixins.word.validate_office_file')
+ @patch('mcwaddams.mixins.word.detect_format')
async def test_convert_to_markdown_non_word_document(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test that non-Word documents are rejected."""
mock_resolve.return_value = "/test.xlsx"
@@ -90,9 +90,9 @@ class TestConvertToMarkdown:
await mixin.convert_to_markdown("/test.xlsx")
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.word.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.word.validate_office_file')
- @patch('mcp_office_tools.mixins.word.detect_format')
+ @patch('mcwaddams.mixins.word.resolve_office_file_path')
+ @patch('mcwaddams.mixins.word.validate_office_file')
+ @patch('mcwaddams.mixins.word.detect_format')
async def test_convert_to_markdown_docx_success(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test successful DOCX to markdown conversion."""
# Setup mocks
@@ -141,9 +141,9 @@ class TestConvertToMarkdown:
async def test_convert_to_markdown_parameter_handling(self, mixin):
"""Test convert_to_markdown parameter validation and handling."""
# Mock all dependencies for parameter testing
- with patch('mcp_office_tools.mixins.word.resolve_office_file_path') as mock_resolve:
- with patch('mcp_office_tools.mixins.word.validate_office_file') as mock_validate:
- with patch('mcp_office_tools.mixins.word.detect_format') as mock_detect:
+ with patch('mcwaddams.mixins.word.resolve_office_file_path') as mock_resolve:
+ with patch('mcwaddams.mixins.word.validate_office_file') as mock_validate:
+ with patch('mcwaddams.mixins.word.detect_format') as mock_detect:
mock_resolve.return_value = "/test.docx"
mock_validate.return_value = {"is_valid": True, "errors": []}
mock_detect.return_value = {"category": "word", "extension": ".docx", "format_name": "Word"}
@@ -185,9 +185,9 @@ class TestConvertToMarkdown:
@pytest.mark.asyncio
async def test_convert_to_markdown_bookmark_priority(self, mixin):
"""Test that bookmark extraction takes priority over page ranges."""
- with patch('mcp_office_tools.mixins.word.resolve_office_file_path') as mock_resolve:
- with patch('mcp_office_tools.mixins.word.validate_office_file') as mock_validate:
- with patch('mcp_office_tools.mixins.word.detect_format') as mock_detect:
+ with patch('mcwaddams.mixins.word.resolve_office_file_path') as mock_resolve:
+ with patch('mcwaddams.mixins.word.validate_office_file') as mock_validate:
+ with patch('mcwaddams.mixins.word.detect_format') as mock_detect:
mock_resolve.return_value = "/test.docx"
mock_validate.return_value = {"is_valid": True, "errors": []}
mock_detect.return_value = {"category": "word", "extension": ".docx", "format_name": "Word"}
@@ -225,9 +225,9 @@ class TestConvertToMarkdown:
@pytest.mark.asyncio
async def test_convert_to_markdown_summary_mode(self, mixin):
"""Test summary_only mode functionality."""
- with patch('mcp_office_tools.mixins.word.resolve_office_file_path') as mock_resolve:
- with patch('mcp_office_tools.mixins.word.validate_office_file') as mock_validate:
- with patch('mcp_office_tools.mixins.word.detect_format') as mock_detect:
+ with patch('mcwaddams.mixins.word.resolve_office_file_path') as mock_resolve:
+ with patch('mcwaddams.mixins.word.validate_office_file') as mock_validate:
+ with patch('mcwaddams.mixins.word.detect_format') as mock_detect:
mock_resolve.return_value = "/test.docx"
mock_validate.return_value = {"is_valid": True, "errors": []}
mock_detect.return_value = {"category": "word", "extension": ".docx", "format_name": "Word"}
@@ -373,9 +373,9 @@ class TestLegacyWordSupport:
return mixin
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.word.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.word.validate_office_file')
- @patch('mcp_office_tools.mixins.word.detect_format')
+ @patch('mcwaddams.mixins.word.resolve_office_file_path')
+ @patch('mcwaddams.mixins.word.validate_office_file')
+ @patch('mcwaddams.mixins.word.detect_format')
async def test_convert_legacy_doc_to_markdown(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test conversion of legacy .doc files."""
mock_resolve.return_value = "/test.doc"
@@ -425,9 +425,9 @@ class TestPageRangeFiltering:
return mixin
@pytest.mark.asyncio
- @patch('mcp_office_tools.mixins.word.resolve_office_file_path')
- @patch('mcp_office_tools.mixins.word.validate_office_file')
- @patch('mcp_office_tools.mixins.word.detect_format')
+ @patch('mcwaddams.mixins.word.resolve_office_file_path')
+ @patch('mcwaddams.mixins.word.validate_office_file')
+ @patch('mcwaddams.mixins.word.detect_format')
async def test_page_range_filters_different_content(self, mock_detect, mock_validate, mock_resolve, mixin):
"""Test that different page_range values return different content.
diff --git a/torture_test.py b/torture_test.py
index 7fc1060..656c87e 100644
--- a/torture_test.py
+++ b/torture_test.py
@@ -17,8 +17,8 @@ warnings.filterwarnings("ignore", category=FutureWarning)
# Add src to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
-from mcp_office_tools.mixins.excel import ExcelMixin
-from mcp_office_tools.mixins.word import WordMixin
+from mcwaddams.mixins.excel import ExcelMixin
+from mcwaddams.mixins.word import WordMixin
# Test files - real files from user's system
diff --git a/uv.lock b/uv.lock
index ac2294a..8de8216 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1537,7 +1537,7 @@ wheels = [
]
[[package]]
-name = "mcp-office-tools"
+name = "mcwaddams"
version = "0.1.0"
source = { editable = "." }
dependencies = [
diff --git a/view_dashboard.sh b/view_dashboard.sh
index 8a17422..18d8b28 100755
--- a/view_dashboard.sh
+++ b/view_dashboard.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# Quick script to open the test dashboard in browser
-DASHBOARD_PATH="/home/rpm/claude/mcp-office-tools/reports/test_dashboard.html"
+DASHBOARD_PATH="/home/rpm/claude/mcwaddams/reports/test_dashboard.html"
echo "📊 Opening MCP Office Tools Test Dashboard..."
echo "Dashboard: $DASHBOARD_PATH"