@burtthecoder/mcp-shodan 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/build/index.js +232 -0
  4. package/package.json +50 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Burt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # Shodan MCP Server
2
+
3
+ A Model Context Protocol (MCP) server for querying the [Shodan API](https://shodan.io). This server provides tools for IP lookups, device searches, DNS lookups, vulnerability queries, and more. It is designed to integrate seamlessly with MCP-compatible applications like [Claude Desktop](https://claude.ai).
4
+
5
+ ## Features
6
+
7
+ - **IP Lookup**: Retrieve detailed information about an IP address
8
+ - **Search**: Search for devices on Shodan matching specific queries
9
+ - **Ports**: Get a list of ports that Shodan is scanning
10
+ - **Vulnerabilities**: Fetch information about known vulnerabilities (CVE)
11
+ - **DNS Lookup**: Resolve hostnames to IP addresses
12
+
13
+ ## Tools
14
+
15
+ ### 1. IP Lookup Tool
16
+ - Name: `ip_lookup`
17
+ - Description: Retrieve detailed information about an IP address
18
+ - Parameters:
19
+ * `ip` (required): IP address to lookup
20
+
21
+ ### 2. Search Tool
22
+ - Name: `search`
23
+ - Description: Search for devices on Shodan
24
+ - Parameters:
25
+ * `query` (required): Shodan search query
26
+ * `max_results` (optional, default: 10): Number of results to return
27
+
28
+ ### 3. Vulnerabilities Tool
29
+ - Name: `vulnerabilities`
30
+ - Description: Fetch information about known vulnerabilities
31
+ - Parameters:
32
+ * `cve` (required): CVE identifier
33
+
34
+ ### 4. DNS Lookup Tool
35
+ - Name: `dns_lookup`
36
+ - Description: Resolve hostnames to IP addresses
37
+ - Parameters:
38
+ * `hostnames` (required): Array of hostnames to resolve
39
+
40
+ ## Requirements
41
+
42
+ - Node.js (v18 or later)
43
+ - A valid [Shodan API Key](https://account.shodan.io/)
44
+
45
+ ## Setup Guide
46
+
47
+ ### 1. Installation
48
+
49
+ ```bash
50
+ git clone <repository_url>
51
+ cd mcp-shodan
52
+ npm install
53
+ ```
54
+
55
+ ### 2. Configuration
56
+
57
+ Create a `.env` file in the root directory:
58
+ ```
59
+ SHODAN_API_KEY=your_shodan_api_key
60
+ ```
61
+
62
+ ### 3. Build and Run
63
+
64
+ ```bash
65
+ npm run build
66
+ npm start
67
+ ```
68
+
69
+ ### 4. Configure Claude Desktop
70
+
71
+ There are two ways to configure the Shodan MCP server in Claude Desktop:
72
+
73
+ #### Option 1: Direct Node Execution (Local Development)
74
+ ```json
75
+ {
76
+ "mcpServers": {
77
+ "shodan-mcp": {
78
+ "command": "node",
79
+ "args": ["path/to/mcp-shodan/build/index.js"],
80
+ "env": {
81
+ "SHODAN_API_KEY": "your_shodan_api_key",
82
+ "DEBUG": "*"
83
+ }
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ #### Option 2: NPX Installation (Recommended for Users)
90
+ ```json
91
+ {
92
+ "mcpServers": {
93
+ "shodan-mcp": {
94
+ "command": "npx",
95
+ "args": ["@burtthecoder/mcp-shodan"],
96
+ "env": {
97
+ "SHODAN_API_KEY": "your_shodan_api_key",
98
+ "DEBUG": "*"
99
+ }
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ The npx method automatically downloads and runs the latest version of the package from npm.
106
+
107
+ Configuration file location:
108
+
109
+ Windows: %APPDATA%\Claude\claude_desktop_config.json
110
+ macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
111
+
112
+ ## Usage
113
+
114
+ 1. Start the MCP server:
115
+ ```bash
116
+ npm start
117
+ ```
118
+
119
+ 2. Launch Claude Desktop and ensure the Shodan MCP server is detected
120
+ 3. Use any of the available tools through the Claude interface
121
+
122
+ ## Development
123
+
124
+ To run in development mode with hot reloading:
125
+ ```bash
126
+ npm run dev
127
+ ```
128
+
129
+ ## Error Handling
130
+
131
+ The server includes comprehensive error handling for:
132
+ - Invalid API keys
133
+ - Rate limiting
134
+ - Network errors
135
+ - Invalid input parameters
136
+
137
+ ## Version History
138
+
139
+ - v1.0.0: Initial release with core functionality
140
+
141
+ ## Contributing
142
+
143
+ 1. Fork the repository
144
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
145
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
146
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
147
+ 5. Open a Pull Request
148
+
149
+ ## License
150
+
151
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
package/build/index.js ADDED
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, InitializeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import axios from "axios";
6
+ import dotenv from "dotenv";
7
+ import { z } from "zod";
8
+ import { zodToJsonSchema } from "zod-to-json-schema";
9
+ import fs from "fs";
10
+ dotenv.config();
11
+ const logFilePath = "E:/dev/shodan-mcp/server.log";
12
+ const SHODAN_API_KEY = process.env.SHODAN_API_KEY;
13
+ if (!SHODAN_API_KEY) {
14
+ throw new Error("SHODAN_API_KEY environment variable is required.");
15
+ }
16
+ const API_BASE_URL = "https://api.shodan.io";
17
+ // Logging Helper Function
18
+ function logToFile(message) {
19
+ const timestamp = new Date().toISOString();
20
+ const formattedMessage = `[${timestamp}] ${message}\n`;
21
+ fs.appendFileSync(logFilePath, formattedMessage, "utf8");
22
+ console.error(formattedMessage.trim()); // Use stderr for logging to avoid interfering with stdout
23
+ }
24
+ // Tool Schemas
25
+ const IpLookupArgsSchema = z.object({
26
+ ip: z.string().describe("The IP address to query."),
27
+ });
28
+ const SearchArgsSchema = z.object({
29
+ query: z.string().describe("Search query for Shodan."),
30
+ max_results: z
31
+ .number()
32
+ .optional()
33
+ .default(10)
34
+ .describe("Maximum results to return."),
35
+ });
36
+ const VulnerabilitiesArgsSchema = z.object({
37
+ cve: z.string().describe("The CVE identifier to query."),
38
+ });
39
+ const DnsLookupArgsSchema = z.object({
40
+ hostnames: z.array(z.string()).describe("List of hostnames to resolve."),
41
+ });
42
+ // Helper Function to Query Shodan API
43
+ async function queryShodan(endpoint, params) {
44
+ try {
45
+ const response = await axios.get(`${API_BASE_URL}${endpoint}`, {
46
+ params: { ...params, key: SHODAN_API_KEY },
47
+ timeout: 10000,
48
+ });
49
+ return response.data;
50
+ }
51
+ catch (error) {
52
+ const errorMessage = error.response?.data?.error || error.message;
53
+ logToFile(`Shodan API error: ${errorMessage}`);
54
+ throw new Error(`Shodan API error: ${errorMessage}`);
55
+ }
56
+ }
57
+ // Server Setup
58
+ const server = new Server({
59
+ name: "shodan-mcp",
60
+ version: "1.0.0",
61
+ }, {
62
+ capabilities: {
63
+ tools: {
64
+ listChanged: true,
65
+ },
66
+ },
67
+ });
68
+ // Handle Initialization
69
+ server.setRequestHandler(InitializeRequestSchema, async (request) => {
70
+ logToFile("Received initialize request.");
71
+ return {
72
+ protocolVersion: "2024-11-05",
73
+ capabilities: {
74
+ tools: {
75
+ listChanged: true,
76
+ },
77
+ },
78
+ serverInfo: {
79
+ name: "shodan-mcp",
80
+ version: "1.0.0",
81
+ },
82
+ instructions: "This server provides tools for querying Shodan, including IP lookups, searches, and vulnerabilities.",
83
+ };
84
+ });
85
+ // Register Tools
86
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
87
+ const tools = [
88
+ {
89
+ name: "ip_lookup",
90
+ description: "Retrieve information about an IP address.",
91
+ inputSchema: zodToJsonSchema(IpLookupArgsSchema),
92
+ },
93
+ {
94
+ name: "search",
95
+ description: "Search for devices on Shodan.",
96
+ inputSchema: zodToJsonSchema(SearchArgsSchema),
97
+ },
98
+ {
99
+ name: "vulnerabilities",
100
+ description: "Retrieve vulnerability information for a CVE.",
101
+ inputSchema: zodToJsonSchema(VulnerabilitiesArgsSchema),
102
+ },
103
+ {
104
+ name: "dns_lookup",
105
+ description: "Perform DNS lookups using Shodan.",
106
+ inputSchema: zodToJsonSchema(DnsLookupArgsSchema),
107
+ },
108
+ ];
109
+ logToFile("Registered tools.");
110
+ return { tools };
111
+ });
112
+ // Handle Tool Calls
113
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
114
+ logToFile(`Tool called: ${request.params.name}`);
115
+ try {
116
+ const { name, arguments: args } = request.params;
117
+ switch (name) {
118
+ case "ip_lookup": {
119
+ const parsedIpArgs = IpLookupArgsSchema.safeParse(args);
120
+ if (!parsedIpArgs.success) {
121
+ throw new Error("Invalid ip_lookup arguments");
122
+ }
123
+ const result = await queryShodan(`/shodan/host/${parsedIpArgs.data.ip}`, {});
124
+ return {
125
+ content: [
126
+ {
127
+ type: "text",
128
+ text: JSON.stringify(result, null, 2),
129
+ },
130
+ ],
131
+ };
132
+ }
133
+ case "search": {
134
+ const parsedSearchArgs = SearchArgsSchema.safeParse(args);
135
+ if (!parsedSearchArgs.success) {
136
+ throw new Error("Invalid search arguments");
137
+ }
138
+ const result = await queryShodan("/shodan/host/search", {
139
+ query: parsedSearchArgs.data.query,
140
+ limit: parsedSearchArgs.data.max_results,
141
+ });
142
+ return {
143
+ content: [
144
+ {
145
+ type: "text",
146
+ text: JSON.stringify(result, null, 2),
147
+ },
148
+ ],
149
+ };
150
+ }
151
+ case "vulnerabilities": {
152
+ const parsedVulnArgs = VulnerabilitiesArgsSchema.safeParse(args);
153
+ if (!parsedVulnArgs.success) {
154
+ throw new Error("Invalid vulnerabilities arguments");
155
+ }
156
+ const result = await queryShodan(`/shodan/cve/${parsedVulnArgs.data.cve}`, {});
157
+ return {
158
+ content: [
159
+ {
160
+ type: "text",
161
+ text: JSON.stringify(result, null, 2),
162
+ },
163
+ ],
164
+ };
165
+ }
166
+ case "dns_lookup": {
167
+ const parsedDnsArgs = DnsLookupArgsSchema.safeParse(args);
168
+ if (!parsedDnsArgs.success) {
169
+ throw new Error("Invalid dns_lookup arguments");
170
+ }
171
+ // Ensure proper formatting of hostnames for the API request
172
+ const hostnamesString = parsedDnsArgs.data.hostnames.join(",");
173
+ // Log the request parameters for debugging
174
+ logToFile(`DNS lookup request parameters: ${JSON.stringify({ hostnames: hostnamesString })}`);
175
+ const result = await queryShodan("/dns/resolve", {
176
+ hostnames: hostnamesString
177
+ });
178
+ // Log the raw response for debugging
179
+ logToFile(`DNS lookup raw response: ${JSON.stringify(result)}`);
180
+ return {
181
+ content: [
182
+ {
183
+ type: "text",
184
+ text: JSON.stringify(result, null, 2)
185
+ },
186
+ ],
187
+ };
188
+ }
189
+ default:
190
+ throw new Error(`Unknown tool: ${name}`);
191
+ }
192
+ }
193
+ catch (error) {
194
+ const errorMessage = error instanceof Error ? error.message : String(error);
195
+ logToFile(`Error handling tool call: ${errorMessage}`);
196
+ return {
197
+ content: [
198
+ {
199
+ type: "text",
200
+ text: `Error: ${errorMessage}`,
201
+ },
202
+ ],
203
+ isError: true,
204
+ };
205
+ }
206
+ });
207
+ // Start the Server
208
+ async function runServer() {
209
+ logToFile("Starting Shodan MCP Server...");
210
+ try {
211
+ const transport = new StdioServerTransport();
212
+ await server.connect(transport);
213
+ logToFile("Shodan MCP Server is running.");
214
+ }
215
+ catch (error) {
216
+ logToFile(`Error connecting server: ${error.message}`);
217
+ process.exit(1);
218
+ }
219
+ }
220
+ // Handle process events
221
+ process.on('uncaughtException', (error) => {
222
+ logToFile(`Uncaught exception: ${error.message}`);
223
+ process.exit(1);
224
+ });
225
+ process.on('unhandledRejection', (reason) => {
226
+ logToFile(`Unhandled rejection: ${reason}`);
227
+ process.exit(1);
228
+ });
229
+ runServer().catch((error) => {
230
+ logToFile(`Fatal error: ${error.message}`);
231
+ process.exit(1);
232
+ });
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "type": "module",
3
+ "name": "@burtthecoder/mcp-shodan",
4
+ "version": "1.0.4",
5
+ "description": "A Model Context Protocol server for Shodan API queries.",
6
+ "main": "./build/index.js",
7
+ "bin": {
8
+ "mcp-shodan": "build/index.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node build/index.js",
12
+ "dev": "ts-node src/index.ts",
13
+ "build": "tsc"
14
+ },
15
+ "dependencies": {
16
+ "@modelcontextprotocol/sdk": "^0.6.0",
17
+ "axios": "^1.7.8",
18
+ "dotenv": "^16.4.5",
19
+ "zod": "^3.22.2",
20
+ "zod-to-json-schema": "^3.23.5"
21
+ },
22
+ "devDependencies": {
23
+ "typescript": "^5.3.3",
24
+ "@types/node": "^20.11.24"
25
+ },
26
+ "files": [
27
+ "build"
28
+ ],
29
+ "author": "BurtTheCoder",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/BurtTheCoder/mcp-shodan.git"
34
+ },
35
+ "keywords": [
36
+ "mcp",
37
+ "shodan",
38
+ "mcp-shodan",
39
+ "cybersecurity",
40
+ "agents",
41
+ "network-reconnaissance",
42
+ "security-tools",
43
+ "shodan-api",
44
+ "shodan-integraton"
45
+ ],
46
+ "bugs": {
47
+ "url": "https://github.com/BurtTheCoder/mcp-shodan/issues"
48
+ },
49
+ "homepage": "https://github.com/BurtTheCoder/mcp-shodan#readme"
50
+ }