Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions cmd/mcp-http/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/teamwork/mcp/internal/config"
"github.com/teamwork/mcp/internal/request"
"github.com/teamwork/mcp/internal/toolsets"
"github.com/teamwork/mcp/internal/twdesk"
"github.com/teamwork/mcp/internal/twprojects"
"github.com/teamwork/twapi-go-sdk/session"
)
Expand Down Expand Up @@ -91,11 +92,17 @@ func main() {
}

func newMCPServer(resources config.Resources) (*server.MCPServer, error) {
group := twprojects.DefaultToolsetGroup(false, false, resources.TeamworkEngine())
if err := group.EnableToolsets(toolsets.MethodAll); err != nil {
projectsGroup := twprojects.DefaultToolsetGroup(false, false, resources.TeamworkEngine())
if err := projectsGroup.EnableToolsets(toolsets.MethodAll); err != nil {
return nil, fmt.Errorf("failed to enable toolsets: %w", err)
}
return config.NewMCPServer(resources, group), nil

deskGroup := twdesk.DefaultToolsetGroup(resources.DeskClient())
if err := deskGroup.EnableToolsets(toolsets.MethodAll); err != nil {
return nil, fmt.Errorf("failed to enable desk toolsets: %w", err)
}

return config.NewMCPServer(resources, projectsGroup, deskGroup), nil
}

func newRouter(resources config.Resources) *http.ServeMux {
Expand Down
15 changes: 11 additions & 4 deletions cmd/mcp-stdio/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/teamwork/mcp/internal/auth"
"github.com/teamwork/mcp/internal/config"
"github.com/teamwork/mcp/internal/toolsets"
"github.com/teamwork/mcp/internal/twdesk"
"github.com/teamwork/mcp/internal/twprojects"
"github.com/teamwork/twapi-go-sdk/session"
)
Expand Down Expand Up @@ -67,11 +68,17 @@ func main() {
}

func newMCPServer(resources config.Resources) (*server.MCPServer, error) {
group := twprojects.DefaultToolsetGroup(readOnly, false, resources.TeamworkEngine())
if err := group.EnableToolsets(methods...); err != nil {
return nil, fmt.Errorf("failed to enable toolsets: %w", err)
projectsGroup := twprojects.DefaultToolsetGroup(readOnly, false, resources.TeamworkEngine())
if err := projectsGroup.EnableToolsets(methods...); err != nil {
return nil, fmt.Errorf("failed to enable projects toolsets: %w", err)
}
return config.NewMCPServer(resources, group), nil

deskGroup := twdesk.DefaultToolsetGroup(resources.DeskClient())
if err := deskGroup.EnableToolsets(methods...); err != nil {
return nil, fmt.Errorf("failed to enable desk toolsets: %w", err)
}

return config.NewMCPServer(resources, projectsGroup, deskGroup), nil
}

func mcpError(logger *slog.Logger, err error, code int) {
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/getsentry/sentry-go/slog v0.35.3
github.com/mark3labs/mcp-go v0.39.1
github.com/teamwork/twapi-go-sdk v1.4.0
github.com/teamwork/desksdkgo v0.0.0-20250814193340-a4429f1f7c89
)

require (
Expand Down Expand Up @@ -59,6 +60,7 @@ require (
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect
github.com/shirou/gopsutil/v4 v4.25.3 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/tinylib/msgp v1.2.5 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/wo
github.com/shirou/gopsutil/v4 v4.25.3 h1:SeA68lsu8gLggyMbmCn8cmp97V1TI9ld9sVzAUcKcKE=
github.com/shirou/gopsutil/v4 v4.25.3/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
Expand All @@ -175,6 +177,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/teamwork/twapi-go-sdk v1.4.0 h1:lajL5uJ7IacmuSP+2pYwxjzYpR1IMBM0Afd3iccAmzc=
github.com/teamwork/twapi-go-sdk v1.4.0/go.mod h1:PTxcuGSCYS5UXWbSZEbXalWnVttScOr+ia5rM3uulRM=
github.com/teamwork/desksdkgo v0.0.0-20250814193340-a4429f1f7c89 h1:umaBFmccZtErgXsappc3zV15hk7mtFkKvxFb+nTgyng=
github.com/teamwork/desksdkgo v0.0.0-20250814193340-a4429f1f7c89/go.mod h1:C+I+CxzFx2jitb7QWlR/w2YjroGQ7C/5LW4hQkba2ko=
github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
Expand Down Expand Up @@ -287,6 +291,7 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
Expand Down
26 changes: 23 additions & 3 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/mark3labs/mcp-go/client/transport"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
desksdk "github.com/teamwork/desksdkgo/client"
"github.com/teamwork/mcp/internal/request"
"github.com/teamwork/mcp/internal/toolsets"
twapi "github.com/teamwork/twapi-go-sdk"
Expand Down Expand Up @@ -116,6 +117,11 @@ func Load(logOutput io.Writer) (Resources, func()) {
twapi.WithLogger(resources.logger),
)

resources.deskClient = desksdk.NewClient(
resources.Info.APIURL,
desksdk.WithAPIKey(resources.Info.BearerToken),
)

if resources.Info.DatadogAPM.Enabled {
if err := startDatadog(resources); err != nil {
resources.logger.Error("failed to start datadog tracer",
Expand All @@ -136,13 +142,27 @@ func Load(logOutput io.Writer) (Resources, func()) {

// NewMCPServer creates a new MCP server with the given resources and toolset
// group.
func NewMCPServer(resources Resources, group *toolsets.ToolsetGroup) *server.MCPServer {
func NewMCPServer(resources Resources, groups ...*toolsets.ToolsetGroup) *server.MCPServer {
// Determine if any group has tools
hasTools := false
for _, group := range groups {
if group.HasTools() {
hasTools = true
break
}
}

mcpServer := server.NewMCPServer(mcpName, strings.TrimPrefix(resources.Info.Version, "v"),
server.WithRecovery(),
server.WithToolCapabilities(group.HasTools()),
server.WithToolCapabilities(hasTools),
server.WithLogging(),
)
group.RegisterAll(mcpServer)

// Register all toolset groups
for _, group := range groups {
group.RegisterAll(mcpServer)
}

return mcpServer
}

Expand Down
7 changes: 7 additions & 0 deletions internal/config/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"strings"

desksdk "github.com/teamwork/desksdkgo/client"
twapi "github.com/teamwork/twapi-go-sdk"
)

Expand All @@ -18,6 +19,7 @@ var Version = "dev"
type Resources struct {
teamworkHTTPClient *http.Client
teamworkEngine *twapi.Engine
deskClient *desksdk.Client
logger *slog.Logger

// Info stores environment variables mappings.
Expand Down Expand Up @@ -116,6 +118,11 @@ func (r *Resources) TeamworkEngine() *twapi.Engine {
return r.teamworkEngine
}

// DeskClient returns the Teamwork Desk Client for use.
func (r *Resources) DeskClient() *desksdk.Client {
return r.deskClient
}

func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
Expand Down
Loading