@@ -9,10 +9,17 @@ guides) and prompt templates for common workflows.
99## Repository Layout
1010
1111```
12+ pyproject.toml — Project metadata, version (single source of truth), and dependencies (uv)
13+ Dockerfile — Multi-stage build; non-root user, health checks
14+ docker-compose.yml — Compose stack with optional Prometheus + Grafana
15+
1216src/webex_bot_mcp/
17+ __init__.py — Package init; reads __version__ from importlib.metadata
18+ __main__.py — Enables `python -m webex_bot_mcp`
1319 main.py — MCP server entry point; registers all tools/resources/prompts
1420 config.py — WebexConfig dataclass; loaded via get_config() or WebexConfig.from_env()
1521 health_check.py — Standalone diagnostic script; validates env and API connectivity
22+
1623 tools/
1724 __init__.py — Re-exports every tool function
1825 common.py — Shared: WebexAPI client, create_error_response, create_success_response,
@@ -23,12 +30,15 @@ src/webex_bot_mcp/
2330 memberships.py — Membership CRUD (list, add, update, delete) + space aliases
2431 people.py — get_webex_me, list_webex_people
2532
26- pyproject.toml — Project metadata and dependencies (uses uv, src layout)
27- Dockerfile — Multi-stage build; non-root user, health checks
28- docker-compose.yml — Compose stack with optional Prometheus + Grafana
29-
3033tests/
3134 test_messages.py — Unit tests (85 cases); mocks webexpythonsdk at sys.modules level
35+
36+ .github/
37+ workflows/
38+ publish.yml — Builds + publishes to TestPyPI then PyPI on tag/workflow_dispatch
39+ release-please.yml — Creates release PRs and tags from conventional commits
40+ release-please-config.json — release-please package config
41+ .release-please-manifest.json — Tracks current released version
3242```
3343
3444## Key Conventions
@@ -74,18 +84,25 @@ params['files'] = [files] if isinstance(files, str) else files
7484## Running the Server
7585
7686``` bash
77- # stdio (default — for Claude Desktop / MCP clients)
87+ # If installed from PyPI (pip install webex-bot-mcp)
88+ webex-bot-mcp # stdio (default)
89+ webex-bot-mcp --transport streamable-http --port 8000 # HTTP transport
90+
91+ # From source checkout (development)
7892uv run webex-bot-mcp
93+ uv run python -m webex_bot_mcp --transport streamable-http --host 0.0.0.0 --port 8000
7994
80- # HTTP transport
81- uv run webex-bot-mcp --transport streamable-http --host 0.0.0.0 --port 8000
95+ # Health check
96+ webex-bot-mcp-health
8297```
8398
8499Required environment variable: ` WEBEX_ACCESS_TOKEN `
85100
86101## Running Tests
87102
88103``` bash
104+ python -m unittest discover -s tests -v
105+ # or, from a source checkout with uv:
89106uv run python -m unittest discover -s tests -v
90107```
91108
@@ -116,6 +133,63 @@ Must run via `uv run` so the `src/webex_bot_mcp` package is on the Python path.
116133| ` METRICS_ENABLED ` | | ` false ` | Enable metrics endpoint |
117134| ` METRICS_ENDPOINT ` | | — | Prometheus push endpoint |
118135
136+ ## Releases & Conventional Commits
137+
138+ Releases are fully automated via ** release-please** + ** GitHub Actions** . No manual version
139+ bumping or tagging is needed for normal releases.
140+
141+ ### How it works
142+
143+ 1 . Merge commits to ` main ` using the ** conventional commit** format (see below).
144+ 2 . release-please watches ` main ` and maintains a "Release PR" that accumulates unreleased
145+ changes, updating ` CHANGELOG.md ` and ` pyproject.toml ` version automatically.
146+ 3 . When you're ready to release, ** merge the Release PR** — release-please creates a GitHub
147+ tag + release automatically.
148+ 4 . The ` publish.yml ` workflow fires on the new tag, builds the wheel, publishes to TestPyPI
149+ (requires approval from the ` testpypi ` environment), then publishes to PyPI (requires
150+ approval from the ` pypi ` environment).
151+
152+ You can also trigger a publish manually from the GitHub Actions tab via ` workflow_dispatch `
153+ (useful if you need to republish without a new tag).
154+
155+ ### Conventional commit format
156+
157+ ```
158+ <type>(<scope>): <short description>
159+
160+ [optional body]
161+
162+ [optional footer(s)]
163+ ```
164+
165+ | Type | Version bump | Use for |
166+ | ---| ---| ---|
167+ | ` feat: ` | minor | New tool, resource, or user-visible feature |
168+ | ` fix: ` | patch | Bug fix |
169+ | ` feat!: ` or ` BREAKING CHANGE: ` footer | major | Breaking API change |
170+ | ` chore: ` | none | Build, CI, dependency updates |
171+ | ` docs: ` | none | Documentation only |
172+ | ` refactor: ` | none | Code restructure, no behavior change |
173+ | ` test: ` | none | Test additions or fixes |
174+ | ` perf: ` | patch | Performance improvement |
175+
176+ ** Examples:**
177+ ```
178+ feat(messages): add markdown formatting support
179+ fix(rooms): handle 404 when room already deleted
180+ chore(deps): update fastmcp to 2.5.0
181+ docs: add conventional commits guide to CLAUDE.md
182+ feat!: rename list_webex_rooms to list_rooms
183+
184+ BREAKING CHANGE: tool name changed for consistency
185+ ```
186+
187+ ### Version source of truth
188+
189+ Version lives ** only** in ` pyproject.toml ` . Code reads it at runtime via
190+ ` importlib.metadata.version("webex-bot-mcp") ` . Never hard-code a version string anywhere
191+ else in the source.
192+
119193## Dependency Management
120194
121195Uses ` uv ` . The declared runtime dependency for dotenv is ` python-dotenv>=1.0.0 `
0 commit comments