speechwire-mcp 0.1.0__tar.gz

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.
Files changed (49) hide show
  1. speechwire_mcp-0.1.0/.env.example +6 -0
  2. speechwire_mcp-0.1.0/.github/copilot-instructions.md +127 -0
  3. speechwire_mcp-0.1.0/.github/workflows/ci.yml +22 -0
  4. speechwire_mcp-0.1.0/.github/workflows/publish.yml +87 -0
  5. speechwire_mcp-0.1.0/.gitignore +36 -0
  6. speechwire_mcp-0.1.0/LICENSE +21 -0
  7. speechwire_mcp-0.1.0/PKG-INFO +93 -0
  8. speechwire_mcp-0.1.0/README.md +64 -0
  9. speechwire_mcp-0.1.0/pyproject.toml +55 -0
  10. speechwire_mcp-0.1.0/src/speechwire_mcp/__init__.py +37 -0
  11. speechwire_mcp-0.1.0/src/speechwire_mcp/__main__.py +5 -0
  12. speechwire_mcp-0.1.0/src/speechwire_mcp/client.py +411 -0
  13. speechwire_mcp-0.1.0/src/speechwire_mcp/judges/__init__.py +23 -0
  14. speechwire_mcp-0.1.0/src/speechwire_mcp/judges/client.py +424 -0
  15. speechwire_mcp-0.1.0/src/speechwire_mcp/judges/parsers.py +533 -0
  16. speechwire_mcp-0.1.0/src/speechwire_mcp/login/__init__.py +6 -0
  17. speechwire_mcp-0.1.0/src/speechwire_mcp/login/client.py +65 -0
  18. speechwire_mcp-0.1.0/src/speechwire_mcp/login/parsers.py +189 -0
  19. speechwire_mcp-0.1.0/src/speechwire_mcp/parsing_helpers.py +75 -0
  20. speechwire_mcp-0.1.0/src/speechwire_mcp/results/__init__.py +3 -0
  21. speechwire_mcp-0.1.0/src/speechwire_mcp/results/client.py +48 -0
  22. speechwire_mcp-0.1.0/src/speechwire_mcp/results/parsers.py +310 -0
  23. speechwire_mcp-0.1.0/src/speechwire_mcp/rooms/__init__.py +11 -0
  24. speechwire_mcp-0.1.0/src/speechwire_mcp/rooms/client.py +83 -0
  25. speechwire_mcp-0.1.0/src/speechwire_mcp/rooms/parsers.py +372 -0
  26. speechwire_mcp-0.1.0/src/speechwire_mcp/schematics/__init__.py +6 -0
  27. speechwire_mcp-0.1.0/src/speechwire_mcp/schematics/client.py +49 -0
  28. speechwire_mcp-0.1.0/src/speechwire_mcp/schematics/parsers.py +243 -0
  29. speechwire_mcp-0.1.0/src/speechwire_mcp/server.py +802 -0
  30. speechwire_mcp-0.1.0/src/speechwire_mcp/structure/__init__.py +9 -0
  31. speechwire_mcp-0.1.0/src/speechwire_mcp/structure/client.py +61 -0
  32. speechwire_mcp-0.1.0/src/speechwire_mcp/structure/parsers.py +249 -0
  33. speechwire_mcp-0.1.0/src/speechwire_mcp/teams/__init__.py +7 -0
  34. speechwire_mcp-0.1.0/src/speechwire_mcp/teams/client.py +87 -0
  35. speechwire_mcp-0.1.0/src/speechwire_mcp/teams/parsers.py +395 -0
  36. speechwire_mcp-0.1.0/tests/conftest.py +4 -0
  37. speechwire_mcp-0.1.0/tests/fake_data.py +124 -0
  38. speechwire_mcp-0.1.0/tests/test_add_judge.py +127 -0
  39. speechwire_mcp-0.1.0/tests/test_client_state.py +335 -0
  40. speechwire_mcp-0.1.0/tests/test_login_parsers.py +782 -0
  41. speechwire_mcp-0.1.0/tests/test_parsers.py +927 -0
  42. speechwire_mcp-0.1.0/tests/test_post.py +161 -0
  43. speechwire_mcp-0.1.0/tests/test_results_parsers.py +402 -0
  44. speechwire_mcp-0.1.0/tests/test_rooms_parsers.py +521 -0
  45. speechwire_mcp-0.1.0/tests/test_schematics_parsers.py +354 -0
  46. speechwire_mcp-0.1.0/tests/test_session_expiry.py +389 -0
  47. speechwire_mcp-0.1.0/tests/test_structure_parsers.py +544 -0
  48. speechwire_mcp-0.1.0/tests/test_teams_parsers.py +623 -0
  49. speechwire_mcp-0.1.0/tests/test_update_judge.py +408 -0
@@ -0,0 +1,6 @@
1
+ SPEECHWIRE_EMAIL=
2
+ SPEECHWIRE_PASSWORD=
3
+ # Optional — omit to use discovery mode:
4
+ # SPEECHWIRE_ACCOUNT_ID=
5
+ # SPEECHWIRE_CIRCUIT_ID=
6
+ # SPEECHWIRE_TOURNAMENT_ID=
@@ -0,0 +1,127 @@
1
+ # Copilot Instructions for SpeechWireMCP
2
+
3
+ ## Project Overview
4
+
5
+ SpeechWireMCP is a Model Context Protocol (MCP) server that gives AI assistants
6
+ secure access to SpeechWire tournament judge data for speech-and-debate
7
+ (forensics) competitions. It scrapes manage.speechwire.com behind an
8
+ authenticated session and exposes structured data through MCP tools.
9
+
10
+ ## Tech Stack
11
+
12
+ - **Python 3.11+** — use modern syntax (`X | Y` unions, `list[dict]`, etc.)
13
+ - **MCP SDK** (`mcp` package, `FastMCP`) — tool registration via `@mcp.tool()`
14
+ - **requests** — HTTP client with a stateful `requests.Session` for auth cookies
15
+ - **BeautifulSoup4** — HTML parsing of SpeechWire pages
16
+ - **Hatchling** — PEP 517 build backend
17
+ - **pytest** — testing
18
+ - **ruff** — linting (line-length 100, target py311)
19
+
20
+ ## Architecture
21
+
22
+ ```
23
+ src/speechwire_mcp/
24
+ ├── server.py # FastMCP server, tool definitions, lazy client init
25
+ ├── client.py # SpeechWireClient (4-step auth), _fetch_and_parse helper
26
+ ├── parsing_helpers.py # Shared BS4 utilities (make_soup, td_safe, extract_int_query_param)
27
+ ├── judges/
28
+ │ ├── client.py # Judge data retrieval (list, contact, availability, school)
29
+ │ └── parsers.py # Judge HTML → structured data parsing
30
+ ├── login/
31
+ │ ├── client.py # Account & tournament discovery after login
32
+ │ └── parsers.py # Account list & tournament list parsing
33
+ ├── rooms/
34
+ │ ├── client.py # Room list, usage grid, count retrieval
35
+ │ └── parsers.py # Room HTML → structured data parsing
36
+ ├── results/
37
+ │ ├── client.py # Tab sheet results retrieval
38
+ │ └── parsers.py # Results HTML → structured data parsing
39
+ ├── schematics/
40
+ │ ├── client.py # Schematic event list & round schematic retrieval
41
+ │ └── parsers.py # Schematic HTML → structured data parsing
42
+ ├── structure/
43
+ │ ├── client.py # Timeslot & grouping retrieval
44
+ │ └── parsers.py # Schedule/grouping HTML → structured data parsing
45
+ └── teams/
46
+ ├── client.py # Team list, entries, hybrid entries retrieval
47
+ └── parsers.py # Team HTML → structured data parsing
48
+ ```
49
+
50
+ - **server.py** is the MCP entry point. Tools are thin wrappers that delegate to
51
+ domain modules (`judges/`, `login/`, `rooms/`, `results/`, `schematics/`,
52
+ `structure/`, `teams/`).
53
+ - **client.py** owns all HTTP and authentication logic. The client automatically
54
+ re-authenticates when it detects a session expiry.
55
+ - **parsing_helpers.py** provides shared BeautifulSoup utilities used by all
56
+ domain parsers.
57
+ - Each **domain module** follows the same pattern: `client.py` calls
58
+ `_fetch_and_parse` with a URL and parser; `parsers.py` contains pure functions
59
+ that take HTML strings and return dicts/lists — keep them side-effect free for
60
+ easy testing.
61
+ - **`_fetch_and_parse`** is the shared pattern: fetch a page, run a parser,
62
+ return a safe default on any failure. Accepts an optional `params` dict for
63
+ query parameters — prefer `params={"key": "val"}` over f-string URL
64
+ interpolation.
65
+
66
+ ## Conventions
67
+
68
+ - **Error handling:** never raise from MCP tools. Log errors and return sensible
69
+ defaults (empty list, `None`, etc.) so the AI client always gets a valid
70
+ response.
71
+ - **Logging:** use `logging.getLogger(__name__)` in every module.
72
+ - **No real PII in code or tests:** never use real names, emails, phone
73
+ numbers, or other personally identifiable information anywhere in the
74
+ repository. All test data must use the fictional West Wing characters and
75
+ schools defined in `tests/fake_data.py`. Import constants from that module
76
+ rather than inventing new names inline. Use the `email_for()` helper for
77
+ fake email addresses (all `@example.com`).
78
+ - **Type hints:** annotate all public functions. Use built-in generics
79
+ (`list`, `dict`, `str | None`) — no `typing.List`/`typing.Optional`.
80
+ - **Docstrings:** use NumPy-style docstrings (`Parameters`, `Returns` sections).
81
+ - **Line length:** 100 characters max (enforced by ruff).
82
+ - **URL construction:** use `params={"key": "val"}` in `_fetch_and_parse`
83
+ calls rather than f-string interpolation to prevent injection risks.
84
+ - **Tests:** parser functions get unit tests in `tests/` with sample HTML
85
+ fixtures. Use `pytest`.
86
+
87
+ ## Environment Variables
88
+
89
+ The server requires these at runtime (never hard-code credentials):
90
+
91
+ | Variable | Purpose |
92
+ |----------|---------|
93
+ | `SPEECHWIRE_EMAIL` | Account email |
94
+ | `SPEECHWIRE_PASSWORD` | Account password |
95
+ | `SPEECHWIRE_ACCOUNT_ID` | Numeric account ID |
96
+ | `SPEECHWIRE_CIRCUIT_ID` | Numeric circuit ID |
97
+ | `SPEECHWIRE_TOURNAMENT_ID` | Numeric tournament ID |
98
+ | `SPEECHWIRE_MCP_TRANSPORT` | `stdio` (default) or `sse` |
99
+ | `SPEECHWIRE_MCP_HOST` | SSE bind host (default `127.0.0.1`) |
100
+ | `SPEECHWIRE_MCP_PORT` | SSE bind port (default `8080`) |
101
+
102
+ ## Development Workflow
103
+
104
+ ```bash
105
+ pip install -e ".[dev]" # editable install with dev deps
106
+ ruff check src/ tests/ # lint
107
+ pytest # test
108
+ ```
109
+
110
+ CI runs on Python 3.11, 3.12, and 3.13. Publishing to PyPI is triggered by
111
+ pushing a `v*` tag.
112
+
113
+ ## Adding a New MCP Tool
114
+
115
+ 1. Add a parser in `<domain>/parsers.py` (pure function, HTML → data).
116
+ 2. Add a retrieval function in `<domain>/client.py` using `_fetch_and_parse`.
117
+ 3. Export it from `<domain>/__init__.py`.
118
+ 4. Register the tool in `server.py` with `@mcp.tool()` and a clear docstring.
119
+ 5. Write parser tests in `tests/`.
120
+
121
+ ## Process
122
+
123
+ - **Never make git commits or push branches without explicit permission.**
124
+ - **Do not add new dependencies** (packages, libraries, tools) without asking
125
+ first.
126
+ - **Run `ruff check src/ tests/` and `pytest`** before declaring work complete.
127
+ - **Do not modify files outside `src/` and `tests/`** without asking first.
@@ -0,0 +1,22 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.11", "3.12", "3.13"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ - run: pip install -e ".[dev]"
21
+ - run: ruff check src/ tests/
22
+ - run: pytest
@@ -0,0 +1,87 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - run: pip install -e ".[dev]"
20
+ - run: ruff check src/ tests/
21
+ - run: pytest
22
+
23
+ build:
24
+ needs: test
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.12"
31
+ - run: pip install build
32
+ - run: python -m build
33
+ - uses: actions/upload-artifact@v4
34
+ with:
35
+ name: dist
36
+ path: dist/
37
+
38
+ publish-testpypi:
39
+ needs: build
40
+ runs-on: ubuntu-latest
41
+ environment: testpypi
42
+ permissions:
43
+ id-token: write
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+ with:
47
+ fetch-depth: 0
48
+ - name: Check if tag is on dev
49
+ id: check
50
+ run: |
51
+ if git branch -r --contains "${{ github.ref_name }}" | grep -q 'origin/dev'; then
52
+ echo "on_dev=true" >> "$GITHUB_OUTPUT"
53
+ fi
54
+ - uses: actions/download-artifact@v4
55
+ if: steps.check.outputs.on_dev == 'true'
56
+ with:
57
+ name: dist
58
+ path: dist/
59
+ - uses: pypa/gh-action-pypi-publish@release/v1
60
+ if: steps.check.outputs.on_dev == 'true'
61
+ with:
62
+ repository-url: https://test.pypi.org/legacy/
63
+
64
+ publish-pypi:
65
+ needs: build
66
+ runs-on: ubuntu-latest
67
+ environment: pypi
68
+ permissions:
69
+ id-token: write
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+ with:
73
+ fetch-depth: 0
74
+ - name: Check if tag is on main
75
+ id: check
76
+ run: |
77
+ if git branch -r --contains "${{ github.ref_name }}" | grep -q 'origin/main'; then
78
+ echo "on_main=true" >> "$GITHUB_OUTPUT"
79
+ fi
80
+ - uses: actions/download-artifact@v4
81
+ if: steps.check.outputs.on_main == 'true'
82
+ with:
83
+ name: dist
84
+ path: dist/
85
+ - uses: pypa/gh-action-pypi-publish@release/v1
86
+ if: steps.check.outputs.on_main == 'true'
87
+
@@ -0,0 +1,36 @@
1
+ # OS files
2
+ .DS_Store
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # Distribution / packaging
10
+ dist/
11
+ build/
12
+ *.egg-info/
13
+ *.egg
14
+
15
+ # Virtual environments
16
+ .venv/
17
+ venv/
18
+
19
+ # IDE
20
+ .vscode/
21
+ .idea/
22
+
23
+ # Environment files
24
+ .env
25
+ .env.local
26
+
27
+ # pytest / ruff cache
28
+ .pytest_cache/
29
+ .ruff_cache/
30
+
31
+ # Notebooks (may contain credentials)
32
+ notebooks/
33
+ *.ipynb
34
+
35
+ # Copilot
36
+ .copilot/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jessica Moore
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.4
2
+ Name: speechwire-mcp
3
+ Version: 0.1.0
4
+ Summary: Model Context Protocol (MCP) server for interacting with SpeechWire tournament management
5
+ Project-URL: Homepage, https://github.com/jessica-writes-code/speechwire-mcp
6
+ Project-URL: Repository, https://github.com/jessica-writes-code/speechwire-mcp
7
+ Project-URL: Issues, https://github.com/jessica-writes-code/speechwire-mcp/issues
8
+ Author: Jessica Moore
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: forensics,mcp,model-context-protocol,speech-and-debate,speechwire
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: beautifulsoup4<5.0,>=4.12.0
23
+ Requires-Dist: mcp<2.0,>=1.0.0
24
+ Requires-Dist: requests<3.0,>=2.32.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=8.0; extra == 'dev'
27
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # SpeechWire MCP Server
31
+
32
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](#) [![PyPI](https://img.shields.io/pypi/v/speechwire-mcp)](#)
33
+
34
+ A [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server that provides AI assistants with secure, authenticated access to [SpeechWire](https://www.speechwire.com/) tournament data for speech-and-debate (forensics) competitions.
35
+
36
+ The server scrapes manage.speechwire.com behind an authenticated session and exposes structured tournament data through MCP tools, enabling AI assistants to help tournament directors manage judge assignments, rooms, teams, entries, and round pairings.
37
+
38
+ ## Features
39
+
40
+ - **Judge management** — list judges, contact info, availability, school associations, judge types, and add new judges
41
+ - **Team & entry data** — team rosters, entries by team, hybrid/cross-school entries
42
+ - **Room management** — room lists, usage grids, room-vs-section counts
43
+ - **Schematics** — event lists, round-by-round pairings with judges, rooms, and competitors
44
+ - **Tournament structure** — timeslots, competition groupings
45
+ - **Results** — tab sheets with round outcomes, speaker scores, and placements
46
+ - **Account discovery** — list and select accounts and tournaments interactively
47
+ - **Session management** — automatic re-authentication on session expiry
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install speechwire-mcp
53
+ ```
54
+
55
+ Set your SpeechWire credentials as environment variables:
56
+
57
+ ```bash
58
+ export SPEECHWIRE_EMAIL="your-email@example.com"
59
+ export SPEECHWIRE_PASSWORD="your-password"
60
+ ```
61
+
62
+ ## Available MCP Tools
63
+
64
+ | Tool | Description |
65
+ |------|-------------|
66
+ | `speechwire_list_user_accounts` | List accounts available after login |
67
+ | `speechwire_select_user_account` | Select an account to work with |
68
+ | `speechwire_list_user_tournaments` | List tournaments for the selected account |
69
+ | `speechwire_select_user_tournament` | Select a tournament to activate |
70
+ | `speechwire_list_judges` | List all judges with roster details |
71
+ | `speechwire_get_judge_contact` | Get judge email and phone |
72
+ | `speechwire_get_judge_availability` | Get judge availability by timeslot |
73
+ | `speechwire_get_judge_school` | Get judge's school association |
74
+ | `speechwire_add_judge` | Add a new judge to the tournament |
75
+ | `speechwire_update_judge_email` | Update a judge's email address |
76
+ | `speechwire_update_judge_availability` | Update a judge's availability slots |
77
+ | `speechwire_update_judge_school` | Update a judge's school/team affiliation |
78
+ | `speechwire_list_judge_types` | List configured judge types |
79
+ | `speechwire_list_rooms` | List tournament rooms |
80
+ | `speechwire_get_room_usage` | Get room time-slot usage grid |
81
+ | `speechwire_get_room_counts` | Get rooms vs. sections per grouping/round |
82
+ | `speechwire_list_teams` | List registered teams |
83
+ | `speechwire_get_team_entries` | Get entries for a specific team |
84
+ | `speechwire_list_hybrid_entries` | List cross-school hybrid entries |
85
+ | `speechwire_list_timeslots` | List tournament schedule timeslots |
86
+ | `speechwire_list_groupings` | List competition groupings |
87
+ | `speechwire_list_schematic_events` | List schematic events with available rounds |
88
+ | `speechwire_get_round_schematic` | Get pairings for a specific event round |
89
+ | `speechwire_get_tab_sheet` | Get results tab sheet for a grouping |
90
+
91
+ ## License
92
+
93
+ [MIT](LICENSE)
@@ -0,0 +1,64 @@
1
+ # SpeechWire MCP Server
2
+
3
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](#) [![PyPI](https://img.shields.io/pypi/v/speechwire-mcp)](#)
4
+
5
+ A [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server that provides AI assistants with secure, authenticated access to [SpeechWire](https://www.speechwire.com/) tournament data for speech-and-debate (forensics) competitions.
6
+
7
+ The server scrapes manage.speechwire.com behind an authenticated session and exposes structured tournament data through MCP tools, enabling AI assistants to help tournament directors manage judge assignments, rooms, teams, entries, and round pairings.
8
+
9
+ ## Features
10
+
11
+ - **Judge management** — list judges, contact info, availability, school associations, judge types, and add new judges
12
+ - **Team & entry data** — team rosters, entries by team, hybrid/cross-school entries
13
+ - **Room management** — room lists, usage grids, room-vs-section counts
14
+ - **Schematics** — event lists, round-by-round pairings with judges, rooms, and competitors
15
+ - **Tournament structure** — timeslots, competition groupings
16
+ - **Results** — tab sheets with round outcomes, speaker scores, and placements
17
+ - **Account discovery** — list and select accounts and tournaments interactively
18
+ - **Session management** — automatic re-authentication on session expiry
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install speechwire-mcp
24
+ ```
25
+
26
+ Set your SpeechWire credentials as environment variables:
27
+
28
+ ```bash
29
+ export SPEECHWIRE_EMAIL="your-email@example.com"
30
+ export SPEECHWIRE_PASSWORD="your-password"
31
+ ```
32
+
33
+ ## Available MCP Tools
34
+
35
+ | Tool | Description |
36
+ |------|-------------|
37
+ | `speechwire_list_user_accounts` | List accounts available after login |
38
+ | `speechwire_select_user_account` | Select an account to work with |
39
+ | `speechwire_list_user_tournaments` | List tournaments for the selected account |
40
+ | `speechwire_select_user_tournament` | Select a tournament to activate |
41
+ | `speechwire_list_judges` | List all judges with roster details |
42
+ | `speechwire_get_judge_contact` | Get judge email and phone |
43
+ | `speechwire_get_judge_availability` | Get judge availability by timeslot |
44
+ | `speechwire_get_judge_school` | Get judge's school association |
45
+ | `speechwire_add_judge` | Add a new judge to the tournament |
46
+ | `speechwire_update_judge_email` | Update a judge's email address |
47
+ | `speechwire_update_judge_availability` | Update a judge's availability slots |
48
+ | `speechwire_update_judge_school` | Update a judge's school/team affiliation |
49
+ | `speechwire_list_judge_types` | List configured judge types |
50
+ | `speechwire_list_rooms` | List tournament rooms |
51
+ | `speechwire_get_room_usage` | Get room time-slot usage grid |
52
+ | `speechwire_get_room_counts` | Get rooms vs. sections per grouping/round |
53
+ | `speechwire_list_teams` | List registered teams |
54
+ | `speechwire_get_team_entries` | Get entries for a specific team |
55
+ | `speechwire_list_hybrid_entries` | List cross-school hybrid entries |
56
+ | `speechwire_list_timeslots` | List tournament schedule timeslots |
57
+ | `speechwire_list_groupings` | List competition groupings |
58
+ | `speechwire_list_schematic_events` | List schematic events with available rounds |
59
+ | `speechwire_get_round_schematic` | Get pairings for a specific event round |
60
+ | `speechwire_get_tab_sheet` | Get results tab sheet for a grouping |
61
+
62
+ ## License
63
+
64
+ [MIT](LICENSE)
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "speechwire-mcp"
7
+ version = "0.1.0"
8
+ description = "Model Context Protocol (MCP) server for interacting with SpeechWire tournament management"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ authors = [
13
+ { name = "Jessica Moore" },
14
+ ]
15
+ keywords = ["speechwire", "mcp", "model-context-protocol", "speech-and-debate", "forensics"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ "Topic :: Software Development :: Libraries",
26
+ ]
27
+ dependencies = [
28
+ "mcp>=1.0.0,<2.0",
29
+ "requests>=2.32.0,<3.0",
30
+ "beautifulsoup4>=4.12.0,<5.0",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ dev = [
35
+ "pytest>=8.0",
36
+ "ruff>=0.4.0",
37
+ ]
38
+
39
+ [project.scripts]
40
+ speechwire-mcp = "speechwire_mcp.server:main"
41
+
42
+ [project.urls]
43
+ Homepage = "https://github.com/jessica-writes-code/speechwire-mcp"
44
+ Repository = "https://github.com/jessica-writes-code/speechwire-mcp"
45
+ Issues = "https://github.com/jessica-writes-code/speechwire-mcp/issues"
46
+
47
+ [tool.hatch.build.targets.wheel]
48
+ packages = ["src/speechwire_mcp"]
49
+
50
+ [tool.pytest.ini_options]
51
+ testpaths = ["tests"]
52
+
53
+ [tool.ruff]
54
+ target-version = "py311"
55
+ line-length = 100
@@ -0,0 +1,37 @@
1
+ """speechwire-mcp: Model Context Protocol server for SpeechWire tournament management."""
2
+
3
+ from speechwire_mcp.client import SpeechWireClient, SpeechWireAuthError
4
+ from speechwire_mcp.judges import (
5
+ get_judge_list,
6
+ get_judge_contact,
7
+ get_judge_availability,
8
+ get_judge_school,
9
+ )
10
+ from speechwire_mcp.login import get_accounts, get_tournaments
11
+ from speechwire_mcp.rooms import get_room_counts, get_room_list, get_room_usage
12
+ from speechwire_mcp.schematics import get_schematic_events, get_round_schematic
13
+ from speechwire_mcp.structure import get_groupings, get_timeslots
14
+ from speechwire_mcp.teams import get_team_list, get_team_entries, get_hybrid_entries
15
+ from speechwire_mcp.results import get_tab_sheet
16
+
17
+ __all__ = [
18
+ "SpeechWireClient",
19
+ "SpeechWireAuthError",
20
+ "get_judge_list",
21
+ "get_judge_contact",
22
+ "get_judge_availability",
23
+ "get_judge_school",
24
+ "get_accounts",
25
+ "get_tournaments",
26
+ "get_room_counts",
27
+ "get_room_list",
28
+ "get_room_usage",
29
+ "get_schematic_events",
30
+ "get_round_schematic",
31
+ "get_groupings",
32
+ "get_timeslots",
33
+ "get_team_list",
34
+ "get_team_entries",
35
+ "get_hybrid_entries",
36
+ "get_tab_sheet",
37
+ ]
@@ -0,0 +1,5 @@
1
+ """Run the SpeechWire MCP server: python -m speechwire_mcp"""
2
+
3
+ from speechwire_mcp.server import main
4
+
5
+ main()