Skip to content

Commit ce5026f

Browse files
committed
Release v2.7.8
1 parent 4428e98 commit ce5026f

32 files changed

Lines changed: 3784 additions & 250 deletions

docker/Dockerfile.chat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=2.7.7" \
19+
"praisonai>=2.7.8" \
2020
"praisonai[chat]" \
2121
"embedchain[github,youtube]"
2222

docker/Dockerfile.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
2020
# Install Python packages (using latest versions)
2121
RUN pip install --no-cache-dir \
2222
praisonai_tools \
23-
"praisonai>=2.7.7" \
23+
"praisonai>=2.7.8" \
2424
"praisonai[ui]" \
2525
"praisonai[chat]" \
2626
"praisonai[realtime]" \

docker/Dockerfile.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=2.7.7" \
19+
"praisonai>=2.7.8" \
2020
"praisonai[ui]" \
2121
"praisonai[crewai]"
2222

examples/mcp/README.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# MCP Server Examples
2+
3+
Examples demonstrating the MCP Server v2 features per MCP Protocol Version 2025-11-25.
4+
5+
## Features Demonstrated
6+
7+
### 1. Pagination (`pagination_example.py`)
8+
9+
Demonstrates pagination for `tools/list`, `resources/list`, and `prompts/list`:
10+
11+
- Opaque cursor encoding (base64url)
12+
- Server-determined page size (default: 50, max: 100)
13+
- `nextCursor` for fetching more results
14+
- Cursor validation with JSON-RPC errors
15+
16+
```bash
17+
python pagination_example.py
18+
```
19+
20+
### 2. Tool Annotations (`tool_annotations_example.py`)
21+
22+
Demonstrates MCP 2025-11-25 tool annotation hints:
23+
24+
- `readOnlyHint`: Tool only reads data
25+
- `destructiveHint`: Tool may have destructive effects
26+
- `idempotentHint`: Safe to call multiple times
27+
- `openWorldHint`: Interacts with external world
28+
29+
```bash
30+
python tool_annotations_example.py
31+
```
32+
33+
### 3. CLI Tools (`cli_tools_example.sh`)
34+
35+
Demonstrates the new CLI commands:
36+
37+
```bash
38+
# List tools with pagination
39+
praisonai mcp list-tools --limit 10
40+
praisonai mcp list-tools --cursor <cursor> --json
41+
42+
# Search tools
43+
praisonai mcp tools search "query"
44+
praisonai mcp tools search --category memory
45+
praisonai mcp tools search --read-only
46+
praisonai mcp tools search --json
47+
48+
# Get tool info
49+
praisonai mcp tools info <tool-name>
50+
praisonai mcp tools info <tool-name> --json
51+
52+
# Get tool schema
53+
praisonai mcp tools schema <tool-name>
54+
```
55+
56+
## API Reference
57+
58+
### Pagination
59+
60+
```python
61+
from praisonai.mcp_server.registry import MCPToolRegistry
62+
63+
registry = MCPToolRegistry()
64+
# ... register tools ...
65+
66+
# Get first page
67+
tools, next_cursor = registry.list_paginated(page_size=50)
68+
69+
# Get next page
70+
if next_cursor:
71+
more_tools, next_cursor = registry.list_paginated(cursor=next_cursor)
72+
```
73+
74+
### Tool Search
75+
76+
```python
77+
# Search by query
78+
tools, next_cursor, total = registry.search(query="memory")
79+
80+
# Filter by category
81+
tools, _, _ = registry.search(category="file")
82+
83+
# Filter by read-only hint
84+
tools, _, _ = registry.search(read_only=True)
85+
86+
# Combined filters with pagination
87+
tools, next_cursor, total = registry.search(
88+
query="data",
89+
category="storage",
90+
read_only=True,
91+
page_size=10,
92+
)
93+
```
94+
95+
### Tool Annotations
96+
97+
```python
98+
from praisonai.mcp_server.registry import MCPToolDefinition
99+
100+
# Read-only tool
101+
tool = MCPToolDefinition(
102+
name="data.read",
103+
description="Read data",
104+
handler=read_handler,
105+
input_schema={"type": "object"},
106+
read_only_hint=True,
107+
destructive_hint=False,
108+
)
109+
110+
# Destructive tool
111+
tool = MCPToolDefinition(
112+
name="file.delete",
113+
description="Delete file",
114+
handler=delete_handler,
115+
input_schema={"type": "object"},
116+
destructive_hint=True,
117+
idempotent_hint=False,
118+
)
119+
```
120+
121+
## MCP Protocol Compliance
122+
123+
These examples comply with MCP Protocol Version 2025-11-25:
124+
125+
- Pagination uses opaque cursors (base64url encoded)
126+
- Server determines page size (client cannot override)
127+
- Invalid cursors return JSON-RPC error code -32602
128+
- Tool annotations follow the spec defaults:
129+
- `readOnlyHint`: false
130+
- `destructiveHint`: true
131+
- `idempotentHint`: false
132+
- `openWorldHint`: true

examples/mcp/cli_tools_example.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
# MCP CLI Tools Examples
3+
#
4+
# Demonstrates the new CLI commands for MCP tool management:
5+
# - praisonai mcp tools search
6+
# - praisonai mcp tools info
7+
# - praisonai mcp tools schema
8+
# - praisonai mcp list-tools (with pagination)
9+
#
10+
# Usage:
11+
# chmod +x cli_tools_example.sh
12+
# ./cli_tools_example.sh
13+
14+
echo "========================================"
15+
echo "MCP CLI Tools Examples"
16+
echo "MCP Protocol Version: 2025-11-25"
17+
echo "========================================"
18+
19+
echo ""
20+
echo "--- List Tools (with pagination) ---"
21+
echo "Command: praisonai mcp list-tools --limit 5"
22+
praisonai mcp list-tools --limit 5
23+
24+
echo ""
25+
echo "--- List Tools (JSON output) ---"
26+
echo "Command: praisonai mcp list-tools --json --limit 3"
27+
praisonai mcp list-tools --json --limit 3
28+
29+
echo ""
30+
echo "--- Tools Help ---"
31+
echo "Command: praisonai mcp tools --help"
32+
praisonai mcp tools --help
33+
34+
echo ""
35+
echo "--- Search Tools ---"
36+
echo "Command: praisonai mcp tools search 'workflow'"
37+
praisonai mcp tools search "workflow"
38+
39+
echo ""
40+
echo "--- Search Read-Only Tools ---"
41+
echo "Command: praisonai mcp tools search --read-only"
42+
praisonai mcp tools search --read-only
43+
44+
echo ""
45+
echo "--- Search with JSON Output ---"
46+
echo "Command: praisonai mcp tools search 'memory' --json"
47+
praisonai mcp tools search "memory" --json
48+
49+
echo ""
50+
echo "========================================"
51+
echo "Examples completed!"
52+
echo "========================================"

examples/mcp/pagination_example.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#!/usr/bin/env python3
2+
"""
3+
MCP Pagination Example
4+
5+
Demonstrates the pagination feature for tools/list, resources/list, and prompts/list
6+
per MCP 2025-11-25 specification.
7+
8+
Usage:
9+
python pagination_example.py
10+
"""
11+
12+
from praisonai.mcp_server.registry import (
13+
MCPToolRegistry,
14+
encode_cursor,
15+
decode_cursor,
16+
DEFAULT_PAGE_SIZE,
17+
)
18+
19+
20+
def demo_tool_pagination():
21+
"""Demonstrate tool pagination."""
22+
print("\n" + "=" * 60)
23+
print("Tool Pagination Demo")
24+
print("=" * 60)
25+
26+
# Create registry with many tools
27+
registry = MCPToolRegistry()
28+
for i in range(75):
29+
registry.register(
30+
name=f"example.tool_{i:03d}",
31+
handler=lambda: f"Tool {i} executed",
32+
description=f"Example tool number {i}",
33+
)
34+
35+
print(f"\nRegistered {len(registry.list_all())} tools")
36+
print(f"Default page size: {DEFAULT_PAGE_SIZE}")
37+
38+
# First page
39+
print("\n--- First Page ---")
40+
tools, next_cursor = registry.list_paginated()
41+
print(f"Tools returned: {len(tools)}")
42+
print(f"First tool: {tools[0]['name']}")
43+
print(f"Last tool: {tools[-1]['name']}")
44+
print(f"Next cursor: {next_cursor}")
45+
46+
# Second page
47+
print("\n--- Second Page (using cursor) ---")
48+
tools2, next_cursor2 = registry.list_paginated(cursor=next_cursor)
49+
print(f"Tools returned: {len(tools2)}")
50+
print(f"First tool: {tools2[0]['name']}")
51+
print(f"Last tool: {tools2[-1]['name']}")
52+
print(f"Next cursor: {next_cursor2}")
53+
54+
# Custom page size
55+
print("\n--- Custom Page Size (10) ---")
56+
tools3, next_cursor3 = registry.list_paginated(page_size=10)
57+
print(f"Tools returned: {len(tools3)}")
58+
print(f"Next cursor: {next_cursor3}")
59+
60+
61+
def demo_cursor_encoding():
62+
"""Demonstrate cursor encoding/decoding."""
63+
print("\n" + "=" * 60)
64+
print("Cursor Encoding Demo")
65+
print("=" * 60)
66+
67+
# Simple offset
68+
cursor1 = encode_cursor(50)
69+
offset1, _ = decode_cursor(cursor1)
70+
print(f"\nOffset 50 -> Cursor: {cursor1}")
71+
print(f"Decoded back: offset={offset1}")
72+
73+
# With snapshot hash
74+
cursor2 = encode_cursor(100, "abc123hash")
75+
offset2, snapshot = decode_cursor(cursor2)
76+
print(f"\nOffset 100 with snapshot -> Cursor: {cursor2}")
77+
print(f"Decoded back: offset={offset2}, snapshot={snapshot}")
78+
79+
80+
def demo_tool_search():
81+
"""Demonstrate tool search with pagination."""
82+
print("\n" + "=" * 60)
83+
print("Tool Search Demo")
84+
print("=" * 60)
85+
86+
registry = MCPToolRegistry()
87+
88+
# Register tools with different categories
89+
from praisonai.mcp_server.registry import MCPToolDefinition
90+
91+
tools_data = [
92+
("memory.show", "Show memory contents", "memory", True, False),
93+
("memory.clear", "Clear memory", "memory", False, True),
94+
("file.read", "Read a file", "file", True, False),
95+
("file.write", "Write to a file", "file", False, True),
96+
("file.delete", "Delete a file", "file", False, True),
97+
("web.search", "Search the web", "web", True, False),
98+
("web.fetch", "Fetch a URL", "web", True, False),
99+
]
100+
101+
for name, desc, category, read_only, destructive in tools_data:
102+
registry._tools[name] = MCPToolDefinition(
103+
name=name,
104+
description=desc,
105+
handler=lambda: None,
106+
input_schema={"type": "object"},
107+
category=category,
108+
read_only_hint=read_only,
109+
destructive_hint=destructive,
110+
)
111+
112+
# Search by query
113+
print("\n--- Search: 'memory' ---")
114+
results, _, total = registry.search(query="memory")
115+
print(f"Found {total} tools:")
116+
for tool in results:
117+
print(f" - {tool['name']}")
118+
119+
# Search by category
120+
print("\n--- Search: category='file' ---")
121+
results, _, total = registry.search(category="file")
122+
print(f"Found {total} tools:")
123+
for tool in results:
124+
print(f" - {tool['name']}")
125+
126+
# Search read-only tools
127+
print("\n--- Search: read_only=True ---")
128+
results, _, total = registry.search(read_only=True)
129+
print(f"Found {total} read-only tools:")
130+
for tool in results:
131+
print(f" - {tool['name']}")
132+
133+
134+
def main():
135+
"""Run all demos."""
136+
print("\n" + "#" * 60)
137+
print("# MCP Pagination & Search Examples")
138+
print("# MCP Protocol Version: 2025-11-25")
139+
print("#" * 60)
140+
141+
demo_cursor_encoding()
142+
demo_tool_pagination()
143+
demo_tool_search()
144+
145+
print("\n" + "=" * 60)
146+
print("All demos completed!")
147+
print("=" * 60 + "\n")
148+
149+
150+
if __name__ == "__main__":
151+
main()

0 commit comments

Comments
 (0)