Skip to content

Commit b5b094a

Browse files
authored
Add MCP server with search and get object tool (#1)
1 parent bc3349b commit b5b094a

File tree

7 files changed

+635
-1
lines changed

7 files changed

+635
-1
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 DevRev, Inc.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,64 @@
22

33
## Overview
44

5-
A Model Context Protocol server for DevRev.
5+
A Model Context Protocol server for DevRev. It is used to search and retrieve information using the DevRev APIs.
6+
7+
## Tools
8+
9+
- `search`: Search for information using the DevRev search API with the provided query and namespace.
10+
- `get_object`: Get all information about a DevRev issue or ticket using its ID.
11+
12+
## Configuration
13+
14+
### Get the DevRev API key
15+
16+
1. Go to https://app.devrev.ai/signup and create an account.
17+
2. Import your data from your existing data sources like Salesforce, Zendesk while following the instructions [here](https://devrev.ai/docs/import#available-sources).
18+
3. Generate an access token while following the instructions [here](https://developer.devrev.ai/public/about/authentication#personal-access-token-usage).
19+
20+
### Usage with Claude Desktop
21+
22+
On MacOS: `~/Library/Application\ Support/Claude/claude_desktop_config.json`
23+
24+
On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
25+
26+
<details>
27+
<summary>Published Servers Configuration</summary>
28+
29+
```json
30+
"mcpServers": {
31+
"devrev": {
32+
"command": "uvx",
33+
"args": [
34+
"devrev-mcp"
35+
],
36+
"env": {
37+
"DEVREV_API_KEY": "YOUR_DEVREV_API_KEY"
38+
}
39+
}
40+
}
41+
```
42+
43+
</details>
44+
45+
<details>
46+
<summary>Development/Unpublished Servers Configuration</summary>
47+
48+
```json
49+
"mcpServers": {
50+
"devrev": {
51+
"command": "uv",
52+
"args": [
53+
"--directory",
54+
"Path to src/devrev_mcp directory",
55+
"run",
56+
"devrev-mcp"
57+
],
58+
"env": {
59+
"DEVREV_API_KEY": "YOUR_DEVREV_API_KEY"
60+
}
61+
}
62+
}
63+
```
64+
65+
</details>

pyproject.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[project]
2+
name = "devrev-mcp"
3+
version = "0.1.1"
4+
description = "A MCP server project"
5+
readme = "README.md"
6+
requires-python = ">=3.11"
7+
dependencies = [ "mcp>=1.0.0", "requests"]
8+
[[project.authors]]
9+
name = "Sunil Pandey"
10+
11+
12+
[build-system]
13+
requires = [ "hatchling",]
14+
build-backend = "hatchling.build"
15+
16+
[project.scripts]
17+
devrev-mcp = "devrev_mcp:main"

src/devrev_mcp/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Copyright (c) 2025 DevRev, Inc.
3+
SPDX-License-Identifier: MIT
4+
5+
DevRev MCP server package initialization.
6+
"""
7+
8+
from . import server
9+
import asyncio
10+
11+
def main():
12+
"""Main entry point for the package."""
13+
asyncio.run(server.main())
14+
15+
# Optionally expose other important items at package level
16+
__all__ = ['main', 'server']

src/devrev_mcp/server.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
"""
2+
Copyright (c) 2025 DevRev, Inc.
3+
SPDX-License-Identifier: MIT
4+
5+
This module implements the MCP server for DevRev integration.
6+
"""
7+
8+
import asyncio
9+
import os
10+
import requests
11+
12+
from mcp.server.models import InitializationOptions
13+
import mcp.types as types
14+
from mcp.server import NotificationOptions, Server
15+
from pydantic import AnyUrl
16+
import mcp.server.stdio
17+
from .utils import make_devrev_request
18+
19+
server = Server("devrev_mcp")
20+
21+
@server.list_tools()
22+
async def handle_list_tools() -> list[types.Tool]:
23+
"""
24+
List available tools.
25+
Each tool specifies its arguments using JSON Schema validation.
26+
"""
27+
return [
28+
types.Tool(
29+
name="search",
30+
description="Search DevRev using the provided query",
31+
inputSchema={
32+
"type": "object",
33+
"properties": {
34+
"query": {"type": "string"},
35+
"namespace": {"type": "string", "enum": ["article", "issue", "ticket"]},
36+
},
37+
"required": ["query", "namespace"],
38+
},
39+
),
40+
types.Tool(
41+
name="get_object",
42+
description="Get all information about a DevRev issue and ticket using its ID",
43+
inputSchema={
44+
"type": "object",
45+
"properties": {
46+
"id": {"type": "string"},
47+
},
48+
"required": ["id"],
49+
},
50+
)
51+
]
52+
53+
@server.call_tool()
54+
async def handle_call_tool(
55+
name: str, arguments: dict | None
56+
) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
57+
"""
58+
Handle tool execution requests.
59+
Tools can modify server state and notify clients of changes.
60+
"""
61+
if name == "search":
62+
if not arguments:
63+
raise ValueError("Missing arguments")
64+
65+
query = arguments.get("query")
66+
if not query:
67+
raise ValueError("Missing query parameter")
68+
69+
namespace = arguments.get("namespace")
70+
if not namespace:
71+
raise ValueError("Missing namespace parameter")
72+
73+
response = make_devrev_request(
74+
"search.hybrid",
75+
{"query": query, "namespace": namespace}
76+
)
77+
if response.status_code != 200:
78+
error_text = response.text
79+
return [
80+
types.TextContent(
81+
type="text",
82+
text=f"Search failed with status {response.status_code}: {error_text}"
83+
)
84+
]
85+
86+
search_results = response.json()
87+
return [
88+
types.TextContent(
89+
type="text",
90+
text=f"Search results for '{query}':\n{search_results}"
91+
)
92+
]
93+
elif name == "get_object":
94+
if not arguments:
95+
raise ValueError("Missing arguments")
96+
97+
id = arguments.get("id")
98+
if not id:
99+
raise ValueError("Missing id parameter")
100+
101+
response = make_devrev_request(
102+
"works.get",
103+
{"id": id}
104+
)
105+
if response.status_code != 200:
106+
error_text = response.text
107+
return [
108+
types.TextContent(
109+
type="text",
110+
text=f"Get object failed with status {response.status_code}: {error_text}"
111+
)
112+
]
113+
114+
object_info = response.json()
115+
return [
116+
types.TextContent(
117+
type="text",
118+
text=f"Object information for '{id}':\n{object_info}"
119+
)
120+
]
121+
else:
122+
raise ValueError(f"Unknown tool: {name}")
123+
124+
async def main():
125+
# Run the server using stdin/stdout streams
126+
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
127+
await server.run(
128+
read_stream,
129+
write_stream,
130+
InitializationOptions(
131+
server_name="devrev_mcp",
132+
server_version="0.1.1",
133+
capabilities=server.get_capabilities(
134+
notification_options=NotificationOptions(),
135+
experimental_capabilities={},
136+
),
137+
),
138+
)

src/devrev_mcp/utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
Copyright (c) 2025 DevRev, Inc.
3+
SPDX-License-Identifier: MIT
4+
5+
This module provides utility functions for making authenticated requests to the DevRev API.
6+
"""
7+
8+
import os
9+
import requests
10+
from typing import Any, Dict
11+
12+
def make_devrev_request(endpoint: str, payload: Dict[str, Any]) -> requests.Response:
13+
"""
14+
Make an authenticated request to the DevRev API.
15+
16+
Args:
17+
endpoint: The API endpoint path (e.g., "works.get" or "search.hybrid")
18+
payload: The JSON payload to send
19+
20+
Returns:
21+
requests.Response object
22+
23+
Raises:
24+
ValueError: If DEVREV_API_KEY environment variable is not set
25+
"""
26+
api_key = os.environ.get("DEVREV_API_KEY")
27+
if not api_key:
28+
raise ValueError("DEVREV_API_KEY environment variable is not set")
29+
30+
headers = {
31+
"Authorization": f"{api_key}",
32+
"Content-Type": "application/json",
33+
}
34+
35+
return requests.post(
36+
f"https://api.devrev.ai/{endpoint}",
37+
headers=headers,
38+
json=payload
39+
)

0 commit comments

Comments
 (0)