GamerC0der commited on
Commit
2cf9499
·
verified ·
1 Parent(s): 4453ec4

Create mcp.py

Browse files
Files changed (1) hide show
  1. mcp.py +128 -0
mcp.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import json
3
+ import sys
4
+ import urllib.request
5
+ import re
6
+ from http.server import BaseHTTPRequestHandler, HTTPServer
7
+ import threading
8
+
9
+ async def scrape_site(url: str) -> str:
10
+ req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
11
+ with urllib.request.urlopen(req) as response:
12
+ return response.read().decode('utf-8')
13
+
14
+ async def plaintext(url: str) -> str:
15
+ html = await scrape_site(url)
16
+ html = re.sub(r'<script[^>]*>.*?</script>', '', html, flags=re.DOTALL | re.IGNORECASE)
17
+ html = re.sub(r'<style[^>]*>.*?</style>', '', html, flags=re.DOTALL | re.IGNORECASE)
18
+ text = re.sub(r'<[^>]+>', '', html)
19
+ return ' '.join(text.split())
20
+
21
+ class SimpleMCPServer:
22
+ def __init__(self):
23
+ self.tools = {}
24
+
25
+ def register_tool(self, name, func, description=""):
26
+ self.tools[name] = {"function": func, "description": description}
27
+
28
+ async def handle_request(self, request):
29
+ try:
30
+ req = json.loads(request)
31
+ method = req.get("method")
32
+
33
+ if method == "initialize":
34
+ return json.dumps({
35
+ "jsonrpc": "2.0",
36
+ "id": req.get("id"),
37
+ "result": {
38
+ "protocolVersion": "2024-11-05",
39
+ "capabilities": {"tools": {"listChanged": True}},
40
+ "serverInfo": {"name": "simple-mcp", "version": "1.0.0"}
41
+ }
42
+ })
43
+
44
+ if method == "tools/list":
45
+ tools = [{"name": name, "description": info["description"]} for name, info in self.tools.items()]
46
+ return json.dumps({"jsonrpc": "2.0", "id": req.get("id"), "result": {"tools": tools}})
47
+
48
+ if method == "tools/call":
49
+ tool_name = req["params"]["name"]
50
+ args = req["params"].get("arguments", {})
51
+ if tool_name in self.tools:
52
+ result = await self.tools[tool_name]["function"](**args)
53
+ return json.dumps({
54
+ "jsonrpc": "2.0",
55
+ "id": req.get("id"),
56
+ "result": {"content": [{"type": "text", "text": result}]}
57
+ })
58
+
59
+ except Exception as e:
60
+ return json.dumps({"jsonrpc": "2.0", "error": {"code": -32000, "message": str(e)}})
61
+
62
+
63
+ class MCPRequestHandler(BaseHTTPRequestHandler):
64
+ def __init__(self, server_instance, *args, **kwargs):
65
+ self.server_instance = server_instance
66
+ super().__init__(*args, **kwargs)
67
+
68
+ def do_POST(self):
69
+ try:
70
+ content_length = int(self.headers['Content-Length'])
71
+ post_data = self.rfile.read(content_length).decode('utf-8')
72
+
73
+ loop = asyncio.new_event_loop()
74
+ asyncio.set_event_loop(loop)
75
+ try:
76
+ response = loop.run_until_complete(self.server_instance.handle_request(post_data))
77
+ finally:
78
+ loop.close()
79
+
80
+ self.send_response(200)
81
+ self.send_header('Content-Type', 'application/json')
82
+ self.send_header('Access-Control-Allow-Origin', '*')
83
+ self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
84
+ self.send_header('Access-Control-Allow-Headers', 'Content-Type')
85
+ self.end_headers()
86
+ self.wfile.write(response.encode('utf-8'))
87
+ except Exception as e:
88
+ self.send_response(500)
89
+ self.send_header('Content-Type', 'application/json')
90
+ self.end_headers()
91
+ error_response = json.dumps({"jsonrpc": "2.0", "error": {"code": -32000, "message": str(e)}})
92
+ self.wfile.write(error_response.encode('utf-8'))
93
+
94
+ def do_OPTIONS(self):
95
+ self.send_response(200)
96
+ self.send_header('Access-Control-Allow-Origin', '*')
97
+ self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
98
+ self.send_header('Access-Control-Allow-Headers', 'Content-Type')
99
+ self.end_headers()
100
+
101
+ def run_http_server(server_instance):
102
+ def handler_factory(server_instance):
103
+ def create_handler(*args, **kwargs):
104
+ return MCPRequestHandler(server_instance, *args, **kwargs)
105
+ return create_handler
106
+
107
+ httpd = HTTPServer(('0.0.0.0', 7860), handler_factory(server_instance))
108
+ print("Simple MCP HTTP Server started on port 7860")
109
+ print("Available tools: scrape_site, plaintext")
110
+ httpd.serve_forever()
111
+
112
+ async def main():
113
+ server = SimpleMCPServer()
114
+ server.register_tool("scrape_site", scrape_site, "Get HTML content from a website URL")
115
+ server.register_tool("plaintext", plaintext, "Get plain text content from a website URL (removes HTML tags, scripts, and styles)")
116
+
117
+ server_thread = threading.Thread(target=run_http_server, args=(server,))
118
+ server_thread.daemon = True
119
+ server_thread.start()
120
+
121
+ try:
122
+ while True:
123
+ await asyncio.sleep(1)
124
+ except KeyboardInterrupt:
125
+ print("Server shutting down...")
126
+
127
+ if __name__ == "__main__":
128
+ asyncio.run(main())