-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathadvanced_usage.py
More file actions
170 lines (137 loc) · 6.25 KB
/
advanced_usage.py
File metadata and controls
170 lines (137 loc) · 6.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
"""
Example script demonstrating how to use OpenAPI2MCP programmatically.
"""
import argparse
import asyncio
import json
import os
import sys
from typing import Dict, Any, List
import uvicorn
import yaml
from dotenv import load_dotenv
from openapi2mcp.auth import OAuthHandler
from openapi2mcp.openapi_parser import OpenAPIParser
from openapi2mcp.server import MCPServer
# Load environment variables from .env file
load_dotenv()
async def list_tools_from_spec(spec_file: str) -> List[Dict[str, Any]]:
"""
Extract and print tools from an OpenAPI specification file.
Args:
spec_file: Path to the OpenAPI specification file
Returns:
List of tools extracted from the specification
"""
print(f"Loading OpenAPI specification from {spec_file}...")
# Load the OpenAPI specification
if spec_file.endswith(('.yaml', '.yml')):
with open(spec_file, 'r') as f:
spec = yaml.safe_load(f)
else: # Assume JSON
with open(spec_file, 'r') as f:
spec = json.load(f)
# Extract tools from the specification
parser = OpenAPIParser(spec)
tools = parser.extract_tools()
print(f"Extracted {len(tools)} tools from the specification.\n")
print("Available tools:")
for i, tool in enumerate(tools, 1):
print(f"{i}. {tool['name']} - {tool.get('description', '').split('\n')[0]}")
return tools
async def run_mcp_server(spec_file: str, host: str = "127.0.0.1", port: int = 8000) -> None:
"""
Run an MCP server with tools from an OpenAPI specification file.
Args:
spec_file: Path to the OpenAPI specification file
host: Host to run the server on (default: 127.0.0.1)
port: Port to run the server on (default: 8000)
"""
print(f"Starting MCP server with specification from {spec_file}...")
# Load authentication configuration from environment variables
auth_config = {
"client_id": os.environ.get("API_CLIENT_ID"),
"client_secret": os.environ.get("API_CLIENT_SECRET"),
"token_url": os.environ.get("API_TOKEN_URL")
}
# Create an OAuth handler if all required config is present
auth_handler = None
if all(auth_config.values()):
auth_handler = OAuthHandler(auth_config)
print("OAuth authentication configured.")
else:
print("OAuth authentication not configured. Set API_CLIENT_ID, API_CLIENT_SECRET, and API_TOKEN_URL environment variables to enable.")
# Create and start the MCP server
server = MCPServer(spec_files=[spec_file], auth_config=auth_config if auth_handler else None)
app = server.get_app()
# Show information about the server
print(f"\nMCP server ready at http://{host}:{port}/mcp")
print(f"Available endpoints:")
print(f"- GET /mcp - Get server information")
print(f"- GET /mcp/tools - Get available tools")
print(f"- POST /mcp/run - Run a tool")
print(f"- GET /mcp/sse - Server-Sent Events endpoint")
# Show example tool usage
if server.tools:
print(f"\nExample tool usage (first tool):")
tool = server.tools[0]
parameters = {}
for param_name, param_schema in tool.get("parameters", {}).get("properties", {}).items():
# Generate a sample value for each parameter
if param_schema.get("type") == "string":
if "enum" in param_schema:
parameters[param_name] = param_schema["enum"][0]
else:
parameters[param_name] = f"sample_{param_name}"
elif param_schema.get("type") == "integer":
parameters[param_name] = 10
elif param_schema.get("type") == "boolean":
parameters[param_name] = True
print(f"curl -X POST http://{host}:{port}/mcp/run \\")
print(f" -H \"Content-Type: application/json\" \\")
print(f" -d '{{")
print(f' "name": "{tool["name"]}",')
print(f' "parameters": {json.dumps(parameters, indent=6)}')
print(f" }}'")
print("\nPress Ctrl+C to stop the server.")
# Run the server
uvicorn.run(app, host=host, port=port)
async def export_tools_to_json(spec_file: str, output_file: str) -> None:
"""
Export tools from an OpenAPI specification file to a JSON file.
Args:
spec_file: Path to the OpenAPI specification file
output_file: Path to the output JSON file
"""
print(f"Exporting tools from {spec_file} to {output_file}...")
# Extract tools from the specification
tools = await list_tools_from_spec(spec_file)
# Write tools to the output file
with open(output_file, 'w') as f:
json.dump({"tools": tools}, f, indent=2)
print(f"Successfully exported {len(tools)} tools to {output_file}.")
async def main():
"""Main function."""
parser = argparse.ArgumentParser(description="OpenAPI2MCP Example Script")
parser.add_argument('--spec-file', '-s', required=True, help='Path to the OpenAPI specification file')
subparsers = parser.add_subparsers(dest='action', help='Action to perform')
# 'list' action
list_parser = subparsers.add_parser('list', help='List tools from an OpenAPI specification')
# 'serve' action
serve_parser = subparsers.add_parser('serve', help='Run an MCP server with tools from an OpenAPI specification')
serve_parser.add_argument('--host', default='127.0.0.1', help='Host to run the server on (default: 127.0.0.1)')
serve_parser.add_argument('--port', '-p', type=int, default=8000, help='Port to run the server on (default: 8000)')
# 'export' action
export_parser = subparsers.add_parser('export', help='Export tools from an OpenAPI specification to a JSON file')
export_parser.add_argument('--output', '-o', required=True, help='Path to the output JSON file')
args = parser.parse_args()
if args.action == 'list':
await list_tools_from_spec(args.spec_file)
elif args.action == 'serve':
await run_mcp_server(args.spec_file, args.host, args.port)
elif args.action == 'export':
await export_tools_to_json(args.spec_file, args.output)
else:
parser.print_help()
if __name__ == "__main__":
asyncio.run(main())