Skip to content

Update README with markdown badge instead of HTML #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
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
3 changes: 3 additions & 0 deletions .changes/unreleased/Added-20250609-161700.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kind: Added
body: Add componentChecks tool, listing checks in the rubric
time: 2025-06-09T16:17:00.521062-03:00
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<img src="https://img.shields.io/github/commit-activity/m/OpsLevel/opslevel-mcp" alt="Activity" /></a>
<a href="https://github.com/OpsLevel/opslevel-mcp/releases">
<img src="https://img.shields.io/github/downloads/OpsLevel/opslevel-mcp/total" alt="Downloads" /></a>
<a href="https://app.opslevel.com/services/opslevel_mcp/maturity-report">
<img src="https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fdlmj6PlFjehv6iLE6IQtEGXi_uz3LF9rA5nxb35wiY8" alt="Overall" /></a>

[![Overall](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fapp.opslevel.com%2Fapi%2Fservice_level%2Fdlmj6PlFjehv6iLE6IQtEGXi_uz3LF9rA5nxb35wiY8)](https://app.opslevel.com/services/opslevel_mcp/maturity-report)
</p>


Expand Down
82 changes: 82 additions & 0 deletions src/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"github.com/spf13/cobra"

"github.com/relvacode/iso8601"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/viper"
Expand Down Expand Up @@ -71,6 +72,25 @@ type serializedCheck struct {
Category string
}

type serializedCheckResult struct {
CheckId string
CheckName string
Message string
Status string
LastUpdated iso8601.Time
}

type serializedCheckResultsByLevel struct {
Level serializedLevel
CheckResults []serializedCheckResult
}

type serializedCheckResults struct {
ByLevel []serializedCheckResultsByLevel
CurrentLevel serializedLevel
NextLevel *serializedLevel
}

// newToolResult creates a CallToolResult for the passed object handling any json marshaling errors
func newToolResult(obj any, err error) (*mcp.CallToolResult, error) {
if err != nil {
Expand Down Expand Up @@ -417,6 +437,68 @@ var rootCmd = &cobra.Command{
return newToolResult(checks, nil)
})

s.AddTool(
mcp.NewTool(
"componentChecks",
mcp.WithDescription("Get all the checks for a specific component in the OpsLevel account. Checks are organized by level in a rubric, with each level containing a set of checks that must be passed to achieve that level."),
mcp.WithString("serviceId", mcp.Required(), mcp.Description("The id of the service to fetch.")),
mcp.WithToolAnnotation(mcp.ToolAnnotation{
Title: "Rubric of Checks for Component",
ReadOnlyHint: true,
DestructiveHint: false,
IdempotentHint: true,
OpenWorldHint: true,
}),
),
func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
service, err := client.GetService(req.Params.Arguments["serviceId"].(string))
if err != nil {
return nil, err
}
if service.Id == "" {
return nil, fmt.Errorf("service with id %s not found", req.Params.Arguments["serviceId"].(string))
}

stats, err := service.GetServiceStats(client)
if err != nil {
return nil, err
}

result := serializedCheckResults{
CurrentLevel: serializedLevel{
Alias: stats.Rubric.Level.Alias,
Index: stats.Rubric.Level.Index,
},
}
if stats.Rubric.CheckResults.NextLevel.Level.Alias != "" {
result.NextLevel = &serializedLevel{
Alias: stats.Rubric.CheckResults.NextLevel.Level.Alias,
Index: stats.Rubric.CheckResults.NextLevel.Level.Index,
}
}

for _, checkResultsByLevel := range stats.Rubric.CheckResults.ByLevel.Nodes {
byLevel := serializedCheckResultsByLevel{
Level: serializedLevel{
Alias: checkResultsByLevel.Level.Alias,
Index: checkResultsByLevel.Level.Index,
},
}
for _, checkResult := range checkResultsByLevel.Items.Nodes {
byLevel.CheckResults = append(byLevel.CheckResults, serializedCheckResult{
CheckId: string(checkResult.Check.Id),
CheckName: checkResult.Check.Name,
Message: checkResult.Message,
Status: string(checkResult.Status),
LastUpdated: checkResult.LastUpdated,
})
}
result.ByLevel = append(result.ByLevel, byLevel)
}

return newToolResult(result, nil)
})

log.Info().Msg("Starting MCP server...")
if err := server.ServeStdio(s); err != nil {
if err == context.Canceled {
Expand Down
4 changes: 2 additions & 2 deletions src/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ toolchain go1.24.2
require (
github.com/mark3labs/mcp-go v0.23.1
github.com/opslevel/opslevel-go/v2025 v2025.5.28
github.com/relvacode/iso8601 v1.6.0
github.com/rs/zerolog v1.34.0
github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.20.1
Expand Down Expand Up @@ -37,7 +38,6 @@ require (
github.com/opslevel/moredefaults v0.0.0-20240529152742-17d1318a3c12 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/relvacode/iso8601 v1.6.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand All @@ -55,4 +55,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

// replace github.com/opslevel/opslevel-go/v2025 => ./submodules/opslevel-go
replace github.com/opslevel/opslevel-go/v2025 => ./submodules/opslevel-go
2 changes: 1 addition & 1 deletion src/submodules/opslevel-go
Submodule opslevel-go updated 47 files
+0 −3 .changes/unreleased/Dependency-20250217-114928.yaml
+0 −3 .changes/unreleased/Dependency-20250324-124723.yaml
+0 −3 .changes/unreleased/Dependency-20250331-113252.yaml
+0 −3 .changes/unreleased/Dependency-20250414-191151.yaml
+0 −3 .changes/unreleased/Dependency-20250522-134249.yaml
+0 −3 .changes/unreleased/Docs-20250514-143029.yaml
+0 −3 .changes/unreleased/Feature-20250327-125544.yaml
+0 −3 .changes/unreleased/Feature-20250502-085309.yaml
+0 −3 .changes/unreleased/Feature-20250514-144247.yaml
+0 −3 .changes/unreleased/Feature-20250514-145109.yaml
+0 −3 .changes/unreleased/Feature-20250514-150622.yaml
+0 −3 .changes/unreleased/Feature-20250515-145437.yaml
+0 −3 .changes/unreleased/Feature-20250522-103636.yaml
+0 −3 .changes/unreleased/Feature-20250522-105617.yaml
+0 −3 .changes/unreleased/Feature-20250528-073538.yaml
+3 −0 .changes/unreleased/Feature-20250606-102556.yaml
+3 −0 .changes/unreleased/Removed-20250606-151154.yaml
+20 −0 .changes/v2025.5.28.md
+7 −6 .github/workflows/tests.yml
+21 −0 CHANGELOG.md
+2 −2 actions_test.go
+2 −2 cache_test.go
+5 −0 check.go
+5 −5 check_test.go
+1 −1 clientGQL_test.go
+12 −0 connection.go
+3 −3 document_test.go
+4 −0 go.mod
+1 −0 go.sum
+8 −8 level_test.go
+2 −2 maturity_test.go
+43 −7 object.go
+18 −0 relationship.go
+30 −0 relationship_test.go
+53 −0 scalar.go
+134 −0 scalar_test.go
+21 −0 service.go
+271 −27 service_test.go
+2 −2 system_test.go
+14 −14 team_test.go
+1 −1 testdata/templates/custom_actions.tpl
+4 −0 testdata/templates/levels.tpl
+3 −1 testdata/templates/query/service/get.tpl
+3 −2 testdata/templates/query/team/get.tpl
+4 −4 testdata/templates/scorecards.tpl
+8 −8 user_test.go
+1 −1 version.go
Loading