Files
TaskPool/cmd/mcp/server.go
T
admin f3a44a901e
Build and Deploy / build-and-push (push) Successful in 54s
refactor(mcp): consolidate MCP implementation into internal package
- Move MCP tools registration to internal/mcp
- cmd/mcp now only contains CLI entry logic
- Support env vars TASKPOOL_URL/TASKPOOL_TOKEN for stdio mode
- Remove duplicate client.go from cmd/mcp
2026-07-27 02:43:01 +08:00

154 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package mcp
import (
"fmt"
"net/http"
"os"
"strings"
"github.com/engigu/taskpool/internal/mcp"
imc "github.com/engigu/taskpool/internal/mcp"
)
// Run 启动 TaskPool MCP Server
// 模式:
// - stdio(默认):通过 stdin/stdout 通信,适用于 Claude Desktop / Cursor 等本地 Agent
// - http:通过 HTTP/SSE 通信,适用于 Hermes / OpenClaw 等远程 Agent
//
// 环境变量:
// TASKPOOL_URL 面板地址,如 http://127.0.0.1:8052 或 https://panel.example.com
// TASKPOOL_TOKEN 设置页 OpenAPI Token
// MCP_HTTP_ADDR HTTP 模式监听地址(默认 :8053)
func Run(args []string) {
for _, a := range args {
if a == "-h" || a == "--help" {
printHelp()
return
}
}
mode := "stdio"
httpAddr := ":8053"
for i, a := range args {
if a == "--http" {
mode = "http"
if i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
httpAddr = args[i+1]
}
}
}
if envAddr := os.Getenv("MCP_HTTP_ADDR"); envAddr != "" {
httpAddr = envAddr
}
if mode == "http" {
runHTTP(httpAddr)
} else {
runStdio()
}
}
func runStdio() {
// 使用内部 OpenAPI 客户端(自动获取服务器地址和 Token)
client := imc.GetOpenAPIClient()
fmt.Fprintf(os.Stderr, "[taskpool-mcp] mode=stdio url=%s token=%s\n", client.BaseURL, maskToken(client.Token))
s := mcp.GetServer()
// 设置外部客户端(用于 stdio 模式连接远程服务器)
if client.Token != "" {
mcp.SetExternalClient(client)
}
if err := mcp.ServeStdio(s); err != nil {
fmt.Fprintf(os.Stderr, "[taskpool-mcp] server error: %v\n", err)
os.Exit(1)
}
}
func runHTTP(addr string) {
client := imc.GetOpenAPIClient()
fmt.Fprintf(os.Stderr, "[taskpool-mcp] mode=http addr=%s url=%s token=%s\n", addr, client.BaseURL, maskToken(client.Token))
// 设置外部客户端
if client.Token != "" {
mcp.SetExternalClient(client)
}
handler := mcp.GetHTTPHandler()
// 添加健康检查端点
mux := http.NewServeMux()
mux.Handle("/mcp/", http.StripPrefix("/mcp", handler))
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"ok"}`))
})
fmt.Fprintf(os.Stderr, "[taskpool-mcp] MCP endpoint: http://%s/mcp\n", strings.TrimPrefix(addr, ":"))
if err := http.ListenAndServe(addr, mux); err != nil {
fmt.Fprintf(os.Stderr, "[taskpool-mcp] http server error: %v\n", err)
os.Exit(1)
}
}
func maskToken(t string) string {
t = strings.TrimSpace(t)
if t == "" {
return "(empty)"
}
if len(t) <= 8 {
return "****"
}
return t[:4] + "****" + t[len(t)-4:]
}
func printHelp() {
fmt.Fprintf(os.Stderr, `
TaskPool MCP Server(内置模式)
MCP Server 已集成到后端服务中,推荐直接使用内置端点:
http://your-server:8052/mcp
此命令用于:
- stdio 模式:本地 AgentClaude Desktop / Cursor
- 独立 HTTP 服务:需要单独端口时
用法:
taskpool mcp # stdio 模式
taskpool mcp --http # HTTP 模式,监听 :8053
taskpool mcp --http :9000 # HTTP 模式,指定端口
环境变量(stdio 模式可选):
TASKPOOL_URL 面板地址(默认本机)
TASKPOOL_TOKEN OpenAPI Token(默认从系统设置读取)
Agent 配置示例:
HTTP 模式(推荐):
{
"mcpServers": {
"taskpool": {
"url": "http://your-server:8052/mcp",
"headers": {
"Authorization": "Bearer 你的Token"
}
}
}
}
stdio 模式:
{
"mcpServers": {
"taskpool": {
"command": "taskpool",
"args": ["mcp"]
}
}
}
前置条件:
系统设置 → 启用 OpenAPI → 生成 Token
`)
}