mcpmon 0.1.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,9 @@
1
1
  name: Release
2
2
 
3
3
  on:
4
+ push:
5
+ tags:
6
+ - 'v*'
4
7
  workflow_dispatch:
5
8
  inputs:
6
9
  bump:
@@ -14,26 +17,20 @@ on:
14
17
  - major
15
18
 
16
19
  jobs:
17
- release:
20
+ # Only runs on workflow_dispatch - bumps version and creates tag
21
+ bump:
22
+ if: github.event_name == 'workflow_dispatch'
18
23
  runs-on: ubuntu-latest
19
24
  permissions:
20
25
  contents: write
21
- id-token: write
22
- outputs:
23
- version: ${{ steps.bump.outputs.version }}
24
26
  steps:
25
27
  - uses: actions/checkout@v4
26
28
  with:
27
29
  fetch-depth: 0
28
30
 
29
- - uses: actions/setup-python@v5
30
- with:
31
- python-version: "3.12"
32
-
33
31
  - uses: actions/setup-node@v4
34
32
  with:
35
33
  node-version: '20'
36
- # NOTE: No registry-url - npm OIDC trusted publishers require no auth token present
37
34
 
38
35
  - name: Get current version
39
36
  id: current
@@ -56,6 +53,7 @@ jobs:
56
53
  NEW_VERSION="$major.$minor.$patch"
57
54
  echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
58
55
  sed -i "s/version = \"$CURRENT_VERSION\"/version = \"$NEW_VERSION\"/" pyproject.toml
56
+ sed -i "s/__version__ = \"$CURRENT_VERSION\"/__version__ = \"$NEW_VERSION\"/" mcpmon/__init__.py || true
59
57
  npm version "$NEW_VERSION" --no-git-tag-version
60
58
 
61
59
  - name: Commit and tag
@@ -64,16 +62,40 @@ jobs:
64
62
  run: |
65
63
  git config user.name "github-actions[bot]"
66
64
  git config user.email "github-actions[bot]@users.noreply.github.com"
67
- git add pyproject.toml package.json
65
+ git add pyproject.toml package.json mcpmon/__init__.py
68
66
  git commit -m "(release): v$NEW_VERSION"
69
67
  git tag "v$NEW_VERSION"
70
68
  git push && git push --tags
71
69
 
70
+ # Runs on tag push - publishes to PyPI and npm
71
+ publish:
72
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
73
+ runs-on: ubuntu-latest
74
+ permissions:
75
+ contents: write
76
+ id-token: write
77
+ outputs:
78
+ version: ${{ steps.version.outputs.version }}
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+
82
+ - name: Extract version from tag
83
+ id: version
84
+ run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
85
+
86
+ - uses: actions/setup-python@v5
87
+ with:
88
+ python-version: "3.12"
89
+
90
+ - uses: actions/setup-node@v4
91
+ with:
92
+ node-version: '20'
93
+
72
94
  - name: Create release
73
95
  env:
74
96
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
75
- NEW_VERSION: ${{ steps.bump.outputs.version }}
76
- run: gh release create "v$NEW_VERSION" --generate-notes
97
+ VERSION: ${{ steps.version.outputs.version }}
98
+ run: gh release create "v$VERSION" --generate-notes || true
77
99
 
78
100
  # Publish to PyPI
79
101
  - name: Install build
@@ -93,7 +115,7 @@ jobs:
93
115
  run: npm publish --provenance --access public
94
116
 
95
117
  build-binaries:
96
- needs: release
118
+ needs: publish
97
119
  runs-on: ${{ matrix.os }}
98
120
  permissions:
99
121
  contents: write
@@ -104,12 +126,10 @@ jobs:
104
126
  target: linux-x64
105
127
  - os: macos-latest
106
128
  target: darwin-arm64
107
- - os: macos-13
129
+ - os: macos-15-intel
108
130
  target: darwin-x64
109
131
  steps:
110
132
  - uses: actions/checkout@v4
111
- with:
112
- ref: v${{ needs.release.outputs.version }}
113
133
 
114
134
  - uses: oven-sh/setup-bun@v2
115
135
  with:
@@ -123,6 +143,6 @@ jobs:
123
143
  - name: Upload to release
124
144
  env:
125
145
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
126
- VERSION: ${{ needs.release.outputs.version }}
146
+ VERSION: ${{ needs.publish.outputs.version }}
127
147
  TARGET: ${{ matrix.target }}
128
148
  run: gh release upload "v$VERSION" "mcpmon-$TARGET" --clobber
package/.nojekyll ADDED
File without changes
@@ -0,0 +1,44 @@
1
+ # ============================================================================
2
+ # .pre-commit-config.yaml
3
+ # Install: pip install pre-commit && pre-commit install
4
+ # Run manually: pre-commit run --all-files
5
+ # ============================================================================
6
+
7
+ repos:
8
+ # -------------------------------------------------------------------------
9
+ # SECRET DETECTION
10
+ # -------------------------------------------------------------------------
11
+
12
+ - repo: https://github.com/gitleaks/gitleaks
13
+ rev: v8.18.1
14
+ hooks:
15
+ - id: gitleaks
16
+ name: Detect secrets with gitleaks
17
+
18
+ # -------------------------------------------------------------------------
19
+ # GENERAL
20
+ # -------------------------------------------------------------------------
21
+
22
+ - repo: https://github.com/pre-commit/pre-commit-hooks
23
+ rev: v4.5.0
24
+ hooks:
25
+ - id: trailing-whitespace
26
+ - id: end-of-file-fixer
27
+ - id: check-yaml
28
+ - id: check-json
29
+ - id: check-toml
30
+ - id: check-added-large-files
31
+ args: ['--maxkb=500']
32
+ - id: detect-private-key
33
+ - id: detect-aws-credentials
34
+
35
+ # -------------------------------------------------------------------------
36
+ # PYTHON
37
+ # -------------------------------------------------------------------------
38
+
39
+ - repo: https://github.com/astral-sh/ruff-pre-commit
40
+ rev: v0.3.0
41
+ hooks:
42
+ - id: ruff
43
+ args: [--fix]
44
+ - id: ruff-format
package/README.md CHANGED
@@ -2,51 +2,115 @@
2
2
 
3
3
  Hot reload for MCP servers. Like nodemon, but for MCP.
4
4
 
5
+ ## Features
6
+
7
+ - **Hot reload** - Restart server on file changes
8
+ - **Tool refresh** - Sends `notifications/tools/list_changed` so Claude Code sees new tools without session restart
9
+ - **Gateway mode** - Aggregate multiple MCP servers behind one gateway
10
+ - **Dual implementation** - Python and Bun/TypeScript with full feature parity
11
+
5
12
  ## Install
6
13
 
7
14
  ```bash
8
- # Bun (recommended)
9
- bunx mcpmon
15
+ # Python
16
+ pip install mcpmon
10
17
 
11
- # Or install globally
12
- bun install -g mcpmon
18
+ # Bun (no install needed)
19
+ bunx mcpmon
13
20
 
14
- # Python alternative
15
- pip install mcpmon
21
+ # npm
22
+ npm install -g mcpmon
16
23
 
17
24
  # Or download binary from GitHub releases (no dependencies)
18
25
  ```
19
26
 
20
27
  ## Usage
21
28
 
29
+ ### Single Server Mode
30
+
22
31
  ```bash
23
32
  mcpmon --watch src/ -- python -m my_mcp_server
24
33
  ```
25
34
 
26
- ### Options
35
+ ### Gateway Mode (Multi-Server)
36
+
37
+ ```bash
38
+ mcpmon --config .mcpmon.yaml
39
+ ```
40
+
41
+ ```yaml
42
+ # .mcpmon.yaml
43
+ servers:
44
+ sage:
45
+ command: sage-mcp
46
+ watch: ~/.sage/src/
47
+
48
+ crucible:
49
+ command: crucible-mcp
50
+ watch: ~/crucible/src/
51
+
52
+ my-server:
53
+ command: python
54
+ args: ["-m", "my_server"]
55
+ watch: ./src/
56
+ extensions: py,json
57
+ ```
58
+
59
+ Gateway aggregates tools with prefixes: `sage__recall`, `crucible__review`, etc.
60
+
61
+ ## Options
62
+
63
+ | Option | Description |
64
+ |--------|-------------|
65
+ | `-c, --config <file>` | Config file for multi-server gateway mode |
66
+ | `-w, --watch <dir>` | Directory to watch (default: `.`) |
67
+ | `-e, --ext <exts>` | Extensions to watch, comma-separated (default: `py`) |
68
+ | `-q, --quiet` | Only show errors |
69
+ | `-v, --verbose` | Show file change details |
70
+ | `--debug` | Show all debug output |
71
+ | `-t, --timestamps` | Include timestamps in output |
72
+ | `-l, --log-file <file>` | Also write logs to file |
27
73
 
28
- - `--watch, -w` - Directory to watch (default: current directory)
29
- - `--ext, -e` - File extensions to watch, comma-separated (default: py)
74
+ ### Logging Levels
30
75
 
31
- ### Examples
76
+ ```
77
+ --quiet Only errors
78
+ (default) Start, stop, restart events + PID
79
+ --verbose + file change details
80
+ --debug + everything
81
+ ```
82
+
83
+ ## Examples
32
84
 
33
85
  ```bash
34
- # Watch current directory for .py changes
86
+ # Basic - watch current directory for .py changes
35
87
  mcpmon -- python server.py
36
88
 
37
- # Watch src/ for .py and .json changes
89
+ # Watch specific directory and extensions
38
90
  mcpmon --watch src/ --ext py,json -- python -m myserver
39
91
 
40
- # With crucible-mcp
41
- mcpmon --watch src/crucible/ -- crucible-mcp
92
+ # With timestamps and log file
93
+ mcpmon --timestamps --log-file mcpmon.log -- python server.py
94
+
95
+ # Gateway mode - multiple servers
96
+ mcpmon --config .mcpmon.yaml
97
+ ```
98
+
99
+ ### Sample Output
42
100
 
43
- # With sage-mcp
44
- mcpmon --watch ~/.sage/ --ext py,yaml -- sage-mcp
101
+ ```
102
+ [mcpmon 16:08:50] Watching src/ for .py changes
103
+ [mcpmon 16:08:50 pid:53307] Started: python -m my_server
104
+ [mcpmon 16:08:54] File modified: tools.py
105
+ [mcpmon 16:08:54 pid:53307] Restarting...
106
+ [mcpmon 16:08:54 pid:53411] Started: python -m my_server
107
+ [mcpmon 16:08:54 pid:53411] Restart #1 complete
108
+ [mcpmon 16:08:54] Sent tools/list_changed notification
45
109
  ```
46
110
 
47
111
  ## MCP Config
48
112
 
49
- Use mcpmon in your `.mcp.json` for hot reload during development:
113
+ ### Single Server
50
114
 
51
115
  ```json
52
116
  {
@@ -59,9 +123,47 @@ Use mcpmon in your `.mcp.json` for hot reload during development:
59
123
  }
60
124
  ```
61
125
 
62
- ## How it works
126
+ ### Gateway (Multiple Servers)
127
+
128
+ ```json
129
+ {
130
+ "mcpServers": {
131
+ "gateway": {
132
+ "command": "mcpmon",
133
+ "args": ["--config", ".mcpmon.yaml"]
134
+ }
135
+ }
136
+ }
137
+ ```
138
+
139
+ ## How It Works
63
140
 
141
+ ### Single Server Mode
64
142
  1. Starts your MCP server as a subprocess
65
143
  2. Watches specified directory for file changes
66
144
  3. On change: SIGTERM → wait 2s → SIGKILL → restart
67
- 4. Claude Code automatically reconnects to the restarted server
145
+ 4. Sends `notifications/tools/list_changed` notification
146
+ 5. Claude Code refreshes tool cache automatically
147
+
148
+ ### Gateway Mode
149
+ 1. Reads config file, starts all backend servers
150
+ 2. Aggregates tools from all backends (prefixed: `backend__tool`)
151
+ 3. Routes tool calls to correct backend
152
+ 4. Watches each backend's files independently
153
+ 5. Hot-reloads individual backends on change
154
+ 6. Hot-adds/removes backends when config changes
155
+
156
+ ## Development
157
+
158
+ ```bash
159
+ # Python
160
+ pip install -e ".[dev]"
161
+ pytest tests/ -v # 42 tests
162
+
163
+ # Bun/TypeScript
164
+ bun test # 16 tests
165
+ ```
166
+
167
+ ## License
168
+
169
+ MIT
package/__main__.py ADDED
@@ -0,0 +1,6 @@
1
+ """Allow running mcpmon as `python -m mcpmon`."""
2
+
3
+ from mcpmon import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
package/bun.lock ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "configVersion": 1,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "mcpmon",
7
+ "dependencies": {
8
+ "yaml": "^2.8.2",
9
+ },
10
+ },
11
+ },
12
+ "packages": {
13
+ "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
14
+ }
15
+ }