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
24 changes: 24 additions & 0 deletions .bumpver.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[bumpver]
current_version = "0.1.1"
version_pattern = "MAJOR.MINOR.PATCH"
commit_message = "bump: version {old_version} → {new_version}"
tag_message = "v{new_version}"
tag_scope = "default"

[bumpver.file_patterns]
# pyproject.toml
"pyproject.toml" = [
'version = "{version}"'
]
# Python package __init__
"stackhawk_mcp/__init__.py" = [
'__version__ = "{version}"'
]
# README version badge or text
"README.md" = [
'**Current Version: {version}**'
]
# DXT file version
"stackhawk-mcp.dxt" = [
'"version": "{version}"'
]
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @stackhawk/engineering
37 changes: 37 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## StackHawk Pull Request

> Description here

<!-- share a quality (SFW) gif or photo, or before-and-after views -->
![replace me](giphy-url.gif)

### Type of change

- [x] Code
- [ ] Documentation
- [ ] Release
- [ ] Other _(please explain)_

### Related Issues

<!-- automation will associate the issue with this PR when the issue slug is included in the branch name or request title -->
> [NGNRNG-XXX](https://stackhawk.atlassian.net/browse/NGNRNG-XXX)

### Code

- [ ] This PR has a descriptive title, attached issue id, and information useful to a reviewer
- [ ] The "Ready for Review" label attached to the PR, and reviewers have been informed
- [ ] All lint rules and tests related to the changed code pass locally

Did you add or update tests to cover this change?
- [ ] Yes
- [ ] No: _(please explain)_

### Documentation

- [ ] Documentation has been updated, with attention to spelling, grammar and clarity

### Release

- [ ] This software deployment has been communicated to the team
- [ ] Relevant changes are reflected in the product changelog
46 changes: 45 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,48 @@ jobs:
pip install .
- name: Run tests
run: |
pytest --maxfail=1 --disable-warnings
pytest --maxfail=1 --disable-warnings

tag-version:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get version from pyproject.toml
id: get_version
run: |
VERSION=$(grep '^version = ' pyproject.toml | head -1 | cut -d '"' -f2)
echo "::set-output name=version::$VERSION"
- name: Create and push tag for current version
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag v${{ steps.get_version.outputs.version }}
git push origin v${{ steps.get_version.outputs.version }}

bump-version:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [test, tag-version]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install bumpver
run: |
python -m pip install --upgrade pip
pip install bumpver
- name: Bump patch version with bumpver
run: bumpver update --patch --no-tag --commit
- name: Push version bump commit
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git push
25 changes: 24 additions & 1 deletion .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,37 @@ jobs:
environment: pypi
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build
pip install build bumpver
- name: Bump minor version with bumpver
if: github.ref == 'refs/heads/main'
run: bumpver update --minor --commit
- name: Get version from pyproject.toml
id: get_version
run: |
VERSION=$(grep '^version = ' pyproject.toml | head -1 | cut -d '"' -f2)
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Create and push tag for new version
if: github.ref == 'refs/heads/main'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag v${{ steps.get_version.outputs.version }}
git push origin v${{ steps.get_version.outputs.version }}
- name: Push version bump commit
if: github.ref == 'refs/heads/main'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git push
- name: Build package
run: |
python -m build
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# StackHawk MCP Server

**Current Version: 0.1.0**
**Current Version: 0.1.1**
_Requires Python 3.10 or higher_

A Model Context Protocol (MCP) server for integrating with StackHawk's security scanning platform. Provides security analytics, YAML configuration management, sensitive data/threat surface analysis, and anti-hallucination tools for LLMs.
Expand Down Expand Up @@ -39,7 +39,12 @@ A Model Context Protocol (MCP) server for integrating with StackHawk's security
pip install stackhawk-mcp
# Requires Python 3.10 or higher
```
2. **Set your StackHawk API key:**
2. **Install locally from the repo:**
```bash
pip install --user .
# Run this command from the root of the cloned repository
```
3. **Set your StackHawk API key:**
```bash
export STACKHAWK_API_KEY="your-api-key-here"
```
Expand Down
11 changes: 7 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"

[project]
name = "stackhawk-mcp"
version = "0.1.0"
version = "0.1.1"
description = "StackHawk MCP Server for Security Analytics and Developer Integration"
authors = [{name = "StackHawk, Inc.", email = "support@stackhawk.com"}]
license = {text = "Apache-2.0"}
license = "Apache-2.0"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
Expand All @@ -27,7 +27,7 @@ dev = [
]

[project.scripts]
stackhawk-mcp = "stackhawk_mcp.server:main"
stackhawk-mcp = "stackhawk_mcp.__main__:cli"

[project.urls]
Homepage = "https://github.com/stackhawk/stackhawk-mcp"
Expand All @@ -45,4 +45,7 @@ disallow_untyped_defs = true

[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
testpaths = ["tests"]

[tool.setuptools.packages.find]
include = ["stackhawk_mcp*"]
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pytest>=7.0.0
pytest-asyncio>=0.21.0
black>=23.0.0
mypy>=1.0.0
bumpver>=2023.1129

# FastAPI dependencies
fastapi
Expand Down
2 changes: 1 addition & 1 deletion stackhawk-mcp.dxt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "stackhawk-mcp",
"description": "StackHawk MCP Server for security testing, analytics, YAML validation, and vulnerability management.",
"version": "1.0.0",
"version": "0.1.1",
"author": "StackHawk",
"license": "MIT",
"homepage": "https://github.com/stackhawk/stackhawk-mcp",
Expand Down
2 changes: 1 addition & 1 deletion stackhawk_mcp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
with the StackHawk API through the Model Context Protocol (MCP).
"""

__version__ = "0.1.0"
__version__ = "0.1.1"
__author__ = "StackHawk MCP Team"
__email__ = "support@stackhawk.com"
8 changes: 8 additions & 0 deletions stackhawk_mcp/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import asyncio
from .server import main

def cli():
asyncio.run(main())

if __name__ == "__main__":
cli()
10 changes: 6 additions & 4 deletions stackhawk_mcp/http_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import uvicorn
import asyncio
from stackhawk_mcp.server import StackHawkMCPServer
from stackhawk_mcp import __version__

app = FastAPI()

Expand All @@ -21,9 +22,10 @@

# Get API key from environment
API_KEY = os.environ.get("STACKHAWK_API_KEY", "changeme")
BASE_URL = os.environ.get("STACKHAWK_BASE_URL", "https://api.stackhawk.com")

# Create the MCP server instance
mcp_server = StackHawkMCPServer(api_key=API_KEY)
mcp_server = StackHawkMCPServer(api_key=API_KEY, base_url=BASE_URL)

# Store active SSE connections
active_connections = {}
Expand Down Expand Up @@ -70,7 +72,7 @@ async def handle_initialize_request(request_data):
},
"serverInfo": {
"name": "StackHawk MCP",
"version": "0.1.0"
"version": __version__
}
}
)
Expand Down Expand Up @@ -236,7 +238,7 @@ async def root():
"id": 1,
"result": {
"serverName": "StackHawk MCP",
"serverVersion": "0.1.0",
"serverVersion": __version__,
"protocolVersion": "v1"
}
})
Expand All @@ -248,7 +250,7 @@ async def root_post():
"id": 1,
"result": {
"serverName": "StackHawk MCP",
"serverVersion": "0.1.0",
"serverVersion": __version__,
"protocolVersion": "v1"
}
})
Expand Down
11 changes: 7 additions & 4 deletions stackhawk_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
)
import mcp.server.stdio
import mcp.types as types
from stackhawk_mcp import __version__

# Configure logging to stderr so Claude Desktop can see it
logging.basicConfig(
Expand All @@ -44,7 +45,7 @@
)
logger = logging.getLogger("stackhawk-mcp")

STACKHAWK_MCP_VERSION = "0.1.0"
STACKHAWK_MCP_VERSION = __version__


def debug_print(message):
Expand Down Expand Up @@ -597,9 +598,9 @@ async def _get_application_vulnerabilities(self, app_id: str = None, severity_fi
class StackHawkMCPServer:
"""StackHawk MCP Server implementation"""

def __init__(self, api_key: str):
def __init__(self, api_key: str, base_url: str = "https://api.stackhawk.com"):
debug_print("Initializing StackHawkMCPServer...")
self.client = StackHawkClient(api_key)
self.client = StackHawkClient(api_key, base_url)
self.server = Server("stackhawk-mcp")
self._schema_cache: Optional[Dict[str, Any]] = None
self._schema_cache_time: Optional[datetime] = None
Expand Down Expand Up @@ -2380,16 +2381,18 @@ async def main():
import os

api_key = os.environ.get("STACKHAWK_API_KEY")
base_url = os.environ.get("STACKHAWK_BASE_URL", "https://api.stackhawk.com")
if not api_key:
debug_print("ERROR: STACKHAWK_API_KEY environment variable is required")
sys.exit(1)

debug_print(f"API key found: {api_key[:20]}...")
debug_print(f"Base URL: {base_url}")

server = None
try:
debug_print("Creating StackHawkMCPServer...")
server = StackHawkMCPServer(api_key)
server = StackHawkMCPServer(api_key, base_url)
debug_print("Running server...")
await server.run()
except KeyboardInterrupt:
Expand Down