From 6267502a6c71223586a2d48c4bc15aa99c02a416 Mon Sep 17 00:00:00 2001 From: Kyle Rockman Date: Mon, 14 Apr 2025 09:42:28 -0500 Subject: [PATCH 1/8] Blockout bigger MCP server --- src/cmd/mcp.go | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ src/go.mod | 17 ++++++ src/go.sum | 41 ++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 src/cmd/mcp.go diff --git a/src/cmd/mcp.go b/src/cmd/mcp.go new file mode 100644 index 00000000..eee3fece --- /dev/null +++ b/src/cmd/mcp.go @@ -0,0 +1,147 @@ +package cmd + +import ( + "encoding/json" + mcp_golang "github.com/metoro-io/mcp-golang" + "github.com/metoro-io/mcp-golang/transport/stdio" + "github.com/spf13/cobra" +) + +type NullArguments struct{} + +type LightweightComponent struct { + Id string `json:"id"` + Name string `json:"name"` + Owner string `json:"owner"` + URL string `json:"url"` +} + +var mcpCmd = &cobra.Command{ + Use: "mcp", + Short: "MCP Server", + Long: "MCP Server", + + RunE: func(cmd *cobra.Command, args []string) error { + done := make(chan struct{}) + + //transport := http.NewHTTPTransport("/mcp") + //transport.WithAddr(":8080") + //server := mcp_golang.NewServer(transport) + server := mcp_golang.NewServer(stdio.NewStdioServerTransport()) + + // Register Teams + if err := server.RegisterTool("teams", "Get all the team names, identifiers and metadata for the opslevel account. Teams are owners of other objects in opslevel. Only use this if you need to search all teams.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { + client := getClientGQL() + resp, err := client.ListTeams(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil + }); err != nil { + panic(err) + } + + // Register Users + if err := server.RegisterTool("users", "Get all the user names, e-mail addresses and metadata for the opslevel account. Users are the people in opslevel. Only use this if you need to search all users.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { + client := getClientGQL() + resp, err := client.ListUsers(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil + }); err != nil { + panic(err) + } + + // Register Actions + if err := server.RegisterTool("actions", "Get all the information about actions the user can run in the opslevel account", func(args NullArguments) (*mcp_golang.ToolResponse, error) { + client := getClientGQL() + resp, err := client.ListTriggerDefinitions(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil + }); err != nil { + panic(err) + } + + // Register Filters + if err := server.RegisterTool("filters", "Get all the rubric filter names and which predicates they have for the opslevel account", func(args NullArguments) (*mcp_golang.ToolResponse, error) { + client := getClientGQL() + resp, err := client.ListFilters(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil + }); err != nil { + panic(err) + } + + // Register Components + if err := server.RegisterTool("components", "Get all the components in the opslevel account. Components are objects in opslevel that represent things like apis, libraries, services, frontends, backends, etc.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { + client := getClientGQL() + resp, err := client.ListServices(nil) + if err != nil { + return nil, err + } + var components []LightweightComponent + for _, node := range resp.Nodes { + components = append(components, LightweightComponent{ + Id: string(node.Id), + Name: node.Name, + Owner: node.Owner.Alias, + URL: node.HtmlURL, + }) + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil + }); err != nil { + panic(err) + } + + // Register Infra + if err := server.RegisterTool("infrastructure", "Get all the infrastructure in the opslevel account. Infrastructure are objects in opslevel that represent cloud provider resources like vpc, databases, caches, networks, vms, etc.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { + client := getClientGQL() + resp, err := client.ListInfrastructure(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil + }); err != nil { + panic(err) + } + + if err := server.Serve(); err != nil { + panic(err) + } + <-done + return nil + }, +} + +func init() { + rootCmd.AddCommand(mcpCmd) +} diff --git a/src/go.mod b/src/go.mod index 732620a7..b09b000f 100644 --- a/src/go.mod +++ b/src/go.mod @@ -31,7 +31,9 @@ require ( github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/ProtonMail/go-crypto v1.1.5 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/buger/jsonparser v1.1.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cloudflare/circl v1.6.0 // indirect @@ -40,6 +42,8 @@ require ( github.com/emirpasic/gods v1.18.1 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.8.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/go-ini/ini v1.67.0 // indirect @@ -50,6 +54,7 @@ require ( github.com/go-playground/validator/v10 v10.25.0 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gobwas/glob v0.2.3 // indirect + github.com/goccy/go-json v0.9.7 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect @@ -58,12 +63,18 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hasura/go-graphql-client v0.13.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/invopop/jsonschema v0.12.0 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/metoro-io/mcp-golang v0.9.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opslevel/moredefaults v0.0.0-20240529152742-17d1318a3c12 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect @@ -83,6 +94,12 @@ require ( github.com/spf13/cast v1.7.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect + github.com/tidwall/gjson v1.18.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + github.com/ugorji/go/codec v1.2.7 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect diff --git a/src/go.sum b/src/go.sum index cf908795..15c3841c 100644 --- a/src/go.sum +++ b/src/go.sum @@ -21,8 +21,12 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -80,6 +84,10 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/ github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -111,6 +119,8 @@ github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIx github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -127,6 +137,7 @@ github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -149,12 +160,17 @@ github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/itchyny/gojq v0.12.17 h1:8av8eGduDb5+rvEdaOO+zQUjA04MS0m3Ps8HiD+fceg= github.com/itchyny/gojq v0.12.17/go.mod h1:WBrEMkgAfAGO1LUcGOckBl5O726KPp+OlkKug0I/FEY= github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= @@ -168,6 +184,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -177,6 +195,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/metoro-io/mcp-golang v0.9.0 h1:GpFENjieZ/KosTu7CE7tyGI/a2FhiG0nandR0d8B3rE= +github.com/metoro-io/mcp-golang v0.9.0/go.mod h1:ifLP9ZzKpN1UqFWNTpAHOqSvNkMK6b7d1FSZ5Lu0lN0= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -185,6 +205,11 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= @@ -248,6 +273,7 @@ github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -256,6 +282,21 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= From 5584ea906847d7bfd83e1a5f420efb8691b30806 Mon Sep 17 00:00:00 2001 From: Kyle Date: Tue, 15 Apr 2025 14:12:57 -0500 Subject: [PATCH 2/8] Kr/mcp add beta (#388) * nest mcp under beta subcommand * Fix lint * fix lint again --- src/cmd/beta.go | 13 +++++++++++++ src/cmd/mcp.go | 11 ++++++----- src/go.mod | 19 ++++++------------- src/go.sum | 46 ++++++++++++++-------------------------------- 4 files changed, 39 insertions(+), 50 deletions(-) create mode 100644 src/cmd/beta.go diff --git a/src/cmd/beta.go b/src/cmd/beta.go new file mode 100644 index 00000000..268dec3a --- /dev/null +++ b/src/cmd/beta.go @@ -0,0 +1,13 @@ +package cmd + +import "github.com/spf13/cobra" + +var betaCmd = &cobra.Command{ + Use: "beta", + Short: "Beta commands that are subject to removal", + Long: "Beta commands that are subject to removal", +} + +func init() { + rootCmd.AddCommand(betaCmd) +} diff --git a/src/cmd/mcp.go b/src/cmd/mcp.go index eee3fece..a01a1ff4 100644 --- a/src/cmd/mcp.go +++ b/src/cmd/mcp.go @@ -2,6 +2,7 @@ package cmd import ( "encoding/json" + mcp_golang "github.com/metoro-io/mcp-golang" "github.com/metoro-io/mcp-golang/transport/stdio" "github.com/spf13/cobra" @@ -24,9 +25,9 @@ var mcpCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { done := make(chan struct{}) - //transport := http.NewHTTPTransport("/mcp") - //transport.WithAddr(":8080") - //server := mcp_golang.NewServer(transport) + // transport := http.NewHTTPTransport("/mcp") + // transport.WithAddr(":8080") + // server := mcp_golang.NewServer(transport) server := mcp_golang.NewServer(stdio.NewStdioServerTransport()) // Register Teams @@ -109,7 +110,7 @@ var mcpCmd = &cobra.Command{ URL: node.HtmlURL, }) } - data, err := json.Marshal(resp.Nodes) + data, err := json.Marshal(components) if err != nil { return nil, err } @@ -143,5 +144,5 @@ var mcpCmd = &cobra.Command{ } func init() { - rootCmd.AddCommand(mcpCmd) + betaCmd.AddCommand(mcpCmd) } diff --git a/src/go.mod b/src/go.mod index b09b000f..024bd901 100644 --- a/src/go.mod +++ b/src/go.mod @@ -11,6 +11,7 @@ require ( github.com/gosimple/slug v1.15.0 github.com/itchyny/gojq v0.12.17 github.com/manifoldco/promptui v0.9.0 + github.com/metoro-io/mcp-golang v0.9.0 github.com/mitchellh/mapstructure v1.5.0 github.com/open-policy-agent/opa v0.67.1 github.com/opslevel/opslevel-go/v2024 v2024.12.24 @@ -42,8 +43,6 @@ require ( github.com/emirpasic/gods v1.18.1 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect - github.com/gin-contrib/sse v0.1.0 // indirect - github.com/gin-gonic/gin v1.8.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/go-ini/ini v1.67.0 // indirect @@ -51,10 +50,9 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.25.0 // indirect + github.com/go-playground/validator/v10 v10.26.0 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/goccy/go-json v0.9.7 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect @@ -66,15 +64,11 @@ require ( github.com/invopop/jsonschema v0.12.0 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/metoro-io/mcp-golang v0.9.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opslevel/moredefaults v0.0.0-20240529152742-17d1318a3c12 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect @@ -98,7 +92,6 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/ugorji/go/codec v1.2.7 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect @@ -109,10 +102,10 @@ require ( go.opentelemetry.io/otel/sdk v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/net v0.37.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/crypto v0.37.0 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/text v0.24.0 // indirect google.golang.org/protobuf v1.36.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/src/go.sum b/src/go.sum index 15c3841c..8689142e 100644 --- a/src/go.sum +++ b/src/go.sum @@ -84,10 +84,6 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/ github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= -github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -111,16 +107,14 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8= -github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= +github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= +github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= -github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -137,7 +131,6 @@ github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -169,8 +162,6 @@ github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJG github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= @@ -205,11 +196,6 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= @@ -273,7 +259,6 @@ github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -292,9 +277,6 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= @@ -326,17 +308,17 @@ go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -348,14 +330,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= +golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 5e224490f723eed169841a79f16770b0a7be7539 Mon Sep 17 00:00:00 2001 From: Evan Huus <109987149+eapache-opslevel@users.noreply.github.com> Date: Wed, 16 Apr 2025 15:05:29 -0400 Subject: [PATCH 3/8] Add run script for Claude Desktop hot-reloading (#397) --- src/run.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100755 src/run.sh diff --git a/src/run.sh b/src/run.sh new file mode 100755 index 00000000..85f4b3b9 --- /dev/null +++ b/src/run.sh @@ -0,0 +1,8 @@ +#! /bin/sh + +# Stub script to call `go run` but with the right working directory so that go's +# module system is happy, when called by systems like Claude Desktop that don't +# permit setting the working directory. Primarily useful for development. + +cd "$(dirname "$0")" +go run main.go "$@" From 855c63f42969a94683475044bddb58eaa86a0212 Mon Sep 17 00:00:00 2001 From: Kyle Date: Wed, 16 Apr 2025 14:06:47 -0500 Subject: [PATCH 4/8] Add Domains and Systems (#390) --- src/cmd/mcp.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/cmd/mcp.go b/src/cmd/mcp.go index a01a1ff4..42867063 100644 --- a/src/cmd/mcp.go +++ b/src/cmd/mcp.go @@ -135,6 +135,38 @@ var mcpCmd = &cobra.Command{ panic(err) } + // Register Domains + if err := server.RegisterTool("domains", "Get all the domains in the opslevel account. Domains are objects in opslevel that represent a top-level abstraction used to organize and categorize software systems.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { + client := getClientGQL() + resp, err := client.ListDomains(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil + }); err != nil { + panic(err) + } + + // Register Systems + if err := server.RegisterTool("systems", "Get all the systems in the opslevel account. Systems are objects in opslevel that represent a grouping of services or components that act together to serve a business function or process.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { + client := getClientGQL() + resp, err := client.ListSystems(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil + }); err != nil { + panic(err) + } + if err := server.Serve(); err != nil { panic(err) } From 814b7cdd1094c4a11b5a56f87dc6ba2aa0a4ca30 Mon Sep 17 00:00:00 2001 From: Evan Huus <109987149+eapache-opslevel@users.noreply.github.com> Date: Wed, 16 Apr 2025 15:06:01 -0400 Subject: [PATCH 5/8] Ignore built binary path (#396) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9abefd28..57443f01 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ go.work* **coverage.txt src/*.yaml .vscode/ +src/cli From 83f068a836c1e1e353aa9f315d28c2f069b2a4b9 Mon Sep 17 00:00:00 2001 From: Kyle Date: Wed, 16 Apr 2025 14:38:49 -0500 Subject: [PATCH 6/8] overhaul contributing based on feedback from evan (#393) * overhaul contributing based on feedback from evan * more fixes after personal review * Apply suggestions from code review * Apply suggestions from code review --- CONTRIBUTING.md | 186 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 132 insertions(+), 54 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 824e9b26..6ff3872e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,104 +1,182 @@ -# Contributing +# Contributing to opslevel-cli -1. [About this document](#about-this-document) -1. [Getting the code](#getting-the-code) -1. [Local development](#local-development) -1. [Submitting a Pull Request](#submitting-a-pull-request) +👋 Welcome, and thank you for your interest in contributing to `opslevel-cli`! This guide will help you ramp up, propose changes, develop locally, and contribute code effectively. -## About this document +--- -This document is a guide intended for folks interested in contributing to `opslevel-cli`. Below, we document the process by which members of the community should create issues and submit pull requests (PRs) in this repository. This guide assumes you are using macOS and are comfortable with the command line. +## Table of Contents -If you're new to Golang development or contributing to open-source software, we encourage you to read this document from start to finish. +1. [About the CLI](#about-the-cli) +2. [Getting Started](#getting-started) +3. [Development Workflow](#development-workflow) +4. [Proposing and Submitting Changes](#proposing-and-submitting-changes) +5. [Command Architecture & Style](#command-architecture--style) +6. [Testing & Tooling](#testing--tooling) +7. [Release Process](#release-process) -## Proposing a change +--- -This project is what it is today because community members like you have opened issues, provided feedback, and contributed to the knowledge loop for the entire community. Whether you are a seasoned open source contributor or a first-time committer, we welcome and encourage you to contribute code, documentation, ideas, or problem statements to this project. +## About the CLI -### Defining the problem +The `opslevel-cli` is a command-line interface for interacting with the [OpsLevel](https://www.opslevel.com) API. It helps engineers automate, inspect, and manage their service catalog, ownership, checks, and more. -If you have an idea for a new feature or if you've discovered a bug, the first step is to open an issue. Please check the list of [open issues](https://github.com/OpsLevel/cli/issues) before creating a new one. If you find a relevant issue, please add a comment to the open issue instead of creating a new one. +### Architecture -> **Note:** All community-contributed Pull Requests _must_ be associated with an open issue. If you submit a Pull Request that does not pertain to an open issue, you will be asked to create an issue describing the problem before the Pull Request can be reviewed. +**[Cobra](https://github.com/spf13/cobra)** is the library we use to define our CLI. Commands are defined as Go structs with handlers, descriptions, and flags. +- **[Viper](https://github.com/spf13/viper)** handles flag parsing, environment variables, and configuration files. Examples of our usage of it are [here](https://github.com/OpsLevel/cli/blob/main/src/cmd/root.go#L44) and [here](https://github.com/OpsLevel/cli/blob/main/src/cmd/policy.go#L246) +- Modular command files live under `/cmd`, grouped by functionality (e.g., services, checks, etc.). +- Commands are registered to `rootCmd` via `init()` functions. +- 80% of our functionality is provided by opslevel-go and the purpose of this CLI is just to marshal data between the user and opslevel-go in a UX friendly way. +- Most commands follow the standard CRUD pattern `opslevel create ...`, `opslevel get ...`, `opslevel list ...`, `opslevel update ...`, `opslevel delete ...`, etc. +- We have an `opslevel beta` subcommand for experimental commands that are subject to change. -### Submitting a change +--- -If an issue is appropriately well scoped and describes a beneficial change to the codebase, then anyone may submit a Pull Request to implement the functionality described in the issue. See the sections below on how to do this. +## Getting Started -The maintainers will add a `good first issue` label if an issue is suitable for a first-time contributor. This label often means that the required code change is small or a net-new addition that does not impact existing functionality. You can see the list of currently open issues on the [Contribute](https://github.com/OpsLevel/cli/contribute) page. +### Clone the Repo -## Getting the code +If you're an external contributor fork the repo, then: -### Installing git - -You will need `git` in order to download and modify the source code. On macOS, the best way to download git is to just install [Xcode](https://developer.apple.com/support/xcode/). +```bash +git clone https://github.com/YOUR_USERNAME/cli.git +cd cli +git checkout -b my-feature +``` -### External contributors +If you're part of the OpsLevel org: -If you are not a member of the `OpsLevel` GitHub organization, you can contribute by forking the repository. For a detailed overview on forking, check out the [GitHub docs on forking](https://help.github.com/en/articles/fork-a-repo). In short, you will need to: +```bash +git clone git@github.com:OpsLevel/cli.git +cd cli +git checkout -b my-feature +``` -1. fork the repository -2. clone your fork locally -3. check out a new branch for your proposed changes -4. push changes to your fork -5. open a pull request from your forked repository +> You might need to be given permissions to the repo, please reach out to team platform. -### OpsLevel contributors +### Prerequisites -If you are a member of the `OpsLevel` GitHub organization, you will have push access to the repo. Rather than forking to make your changes, just clone the repository, check out a new branch, and push directly to that branch. +- [Task](https://taskfile.dev) +- An [OpsLevel API Token](https://app.opslevel.com/api_tokens) -## Local Development +You can use `task setup` to run an idempotent one-time setup. -### Installation +Set your API token: -First make sure you have working [golang development environment](https://learn.gopherguides.com/courses/preparing-your-environment-for-go-development) setup. +```sh +export OPSLEVEL_API_TOKEN=your_token_here +``` -You will also need an [OpsLevel API Token](https://app.opslevel.com/api_tokens) from your account to successfully make API calls against. Once you have the API token it is best to put it in your terminal's environment +If you need to target a different environment, set the `OPSLEVEL_API_URL` environment variable: ```sh - export OPSLEVEL_API_TOKEN=XXXXXXXXX +export OPSLEVEL_API_URL=https://self-hosted.opslevel.dev/ ``` -### Local Development Testing +--- + +## Development Workflow -You can run your local code as if it was a prebuilt CLI using: +### Run the CLI Locally ```sh -go run main.go -h +cd ./src +go run main.go --help ``` -This way you can iterate on the CLI code quickly to test out your new functionality. +This is the easiest way to test your changes live. -#### Local Development with an `opslevel-go` Feature Branch +### Using a commit from an `opslevel-go` Branch -To test local code against a feature branch in the `opslevel-go` repository, run: +Sometimes you will need to make CLI changes in tandem with changes to [`opslevel-go`](https://github.com/OpsLevel/opslevel-go). +To test changes from a local branch of [`opslevel-go`](https://github.com/OpsLevel/opslevel-go): ```sh -# initializes opslevel-go submodule then sets up src/go.work +# Set up workspace using task task workspace -# git checkouts my-feature-branch in the src/submodules/opslevel-go directory +# Switch to your feature branch in the submodule git -C ./src/submodules/opslevel-go checkout --track origin/my-feature-branch ``` -Code imported from `github.com/opslevel/opslevel-go` will now be sourced from the -local `my-feature-branch`. +All CLI calls will now use your local `opslevel-go` code checked out into the submodule at `./src/submodules/opslevel-go`. +This way you can effectively work on both the CLI and `opslevel-go` in parallel if needed. + +## Testing & Tooling + +- Use `task test` to run tests locally +- Use `task lint` to check for code quality issues locally +- Use `task fix` to fix formatting, linting, go.mod, and update submodule all in one go + +Our CI pipeline will run `task ci` which can also be run locally to debug any issue that might only arise in CI. + +--- + +## Proposing and Submitting Changes + +### 1. Open an Issue -### Changie (Change log generation) +If you're fixing a bug or adding a feature, please [open an issue](https://github.com/OpsLevel/cli/issues) first. This helps us track discussions and ensures your work aligns with project goals. -Before submitting the pull request, you need add a change entry via Changie so that your contribution changes can be tracked for our next release. +> **Note:** All PRs must be tied to a GitHub issue. -To install Changie, follow the directions [here](https://changie.dev/guide/installation/). +Look for issues marked `good first issue` if you're new. + +### 2. Submit a Pull Request + +- Push your changes to your fork or feature branch +- Run `changie new` to create a changelog entry +- Open a PR to `main` or the relevant feature branch +- Our GitHub Actions pipeline will run tests and lint checks +- A maintainer will review your PR and request changes if needed + +Once approved and merged, your change will be included in the next release. + +--- + +## Command Architecture & Style + +- Each CLI command lives in its own file under `/cmd` +- Commands should: + - Register themselves via `init()` + - Use `RunE` instead of `Run` for error handling +- Flags and environment variables should be registered with Viper for consistency +- Prefer readable, minimalistic command logic — delegate heavy logic to opslevel-go unless it's not possible + +### Minimal Command Example + +The following shows the minimum amount of code needed to create a command. There are a plethora of commands already registered to the root command, so this is just an example of how to create a new command. +Please take a look at the existing commands to get a feel for how they work and whats possible. + +```go +var exampleCmd = &cobra.Command{ + Use: "example", + Short: "Hello World Command", + Long: "Hello World Command to show how an example command works", + RunE: func(cmd *cobra.Command, args []string) error { + log.Info().Msg("Hello World!") + return nil + }, +} + +func init() { + rootCmd.AddCommand(exampleCmd) +} +``` -Next, to create a new change entry, in the root of the repository run: `changie new` +--- -Follow the prompts to create your change entry - remember this is what will show up in the changelog. Changie registers the change in a .yaml file, and that file must be included in your pull request before we can release. +## Release Process -## Submitting a Pull Request +- All customer facing changes must have a [Changie](https://changie.dev) changelog entry + - Run: `changie new` + - Follow prompts to categorize your change + - This generates a YAML file in `.changes/` that must be committed with your PR -OpsLevel provides a CI environment to test changes through GitHub Actions. For example, if you submit a pull request to the repo, GitHub will trigger automated code checks and tests upon approval from an OpsLevel maintainer. +- CI/CD (GitHub Actions) runs lint and tests automatically on pull requests and the main branch +- Maintainers will merge once approved +- Your contribution will be included in the next versioned release (triggered by a maintainer) -A maintainer will review your PR. They may suggest code revision for style or clarity, or request that you add unit or integration test(s). These are good things! We believe that, with a little bit of help, anyone can contribute high-quality code. -- First time contributors should be aware that code checks + unit tests require a maintainer to approve. +--- -Once all tests are passing and your PR has been approved, a maintainer will merge your changes into the active development branch. And that's it! It will be available in the next release that is cut. Happy developing :tada: +Happy hacking 🎉 and thank you for helping improve the `opslevel-cli`! From 8f3ee1d05372bc0587637cf3a613a9e9e669b6d4 Mon Sep 17 00:00:00 2001 From: Kyle Date: Thu, 17 Apr 2025 11:26:05 -0500 Subject: [PATCH 7/8] Kr/mcp switch lib (#399) * Convert to mcp-go * convert rest * fix lint * fix lint --- src/cmd/mcp.go | 263 +++++++++++++++++++++++++------------------------ src/go.mod | 12 +-- src/go.sum | 27 +---- 3 files changed, 140 insertions(+), 162 deletions(-) diff --git a/src/cmd/mcp.go b/src/cmd/mcp.go index 42867063..f424035b 100644 --- a/src/cmd/mcp.go +++ b/src/cmd/mcp.go @@ -1,10 +1,12 @@ package cmd import ( + "context" "encoding/json" - mcp_golang "github.com/metoro-io/mcp-golang" - "github.com/metoro-io/mcp-golang/transport/stdio" + "github.com/mark3labs/mcp-go/mcp" + "github.com/mark3labs/mcp-go/server" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -25,152 +27,155 @@ var mcpCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { done := make(chan struct{}) - // transport := http.NewHTTPTransport("/mcp") - // transport.WithAddr(":8080") - // server := mcp_golang.NewServer(transport) - server := mcp_golang.NewServer(stdio.NewStdioServerTransport()) + s := server.NewMCPServer( + "OpsLevel", + "1.0.0", + ) // Register Teams - if err := server.RegisterTool("teams", "Get all the team names, identifiers and metadata for the opslevel account. Teams are owners of other objects in opslevel. Only use this if you need to search all teams.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { - client := getClientGQL() - resp, err := client.ListTeams(nil) - if err != nil { - return nil, err - } - data, err := json.Marshal(resp.Nodes) - if err != nil { - return nil, err - } - return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil - }); err != nil { - panic(err) - } + s.AddTool( + mcp.NewTool("teams", + mcp.WithDescription("Get all the team names, identifiers and metadata for the opslevel account. Teams are owners of other objects in opslevel. Only use this if you need to search all teams.")), + func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { + client := getClientGQL() + resp, err := client.ListTeams(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp.NewToolResultText(string(data)), nil + }) // Register Users - if err := server.RegisterTool("users", "Get all the user names, e-mail addresses and metadata for the opslevel account. Users are the people in opslevel. Only use this if you need to search all users.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { - client := getClientGQL() - resp, err := client.ListUsers(nil) - if err != nil { - return nil, err - } - data, err := json.Marshal(resp.Nodes) - if err != nil { - return nil, err - } - return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil - }); err != nil { - panic(err) - } + s.AddTool( + mcp.NewTool("users", mcp.WithDescription("Get all the user names, e-mail addresses and metadata for the opslevel account. Users are the people in opslevel. Only use this if you need to search all users.")), + func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { + client := getClientGQL() + resp, err := client.ListUsers(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp.NewToolResultText(string(data)), nil + }) // Register Actions - if err := server.RegisterTool("actions", "Get all the information about actions the user can run in the opslevel account", func(args NullArguments) (*mcp_golang.ToolResponse, error) { - client := getClientGQL() - resp, err := client.ListTriggerDefinitions(nil) - if err != nil { - return nil, err - } - data, err := json.Marshal(resp.Nodes) - if err != nil { - return nil, err - } - return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil - }); err != nil { - panic(err) - } + s.AddTool( + mcp.NewTool("actions", mcp.WithDescription("Get all the information about actions the user can run in the opslevel account")), + func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { + client := getClientGQL() + resp, err := client.ListTriggerDefinitions(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp.NewToolResultText(string(data)), nil + }) // Register Filters - if err := server.RegisterTool("filters", "Get all the rubric filter names and which predicates they have for the opslevel account", func(args NullArguments) (*mcp_golang.ToolResponse, error) { - client := getClientGQL() - resp, err := client.ListFilters(nil) - if err != nil { - return nil, err - } - data, err := json.Marshal(resp.Nodes) - if err != nil { - return nil, err - } - return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil - }); err != nil { - panic(err) - } + s.AddTool( + mcp.NewTool("filters", mcp.WithDescription("Get all the rubric filter names and which predicates they have for the opslevel account")), + func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { + client := getClientGQL() + resp, err := client.ListFilters(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp.NewToolResultText(string(data)), nil + }) // Register Components - if err := server.RegisterTool("components", "Get all the components in the opslevel account. Components are objects in opslevel that represent things like apis, libraries, services, frontends, backends, etc.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { - client := getClientGQL() - resp, err := client.ListServices(nil) - if err != nil { - return nil, err - } - var components []LightweightComponent - for _, node := range resp.Nodes { - components = append(components, LightweightComponent{ - Id: string(node.Id), - Name: node.Name, - Owner: node.Owner.Alias, - URL: node.HtmlURL, - }) - } - data, err := json.Marshal(components) - if err != nil { - return nil, err - } - return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil - }); err != nil { - panic(err) - } + s.AddTool( + mcp.NewTool("components", mcp.WithDescription("Get all the components in the opslevel account. Components are objects in opslevel that represent things like apis, libraries, services, frontends, backends, etc.")), + func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { + client := getClientGQL() + resp, err := client.ListServices(nil) + if err != nil { + return nil, err + } + var components []LightweightComponent + for _, node := range resp.Nodes { + components = append(components, LightweightComponent{ + Id: string(node.Id), + Name: node.Name, + Owner: node.Owner.Alias, + URL: node.HtmlURL, + }) + } + data, err := json.Marshal(components) + if err != nil { + return nil, err + } + return mcp.NewToolResultText(string(data)), nil + }) // Register Infra - if err := server.RegisterTool("infrastructure", "Get all the infrastructure in the opslevel account. Infrastructure are objects in opslevel that represent cloud provider resources like vpc, databases, caches, networks, vms, etc.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { - client := getClientGQL() - resp, err := client.ListInfrastructure(nil) - if err != nil { - return nil, err - } - data, err := json.Marshal(resp.Nodes) - if err != nil { - return nil, err - } - return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil - }); err != nil { - panic(err) - } + s.AddTool( + mcp.NewTool("infrastructure", mcp.WithDescription("Get all the infrastructure in the opslevel account. Infrastructure are objects in opslevel that represent cloud provider resources like vpc, databases, caches, networks, vms, etc.")), + func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { + client := getClientGQL() + resp, err := client.ListInfrastructure(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp.NewToolResultText(string(data)), nil + }) // Register Domains - if err := server.RegisterTool("domains", "Get all the domains in the opslevel account. Domains are objects in opslevel that represent a top-level abstraction used to organize and categorize software systems.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { - client := getClientGQL() - resp, err := client.ListDomains(nil) - if err != nil { - return nil, err - } - data, err := json.Marshal(resp.Nodes) - if err != nil { - return nil, err - } - return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil - }); err != nil { - panic(err) - } + s.AddTool( + mcp.NewTool("domains", mcp.WithDescription("Get all the domains in the opslevel account. Domains are objects in opslevel that represent a top-level abstraction used to organize and categorize software systems.")), + func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { + client := getClientGQL() + resp, err := client.ListDomains(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp.NewToolResultText(string(data)), nil + }) // Register Systems - if err := server.RegisterTool("systems", "Get all the systems in the opslevel account. Systems are objects in opslevel that represent a grouping of services or components that act together to serve a business function or process.", func(args NullArguments) (*mcp_golang.ToolResponse, error) { - client := getClientGQL() - resp, err := client.ListSystems(nil) - if err != nil { - return nil, err - } - data, err := json.Marshal(resp.Nodes) - if err != nil { - return nil, err - } - return mcp_golang.NewToolResponse(mcp_golang.NewTextContent(string(data))), nil - }); err != nil { - panic(err) - } - - if err := server.Serve(); err != nil { + s.AddTool( + mcp.NewTool("systems", mcp.WithDescription("Get all the systems in the opslevel account. Systems are objects in opslevel that represent a grouping of services or components that act together to serve a business function or process.")), + func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { + client := getClientGQL() + resp, err := client.ListSystems(nil) + if err != nil { + return nil, err + } + data, err := json.Marshal(resp.Nodes) + if err != nil { + return nil, err + } + return mcp.NewToolResultText(string(data)), nil + }) + + log.Info().Msg("Starting MCP server...") + if err := server.ServeStdio(s); err != nil { panic(err) } <-done + return nil }, } diff --git a/src/go.mod b/src/go.mod index 024bd901..e18b7bb4 100644 --- a/src/go.mod +++ b/src/go.mod @@ -11,7 +11,7 @@ require ( github.com/gosimple/slug v1.15.0 github.com/itchyny/gojq v0.12.17 github.com/manifoldco/promptui v0.9.0 - github.com/metoro-io/mcp-golang v0.9.0 + github.com/mark3labs/mcp-go v0.21.0 github.com/mitchellh/mapstructure v1.5.0 github.com/open-policy-agent/opa v0.67.1 github.com/opslevel/opslevel-go/v2024 v2024.12.24 @@ -32,9 +32,7 @@ require ( github.com/OneOfOne/xxhash v1.2.8 // indirect github.com/ProtonMail/go-crypto v1.1.5 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect - github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/buger/jsonparser v1.1.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cloudflare/circl v1.6.0 // indirect @@ -61,12 +59,10 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hasura/go-graphql-client v0.13.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/invopop/jsonschema v0.12.0 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -88,15 +84,11 @@ require ( github.com/spf13/cast v1.7.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect - github.com/tidwall/gjson v1.18.0 // indirect - github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.1 // indirect - github.com/tidwall/sjson v1.2.5 // indirect - github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yashtewari/glob-intersection v0.2.0 // indirect + github.com/yosida95/uritemplate/v3 v3.0.2 // indirect go.opentelemetry.io/otel v1.29.0 // indirect go.opentelemetry.io/otel/metric v1.29.0 // indirect go.opentelemetry.io/otel/sdk v1.29.0 // indirect diff --git a/src/go.sum b/src/go.sum index 8689142e..5462af5f 100644 --- a/src/go.sum +++ b/src/go.sum @@ -21,12 +21,8 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= -github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -153,15 +149,12 @@ github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= -github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/itchyny/gojq v0.12.17 h1:8av8eGduDb5+rvEdaOO+zQUjA04MS0m3Ps8HiD+fceg= github.com/itchyny/gojq v0.12.17/go.mod h1:WBrEMkgAfAGO1LUcGOckBl5O726KPp+OlkKug0I/FEY= github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= @@ -175,10 +168,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mark3labs/mcp-go v0.21.0 h1:oyEtiXg8PnrVEFis9b1AwbiUWF2dTbyBP5yLo7SruXE= +github.com/mark3labs/mcp-go v0.21.0/go.mod h1:KmJndYv7GIgcPVwEKJjNcbhVQ+hJGJhrCCB/9xITzpE= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= @@ -186,8 +179,6 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/metoro-io/mcp-golang v0.9.0 h1:GpFENjieZ/KosTu7CE7tyGI/a2FhiG0nandR0d8B3rE= -github.com/metoro-io/mcp-golang v0.9.0/go.mod h1:ifLP9ZzKpN1UqFWNTpAHOqSvNkMK6b7d1FSZ5Lu0lN0= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -267,18 +258,6 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= -github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= -github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= -github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= -github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= -github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= -github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= @@ -287,6 +266,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/yashtewari/glob-intersection v0.2.0 h1:8iuHdN88yYuCzCdjt0gDe+6bAhUwBeEWqThExu54RFg= github.com/yashtewari/glob-intersection v0.2.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= +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= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= From 6ebccfa0953d628ed84f01a3bcf0246e654088cc Mon Sep 17 00:00:00 2001 From: Evan Huus <109987149+eapache-opslevel@users.noreply.github.com> Date: Thu, 17 Apr 2025 14:41:15 -0400 Subject: [PATCH 8/8] Add 'mcp' to mcp graphql UA (#400) --- src/cmd/mcp.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/cmd/mcp.go b/src/cmd/mcp.go index f424035b..6df47bdb 100644 --- a/src/cmd/mcp.go +++ b/src/cmd/mcp.go @@ -3,9 +3,11 @@ package cmd import ( "context" "encoding/json" + "fmt" "github.com/mark3labs/mcp-go/mcp" "github.com/mark3labs/mcp-go/server" + "github.com/opslevel/cli/common" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -32,12 +34,13 @@ var mcpCmd = &cobra.Command{ "1.0.0", ) + client := common.NewGraphClient(fmt.Sprintf("mcp-%s", version)) + // Register Teams s.AddTool( mcp.NewTool("teams", mcp.WithDescription("Get all the team names, identifiers and metadata for the opslevel account. Teams are owners of other objects in opslevel. Only use this if you need to search all teams.")), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - client := getClientGQL() resp, err := client.ListTeams(nil) if err != nil { return nil, err @@ -53,7 +56,6 @@ var mcpCmd = &cobra.Command{ s.AddTool( mcp.NewTool("users", mcp.WithDescription("Get all the user names, e-mail addresses and metadata for the opslevel account. Users are the people in opslevel. Only use this if you need to search all users.")), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - client := getClientGQL() resp, err := client.ListUsers(nil) if err != nil { return nil, err @@ -69,7 +71,6 @@ var mcpCmd = &cobra.Command{ s.AddTool( mcp.NewTool("actions", mcp.WithDescription("Get all the information about actions the user can run in the opslevel account")), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - client := getClientGQL() resp, err := client.ListTriggerDefinitions(nil) if err != nil { return nil, err @@ -85,7 +86,6 @@ var mcpCmd = &cobra.Command{ s.AddTool( mcp.NewTool("filters", mcp.WithDescription("Get all the rubric filter names and which predicates they have for the opslevel account")), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - client := getClientGQL() resp, err := client.ListFilters(nil) if err != nil { return nil, err @@ -101,7 +101,6 @@ var mcpCmd = &cobra.Command{ s.AddTool( mcp.NewTool("components", mcp.WithDescription("Get all the components in the opslevel account. Components are objects in opslevel that represent things like apis, libraries, services, frontends, backends, etc.")), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - client := getClientGQL() resp, err := client.ListServices(nil) if err != nil { return nil, err @@ -126,7 +125,6 @@ var mcpCmd = &cobra.Command{ s.AddTool( mcp.NewTool("infrastructure", mcp.WithDescription("Get all the infrastructure in the opslevel account. Infrastructure are objects in opslevel that represent cloud provider resources like vpc, databases, caches, networks, vms, etc.")), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - client := getClientGQL() resp, err := client.ListInfrastructure(nil) if err != nil { return nil, err @@ -142,7 +140,6 @@ var mcpCmd = &cobra.Command{ s.AddTool( mcp.NewTool("domains", mcp.WithDescription("Get all the domains in the opslevel account. Domains are objects in opslevel that represent a top-level abstraction used to organize and categorize software systems.")), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - client := getClientGQL() resp, err := client.ListDomains(nil) if err != nil { return nil, err @@ -158,7 +155,6 @@ var mcpCmd = &cobra.Command{ s.AddTool( mcp.NewTool("systems", mcp.WithDescription("Get all the systems in the opslevel account. Systems are objects in opslevel that represent a grouping of services or components that act together to serve a business function or process.")), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - client := getClientGQL() resp, err := client.ListSystems(nil) if err != nil { return nil, err