Skip to content
Merged
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
21 changes: 19 additions & 2 deletions cmd/lfx-mcp-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func main() {
f.String("client_assertion_signing_key", "", "PEM-encoded RSA private key for client assertion (takes precedence over client_secret)")
f.String("token_endpoint", "", "OAuth2 token endpoint URL for token exchange")
f.String("lfx_api_url", "", "LFX API URL (used as token exchange audience)")
f.String("tools", "search_projects,get_project", "Comma-separated list of tools to enable")
f.String("tools", "search_projects,get_project,search_committees,get_committee,get_committee_member,search_committee_members", "Comma-separated list of tools to enable")
f.Bool("debug", false, "Enable debug logging")
f.Bool("debug_traffic", false, "Enable HTTP request/response debug logging for outbound LFX API calls")

Expand Down Expand Up @@ -169,7 +169,7 @@ func main() {
HTTPClient: &http.Client{Timeout: 30 * time.Second},
})
if err != nil {
logger.Warn("failed to create token exchange client - project tools will not be available", errKey, err)
logger.Warn("failed to create token exchange client - project and committee tools will not be available", errKey, err)
} else {
var debugLogger *slog.Logger
if cfg.DebugTraffic {
Expand All @@ -180,6 +180,11 @@ func main() {
TokenExchangeClient: tokenExchangeClient,
DebugLogger: debugLogger,
})
tools.SetCommitteeConfig(&tools.CommitteeConfig{
LFXAPIURL: cfg.LFXAPIURL,
TokenExchangeClient: tokenExchangeClient,
DebugLogger: debugLogger,
})
}
}

Expand Down Expand Up @@ -267,6 +272,18 @@ func newServer(cfg Config) *mcp.Server {
if enabledTools["get_project"] {
tools.RegisterGetProject(server)
}
if enabledTools["search_committees"] {
tools.RegisterSearchCommittees(server)
}
if enabledTools["get_committee"] {
tools.RegisterGetCommittee(server)
}
if enabledTools["get_committee_member"] {
tools.RegisterGetCommitteeMember(server)
}
if enabledTools["search_committee_members"] {
tools.RegisterSearchCommitteeMembers(server)
}

return server
}
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ require (
github.com/knadh/koanf/providers/env/v2 v2.0.0
github.com/knadh/koanf/v2 v2.3.2
github.com/lestrrat-go/jwx/v2 v2.1.6
github.com/linuxfoundation/lfx-v2-committee-service v0.2.19
github.com/linuxfoundation/lfx-v2-project-service v0.5.7
github.com/linuxfoundation/lfx-v2-query-service v0.4.12
github.com/modelcontextprotocol/go-sdk v1.4.0
goa.design/goa/v3 v3.25.3
)
Expand All @@ -28,7 +30,6 @@ require (
github.com/lestrrat-go/httprc v1.0.6 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/linuxfoundation/lfx-v2-query-service v0.4.12 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/segmentio/asm v1.2.1 // indirect
Expand Down
14 changes: 2 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
Expand All @@ -33,8 +27,6 @@ github.com/knadh/koanf/providers/env/v2 v2.0.0 h1:Ad5H3eun722u+FvchiIcEIJZsZ2M6o
github.com/knadh/koanf/providers/env/v2 v2.0.0/go.mod h1:1g01PE+Ve1gBfWNNw2wmULRP0tc8RJrjn5p2N/jNCIc=
github.com/knadh/koanf/v2 v2.3.2 h1:Ee6tuzQYFwcZXQpc2MiVeC6qHMandf5SMUJJNoFp/c4=
github.com/knadh/koanf/v2 v2.3.2/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28=
github.com/lestrrat-go/blackmagic v1.0.3 h1:94HXkVLxkZO9vJI/w2u1T0DAoprShFd13xtnSINtDWs=
github.com/lestrrat-go/blackmagic v1.0.3/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA=
github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
Expand All @@ -47,6 +39,8 @@ github.com/lestrrat-go/jwx/v2 v2.1.6 h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVf
github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/linuxfoundation/lfx-v2-committee-service v0.2.19 h1:xMeqXvf7NLk9JlfAEpNHBpwFtvtNTnwR/bOjxY/5Fa4=
github.com/linuxfoundation/lfx-v2-committee-service v0.2.19/go.mod h1:vhFiTH/CEDcs2kHmDofKzJclW1ZtBlfaRH0brL6lfek=
github.com/linuxfoundation/lfx-v2-project-service v0.5.7 h1:qycjiPSogIIHhRXDFSa0Zxu5ZLb/4jt9I8/JJmAJ0M4=
github.com/linuxfoundation/lfx-v2-project-service v0.5.7/go.mod h1:JCQZhtqf6lqxG0LA55qbQrTFwV3oSdAoLKn/1BvcMe4=
github.com/linuxfoundation/lfx-v2-query-service v0.4.12 h1:2sp/7zyhzsq8slNTWefixzjAI88yBYGYPuOjcnGke7I=
Expand All @@ -71,12 +65,8 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
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=
goa.design/goa/v3 v3.22.6 h1:D2qDkAvdpf6ePr2iXKT+Ple5WDrjyes3iOfYD2yCpw0=
goa.design/goa/v3 v3.22.6/go.mod h1:rhssEXxox3+sKnYp18hPNFCz65I4hLWHEtJKewoNJWk=
goa.design/goa/v3 v3.25.3 h1:gnOm2Vu0HMvveKpcqL6aWYQTP2puiwrEJWLQc79/294=
goa.design/goa/v3 v3.25.3/go.mod h1:VZ8CcXJRZh09ijtNJJS2gNyKufpmrM+Ul/Qy3viwcOU=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
Expand Down
37 changes: 35 additions & 2 deletions internal/lfxv2/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ import (

goahttp "goa.design/goa/v3/http"

committeeservice "github.com/linuxfoundation/lfx-v2-committee-service/gen/committee_service"
committeehttpclient "github.com/linuxfoundation/lfx-v2-committee-service/gen/http/committee_service/client"
projecthttpclient "github.com/linuxfoundation/lfx-v2-project-service/api/project/v1/gen/http/project_service/client"
projectservice "github.com/linuxfoundation/lfx-v2-project-service/api/project/v1/gen/project_service"
queryhttpclient "github.com/linuxfoundation/lfx-v2-query-service/gen/http/query_svc/client"
Expand Down Expand Up @@ -117,8 +119,9 @@ type ClientConfig struct {

// Clients holds initialized LFX v2 API service clients.
type Clients struct {
Project *projectservice.Client
QuerySvc *querysvc.Client
Committee *committeeservice.Client
Project *projectservice.Client
QuerySvc *querysvc.Client

tokenExchangeClient *TokenExchangeClient

Expand Down Expand Up @@ -161,6 +164,36 @@ func NewClients(_ context.Context, cfg ClientConfig) (*Clients, error) {
httpClient = clients.wrapWithAuthInterceptor(httpClient)
}

// Initialize committee service client.
committeeURL, err := url.Parse(cfg.APIDomain + "/committees")
if err != nil {
return nil, fmt.Errorf("failed to parse committee service URL: %w", err)
}

committeeHTTPClient := committeehttpclient.NewClient(
committeeURL.Scheme,
committeeURL.Host,
httpClient,
goahttp.RequestEncoder,
goahttp.ResponseDecoder,
false,
)

clients.Committee = committeeservice.NewClient(
committeeHTTPClient.CreateCommittee(),
committeeHTTPClient.GetCommitteeBase(),
committeeHTTPClient.UpdateCommitteeBase(),
committeeHTTPClient.DeleteCommittee(),
committeeHTTPClient.GetCommitteeSettings(),
committeeHTTPClient.UpdateCommitteeSettings(),
committeeHTTPClient.Readyz(),
committeeHTTPClient.Livez(),
committeeHTTPClient.CreateCommitteeMember(),
committeeHTTPClient.GetCommitteeMember(),
committeeHTTPClient.UpdateCommitteeMember(),
committeeHTTPClient.DeleteCommitteeMember(),
)

// Initialize project service client.
projectURL, err := url.Parse(cfg.APIDomain + "/projects")
if err != nil {
Expand Down
Loading