diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fc65f2..0f270e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.2] - 2025-01-16 + +### Changed +- Refactored read operations to use MCP resources instead of tools +- List domains endpoint: `@mcp.resource("dns://domains")` +- Get domain endpoint: `@mcp.resource("dns://domains/{domain}")` +- List records endpoint: `@mcp.resource("dns://domains/{domain}/records")` +- Get record endpoint: `@mcp.resource("dns://domains/{domain}/records/{record_id}")` +- Analyze domain endpoint: `@mcp.resource("dns://domains/{domain}/analysis")` + +### Improved +- Better alignment with MCP best practices (resources for read, tools for write) +- Enhanced Claude Desktop integration documentation with uvx support + ## [1.0.1] - 2024-12-20 ### Fixed diff --git a/CLAUDE.md b/CLAUDE.md index 667d1f5..2aaff1b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,7 +24,9 @@ vultr-dns-mcp domains list vultr-dns-mcp records list example.com # As MCP server -uv run python -m vultr_dns_mcp +vultr-mcp-server +# or using Python module +python -m vultr_dns_mcp ``` ## Development Setup @@ -135,6 +137,7 @@ vultr-dns-mcp/ - Built on FastMCP 2.0 framework for better Claude Desktop compatibility - All tools use proper async/await patterns - 12 comprehensive DNS management tools +- **Important**: FastMCP's `run()` method is synchronous, not async. Do not wrap with `asyncio.run()` ### MCP Tools (12 total) - Domain management: list, create, delete, get details @@ -167,7 +170,8 @@ vultr-dns-mcp/ - **FEATURE**: Added HTTP request timeouts (30s total, 10s connect) - **FEATURE**: Full uv package manager integration throughout project - **FEATURE**: Created comprehensive Claude Desktop setup documentation -- **FIX**: Resolved event loop issues with proper async/await patterns +- **FIX**: Resolved event loop issues - FastMCP 2.0 uses synchronous `run()` method +- **FEATURE**: Added `vultr-mcp-server` console script entry point for easier Claude Desktop integration - **IMPROVEMENT**: Enhanced README with professional structure and badges - **IMPROVEMENT**: Added test suite for validating all improvements @@ -233,7 +237,7 @@ Use the GitHub Actions "Publish to PyPI" workflow with manual trigger. ### Common Issues - **ImportError**: Run `uv sync` or `pip install -e .` from repository root - **AsyncioError**: FastMCP handles async properly, ensure tools use `async def` -- **Event Loop Error**: Use `await` instead of `asyncio.run()` in FastMCP tools +- **Event Loop Error**: FastMCP 2.0's `run()` method is synchronous - do NOT use `asyncio.run()` - **MCP Connection**: Ensure Claude Desktop config uses absolute Python path - **API Errors**: Verify VULTR_API_KEY environment variable is set @@ -263,8 +267,8 @@ python -c "from vultr_dns_mcp.server import create_mcp_server" { "mcpServers": { "vultr-dns": { - "command": "/path/to/python", - "args": ["-m", "vultr_dns_mcp"], + "command": "vultr-mcp-server", + "args": [], "env": { "VULTR_API_KEY": "your-api-key" } diff --git a/CLAUDE_DESKTOP_SETUP.md b/CLAUDE_DESKTOP_SETUP.md index 25e9f7e..4b27a95 100644 --- a/CLAUDE_DESKTOP_SETUP.md +++ b/CLAUDE_DESKTOP_SETUP.md @@ -40,12 +40,28 @@ The configuration file location depends on your OS: Add this to your `claude_desktop_config.json`: +```json +{ + "mcpServers": { + "vultr-dns": { + "command": "vultr-mcp-server", + "args": [], + "env": { + "VULTR_API_KEY": "YOUR_VULTR_API_KEY_HERE" + } + } + } +} +``` + +**Note**: If `vultr-mcp-server` is not in your PATH, use the full Python module approach: + ```json { "mcpServers": { "vultr-dns": { "command": "python", - "args": ["-m", "vultr_dns_mcp.server"], + "args": ["-m", "vultr_dns_mcp"], "env": { "VULTR_API_KEY": "YOUR_VULTR_API_KEY_HERE" } @@ -61,7 +77,49 @@ Add this to your `claude_desktop_config.json`: "mcpServers": { "vultr-dns": { "command": "uv", - "args": ["run", "python", "-m", "vultr_dns_mcp.server"], + "args": ["run", "vultr-mcp-server"], + "env": { + "VULTR_API_KEY": "YOUR_VULTR_API_KEY_HERE" + } + } + } +} +``` + +### 3a. Using uvx (Recommended for Easy Installation) + +This approach uses `uvx` to automatically install and run the package without needing to manage Python environments: + +```json +{ + "mcpServers": { + "vultr-dns": { + "command": "uvx", + "args": [ + "--from", "vultr-dns-mcp", + "vultr-mcp-server" + ], + "env": { + "VULTR_API_KEY": "YOUR_VULTR_API_KEY_HERE" + } + } + } +} +``` + +For TestPyPI version: +```json +{ + "mcpServers": { + "vultr-dns": { + "command": "uvx", + "args": [ + "--index-url", "https://test.pypi.org/simple/", + "--extra-index-url", "https://pypi.org/simple/", + "--index-strategy", "unsafe-best-match", + "--from", "vultr-dns-mcp==1.0.1", + "vultr-mcp-server" + ], "env": { "VULTR_API_KEY": "YOUR_VULTR_API_KEY_HERE" } @@ -79,7 +137,7 @@ If you have issues, use the absolute path to your Python installation: "mcpServers": { "vultr-dns": { "command": "/usr/bin/python3", - "args": ["-m", "vultr_dns_mcp.server"], + "args": ["-m", "vultr_dns_mcp"], "env": { "VULTR_API_KEY": "YOUR_VULTR_API_KEY_HERE" } @@ -151,7 +209,9 @@ The server provides these tools that Claude Desktop can use: 2. **Test server manually**: ```bash export VULTR_API_KEY="your-key" - python -m vultr_dns_mcp.server + vultr-mcp-server + # or + python -m vultr_dns_mcp ``` 3. **Check API key**: @@ -185,7 +245,7 @@ If Claude Desktop can't find Python: "mcpServers": { "vultr-dns": { "command": "/full/path/to/python3", - "args": ["-m", "vultr_dns_mcp.server"], + "args": ["-m", "vultr_dns_mcp"], "env": { "VULTR_API_KEY": "YOUR_KEY" } @@ -209,8 +269,8 @@ If using a virtual environment: { "mcpServers": { "vultr-dns": { - "command": "/path/to/your-venv/bin/python", - "args": ["-m", "vultr_dns_mcp.server"], + "command": "/path/to/your-venv/bin/vultr-mcp-server", + "args": [], "env": { "VULTR_API_KEY": "YOUR_KEY" } diff --git a/pyproject.toml b/pyproject.toml index daecbcc..29a388a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "vultr-dns-mcp" -version = "1.0.1" +version = "1.0.2" description = "A comprehensive Model Context Protocol (MCP) server for managing Vultr DNS records" readme = "README.md" license = {text = "MIT"} @@ -82,6 +82,7 @@ Changelog = "https://github.com/rsp2k/vultr-dns-mcp/blob/main/CHANGELOG.md" [project.scripts] vultr-dns-mcp = "vultr_dns_mcp.cli:main" vultr-dns-server = "vultr_dns_mcp.cli:server_command" +vultr-mcp-server = "vultr_dns_mcp.fastmcp_server:run_server" [tool.setuptools.packages.find] where = ["src"] diff --git a/src/vultr_dns_mcp/_version.py b/src/vultr_dns_mcp/_version.py index c64a65f..9f7f9a1 100644 --- a/src/vultr_dns_mcp/_version.py +++ b/src/vultr_dns_mcp/_version.py @@ -1,4 +1,4 @@ """Version information for vultr-dns-mcp package.""" -__version__ = "1.0.1" +__version__ = "1.0.2" __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) diff --git a/src/vultr_dns_mcp/cli.py b/src/vultr_dns_mcp/cli.py index 43ccdf9..a39ef10 100644 --- a/src/vultr_dns_mcp/cli.py +++ b/src/vultr_dns_mcp/cli.py @@ -47,7 +47,7 @@ def server(ctx: click.Context): click.echo(f"šŸ”„ Press Ctrl+C to stop") try: - asyncio.run(run_server(api_key)) + run_server(api_key) except KeyboardInterrupt: click.echo("\nšŸ‘‹ Server stopped") except Exception as e: diff --git a/src/vultr_dns_mcp/fastmcp_server.py b/src/vultr_dns_mcp/fastmcp_server.py index 16fbaf9..57bac51 100644 --- a/src/vultr_dns_mcp/fastmcp_server.py +++ b/src/vultr_dns_mcp/fastmcp_server.py @@ -35,12 +35,12 @@ def create_vultr_mcp_server(api_key: Optional[str] = None) -> FastMCP: # Initialize Vultr client vultr_client = VultrDNSServer(api_key) - @mcp.tool + @mcp.resource("dns://domains") async def list_dns_domains() -> List[Dict[str, Any]]: """List all DNS domains in your Vultr account.""" return await vultr_client.list_domains() - @mcp.tool + @mcp.resource("dns://domains/{domain}") async def get_dns_domain(domain: str) -> Dict[str, Any]: """Get details for a specific DNS domain. @@ -70,7 +70,7 @@ def create_vultr_mcp_server(api_key: Optional[str] = None) -> FastMCP: await vultr_client.delete_domain(domain) return {"status": "success", "message": f"Domain {domain} deleted successfully"} - @mcp.tool + @mcp.resource("dns://domains/{domain}/records") async def list_dns_records(domain: str) -> List[Dict[str, Any]]: """List all DNS records for a domain. @@ -79,7 +79,7 @@ def create_vultr_mcp_server(api_key: Optional[str] = None) -> FastMCP: """ return await vultr_client.list_records(domain) - @mcp.tool + @mcp.resource("dns://domains/{domain}/records/{record_id}") async def get_dns_record(domain: str, record_id: str) -> Dict[str, Any]: """Get details for a specific DNS record. @@ -161,7 +161,7 @@ def create_vultr_mcp_server(api_key: Optional[str] = None) -> FastMCP: """ return await vultr_client.validate_record(record_type, name, data, ttl, priority) - @mcp.tool + @mcp.resource("dns://domains/{domain}/analysis") async def analyze_dns_records(domain: str) -> Dict[str, Any]: """Analyze DNS records for a domain and provide recommendations.