Refactor to use MCP resources for read operations (v1.0.2)
- Convert all read/list operations from tools to resources following MCP best practices - Add @mcp.resource decorators for domains, records, and analysis endpoints - Update version to 1.0.2 - Add uvx support documentation for Claude Desktop integration - Fix CLI asyncio usage for FastMCP synchronous run() method - Add vultr-mcp-server console script entry point This improves alignment with MCP patterns where resources represent readable data and tools perform actions that modify state. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
66c4c3cb18
commit
691963a43b
14
CHANGELOG.md
14
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
|
||||
|
14
CLAUDE.md
14
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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"]
|
||||
|
@ -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())
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user