feat(mcp): stdio MCP server with research tool
U3 of the Claude Desktop .mcpb bundle plan. - internal/engine/run.go invokes python3 with the cached last30days.py, forwards os.Environ() so MCPB user_config env-injection reaches the engine, sets PYTHONPATH so the lib/ imports resolve, and surfaces three distinct error shapes (missing interpreter with install URL, non-zero exit with stderr, timeout). RunOptions.PythonPath lets tests inject a stub without manipulating PATH. - internal/engine/run_test.go drives a shell-script stub interpreter through happy path, env forwarding, PYTHONPATH, non-zero exit with stderr surfacing, timeout, missing python3 (empty PATH), missing last30days.py, empty CacheDir, and timeout-env-override parsing. - internal/tools/research.go registers a single research tool whose schema mirrors /last30days <topic> (required topic, optional emit enum, optional save bool). Validation failures surface as MCP tool errors so Claude sees structured failures instead of transport faults; engine extract or run errors fold engine stderr into the message so users can diagnose without leaving Desktop. - internal/tools/research_test.go covers requireString, emitArgument, boolArgument, handler-level validation routing, and formatRunError. - cmd/last30days-pp-mcp/main.go wires NewMCPServer + tools.Register + ServeStdio. main.Version is ldflags-stamped at build time and namespaces the per-user cache. mcp-go pinned at v0.54.0. Smoke check: ./build/last30days-pp-mcp answers tools/list with the research tool plus full schema and read-only/open-world annotations. go test ./... passes across engine + tools (32 cases).
This commit is contained in:
@@ -1,11 +1,39 @@
|
||||
// Package main is the entry point for the last30days MCP server bundled
|
||||
// as a .mcpb for Claude Desktop. See mcp/README.md for build instructions.
|
||||
// as a .mcpb for Claude Desktop. The server registers a single research
|
||||
// tool (see internal/tools) and serves it over stdio. See mcp/README.md
|
||||
// for build and packaging instructions.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/mark3labs/mcp-go/server"
|
||||
|
||||
"github.com/mvanhorn/last30days-skill/mcp/internal/tools"
|
||||
)
|
||||
|
||||
// Version is stamped at build time via -ldflags "-X main.Version=<tag>".
|
||||
// Defaults to "dev" for local builds.
|
||||
// It namespaces the per-user cache directory in internal/engine so multiple
|
||||
// installed versions can coexist without clobbering each other.
|
||||
var Version = "dev"
|
||||
|
||||
const (
|
||||
serverName = "last30days"
|
||||
serverVersion = "1"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Wired in U3.
|
||||
s := server.NewMCPServer(
|
||||
serverName,
|
||||
serverVersion,
|
||||
server.WithToolCapabilities(false),
|
||||
)
|
||||
|
||||
tools.Register(s, tools.Config{Version: Version})
|
||||
|
||||
if err := server.ServeStdio(s); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "last30days-pp-mcp: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user