Skip to content

Commit c6ee78a

Browse files
committed
Documentation and some minor cleanup
1 parent 6b51035 commit c6ee78a

File tree

11 files changed

+538
-44
lines changed

11 files changed

+538
-44
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License
2+
3+
Copyright (c) 2025 Temporal Technologies Inc. All rights reserved.
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
13+
all 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
21+
THE SOFTWARE.

README.md

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# Nexus MCP
2+
3+
> Bridge Model Context Protocol (MCP) tools with Temporal's reliable workflow execution system via Nexus RPC.
4+
5+
[![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
6+
[![MCP](https://img.shields.io/badge/protocol-MCP-green.svg)](https://modelcontextprotocol.io/)
7+
[![Temporal](https://img.shields.io/badge/powered%20by-Temporal-purple.svg)](https://temporal.io/)
8+
9+
## Overview
10+
11+
Nexus MCP is a bridge that connects the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) with
12+
[Temporal's Nexus RPC framework](https://docs.temporal.io/nexus). It enables MCP tools to be backed by Temporal's
13+
reliable, durable workflow execution system, providing:
14+
15+
- **Reliability**: Tool executions are backed by Temporal's fault-tolerant workflows
16+
- **Durability**: Long-running operations survive process restarts and failures
17+
- **Observability**: Full visibility into tool execution through Temporal's UI
18+
- **Scalability**: Distribute tool execution across multiple workers
19+
20+
The library acts as an adapter, allowing you to expose Temporal Nexus Operations as MCP tools.
21+
22+
## Key Features
23+
24+
- 🔗 **Seamless Integration**: Bridge MCP and Temporal with minimal configuration
25+
- 🛠️ **Automatic Tool Discovery**: Expose Nexus Operations as MCP tools automatically
26+
- 🔧 **Flexible Filtering**: Control which operations are exposed using decorators
27+
- 📊 **Rich Metadata**: Automatic schema generation from Pydantic models
28+
- 🚀 **Production Ready**: Built on proven Temporal infrastructure
29+
30+
## Installation
31+
32+
### Prerequisites
33+
34+
- Python 3.13+
35+
- Access to a Temporal cluster
36+
- MCP-compatible client (e.g., Claude Desktop, custom MCP client)
37+
38+
### Install via uv (recommended)
39+
40+
> NOTE: packages not published yet.
41+
42+
```bash
43+
uv add nexus-mcp
44+
```
45+
46+
### Install via pip
47+
48+
```bash
49+
pip install nexus-mcp
50+
```
51+
52+
### Development Installation
53+
54+
```bash
55+
git clone https://github.com/bergundy/nexus-mcp-python
56+
cd nexus-mcp
57+
uv sync --dev
58+
```
59+
60+
## Quick Start
61+
62+
### 1. Define Your Nexus Service at `service.py`
63+
64+
```python
65+
import nexusrpc
66+
from temporalio import workflow
67+
from pydantic import BaseModel
68+
69+
class CalculateRequest(BaseModel):
70+
expression: str
71+
72+
class CalculateResponse(BaseModel):
73+
result: float
74+
75+
@nexusrpc.service(name="Calculator")
76+
class CalculatorService:
77+
"""A simple calculator service exposed via MCP."""
78+
79+
calculate: nexusrpc.Operation[CalculateRequest, CalculateResponse]
80+
```
81+
82+
### 2. Implement the Service Handler at `service_handler.py`
83+
84+
```python
85+
import nexusrpc
86+
from nexusmcp import MCPServiceHandler
87+
from .service import CalculatorService, CalcluateRequest, CalculateResponse
88+
89+
mcp_service_handler = MCPServiceHandler()
90+
91+
@mcp_service_handler.register
92+
@nexusrpc.handler.service_handler(service=CalculatorService)
93+
class CalculatorHandler:
94+
@nexusrpc.handler.sync_operation
95+
async def calculate(self, _ctx: nexusrpc.handler.StartOperationContext, input: CalculateRequest) -> CalculateResponse:
96+
"""Evaluate a mathematical expression and return the result."""
97+
# Your calculation logic here
98+
result = eval(input.expression) # Don't use eval in production!
99+
return CalculateResponse(result=result)
100+
```
101+
102+
### 4. Create a Nexus endpoint
103+
104+
**Local dev or self hosted deployment**
105+
106+
```bash
107+
temporal operator nexus endpoint create \
108+
--name mcp-gateway \
109+
--target-namespace my-handler-namespace \
110+
--target-task-queue mcp
111+
```
112+
113+
**Temporal Cloud**
114+
115+
> TODO
116+
117+
### 3. Set Up the Temporal Worker with the Nexus handlers at `worker.py`
118+
119+
```python
120+
from temporalio.client import Client
121+
from temporalio.worker import Worker
122+
from .service_handler import mcp_service_handler, CalculatorHandler
123+
124+
async def main():
125+
# Connect to Temporal (replace host and namespace as needed).
126+
client = await Client.connect("localhost:7233", namespace="my-handler-namespace")
127+
128+
async with Worker(
129+
client,
130+
# This task queue should be the target of a Nexus endpoint defined above.
131+
task_queue="mcp",
132+
nexus_service_handlers=[CalculatorHandler(), mcp_service_handler],
133+
):
134+
await asyncio.Event().wait()
135+
```
136+
137+
### 4. Set Up the MCP Gateway
138+
139+
```python
140+
import asyncio
141+
from mcp.server.lowlevel import NotificationOptions, Server
142+
from mcp.server.models import InitializationOptions
143+
from temporalio.client import Client
144+
from nexusmcp import InboundGateway
145+
146+
async def main():
147+
server = Server("nexus-mcp-demo")
148+
# Connect to Temporal (replace host and namespace as needed).
149+
client = await Client.connect("localhost:7233", namespace="my-caller-namespace")
150+
151+
# Create the MCP gateway
152+
gateway = InboundGateway(
153+
client=client,
154+
endpoint="mcp-gateway",
155+
)
156+
gateway.register(server)
157+
158+
async with gateway.run():
159+
# Set up MCP server transport and run here...
160+
161+
162+
if __name__ == "__main__":
163+
asyncio.run(main())
164+
```
165+
166+
### 4. Configure Your MCP Client
167+
168+
Add to your MCP client configuration (e.g., Claude Desktop):
169+
170+
```json
171+
{
172+
"mcpServers": {
173+
"nexus-calculator": {
174+
"command": "python",
175+
"args": ["path/to/your/mcp_server.py"]
176+
}
177+
}
178+
}
179+
```
180+
181+
## Usage Examples
182+
183+
### Tool Filtering
184+
185+
Control which operations are exposed using the `@exclude` decorator:
186+
187+
```python
188+
import nexusrpc
189+
from nexusmcp import MCPServiceHandler, exclude
190+
191+
mcp_service_handler = MCPServiceHandler()
192+
193+
194+
@mcp_service_handler.register
195+
@nexusrpc.handler.service_handler()
196+
class CalculatorHandler:
197+
@exclude
198+
@nexusrpc.handler.sync_operation
199+
async def private_operation(self, _ctx: nexusrpc.handler.StartOperationContext, input: SomeModel) -> SomeModel:
200+
"""This won't be available to MCP clients."""
201+
pass
202+
203+
@nexusrpc.handler.sync_operation
204+
async def public_operation(self, _ctx: nexusrpc.handler.StartOperationContext, input: SomeModel) -> SomeModel:
205+
"""This will be available as an MCP tool."""
206+
pass
207+
```
208+
209+
## Development
210+
211+
### Setting Up Development Environment
212+
213+
```bash
214+
# Install dependencies
215+
uv sync --dev
216+
```
217+
218+
### Running Tests
219+
220+
```bash
221+
# Run all tests
222+
uv run pytest
223+
```
224+
225+
### Code Quality
226+
227+
```bash
228+
# Format code
229+
uv run ruff format
230+
231+
# Lint code
232+
uv run ruff check
233+
234+
# Type checking
235+
uv run mypy .
236+
```
237+
238+
## License
239+
240+
This project is licensed under the MIT License. See the LICENSE file for details.

nexusmcp/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from temporalio import workflow
22

33
with workflow.unsafe.imports_passed_through():
4-
from .inbound_gateway import NexusMCPInboundGateway
4+
from .inbound_gateway import InboundGateway
55
from .service import MCPService
66
from .service_handler import MCPServiceHandler, exclude
77

8-
__all__ = ["MCPService", "MCPServiceHandler", "NexusMCPInboundGateway", "exclude"]
8+
__all__ = ["MCPService", "MCPServiceHandler", "InboundGateway", "exclude"]

0 commit comments

Comments
 (0)