Skip to content

Commit 2fe4f48

Browse files
committed
intitial testing support for SchemaPin.org
1 parent a712a58 commit 2fe4f48

File tree

13 files changed

+1494518
-154
lines changed

13 files changed

+1494518
-154
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Complete Schema Signing Example
4+
5+
This example demonstrates how to use the MockLoop MCP schema signing system
6+
for securing MCP tools with cryptographic signatures.
7+
"""
8+
9+
import asyncio
10+
import os
11+
from pathlib import Path
12+
13+
# Add src to path for imports
14+
import sys
15+
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))
16+
17+
from mockloop_mcp.schemapin import (
18+
signed_tool,
19+
SchemaSigner,
20+
create_test_signer,
21+
get_tool_signature,
22+
get_tool_domain,
23+
verify_tool_signature,
24+
list_signed_tools
25+
)
26+
27+
28+
# Example 1: Basic tool signing with file-based private key
29+
@signed_tool(
30+
domain="example.com",
31+
private_key_path="./examples/schemapin/test-private.pem" # You would use a real key
32+
)
33+
async def example_tool_with_file_key(name: str, count: int = 5) -> dict:
34+
"""
35+
Example MCP tool signed with file-based private key.
36+
37+
Args:
38+
name: The name parameter
39+
count: Number of items (default: 5)
40+
41+
Returns:
42+
Dictionary with results
43+
"""
44+
return {"name": name, "count": count, "status": "success"}
45+
46+
47+
# Example 2: Tool signing with private key content
48+
EXAMPLE_PRIVATE_KEY = """-----BEGIN PRIVATE KEY-----
49+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7VJTUt9Us8cKB...
50+
-----END PRIVATE KEY-----"""
51+
52+
@signed_tool(
53+
domain="example.com",
54+
private_key_content=EXAMPLE_PRIVATE_KEY
55+
)
56+
async def example_tool_with_key_content(data: dict, validate: bool = True) -> dict:
57+
"""
58+
Example MCP tool signed with private key content.
59+
60+
Args:
61+
data: Input data dictionary
62+
validate: Whether to validate input (default: True)
63+
64+
Returns:
65+
Processed data dictionary
66+
"""
67+
if validate:
68+
# Perform validation
69+
pass
70+
return {"processed": data, "validated": validate}
71+
72+
73+
# Example 3: Using environment variables for configuration
74+
@signed_tool(
75+
domain=os.getenv("MOCKLOOP_SIGNING_DOMAIN", "example.com"),
76+
private_key_path=os.getenv("MOCKLOOP_PRIVATE_KEY_PATH"),
77+
private_key_content=os.getenv("MOCKLOOP_PRIVATE_KEY_CONTENT")
78+
)
79+
async def example_tool_with_env_config(message: str) -> dict:
80+
"""
81+
Example MCP tool using environment variables for signing configuration.
82+
83+
Args:
84+
message: Message to process
85+
86+
Returns:
87+
Response dictionary
88+
"""
89+
return {"message": f"Processed: {message}", "timestamp": "2024-01-01T00:00:00Z"}
90+
91+
92+
async def demonstrate_signing_system():
93+
"""Demonstrate the complete signing system."""
94+
print("MockLoop MCP Schema Signing Demonstration")
95+
print("=" * 50)
96+
97+
# Create a test signer for demonstration
98+
print("\n1. Creating test signer...")
99+
create_test_signer("demo.example.com")
100+
print(" Test signer created for domain: demo.example.com")
101+
102+
# Demonstrate tool signature verification
103+
print("\n2. Verifying tool signatures...")
104+
105+
# Note: In a real scenario, these tools would be properly signed
106+
# For demonstration, we'll show the verification process
107+
tools_to_check = [
108+
example_tool_with_file_key,
109+
example_tool_with_key_content,
110+
example_tool_with_env_config
111+
]
112+
113+
for tool in tools_to_check:
114+
signature = get_tool_signature(tool)
115+
domain = get_tool_domain(tool)
116+
is_valid = verify_tool_signature(tool)
117+
118+
print(f" Tool: {tool.__name__}")
119+
print(f" Domain: {domain}")
120+
print(f" Has signature: {signature is not None}")
121+
print(f" Signature valid: {is_valid}")
122+
print()
123+
124+
# List all signed tools in current module
125+
print("3. Listing signed tools...")
126+
signed_tools = list_signed_tools(sys.modules[__name__])
127+
print(f" Found {len(signed_tools)} signed tools:")
128+
for tool_info in signed_tools:
129+
print(f" - {tool_info['name']} (domain: {tool_info['domain']})")
130+
131+
# Demonstrate tool execution with signature injection
132+
print("\n4. Executing signed tool...")
133+
try:
134+
# The @signed_tool decorator automatically injects signature metadata
135+
result = await example_tool_with_env_config("Hello, MockLoop!")
136+
print(f" Tool execution result: {result}")
137+
except Exception as e:
138+
print(f" Tool execution failed: {e}")
139+
140+
print("\n5. Configuration examples:")
141+
print(" Environment variables:")
142+
print(" export MOCKLOOP_SIGNING_DOMAIN=your-domain.com")
143+
print(" export MOCKLOOP_PRIVATE_KEY_PATH=/path/to/private.pem")
144+
print(" # OR")
145+
print(" export MOCKLOOP_PRIVATE_KEY_CONTENT=\"$(cat /path/to/private.pem)\"")
146+
147+
print("\n Batch signing:")
148+
print(" python scripts/sign_all_schemas.py --domain your-domain.com --private-key /path/to/key.pem")
149+
150+
print("\n Signature validation:")
151+
print(" python scripts/validate_signatures.py --domain your-domain.com --public-key /path/to/public.pem")
152+
153+
154+
if __name__ == "__main__":
155+
asyncio.run(demonstrate_signing_system())
156+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"domain": "mockloop.com",
3+
"private_key_path": "/path/to/your/private.pem",
4+
"search_paths": ["src"],
5+
"force_resign": false,
6+
"output_file": "signing_results.json",
7+
"description": "Example configuration for batch signing MCP tools",
8+
"environments": {
9+
"development": {
10+
"domain": "dev.mockloop.com",
11+
"private_key_path": "./dev-keys/private.pem",
12+
"force_resign": true
13+
},
14+
"staging": {
15+
"domain": "staging.mockloop.com",
16+
"private_key_path": "/etc/mockloop/staging-private.pem",
17+
"force_resign": false
18+
},
19+
"production": {
20+
"domain": "mockloop.com",
21+
"private_key_path": "/etc/mockloop/production-private.pem",
22+
"force_resign": false
23+
}
24+
},
25+
"usage_examples": {
26+
"batch_signing": "python scripts/sign_all_schemas.py --config examples/schemapin/signing_config_example.json",
27+
"single_domain": "python scripts/sign_all_schemas.py --domain mockloop.com --private-key /path/to/key.pem",
28+
"with_content": "python scripts/sign_all_schemas.py --domain mockloop.com --private-key-content \"$(cat /path/to/key.pem)\"",
29+
"validation": "python scripts/validate_signatures.py --config examples/schemapin/signing_config_example.json"
30+
}
31+
}

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,8 @@ directory = "htmlcov"
301301

302302
[tool.coverage.xml]
303303
output = "coverage.xml"
304+
305+
[dependency-groups]
306+
dev = [
307+
"ruff>=0.11.11",
308+
]

0 commit comments

Comments
 (0)