Skip to content

Commit 202967b

Browse files
Tom Wentworthclaude
authored andcommitted
Fix authentication issues and prepare for deployment
- Remove hardcoded API keys from scripts - Fix environment variable handling in shell scripts - Redirect error messages to stderr to avoid breaking MCP protocol - Update CLAUDE.md with correct environment variable names - Add DEPLOYMENT.md with deployment instructions - Move test files to tests/ directory - Add CODE_OF_CONDUCT.md - Remove unused example.go file The MCP server now properly handles missing API keys without breaking the JSON protocol, and all authentication is done through environment variables. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 1f001be commit 202967b

21 files changed

+176
-85
lines changed

.claude/settings.local.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,16 @@
4141
"Bash(./start-mcp-server.sh:*)",
4242
"Bash(git push:*)",
4343
"Bash(./test_api.sh:*)",
44-
"Bash(git add:*)"
44+
"Bash(git add:*)",
45+
"Bash(cp:*)",
46+
"Bash(brew install:*)",
47+
"Bash(bfg:*)",
48+
"Bash(git gc:*)",
49+
"Bash(mkdir:*)",
50+
"Bash(golangci-lint run:*)",
51+
"Bash(golangci-lint:*)",
52+
"Bash(pkill:*)",
53+
"Bash(/Users/tomwentworth/incidentio-mcp-golang/test_auth.sh)"
4554
],
4655
"deny": []
4756
},

.golangci.yml

Lines changed: 0 additions & 25 deletions
This file was deleted.

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@
2727
- `/internal/server/` - MCP server logic
2828

2929
# Environment Variables
30-
- INCIDENTIO_API_KEY - Required for API authentication
31-
- INCIDENTIO_ENDPOINT - Optional, defaults to https://api.incident.io
30+
- INCIDENT_IO_API_KEY - Required for API authentication
31+
- INCIDENT_IO_BASE_URL - Optional, defaults to https://api.incident.io/v2

CODE_OF_CONDUCT.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Code of Conduct
2+
3+
## Our Pledge
4+
5+
We as members, contributors, and leaders pledge to make participation in our
6+
community a harassment-free experience for everyone, regardless of age, body
7+
size, visible or invisible disability, ethnicity, sex characteristics, gender
8+
identity and expression, level of experience, education, socio-economic status,
9+
nationality, personal appearance, race, caste, color, religion, or sexual
10+
identity and orientation.
11+
12+
## Our Standards
13+
14+
Examples of behavior that contributes to a positive environment:
15+
16+
* Using welcoming and inclusive language
17+
* Being respectful of differing viewpoints and experiences
18+
* Gracefully accepting constructive criticism
19+
* Focusing on what is best for the community
20+
* Showing empathy towards other community members
21+
22+
Examples of unacceptable behavior:
23+
24+
* The use of sexualized language or imagery, and sexual attention or advances
25+
* Trolling, insulting or derogatory comments, and personal or political attacks
26+
* Public or private harassment
27+
* Publishing others' private information without explicit permission
28+
* Other conduct which could reasonably be considered inappropriate
29+
30+
## Enforcement Responsibilities
31+
32+
Community leaders are responsible for clarifying and enforcing our standards of
33+
acceptable behavior and will take appropriate and fair corrective action in
34+
response to any behavior that they deem inappropriate, threatening, offensive,
35+
or harmful.
36+
37+
## Scope
38+
39+
This Code of Conduct applies within all community spaces, and also applies when
40+
an individual is officially representing the community in public spaces.
41+
42+
## Enforcement
43+
44+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
45+
reported to the community leaders responsible for enforcement at the project
46+
maintainer's email address. All complaints will be reviewed and investigated
47+
promptly and fairly.
48+
49+
## Attribution
50+
51+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
52+
version 2.1, available at
53+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
54+
55+
[homepage]: https://www.contributor-covenant.org
56+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html

DEPLOYMENT.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Deployment Guide
2+
3+
## Prerequisites
4+
5+
1. Go 1.21 or higher installed
6+
2. Valid incident.io API key from https://app.incident.io/settings/api-keys
7+
3. Claude Desktop installed
8+
9+
## Quick Start
10+
11+
### 1. Clone and Build
12+
13+
```bash
14+
git clone https://github.com/tomwentworth/incidentio-mcp-golang.git
15+
cd incidentio-mcp-golang
16+
go build -o bin/mcp-server ./cmd/mcp-server
17+
```
18+
19+
### 2. Configure Claude Desktop
20+
21+
Add to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
22+
23+
```json
24+
{
25+
"mcpServers": {
26+
"incidentio-golang": {
27+
"command": "/path/to/incidentio-mcp-golang/start-mcp-server.sh",
28+
"env": {
29+
"INCIDENT_IO_API_KEY": "your_api_key_here"
30+
}
31+
}
32+
}
33+
}
34+
```
35+
36+
### 3. Restart Claude Desktop
37+
38+
The MCP server will now be available in Claude with access to incident.io tools.
39+
40+
## Environment Variables
41+
42+
- `INCIDENT_IO_API_KEY` (required) - Your incident.io API key
43+
- `INCIDENT_IO_BASE_URL` (optional) - Custom API endpoint (defaults to https://api.incident.io/v2)
44+
45+
## Available Tools
46+
47+
Once deployed, Claude will have access to:
48+
49+
- `list_incidents` - List and filter incidents
50+
- `get_incident` - Get incident details
51+
- `create_incident` - Create new incidents
52+
- `update_incident` - Update incident properties
53+
- `close_incident` - Close an incident
54+
- `list_alerts` - List alerts
55+
- `list_severities` - List severity levels
56+
- `list_incident_statuses` - List incident statuses
57+
- `assign_incident_role` - Assign roles to users
58+
- And more...
59+
60+
## Troubleshooting
61+
62+
1. **Server disconnects immediately**
63+
- Check that your API key is valid
64+
- Ensure the binary has execute permissions: `chmod +x bin/mcp-server`
65+
66+
2. **No tools available**
67+
- Verify the INCIDENT_IO_API_KEY environment variable is set
68+
- Check Claude Desktop logs for errors
69+
70+
3. **Authentication errors**
71+
- Generate a new API key from incident.io settings
72+
- Update the key in your Claude Desktop configuration
73+
74+
## Security Notes
75+
76+
- Never commit your API key to version control
77+
- The `.env` file is gitignored for local development
78+
- API keys should be stored securely in production environments

check-env.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ echo "INCIDENT_IO_API_KEY: ${INCIDENT_IO_API_KEY:+SET}" >&2
99
echo "Go version:" >&2
1010
go version >&2
1111
echo "Starting MCP server..." >&2
12-
exec /Users/tomwentworth/incidentio-mcp-golang/bin/mcp-debug 2>>/tmp/mcp-debug.log
12+
exec "$(dirname "$0")/bin/mcp-debug" 2>>/tmp/mcp-debug.log

cmd/mcp-server/main.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"fmt"
77
"io"
8+
"log"
89
"os"
910
"os/signal"
1011
"syscall"
@@ -41,9 +42,8 @@ func (s *MCPServer) registerTools() {
4142
// Try to initialize incident.io client
4243
client, err := incidentio.NewClient()
4344
if err != nil {
44-
// If client initialization fails, register only example tool
45-
exampleTool := &tools.ExampleTool{}
46-
s.tools[exampleTool.Name()] = exampleTool
45+
// If client initialization fails, no tools are registered
46+
// Don't log to avoid breaking MCP protocol
4747
return
4848
}
4949

@@ -101,7 +101,9 @@ func (s *MCPServer) start(ctx context.Context) {
101101
Message: "Parse error",
102102
},
103103
}
104-
encoder.Encode(errorResp)
104+
if err := encoder.Encode(errorResp); err != nil {
105+
log.Printf("Failed to encode parse error response: %v", err)
106+
}
105107
}
106108
continue
107109
}
@@ -117,7 +119,9 @@ func (s *MCPServer) start(ctx context.Context) {
117119
Message: "Invalid Request: missing or invalid jsonrpc field",
118120
},
119121
}
120-
encoder.Encode(errorResp)
122+
if err := encoder.Encode(errorResp); err != nil {
123+
log.Printf("Failed to encode invalid request response: %v", err)
124+
}
121125
}
122126
continue
123127
}
@@ -133,7 +137,9 @@ func (s *MCPServer) start(ctx context.Context) {
133137

134138
response := s.handleMessage(&msg)
135139
if response != nil {
136-
encoder.Encode(response)
140+
if err := encoder.Encode(response); err != nil {
141+
log.Printf("Failed to encode response: %v", err)
142+
}
137143
}
138144
}
139145
}

internal/incidentio/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func (c *Client) doRequest(method, path string, params url.Values, body interfac
9292
if err != nil {
9393
return nil, fmt.Errorf("request failed: %w", err)
9494
}
95-
defer resp.Body.Close()
95+
defer func() { _ = resp.Body.Close() }()
9696

9797
respBody, err := io.ReadAll(resp.Body)
9898
if err != nil {

internal/server/server.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,20 @@ func (s *Server) Start(ctx context.Context) error {
4747
}
4848

4949
if response != nil {
50-
encoder.Encode(response)
50+
if err := encoder.Encode(response); err != nil {
51+
// Log encoding errors but continue processing
52+
fmt.Fprintf(os.Stderr, "Failed to encode response: %v\n", err)
53+
}
5154
}
5255
}
5356
}
5457
}
5558

5659
func (s *Server) registerTools() {
57-
// Always register example tool
58-
exampleTool := &tools.ExampleTool{}
59-
s.tools[exampleTool.Name()] = exampleTool
60-
6160
// Initialize incident.io client
6261
client, err := incidentio.NewClient()
6362
if err != nil {
64-
// If client initialization fails, we still have the example tool
63+
// If client initialization fails, no tools are registered
6564
return
6665
}
6766

internal/tools/example.go

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)