使用说明
Nmap MCP服务器(Smithery SDK)
该项目使用Smithery SDK实现了一个符合MCP(模型上下文协议)的服务器。它封装了Nmap网络扫描器,将其功能作为MCP框架内的可调用工具公开。
特性
- MCP标准端点(
/mcp):使用JSON-RPC 2.0请求与服务器交互。 nmapScan工具:使用可配置标志在指定目标上启动Nmap扫描。返回详细的扫描结果,包括解析的XML输出。getInfo工具:提供有关Nmap服务及其功能的基本信息。- 对目标和Nmap标志进行输入验证,以提高安全性。
先决条件
安装
- 克隆存储库(或下载源代码)。
- 导航到项目目录:
cd your-project-directory - 安装依赖项:
npm install
运行服务器
要启动服务器,请运行:
npm start
默认情况下,服务器将侦听 http://localhost:5001。您可以设置 PORT 环境变量以使用其他端口。
与服务器交互(MCP)
与服务器的所有交互都是通过 /mcp 端点使用JSON-RPC 2.0。您将发送 POST 请求a Content-Type: application/json 头球
呼叫 nmapScan 工具
要启动Nmap扫描:
请求正文(JSON):
{
"jsonrpc": "2.0",
"id": 1, // Or any unique request ID
"method": "tools/call",
"params": {
"name": "nmapScan",
"arguments": {
"target": "scanme.nmap.org",
"flags": "-A -T4" // Optional, defaults to "-T4 -p 1-1000"
}
}
}
使用cURL的示例:
curl -X POST http://localhost:5001/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "nmapScan",
"arguments": {
"target": "scanme.nmap.org",
"flags": "-A"
}
}
}'
预期响应结构(成功):
服务器将以Nmap扫描的结果进行响应。这 content 数组将包含一个带有摘要的文本对象和完整的JSON解析Nmap XML输出。
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Nmap Scan Results for scanme.nmap.org\n\nScan started: ...\n... (summary of open ports) ...\nScan completed: ...\n\nFull XML Output:\n{\n \"nmaprun\": { ... }\n}"
}
]
}
}
如果扫描失败或输入无效 text 字段将包含错误消息。
呼叫 getInfo 工具
要获取有关该服务的信息,请执行以下操作:
请求正文(JSON):
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "getInfo",
"arguments": {}
}
}
使用cURL的示例:
curl -X POST http://localhost:5001/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "getInfo",
"arguments": {}
}
}'
预期响应结构(成功):
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Nmap Service Information:\n- Service: Network scanning using Nmap\n- Version: 1.0.0\n- Available Tools: nmapScan, getInfo\n- Session ID: N/A\n- Supported Targets: Domain names, IP addresses, CIDR notation\n- Security: Input validation and command sanitization enabled"
}
]
}
}
部署在Smithery
要在Smithery上部署此服务器,您通常需要:
- 确保Nmap在Smithery执行环境中可用。 如果Nmap没有预先安装,这可能涉及自定义Docker映像或构建包。
- 定义启动命令: Smithery需要知道如何启动应用程序(例如。,
npm start). - 端口配置: Smithery将公开应用程序,通常处理端口映射。确保应用程序侦听Smithery期望的端口(通常通过
PORT此服务器通过支持的环境变量process.env.PORT || 5001图案)。 - 打包应用程序: 这通常意味着提供源代码和
package.json(以及package-lock.json).然后,Smithery将构建应用程序,安装依赖项。
有关具体的部署说明以及如何配置符合模型上下文协议的服务,请参阅Smithery文档。
MCP客户端示例
下面是一个如何创建客户端以与此Nmap MCP服务器交互的示例。你需要有 @modelcontextprotocol/sdk 和 @smithery/sdk 安装在客户端项目中的包。
将以下代码另存为 nmap_mcp_client_example.js:
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { createSmitheryUrl } from "@smithery/sdk/shared/config.js";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
// Ensure you have your Smithery API key for the server in an environment variable
const SMITHERY_API_KEY = process.env.SMITHERY_NMAP_API_KEY || "your-smithery-api-key-here"; // Replace with your actual key or ensure env var is set
const NMAP_SERVER_URL = "https://server.smithery.ai/@sideffect263/nmap-mcp-server"; // Replace with your server URL if different
let clientInstance;
let nmapScanTool;
let getInfoTool;
async function initializeNmapClient() {
if (clientInstance) {
console.log("Nmap MCP Client already initialized.");
return clientInstance;
}
console.log("Initializing Nmap MCP Client...");
try {
const config = {}; // Add any specific config for Smithery if needed
const serverUrl = createSmitheryUrl(
NMAP_SERVER_URL,
{ config, apiKey: SMITHERY_API_KEY }
);
const transport = new StreamableHTTPClientTransport(serverUrl);
clientInstance = new Client({
name: "ExampleNmapClient",
version: "1.0.0",
});
console.log("Connecting to Nmap MCP server...");
await clientInstance.connect(transport);
console.log("Successfully connected to Nmap MCP server.");
const toolsResponse = await clientInstance.listTools();
if (toolsResponse && toolsResponse.tools && Array.isArray(toolsResponse.tools)) {
console.log(`Available tools: ${toolsResponse.tools.map((t) => t.name).join(", ")}`);
nmapScanTool = toolsResponse.tools.find(tool => tool.name === 'nmapScan');
getInfoTool = toolsResponse.tools.find(tool => tool.name === 'getInfo');
} else {
throw new Error("Could not list tools from the server.");
}
if (!nmapScanTool) {
throw new Error("Nmap tool ('nmapScan') not found on the MCP server.");
}
console.log(`Found Nmap tool: ${nmapScanTool.name}`);
if (getInfoTool) {
console.log(`Found GetInfo tool: ${getInfoTool.name}`);
} else {
console.warn("GetInfo tool ('getInfo') not found. This might be optional.");
}
return clientInstance;
} catch (error) {
console.error("Failed to initialize Nmap MCP client:", error);
clientInstance = null; // Reset on failure
nmapScanTool = null;
getInfoTool = null;
throw error;
}
}
/**
* Invokes the 'nmapScan' tool on the MCP server.
* @param {Object} params - Parameters for the Nmap tool.
* @param {string} params.target - The target IP, hostname, or CIDR.
* @param {string} params.flags - Nmap flags as a single string (e.g., "-A -T4").
* @returns {Promise<Object>} - The result from the 'nmapScan' tool.
*/
async function invokeNmapScan(params) {
if (!clientInstance || !nmapScanTool) {
console.log("Client not ready. Initializing...");
await initializeNmapClient();
if (!clientInstance || !nmapScanTool) {
throw new Error("Nmap MCP client is not initialized or nmapScan tool not found.");
}
}
const toolInput = {
target: params.target,
flags: params.flags
};
console.log(\`Invoking Nmap tool "\${nmapScanTool.name}" with params:\`, toolInput);
try {
const result = await clientInstance.callTool({
name: nmapScanTool.name,
arguments: toolInput
});
console.log("'nmapScan' tool invocation successful. Result:", JSON.stringify(result, null, 2));
return result;
} catch (error) {
console.error(\`Error invoking 'nmapScan' tool for target \${params.target}:\`, error);
throw error;
}
}
/**
* Invokes the 'getInfo' tool on the MCP server.
* @returns {Promise<Object>} - The result from the 'getInfo' tool.
*/
async function invokeGetInfo() {
if (!clientInstance || !getInfoTool) {
console.log("Client or getInfo tool not ready. Initializing...");
await initializeNmapClient();
if (!clientInstance || !getInfoTool) {
throw new Error("Nmap MCP client is not initialized or getInfo tool not found.");
}
}
console.log(\`Invoking GetInfo tool "\${getInfoTool.name}"\`);
try {
const result = await clientInstance.callTool({
name: getInfoTool.name,
arguments: {} // getInfo usually takes no arguments
});
console.log("'getInfo' tool invocation successful. Result:", JSON.stringify(result, null, 2));
return result;
} catch (error) {
console.error("Error invoking 'getInfo' tool:", error);
throw error;
}
}
// --- Example Usage ---
async function main() {
try {
await initializeNmapClient();
// Example: Get server info
console.log("\\n--- Calling getInfo ---");
const info = await invokeGetInfo();
if (info && info.content && info.content[0] && info.content[0].text) {
console.log("Server Info:", info.content[0].text);
}
// Example: Perform an Nmap scan
console.log("\\n--- Calling nmapScan ---");
const scanParams = {
target: "scanme.nmap.org", // A safe target for testing
flags: "-T4 -F" // Example flags: Fast scan, default timing
};
const scanResult = await invokeNmapScan(scanParams);
if (scanResult && scanResult.content && scanResult.content[0] && scanResult.content[0].text) {
console.log(\`Scan results for \${scanParams.target}:\`, scanResult.content[0].text);
}
} catch (error) {
console.error("\\n--- Example Script Failed ---");
console.error("An error occurred:", error.message);
} finally {
if (clientInstance) {
console.log("\\nDisconnecting client...");
await clientInstance.disconnect();
console.log("Client disconnected.");
}
}
}
// Run the example
main();
export { initializeNmapClient, invokeNmapScan, invokeGetInfo };
要运行此示例客户端:
- 请确保您已安装Node.js。
- 为您的客户端项目创建一个新目录。
- 在此目录中,运行
npm init -y创建apackage.json文件。 - 安装必要的SDK:
npm install @modelcontextprotocol/sdk @smithery/sdk - 将上述代码另存为
nmap_mcp_client_example.js在这个目录中。 - 修改
SMITHERY_NMAP_API_KEY和NMAP_SERVER_URL脚本中的常量,以及您实际的Smithery API密钥和部署的Nmap MCP服务器的URL。 - 如果你
package.json还没有"type": "module",添加它或将导入/导出语法更改为CommonJS(require/module.exports).对于ES模块(如上所述),添加:// package.json { // ... other properties "type": "module" } - 运行客户端:
node nmap_mcp_client_example.js
此客户端将连接到您的Nmap MCP服务器,列出可用工具,调用 getInfo 获取服务器信息,然后调用 nmapScan 执行扫描 scanme.nmap.org.