Last active 1 month ago

Access AI-generated documentation for any GitHub repository. Ask questions, get documentation structure, and read full contents.

liusijin revised this gist 1 month ago. Go to revision

1 file changed, 20 insertions, 53 deletions

DeepWiki.py

@@ -3,50 +3,11 @@
3 3
4 4 import json
5 5 import urllib.request
6 + import ssl
6 7 import time
7 8
8 - # Global session cache
9 - _session_id = None
10 -
11 - def get_session_id():
12 - """Initialize MCP session and get session ID"""
13 - global _session_id
14 - if _session_id:
15 - return _session_id
16 -
17 - url = "https://mcp.deepwiki.com/mcp"
18 - data = {
19 - "jsonrpc": "2.0",
20 - "id": "init",
21 - "method": "initialize",
22 - "params": {
23 - "protocolVersion": "2024-11-05",
24 - "capabilities": {},
25 - "clientInfo": {"name": "nanocode", "version": "1.0"}
26 - }
27 - }
28 -
29 - try:
30 - req = urllib.request.Request(
31 - url,
32 - json.dumps(data).encode(),
33 - {
34 - "Content-Type": "application/json",
35 - "Accept": "application/json, text/event-stream"
36 - }
37 - )
38 - resp = urllib.request.urlopen(req, timeout=30)
39 - _session_id = resp.headers.get("mcp-session-id")
40 - return _session_id
41 - except Exception as e:
42 - return None
43 -
44 9 def mcp_call(tool_name, arguments):
45 10 """Make MCP JSON-RPC call to DeepWiki"""
46 - session_id = get_session_id()
47 - if not session_id:
48 - return "error: Failed to initialize MCP session"
49 -
50 11 url = "https://mcp.deepwiki.com/mcp"
51 12 request_id = str(int(time.time() * 1000))
52 13
@@ -61,16 +22,20 @@ def mcp_call(tool_name, arguments):
61 22 }
62 23
63 24 try:
25 + # Create SSL context that doesn't verify certificates for mitmproxy
26 + ssl_context = ssl.create_default_context()
27 + ssl_context.check_hostname = False
28 + ssl_context.verify_mode = ssl.CERT_NONE
29 +
64 30 req = urllib.request.Request(
65 31 url,
66 32 json.dumps(data).encode(),
67 33 {
68 34 "Content-Type": "application/json",
69 - "Accept": "application/json, text/event-stream",
70 - "mcp-session-id": session_id
35 + "Accept": "application/json, text/event-stream"
71 36 }
72 37 )
73 - resp = urllib.request.urlopen(req, timeout=30)
38 + resp = urllib.request.urlopen(req, timeout=60, context=ssl_context)
74 39
75 40 # Handle SSE response
76 41 response_text = resp.read().decode()
@@ -78,28 +43,30 @@ def mcp_call(tool_name, arguments):
78 43 # Parse SSE format: extract JSON from "data: " lines
79 44 for line in response_text.split('\n'):
80 45 if line.startswith('data: '):
81 - data = line[6:].strip() # Skip "data: " prefix
46 + data_str = line[6:].strip() # Skip "data: " prefix
82 47
83 48 # Skip ping events
84 - if data == "ping":
49 + if data_str == "ping":
85 50 continue
86 51
87 52 try:
88 - result = json.loads(data)
53 + result = json.loads(data_str)
89 54
90 55 if "error" in result:
91 - return f"error: {result['error']['message']}"
56 + return f"error: {result['error'].get('message', str(result['error']))}"
92 57
93 58 # Extract text from MCP response
94 59 content = result.get("result", {}).get("content", [])
95 60 if content:
96 - return "\n".join(item["text"] for item in content if item.get("type") == "text")
61 + texts = [item["text"] for item in content if item.get("type") == "text"]
62 + if texts:
63 + return "\n".join(texts)
97 64 except json.JSONDecodeError:
98 65 continue
99 66
100 - return "error: No data in response"
67 + return "error: No valid data in response"
101 68 except Exception as e:
102 - return f"error: {e}"
69 + return f"error: {type(e).__name__}: {e}"
103 70
104 71 @register_tool(
105 72 "deepwiki_ask",
@@ -107,7 +74,7 @@ def mcp_call(tool_name, arguments):
107 74 {"repo": "string", "question": "string"}
108 75 )
109 76 def deepwiki_ask(args):
110 - """Ask a question about a GitHub repository"""
77 + """Ask a question about a GitHub repository (format: owner/repo)"""
111 78 return mcp_call("ask_question", {
112 79 "repoName": args["repo"],
113 80 "question": args["question"]
@@ -119,7 +86,7 @@ def deepwiki_ask(args):
119 86 {"repo": "string"}
120 87 )
121 88 def deepwiki_structure(args):
122 - """Get documentation structure/topics for a GitHub repository"""
89 + """Get documentation structure/topics for a GitHub repository (format: owner/repo)"""
123 90 return mcp_call("read_wiki_structure", {
124 91 "repoName": args["repo"]
125 92 })
@@ -130,7 +97,7 @@ def deepwiki_structure(args):
130 97 {"repo": "string"}
131 98 )
132 99 def deepwiki_contents(args):
133 - """Get full documentation contents for a GitHub repository"""
100 + """Get full documentation contents for a GitHub repository (format: owner/repo)"""
134 101 return mcp_call("read_wiki_contents", {
135 102 "repoName": args["repo"]
136 103 })

liusijin revised this gist 1 month ago. Go to revision

No changes

liusijin revised this gist 2 months ago. Go to revision

No changes

liusijin revised this gist 2 months ago. Go to revision

No changes

liusijin revised this gist 2 months ago. Go to revision

No changes

liusijin revised this gist 2 months ago. Go to revision

No changes

liusijin revised this gist 2 months ago. Go to revision

1 file changed, 136 insertions

DeepWiki.py(file created)

@@ -0,0 +1,136 @@
1 + #!/usr/bin/env python3
2 + """DeepWiki extension - MCP HTTP client for GitHub repo documentation"""
3 +
4 + import json
5 + import urllib.request
6 + import time
7 +
8 + # Global session cache
9 + _session_id = None
10 +
11 + def get_session_id():
12 + """Initialize MCP session and get session ID"""
13 + global _session_id
14 + if _session_id:
15 + return _session_id
16 +
17 + url = "https://mcp.deepwiki.com/mcp"
18 + data = {
19 + "jsonrpc": "2.0",
20 + "id": "init",
21 + "method": "initialize",
22 + "params": {
23 + "protocolVersion": "2024-11-05",
24 + "capabilities": {},
25 + "clientInfo": {"name": "nanocode", "version": "1.0"}
26 + }
27 + }
28 +
29 + try:
30 + req = urllib.request.Request(
31 + url,
32 + json.dumps(data).encode(),
33 + {
34 + "Content-Type": "application/json",
35 + "Accept": "application/json, text/event-stream"
36 + }
37 + )
38 + resp = urllib.request.urlopen(req, timeout=30)
39 + _session_id = resp.headers.get("mcp-session-id")
40 + return _session_id
41 + except Exception as e:
42 + return None
43 +
44 + def mcp_call(tool_name, arguments):
45 + """Make MCP JSON-RPC call to DeepWiki"""
46 + session_id = get_session_id()
47 + if not session_id:
48 + return "error: Failed to initialize MCP session"
49 +
50 + url = "https://mcp.deepwiki.com/mcp"
51 + request_id = str(int(time.time() * 1000))
52 +
53 + data = {
54 + "jsonrpc": "2.0",
55 + "id": request_id,
56 + "method": "tools/call",
57 + "params": {
58 + "name": tool_name,
59 + "arguments": arguments
60 + }
61 + }
62 +
63 + try:
64 + req = urllib.request.Request(
65 + url,
66 + json.dumps(data).encode(),
67 + {
68 + "Content-Type": "application/json",
69 + "Accept": "application/json, text/event-stream",
70 + "mcp-session-id": session_id
71 + }
72 + )
73 + resp = urllib.request.urlopen(req, timeout=30)
74 +
75 + # Handle SSE response
76 + response_text = resp.read().decode()
77 +
78 + # Parse SSE format: extract JSON from "data: " lines
79 + for line in response_text.split('\n'):
80 + if line.startswith('data: '):
81 + data = line[6:].strip() # Skip "data: " prefix
82 +
83 + # Skip ping events
84 + if data == "ping":
85 + continue
86 +
87 + try:
88 + result = json.loads(data)
89 +
90 + if "error" in result:
91 + return f"error: {result['error']['message']}"
92 +
93 + # Extract text from MCP response
94 + content = result.get("result", {}).get("content", [])
95 + if content:
96 + return "\n".join(item["text"] for item in content if item.get("type") == "text")
97 + except json.JSONDecodeError:
98 + continue
99 +
100 + return "error: No data in response"
101 + except Exception as e:
102 + return f"error: {e}"
103 +
104 + @register_tool(
105 + "deepwiki_ask",
106 + "Ask questions about GitHub repo",
107 + {"repo": "string", "question": "string"}
108 + )
109 + def deepwiki_ask(args):
110 + """Ask a question about a GitHub repository"""
111 + return mcp_call("ask_question", {
112 + "repoName": args["repo"],
113 + "question": args["question"]
114 + })
115 +
116 + @register_tool(
117 + "deepwiki_structure",
118 + "Get repo documentation structure",
119 + {"repo": "string"}
120 + )
121 + def deepwiki_structure(args):
122 + """Get documentation structure/topics for a GitHub repository"""
123 + return mcp_call("read_wiki_structure", {
124 + "repoName": args["repo"]
125 + })
126 +
127 + @register_tool(
128 + "deepwiki_contents",
129 + "Get repo documentation contents",
130 + {"repo": "string"}
131 + )
132 + def deepwiki_contents(args):
133 + """Get full documentation contents for a GitHub repository"""
134 + return mcp_call("read_wiki_contents", {
135 + "repoName": args["repo"]
136 + })
Newer Older