feat: 实现MCP工具和RPC服务,添加启动和扫描功能,更新依赖

This commit is contained in:
tongque 2025-04-29 15:43:42 +08:00
parent 0f0da9fd0a
commit d1e4a864a4
7 changed files with 207 additions and 8 deletions

45
Remote/README.md Normal file
View File

@ -0,0 +1,45 @@
# 使用说明
本模块分为两部分:**RPC 调用** 和 **MCP 调用**
## 启动方式
### 1. RPC 调用
运行以下命令启动 RPC 服务:
```bash
go run remote.go -api 127.0.0.1:8080 -sercet xxxx
```
- `-api`:指定监听地址和端口。
- `-sercet`:指定访问密钥。
### 2. MCP 调用
直接运行:
```bash
go run remote.go
```
- 默认使用 `stdio` 协议。
- 如需指定使用 `sse` 协议,请添加 `-transport sse` 参数:
```bash
go run remote.go -transport sse
```
## 开发调试
在开发 MCP 时,可以借助 [Model Context Protocol Inspector](https://www.npmjs.com/package/@modelcontextprotocol/inspector) 进行调试。
使用以下命令启动调试器:
```bash
npx @modelcontextprotocol/inspector
```
启动后即可在终端中进行调试。

View File

@ -19,9 +19,9 @@ func main() {
flag.StringVar(&secret, "secret", "", "RPC调用使用的秘钥")
flag.StringVar(&transport, "transport", "stdio", "MCP传输协议stdio 或 sse")
Common.Flag(&Info)
//模式参数因为在initoutput中会使用所以需要在这里设置
Common.ApiAddr = "remote"
if apiURL != "" {
Common.ApiAddr = apiURL
server.StartApiServer(apiURL, secret)
} else {
server.StartMcpServer(transport)

View File

@ -1,9 +1,57 @@
package server
import "fmt"
import (
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
"github.com/shadow1ng/fscan/Common"
"github.com/shadow1ng/fscan/Remote/service"
)
func StartMcpServer(transport string) {
mcpServer := NewFscanMCPServer()
if transport == "sse" {
Common.LogSuccess("🚀 启动 MCP SSE 服务器,监听地址: http://localhost:8080")
sseServer := server.NewSSEServer(mcpServer, server.WithBaseURL("http://localhost:8080"))
if err := sseServer.Start(":8080"); err != nil {
Common.LogError(fmt.Sprintf("❌ 启动 SSE 服务器失败: %v", err))
panic(err)
}
} else {
Common.LogSuccess("🚀 启动 MCP Stdio 服务器(标准输入输出模式)")
if err := server.ServeStdio(mcpServer); err != nil {
Common.LogError(fmt.Sprintf("❌ 启动 Stdio 服务器失败: %v", err))
panic(err)
}
}
}
func NewFscanMCPServer() *server.MCPServer {
s := server.NewMCPServer(
"Fscan MCP",
"1.0.0",
)
toolHandler := service.NewFscanMCPTool()
// 添加工具处理器
s.AddTool(
mcp.NewTool("StartScan",
mcp.WithDescription("开始扫描"),
mcp.WithString("target",
mcp.Required(),
mcp.Description("扫描目标"),
),
),
toolHandler.StartScan,
)
s.AddTool(
mcp.NewTool("GetScanResults",
mcp.WithDescription("获取扫描结果"),
),
toolHandler.GetScanResults,
)
return s
func StartMcpServer(transport string) error {
fmt.Println("Starting MCP server...")
fmt.Println("Transport protocol:", transport)
return nil
}

94
Remote/service/mcp.go Normal file
View File

@ -0,0 +1,94 @@
package service
import (
"context"
"errors"
"fmt"
"sync"
"sync/atomic"
"time"
"github.com/mark3labs/mcp-go/mcp"
"github.com/shadow1ng/fscan/Common"
"github.com/shadow1ng/fscan/Core"
)
type FscanMCPTool struct {
scanMutex sync.Mutex
isScanning int32
scanStartTime time.Time
}
func NewFscanMCPTool() *FscanMCPTool {
return &FscanMCPTool{}
}
func (s *FscanMCPTool) StartScan(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
target, ok := request.Params.Arguments["target"].(string)
if !ok {
return nil, errors.New("name must be a string")
}
//构造扫描字符串
arg := fmt.Sprintf("-h %s", target)
if !atomic.CompareAndSwapInt32(&s.isScanning, 0, 1) {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: "已有扫描任务正在运行,请稍后重试",
},
},
}, nil
}
s.scanStartTime = time.Now() // 记录任务开始时间
go func() {
defer atomic.StoreInt32(&s.isScanning, 0)
s.scanMutex.Lock()
defer s.scanMutex.Unlock()
Common.LogDebug("异步执行扫描请求,目标: " + arg)
var info Common.HostInfo
if err := Common.FlagFromRemote(&info, arg); err != nil {
return
}
if err := Common.Parse(&info); err != nil {
return
}
if err := Common.CloseOutput(); err != nil {
Common.LogError(fmt.Sprintf("关闭输出系统失败: %v", err))
return
}
if err := Common.InitOutput(); err != nil {
Common.LogError(fmt.Sprintf("初始化输出系统失败: %v", err))
return
}
Core.Scan(info)
Common.LogDebug("扫描任务完成")
}()
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("扫描任务开始,扫描参数: %s", arg),
},
},
}, nil
}
func (s *FscanMCPTool) GetScanResults(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: Common.OutputFormat + Common.Outputfile,
},
},
}, nil
}

3
go.mod
View File

@ -17,6 +17,7 @@ require (
github.com/hirochachacha/go-smb2 v1.1.0
github.com/jlaffaye/ftp v0.2.0
github.com/lib/pq v1.10.9
github.com/mark3labs/mcp-go v0.23.1
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed
github.com/neo4j/neo4j-go-driver/v4 v4.4.7
github.com/rabbitmq/amqp091-go v1.10.0
@ -74,7 +75,9 @@ require (
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
golang.org/x/term v0.29.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
)

11
go.sum
View File

@ -67,6 +67,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
@ -229,13 +231,16 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mark3labs/mcp-go v0.23.1 h1:RzTzZ5kJ+HxwnutKA4rll8N/pKV6Wh5dhCmiJUu5S9I=
github.com/mark3labs/mcp-go v0.23.1/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@ -330,6 +335,8 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@ -358,6 +365,8 @@ github.com/tfriedel6/canvas v0.12.1/go.mod h1:WIe1YgsQiKA1awmU6tSs8e5DkceDHC5MHg
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/veandco/go-sdl2 v0.4.0/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=