Skip to content

Commit f56672a

Browse files
Add HTTP and SSE transport support to CLI (#15)
1 parent 1ef39d9 commit f56672a

File tree

4 files changed

+101
-1
lines changed

4 files changed

+101
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ and this project attempts to adhere to [Semantic Versioning](https://semver.org/
1818

1919
## [Unreleased]
2020

21+
### Added
22+
23+
- Support for HTTP and SSE transport protocols via CLI arguments (`--transport`, `--host`, `--port`, `--path`)
24+
2125
## [0.4.0]
2226

2327
### Added

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,21 @@ There's also a Django management command if you prefer, but that requires adding
9292
python manage.py mcp_shell
9393
```
9494

95+
### Transport
96+
97+
The server supports multiple transport protocols:
98+
99+
```bash
100+
# Default: STDIO
101+
python -m mcp_django_shell
102+
103+
# HTTP
104+
python -m mcp_django_shell --transport http --host 127.0.0.1 --port 8000
105+
106+
# SSE
107+
python -m mcp_django_shell --transport sse --host 127.0.0.1 --port 8000
108+
```
109+
95110
### Client Configuration
96111

97112
Configure your MCP client using one of the examples below. The command is the same for all clients, just expressed in annoyingly different JSON soup.
@@ -152,6 +167,7 @@ It wouldn't be an MCP server README without a gratuitous list of features punctu
152167
- 🚀 **Zero configuration** - No schemas, no settings, just Django
153168
- 🤖 **LLM-friendly** - Designed for AI assistants that already know Python
154169
- 📦 **Minimal dependencies** - Just FastMCP and Django (you already have Django)
170+
- 🌐 **Multiple transports** - STDIO, HTTP, SSE.. It has it all!
155171
- 🎯 **Does one thing well** - Runs code. That's it. That's the feature.
156172

157173
Inspired by Armin Ronacher's [Your MCP Doesn't Need 30 Tools: It Needs Code](https://lucumr.pocoo.org/2025/8/18/code-mcps/).

src/mcp_django_shell/cli.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,37 @@ def main(argv: Sequence[str] | None = None) -> int:
2626
action="store_true",
2727
help="Enable debug logging",
2828
)
29+
parser.add_argument(
30+
"--transport",
31+
default="stdio",
32+
choices=["stdio", "http", "sse"],
33+
help="Transport protocol to use (default: stdio)",
34+
)
35+
parser.add_argument(
36+
"--host",
37+
default="127.0.0.1",
38+
help="Host to bind to for HTTP/SSE transport (default: 127.0.0.1)",
39+
)
40+
parser.add_argument(
41+
"--port",
42+
type=int,
43+
default=8000,
44+
help="Port to bind to for HTTP/SSE transport (default: 8000)",
45+
)
46+
parser.add_argument(
47+
"--path",
48+
default="/mcp",
49+
help="Path for HTTP transport endpoint (default: /mcp)",
50+
)
2951
args = parser.parse_args(argv)
3052

3153
debug: bool = args.debug
3254
settings: str | None = args.settings
3355
pythonpath: str | None = args.pythonpath
56+
transport: str = args.transport
57+
host: str = args.host
58+
port: int = args.port
59+
path: str = args.path
3460

3561
if debug:
3662
logging.basicConfig(
@@ -54,6 +80,14 @@ def main(argv: Sequence[str] | None = None) -> int:
5480

5581
logger.info("Starting MCP Django Shell server")
5682
logger.debug("Django settings module: %s", django_settings)
83+
logger.debug("Transport: %s", transport)
84+
if transport in ["http", "sse"]:
85+
logger.info(
86+
"Server will be available at %s:%s%s",
87+
host,
88+
port,
89+
path if transport == "http" else "",
90+
)
5791

5892
def signal_handler(signum: int, _frame: Any): # pragma: no cover
5993
logger.info("Received signal %s, shutting down MCP server", signum)
@@ -67,7 +101,16 @@ def signal_handler(signum: int, _frame: Any): # pragma: no cover
67101

68102
from .server import mcp
69103

70-
mcp.run()
104+
kwargs: dict[str, Any] = {"transport": transport}
105+
106+
if transport in ["http", "sse"]:
107+
kwargs["host"] = host
108+
kwargs["port"] = port
109+
110+
if transport == "http":
111+
kwargs["path"] = path
112+
113+
mcp.run(**kwargs)
71114

72115
except Exception as e:
73116
logger.error("MCP server crashed: %s", e, exc_info=True)

tests/test_cli.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,40 @@ def test_cli_with_debug(monkeypatch):
6262
result = main(["--debug"])
6363

6464
assert result == 0
65+
66+
67+
def test_cli_with_http_transport(monkeypatch):
68+
monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tests.settings")
69+
70+
mock_mcp = Mock()
71+
monkeypatch.setattr("mcp_django_shell.server.mcp", mock_mcp)
72+
73+
result = main(
74+
[
75+
"--transport",
76+
"http",
77+
"--host",
78+
"127.0.0.1",
79+
"--port",
80+
"8000",
81+
"--path",
82+
"/mcp",
83+
]
84+
)
85+
86+
mock_mcp.run.assert_called_once_with(
87+
transport="http", host="127.0.0.1", port=8000, path="/mcp"
88+
)
89+
assert result == 0
90+
91+
92+
def test_cli_with_sse_transport(monkeypatch):
93+
monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tests.settings")
94+
95+
mock_mcp = Mock()
96+
monkeypatch.setattr("mcp_django_shell.server.mcp", mock_mcp)
97+
98+
result = main(["--transport", "sse", "--host", "0.0.0.0", "--port", "9000"])
99+
100+
mock_mcp.run.assert_called_once_with(transport="sse", host="0.0.0.0", port=9000)
101+
assert result == 0

0 commit comments

Comments
 (0)