Skip to content

Commit 4cc5a6a

Browse files
authored
feat : mcp init (#1)
mcp server init
1 parent 11b38af commit 4cc5a6a

File tree

11 files changed

+156
-0
lines changed

11 files changed

+156
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ __pycache__/
55

66
# C extensions
77
*.so
8+
.idea
89

910
# Distribution / packaging
1011
.Python

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.10

pyproject.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[project]
2+
name = "python-openstackmcp-server"
3+
version = "0.1.0"
4+
description = "A MCP server providing OpenStack services for MCP clients"
5+
readme = "README.md"
6+
requires-python = ">=3.10"
7+
dependencies = [
8+
"mcp[cli]>=1.12.0",
9+
"openstacksdk>=4.6.0",
10+
"pydantic>=2.11.7",
11+
]
12+
13+
[build-system]
14+
requires = ["hatchling"]
15+
build-backend = "hatchling.build"
16+
17+
[tool.hatch.build.targets.wheel]
18+
packages = ["src/openstack_mcp_server"]
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import sys
2+
import signal
3+
import argparse
4+
import logging
5+
6+
# Configure root logger
7+
logging.basicConfig(
8+
level=logging.INFO,
9+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
10+
handlers=[logging.StreamHandler(sys.stderr)]
11+
)
12+
logger = logging.getLogger("openstack-mcp-server")
13+
14+
15+
def handle_interrupt(signum, frame):
16+
"""Handle keyboard interrupt (Ctrl+C) gracefully."""
17+
logger.info(f"Received signal {signum}, shutting down gracefully...")
18+
sys.exit(0)
19+
20+
21+
def main():
22+
"""Openstack MCP Server main entry point."""
23+
try:
24+
# Import here to avoid circular imports
25+
from openstack_mcp_server.config import MCP_TRANSPORT
26+
from openstack_mcp_server.server import serve
27+
parser = argparse.ArgumentParser(
28+
description="Openstack MCP Server",
29+
)
30+
31+
# Set up signal handler for graceful shutdown
32+
signal.signal(signal.SIGINT, handle_interrupt)
33+
signal.signal(signal.SIGTERM, handle_interrupt)
34+
35+
# Validate transport protocol
36+
if MCP_TRANSPORT not in ["stdio", "sse", "streamable-http"]:
37+
logger.error(
38+
f"Invalid transport protocol: {MCP_TRANSPORT}. Using stdio instead.")
39+
transport = "stdio"
40+
else:
41+
transport = MCP_TRANSPORT
42+
43+
# Start the server
44+
logger.info(f"Starting Openstack MCP Server with {transport} transport")
45+
46+
args = parser.parse_args()
47+
48+
serve(transport=transport, **vars(args))
49+
50+
except KeyboardInterrupt:
51+
logger.info("Keyboard interrupt received. Shutting down gracefully...")
52+
sys.exit(0)
53+
54+
55+
if __name__ == "__main__":
56+
main()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from openstack_mcp_server import main
2+
3+
main()

src/openstack_mcp_server/config.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import os
2+
from pathlib import Path
3+
4+
# Transport protocol
5+
MCP_TRANSPORT = os.environ.get("TRANSPORT", "stdio")
6+
7+
# Application paths
8+
BASE_DIR = Path(__file__).parent.parent.parent

src/openstack_mcp_server/prompts/__init__.py

Whitespace-only changes.

src/openstack_mcp_server/resources/__init__.py

Whitespace-only changes.

src/openstack_mcp_server/server.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from mcp.server.fastmcp import FastMCP
2+
from openstack_mcp_server.tools import register_tool
3+
4+
def serve(transport: str, **kwargs):
5+
"""Serve the MCP server with the specified transport."""
6+
mcp = FastMCP("openstack_mcp_server")
7+
8+
register_tool(mcp)
9+
# resister_resources(mcp)
10+
# register_prompt(mcp)
11+
12+
if transport == "stdio":
13+
mcp.run(transport="stdio", **kwargs)
14+
elif transport == "streamable-http":
15+
mcp.run(transport="streamable-http", **kwargs)
16+
elif transport == "sse":
17+
mcp.run(transport="sse", **kwargs)
18+
else:
19+
raise ValueError(f"Unsupported transport: {transport}")
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from mcp.server.fastmcp import FastMCP
2+
3+
def register_tool(mcp : FastMCP):
4+
"""
5+
Register Openstack MCP tools.
6+
"""
7+
from .nova_tools import NovaTools
8+
9+
NovaTools().register_tools(mcp)

0 commit comments

Comments
 (0)