Skip to content

Switches to FastMCP and adds resource support #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions CLAUDE.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why named it claude.md ?

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This project uses `uv` for package management
- Reference https://gofastmcp.com/llms.txt
- Reference https://developer.devrev.ai/llms.txt
131 changes: 127 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,114 @@ A Model Context Protocol server for DevRev. It is used to search and retrieve in

## Tools

- `search`: Search for information using the DevRev search API with the provided query and namespace.
- `get_object`: Get all information about a DevRev issue or ticket using its ID.
- `create_object`: Create a new issue or ticket in DevRev with specified properties.
- `update_object`: Update an existing issue or ticket in DevRev by modifying its title or body content.
### Core Tools

#### `search`
Search for information using the DevRev search API with hybrid search capabilities.

**Description**: Search DevRev objects using hybrid search. Supports natural language queries across tickets, issues, articles, parts, and users. Returns enriched results with metadata, ownership, status, and organizational context for efficient triage and analysis.

**Parameters**:
- `query` (string, required): The search query string
- `namespace` (string, required): The namespace to search in. Must be one of:
- `article` - Knowledge base articles and documentation
- `issue` - Internal development issues and bugs
- `ticket` - Customer support tickets
- `part` - Product parts and components
- `dev_user` - DevRev users and team members

**Example Usage**:
```
Search for "login error" in tickets namespace to find customer support tickets
Search for "authentication bug" in issues namespace to find development issues
```

#### `get_object`
Retrieve comprehensive information about any DevRev object.

**Description**: Retrieve comprehensive information about any DevRev object including tickets, issues, parts, and users. Returns complete metadata, relationships, assignment details, and history for thorough analysis and investigation.

**Parameters**:
- `id` (string, required): The DevRev object ID (e.g., "TKT-12345", "ISS-67890")

**Example Usage**:
```
Get details for ticket TKT-12345
Get information about issue ISS-67890
```

#### `create_object`
Create new DevRev tickets or issues with full metadata support.

**Description**: Create new DevRev tickets or issues with full metadata support. Supports both customer-facing tickets and internal issues with proper assignment, categorization, and detailed descriptions for workflow automation.

**Parameters**:
- `type` (string, required): The type of object to create ("issue" or "ticket")
- `title` (string, required): The title/summary of the object
- `applies_to_part` (string, required): The part ID this object applies to
- `body` (string, optional): The body/description of the object
- `owned_by` (array of strings, optional): List of user IDs who should own this object

**Example Usage**:
```
Create a customer ticket for a login issue
Create an internal issue for a bug fix
```

#### `update_object`
Update existing DevRev tickets or issues with new information.

**Description**: Update existing DevRev tickets or issues with new information, descriptions, or titles. Maintains object history and audit trails while allowing incremental updates as investigations progress.

**Parameters**:
- `id` (string, required): The ID of the object to update
- `type` (string, required): The type of object ("issue" or "ticket")
- `title` (string, optional): New title for the object
- `body` (string, optional): New body/description for the object

### Advanced Tools

#### `get_timeline_entries`
Retrieve chronological timeline of all activity on a DevRev ticket.

**Description**: Retrieve chronological timeline of all activity on a DevRev ticket including comments, status changes, assignments, and system events. Essential for understanding ticket progression, customer interactions, and audit trails. Accepts flexible ID formats (TKT-12345, 12345, or full don: format) and provides multiple output formats for different use cases.

**Parameters**:
- `id` (string, required): The ticket ID in various formats (TKT-12345, 12345, etc.)
- `format` (string, optional): Output format ("summary" by default)

#### `get_ticket`
Get a DevRev ticket with all associated timeline entries and artifacts.

**Description**: Get a DevRev ticket with all associated timeline entries and artifacts. Provides enriched ticket data with complete conversation history and attached files for comprehensive support analysis.

**Parameters**:
- `id` (string, required): The ticket ID

#### `download_artifact`
Download a DevRev artifact to a specified directory.

**Description**: Download a DevRev artifact to a specified directory. Retrieves the artifact file and saves it locally with proper metadata.

**Parameters**:
- `artifact_id` (string, required): The artifact ID to download
- `download_directory` (string, required): Local directory path to save the artifact

## Resources

The MCP server provides several resource endpoints for accessing DevRev data through URI-based routing:

### Ticket Resources

- `devrev://tickets/{ticket_id}` - Access comprehensive ticket information with navigation links
- `devrev://tickets/{ticket_id}/timeline` - Access enriched timeline for a ticket with customer context
- `devrev://tickets/{ticket_id}/timeline/{entry_id}` - Access individual timeline entry details
- `devrev://tickets/{ticket_id}/artifacts` - Access all artifacts associated with a ticket

### Artifact Resources

- `devrev://artifacts/{artifact_id}` - Access artifact metadata with download URLs
- `devrev://artifacts/{artifact_id}/tickets` - Get all tickets that reference an artifact

## Configuration

Expand Down Expand Up @@ -65,3 +169,22 @@ On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
```

</details>

## Features

- **Hybrid Search**: Advanced search capabilities across all DevRev object types
- **Rich Metadata**: Complete object information including relationships and history
- **Timeline Analysis**: Detailed conversation flows and activity tracking
- **Artifact Management**: File handling with download capabilities
- **Resource Navigation**: URI-based resource access with automatic routing
- **Caching**: Intelligent caching for improved performance
- **Error Handling**: Comprehensive error handling with detailed logging

## Development

This MCP server is built using FastMCP and provides modular tools and resources for DevRev integration. The codebase is organized into:

- `tools/` - Individual tool implementations
- `resources/` - Resource handlers for different object types
- `types.py` - Type definitions and data structures
- `utils.py` - Shared utilities and API helpers
10 changes: 7 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ version = "0.1.2"
description = "A MCP server project"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [ "mcp>=1.0.0", "requests"]
dependencies = [
"fastmcp>=2.0.0",
"requests"
]

[[project.authors]]
name = "Sunil Pandey"
email = "[email protected]"

[build-system]
requires = [ "hatchling",]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project.scripts]
devrev-mcp = "devrev_mcp:main"
devrev-mcp = "devrev_mcp:main_cli"
17 changes: 9 additions & 8 deletions src/devrev_mcp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
Copyright (c) 2025 DevRev, Inc.
SPDX-License-Identifier: MIT

DevRev MCP server package initialization.
DevRev MCP Server package.
This package provides a FastMCP-based server for interacting with DevRev APIs.
"""

from . import server
import asyncio
from .server import main, mcp

def main():
"""Main entry point for the package."""
asyncio.run(server.main())
__version__ = "0.1.1"
__all__ = ["main", "mcp"]

# Optionally expose other important items at package level
__all__ = ['main', 'server']
# Export the main function for the CLI entry point
def main_cli():
"""CLI entry point for the DevRev MCP server."""
main()
68 changes: 68 additions & 0 deletions src/devrev_mcp/cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""
Simple size-limited cache for DevRev MCP server.

Prevents unbounded memory growth by limiting cache size and using simple LRU eviction.
"""

from collections import OrderedDict
from typing import Any, Dict, Optional, Union
import json

# Cache configuration constants
DEFAULT_CACHE_SIZE = 500


class SimpleCache:
"""Simple LRU cache with size limit to prevent memory leaks."""

def __init__(self, max_size: int = DEFAULT_CACHE_SIZE):
"""Initialize cache with maximum size limit."""
self.max_size = max_size
self._cache: OrderedDict[str, str] = OrderedDict()

def get(self, key: str) -> Optional[str]:
"""Get value from cache, moving it to end (most recently used)."""
if key in self._cache:
# Move to end (most recently used)
value = self._cache.pop(key)
self._cache[key] = value
return value
return None

def set(self, key: str, value: Union[str, Dict[str, Any]]) -> None:
"""Set value in cache, evicting oldest if needed."""
# Convert dict to JSON string if needed
if isinstance(value, dict):
cache_value = json.dumps(value, indent=2)
else:
cache_value = str(value)

# Remove if already exists
if key in self._cache:
del self._cache[key]

# Add to end
self._cache[key] = cache_value

# Evict oldest if over limit
while len(self._cache) > self.max_size:
self._cache.popitem(last=False) # Remove oldest (first item)

def delete(self, key: str) -> bool:
"""Remove key from cache."""
if key in self._cache:
del self._cache[key]
return True
return False

def size(self) -> int:
"""Get current number of cache entries."""
return len(self._cache)

def __contains__(self, key: str) -> bool:
"""Check if key exists in cache."""
return key in self._cache


# Global cache instance - replaces devrev_cache = {}
devrev_cache = SimpleCache(max_size=DEFAULT_CACHE_SIZE)
45 changes: 45 additions & 0 deletions src/devrev_mcp/endpoints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""
DevRev API Endpoints Constants

This module defines all DevRev API endpoint strings used throughout the application.
Centralizing these constants prevents typos and makes API changes easier to manage.
"""


class DevRevEndpoints:
"""DevRev API endpoint constants for consistent usage across the application."""

# Works (Tickets, Issues, etc.)
WORKS_GET = "works.get"
WORKS_CREATE = "works.create"
WORKS_UPDATE = "works.update"

# Timeline Entries
TIMELINE_ENTRIES_LIST = "timeline-entries.list"
TIMELINE_ENTRIES_GET = "timeline-entries.get"
TIMELINE_ENTRIES_CREATE = "timeline-entries.create"

# Artifacts
ARTIFACTS_GET = "artifacts.get"
ARTIFACTS_LOCATE = "artifacts.locate"

# Search
SEARCH_HYBRID = "search.hybrid"

# Links
LINKS_LIST = "links.list"
LINK_TYPES_LIST = "link-types.custom.list"


# Convenience exports for simpler imports
WORKS_GET = DevRevEndpoints.WORKS_GET
WORKS_CREATE = DevRevEndpoints.WORKS_CREATE
WORKS_UPDATE = DevRevEndpoints.WORKS_UPDATE
TIMELINE_ENTRIES_LIST = DevRevEndpoints.TIMELINE_ENTRIES_LIST
TIMELINE_ENTRIES_GET = DevRevEndpoints.TIMELINE_ENTRIES_GET
TIMELINE_ENTRIES_CREATE = DevRevEndpoints.TIMELINE_ENTRIES_CREATE
ARTIFACTS_GET = DevRevEndpoints.ARTIFACTS_GET
ARTIFACTS_LOCATE = DevRevEndpoints.ARTIFACTS_LOCATE
SEARCH_HYBRID = DevRevEndpoints.SEARCH_HYBRID
LINKS_LIST = DevRevEndpoints.LINKS_LIST
LINK_TYPES_LIST = DevRevEndpoints.LINK_TYPES_LIST
Loading