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
13 changes: 5 additions & 8 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
GO_VERSION: 1.24.1

defaults:
run:
shell: bash
Expand All @@ -35,11 +32,11 @@ jobs:
uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
go-version-file: go.mod
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: v2.2.2
version: v2.12.2
args: --timeout=5m

test:
Expand All @@ -50,7 +47,7 @@ jobs:
uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
go-version-file: go.mod
- name: Run tests
run: go test -v -race -coverprofile=coverage.txt -covermode=atomic ./...
- name: Upload coverage
Expand All @@ -67,15 +64,15 @@ jobs:
os:
- ubuntu-latest #x64
- ubuntu-24.04-arm #arm64
- macos-13 #x64
- macos-15-intel #x64
- macos-latest #arm64
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
go-version-file: go.mod
- name: Build
run: make build
- name: Verify module
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LD_FLAGS = -s -w \
COMMON_BUILD_ARGS = -ldflags "$(LD_FLAGS)"

GOLANGCI_LINT = $(shell pwd)/_output/tools/bin/golangci-lint
GOLANGCI_LINT_VERSION ?= v2.2.2
GOLANGCI_LINT_VERSION ?= v2.12.2

# NPM version should not append the -dirty flag
NPM_VERSION ?= $(shell echo $(shell git describe --tags --always) | sed 's/^v//')
Expand Down
1 change: 1 addition & 0 deletions cmd/flashduty-mcp-server/main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package main starts the FlashDuty MCP server command.
package main

import (
Expand Down
11 changes: 4 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,37 +1,34 @@
module github.com/futuretea/flashduty-mcp-server

go 1.24.1
go 1.25.5

require (
github.com/futuretea/go-http-client v0.0.2
github.com/mark3labs/mcp-go v0.41.1
github.com/mark3labs/mcp-go v0.54.0
github.com/rs/zerolog v1.33.0
github.com/spf13/cobra v1.10.1
github.com/spf13/viper v1.18.0
)

require (
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/google/jsonschema-go v0.4.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/invopop/jsonschema v0.13.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.9 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
Expand Down
37 changes: 16 additions & 21 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
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/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/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/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/futuretea/go-http-client v0.0.2 h1:MtdYSwj5RzeXoRR+TJbdPfOWwYafrxbKl6FT8T7Vaxw=
github.com/futuretea/go-http-client v0.0.2/go.mod h1:QFXWNOvw6xEl1ztfTYSaJDqUCArH9cABQ0CziFmMOqM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
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/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8=
github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
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/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
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.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mark3labs/mcp-go v0.41.1 h1:w78eWfiQam2i8ICL7AL0WFiq7KHNJQ6UB53ZVtH4KGA=
github.com/mark3labs/mcp-go v0.41.1/go.mod h1:T7tUa2jO6MavG+3P25Oy/jR7iCeJPHImCZHRymCn39g=
github.com/mark3labs/mcp-go v0.54.0 h1:PZhQvd+5xrT43cUoiaKn/hDcvLUhcLc1twSEKYPTcTA=
github.com/mark3labs/mcp-go v0.54.0/go.mod h1:+8WclSK1ZUweCP3hvktSji8n8ABG/95QaEkeVE/Uwas=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
Expand All @@ -49,8 +44,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
Expand All @@ -59,6 +54,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
Expand All @@ -78,12 +75,10 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
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/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.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
Expand All @@ -100,8 +95,8 @@ golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
18 changes: 12 additions & 6 deletions internal/cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package cmd contains the FlashDuty MCP server CLI commands.
package cmd

import (
Expand Down Expand Up @@ -60,11 +61,11 @@ network access. Manage incidents, alerts, channels, teams, members, and
on-call schedules through the FlashDuty API.`,
SilenceUsage: true,
SilenceErrors: true,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
bindFlags(cmd)
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
RunE: func(_ *cobra.Command, _ []string) error {
return runServer(cfgFile, streams)
},
}
Expand Down Expand Up @@ -130,8 +131,12 @@ func runServer(cfgFile string, streams IOStreams) error {
// Start server based on port configuration
if cfg.Port == 0 {
// Stdio mode - use fmt.Fprintf for startup messages as logging is disabled
fmt.Fprintf(streams.ErrOut, "Starting FlashDuty MCP Server in stdio mode\n")
fmt.Fprintf(streams.ErrOut, "Enabled tools: %v\n", server.GetEnabledTools())
if _, err := fmt.Fprintf(streams.ErrOut, "Starting FlashDuty MCP Server in stdio mode\n"); err != nil {
return fmt.Errorf("failed to write startup message: %w", err)
}
if _, err := fmt.Fprintf(streams.ErrOut, "Enabled tools: %v\n", server.GetEnabledTools()); err != nil {
return fmt.Errorf("failed to write enabled tools: %w", err)
}
return server.ServeStdio()
}

Expand All @@ -151,8 +156,9 @@ func newVersionCommand(streams IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "version",
Short: "Print version information",
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(streams.Out, "%s\n", version.GetVersionInfo())
RunE: func(_ *cobra.Command, _ []string) error {
_, err := fmt.Fprintf(streams.Out, "%s\n", version.GetVersionInfo())
return err
},
}

Expand Down
1 change: 1 addition & 0 deletions pkg/core/config/config.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package config loads and validates FlashDuty MCP server configuration.
package config

import (
Expand Down
1 change: 1 addition & 0 deletions pkg/core/logging/logging.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package logging wraps the process-wide structured logger.
package logging

import (
Expand Down
1 change: 1 addition & 0 deletions pkg/core/version/version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package version exposes build-time version metadata.
package version

import (
Expand Down
12 changes: 7 additions & 5 deletions pkg/server/http/http.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package http serves the FlashDuty MCP server over HTTP, SSE, and health endpoints.
package http

import (
Expand All @@ -21,6 +22,7 @@ const (
sseMessageEndpoint = "/message"
)

// Serve starts the HTTP, SSE, and streamable HTTP endpoints.
func Serve(ctx context.Context, mcpServer *mcp.Server, staticConfig *config.StaticConfig) error {
mux := http.NewServeMux()

Expand All @@ -32,17 +34,17 @@ func Serve(ctx context.Context, mcpServer *mcp.Server, staticConfig *config.Stat
}

sseServer := mcpServer.ServeSse(staticConfig.SSEBaseURL, httpServer)
streamableHttpServer := mcpServer.ServeHTTP(httpServer)
streamableHTTPServer := mcpServer.ServeHTTP(httpServer)
mux.Handle(sseEndpoint, sseServer)
mux.Handle(sseMessageEndpoint, sseServer)
mux.Handle(mcpEndpoint, streamableHttpServer)
mux.HandleFunc(healthEndpoint, func(w http.ResponseWriter, r *http.Request) {
mux.Handle(mcpEndpoint, streamableHTTPServer)
mux.HandleFunc(healthEndpoint, func(w http.ResponseWriter, _ *http.Request) {
if mcpServer.IsHealthy() {
w.WriteHeader(http.StatusOK)
w.Write([]byte("healthy"))
_, _ = w.Write([]byte("healthy"))
} else {
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte("unhealthy: FlashDuty client initialization failed"))
_, _ = w.Write([]byte("unhealthy: FlashDuty client initialization failed"))
}
})

Expand Down
2 changes: 2 additions & 0 deletions pkg/server/http/middleware.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package http serves the FlashDuty MCP server over HTTP, SSE, and health endpoints.
package http

import (
Expand All @@ -9,6 +10,7 @@ import (
"github.com/futuretea/flashduty-mcp-server/pkg/core/logging"
)

// RequestMiddleware logs non-health HTTP requests and response statuses.
func RequestMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == healthEndpoint {
Expand Down
3 changes: 2 additions & 1 deletion pkg/server/mcp/mcp.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package mcp configures the FlashDuty MCP server and its tools.
package mcp

import (
Expand Down Expand Up @@ -95,7 +96,7 @@ func (s *Server) shouldEnableTool(toolName string) bool {
func (s *Server) registerTool(tool toolset.ServerTool) error {
client := s.client

toolHandler := server.ToolHandlerFunc(func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
toolHandler := server.ToolHandlerFunc(func(_ context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
logging.Debug("Tool %s called with params: %v", tool.Tool.Name, request.Params.Arguments)

params, _ := request.Params.Arguments.(map[string]any)
Expand Down
5 changes: 3 additions & 2 deletions pkg/toolset/flashduty/aggregation.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package flashduty implements FlashDuty MCP tools and API helpers.
package flashduty

import (
Expand Down Expand Up @@ -245,10 +246,10 @@ func fetchIncidentPage(c *Client, body map[string]any) ([]map[string]any, string
}

// appendIncidentItems appends items to the collection, respecting the max limit.
func appendIncidentItems(all []map[string]any, items []map[string]any, max int) []map[string]any {
func appendIncidentItems(all []map[string]any, items []map[string]any, maxItems int) []map[string]any {
for _, item := range items {
all = append(all, item)
if len(all) >= max {
if len(all) >= maxItems {
break
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/toolset/flashduty/aggregation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func TestBuildCompositeKey_EmptyValues(t *testing.T) {
// single-page response (has_next_page=false) in the standard FlashDuty API envelope.
func newMockServer(t *testing.T, incidents []map[string]any) *httptest.Server {
t.Helper()
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
data := map[string]any{
"items": incidents,
"has_next_page": false,
Expand Down
4 changes: 2 additions & 2 deletions pkg/toolset/flashduty/enrichment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func TestEnrichResponders(t *testing.T) {
}
}

func TestEnrichResponders_NoResponders(t *testing.T) {
func TestEnrichResponders_NoResponders(_ *testing.T) {
obj := map[string]any{}
names := map[int]string{1: "Alice"}
// Should not panic
Expand Down Expand Up @@ -216,7 +216,7 @@ func TestEnrichAssignedTo(t *testing.T) {
}
}

func TestEnrichAssignedTo_NoAssignedTo(t *testing.T) {
func TestEnrichAssignedTo_NoAssignedTo(_ *testing.T) {
obj := map[string]any{}
names := map[int]string{1: "Alice"}
// Should not panic
Expand Down
2 changes: 1 addition & 1 deletion pkg/toolset/flashduty/timeformat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func TestAddTimestampDisplayToList_MultipleItems(t *testing.T) {
}
}

func TestAddTimestampDisplayToList_EmptyList(t *testing.T) {
func TestAddTimestampDisplayToList_EmptyList(_ *testing.T) {
// Should not panic.
AddTimestampDisplayToList([]interface{}{}, time.UTC)
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/toolset/flashduty/toolset.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package flashduty implements FlashDuty MCP tools and API helpers.
package flashduty

import (
Expand All @@ -17,10 +18,12 @@ var (
itemsString = map[string]any{"type": "string"}
)

// GetName returns the FlashDuty toolset name.
func (t *Toolset) GetName() string {
return "flashduty"
}

// GetDescription returns a human-readable FlashDuty toolset description.
func (t *Toolset) GetDescription() string {
return "FlashDuty incident management and alert tools"
}
Expand Down
Loading
Loading