
<h1 align="center">robyn-mcp</h1>

<p align="center">
  Turn Robyn APIs into MCP tools, resources, and prompts instantly.
</p>

<p align="center">
  <a href="https://pypi.org/project/robyn-mcp/"><img src="https://img.shields.io/pypi/v/robyn-mcp.svg" /></a>
  <a href="https://pypi.org/project/robyn-mcp/"><img src="https://img.shields.io/pypi/dm/robyn-mcp.svg" /></a>
  <a href="https://github.com/Vamshi0104/robyn_mcp/blob/main/LICENSE"><img src="https://img.shields.io/github/license/your-org/robyn_mcp" /></a>
  <a href="https://vamshi0104.github.io/robyn_mcp/"><img src="https://img.shields.io/badge/docs-live-blue" /></a>
</p>

---

##  Why robyn-mcp

You already have a Robyn backend.

You shouldn’t need to rebuild it to support MCP.

**robyn-mcp bridges that gap.**

- Convert existing routes → MCP tools
- Add resources & prompts without redesign
- Keep your architecture intact
- Ship production-ready MCP instantly

---

## 🚀 Highlights

- ⚡ Auto-expose Robyn routes as MCP tools  
- 🧠 JSON Schema generation from Python types  
- 🔗 OpenAPI enrichment + `$ref` resolution  
- 🔐 Auth-aware context + header forwarding  
- 📊 Observability (metrics, traces, audit logs)  
- 🗂️ Response caching with tag invalidation  
- 🧪 CLI for validation + debugging  
- 🖥️ Built-in Playground UI  
- 📦 Production-ready packaging  

---

## 📦 Installation

```bash
python -m pip install --upgrade pip
pip install robyn robyn-mcp
python -m robyn_mcp.cli install-note
```

`pip install robyn-mcp` (wheel install) does not execute package post-install Python hooks, so the explicit
`install-note` step is the reliable way to show the banner right after installation.

If you want automatic banner output + installed package summary in one command:

```bash
python scripts/install_with_banner.py --wheel dist/robyn_mcp-1.0.1-py3-none-any.whl
```

---

## ⚡ Quick Start

```python
from robyn import Robyn
from robyn_mcp import RobynMCP, RobynMCPConfig, expose_tool

app = Robyn(__file__)

@app.get("/health")
@expose_tool(summary="Return service health")
def health():
    return {"ok": True}

mcp = RobynMCP(app, config=RobynMCPConfig(require_session=False))
mcp.mount_http("/mcp")

# Prints the ROBYN-MCP banner once, then starts Robyn.
app.start(port=8080)
```

---

## 🗂️ Response Caching With Invalidation Tags

```python
from robyn_mcp import RobynMCPConfig, expose_tool

@expose_tool(operation_id="list_products", side_effect=False, cache_tags=["products"])
def list_products():
    return {"items": [...]}

@expose_tool(operation_id="create_product", side_effect=True, invalidate_tags=["products"])
def create_product(id: str, name: str, price: int):
    ...

config = RobynMCPConfig(
    require_session=False,
    enable_response_cache=True,
    response_cache_ttl_seconds=120,
)
```

Cache behavior:
- Read tools can be cached with TTL.
- Mutation tools can invalidate matching cache tags.
- If no invalidation tags are provided on a mutation, cache is safely cleared by default.

Curl flow:

```bash
# 1) Read (cached after first call)
curl -X POST http://localhost:8080/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_products","arguments":{}}}'

# 2) Mutation (invalidates products cache tag)
curl -X POST http://localhost:8080/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"create_product","arguments":{"id":"sku-2","name":"sock","price":15}}}'

# 3) Read again (fresh result after invalidation)
curl -X POST http://localhost:8080/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_products","arguments":{}}}'
```

See complete runnable example: `examples/cache_invalidation_example.py`.

---

## 🧪 Test

```bash
curl -X POST http://localhost:8080/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
```

---

## 🛠 CLI

```bash
robyn-mcp runtime --json
robyn-mcp validate-endpoint --url http://localhost:8080/mcp
robyn-mcp release-audit --json
robyn-mcp release-bundle --json
```

---

## 🖥 Playground

Enable:

```python
RobynMCPConfig(enable_playground=True)
```

Open:

```
/mcp/playground
```

---

## 📊 Observability

- Tool call metrics  
- Error tracking  
- Latency stats  
- Audit logs  
- Recent traces  

---

## 📁 Structure

```
robyn_mcp/
├── src/
├── tests/
├── examples/
└── scripts/
```

---

## 🧠 Core Concepts

| Concept   | Description |
|----------|------------|
| Tools    | Callable MCP endpoints |
| Resources| Structured data sources |
| Prompts  | Reusable prompt templates |


## Current capabilities

- Route to MCP tool harvesting
- Explicit decorators for tools, resources, and prompts
- JSON Schema generation from Python annotations
- OpenAPI-aware enrichment when route metadata exists
- Streamable-HTTP style single-endpoint dispatch foundation
- Session lifecycle support with TTL
- Request context, principal, tenant, and header forwarding hooks
- Per-tool policy hooks and built-in token-bucket rate limiting
- Response caching for read tools with tag-based invalidation on mutations
- Metrics and recent audit event capture
- Docs, CI, release workflow, smoke tests, and benchmark scaffolding

---

## Final Note

Adopting MCP shouldn’t require rebuilding your backend.

With **robyn-mcp**, your existing Robyn routes become a fully discoverable, inspectable, and production-ready MCP surface - with minimal effort and maximum leverage.
