iflow-mcp_chuckwilliams37-mcp-server-docker 0.1.0__py3-none-any.whl
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.
- app/app.py +136 -0
- iflow_mcp_chuckwilliams37_mcp_server_docker-0.1.0.dist-info/METADATA +192 -0
- iflow_mcp_chuckwilliams37_mcp_server_docker-0.1.0.dist-info/RECORD +5 -0
- iflow_mcp_chuckwilliams37_mcp_server_docker-0.1.0.dist-info/WHEEL +4 -0
- iflow_mcp_chuckwilliams37_mcp_server_docker-0.1.0.dist-info/entry_points.txt +2 -0
app/app.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
from mcp.server import Server
|
|
2
|
+
from mcp.types import Tool, TextContent, ServerCapabilities
|
|
3
|
+
from mcp.server.models import InitializationOptions
|
|
4
|
+
import redis
|
|
5
|
+
import os
|
|
6
|
+
from dotenv import load_dotenv
|
|
7
|
+
import asyncio
|
|
8
|
+
|
|
9
|
+
load_dotenv() # Load .env into environment
|
|
10
|
+
|
|
11
|
+
# Redis connection from env (optional for testing)
|
|
12
|
+
redis_client = None
|
|
13
|
+
try:
|
|
14
|
+
redis_host = os.getenv("REDIS_HOST", "localhost")
|
|
15
|
+
redis_port = int(os.getenv("REDIS_PORT", "6379"))
|
|
16
|
+
redis_client = redis.Redis(host=redis_host, port=redis_port, socket_connect_timeout=1)
|
|
17
|
+
redis_client.ping() # Test connection
|
|
18
|
+
except:
|
|
19
|
+
# Redis connection failed, but continue without it
|
|
20
|
+
redis_client = None
|
|
21
|
+
|
|
22
|
+
# Create MCP server
|
|
23
|
+
app = Server("mcp-server-docker", version="0.1.0")
|
|
24
|
+
|
|
25
|
+
@app.list_resources()
|
|
26
|
+
async def list_resources() -> list:
|
|
27
|
+
"""List available resources"""
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
"uri": "greeting://",
|
|
31
|
+
"name": "Greeting",
|
|
32
|
+
"description": "Get a personalized greeting",
|
|
33
|
+
"mimeType": "text/plain"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"uri": "data://item/",
|
|
37
|
+
"name": "Item",
|
|
38
|
+
"description": "Retrieve item details by ID",
|
|
39
|
+
"mimeType": "application/json"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
@app.read_resource()
|
|
44
|
+
async def read_resource(uri: str) -> str:
|
|
45
|
+
"""Read a resource by URI"""
|
|
46
|
+
if uri.startswith("greeting://"):
|
|
47
|
+
name = uri.replace("greeting://", "")
|
|
48
|
+
return f"Hello, {name}!"
|
|
49
|
+
elif uri.startswith("data://item/"):
|
|
50
|
+
item_id = uri.replace("data://item/", "")
|
|
51
|
+
return f'{{"id": {item_id}, "name": "Sample Item"}}'
|
|
52
|
+
else:
|
|
53
|
+
raise ValueError(f"Unknown resource: {uri}")
|
|
54
|
+
|
|
55
|
+
@app.list_tools()
|
|
56
|
+
async def list_tools() -> list[Tool]:
|
|
57
|
+
"""List available tools"""
|
|
58
|
+
return [
|
|
59
|
+
Tool(
|
|
60
|
+
name="calculator",
|
|
61
|
+
description="Evaluate a mathematical expression",
|
|
62
|
+
inputSchema={
|
|
63
|
+
"type": "object",
|
|
64
|
+
"properties": {
|
|
65
|
+
"expression": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"description": "Mathematical expression to evaluate"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"required": ["expression"]
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
@app.call_tool()
|
|
76
|
+
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
|
77
|
+
"""Handle tool calls"""
|
|
78
|
+
if name == "calculator":
|
|
79
|
+
expression = arguments.get("expression", "")
|
|
80
|
+
try:
|
|
81
|
+
result = eval(expression)
|
|
82
|
+
return [TextContent(type="text", text=str(result))]
|
|
83
|
+
except Exception as e:
|
|
84
|
+
return [TextContent(type="text", text=f"Error: {str(e)}")]
|
|
85
|
+
else:
|
|
86
|
+
raise ValueError(f"Unknown tool: {name}")
|
|
87
|
+
|
|
88
|
+
@app.list_prompts()
|
|
89
|
+
async def list_prompts() -> list:
|
|
90
|
+
"""List available prompts"""
|
|
91
|
+
return [
|
|
92
|
+
{
|
|
93
|
+
"name": "summarize",
|
|
94
|
+
"description": "Summarize the provided text",
|
|
95
|
+
"arguments": [
|
|
96
|
+
{
|
|
97
|
+
"name": "text",
|
|
98
|
+
"description": "Text to summarize",
|
|
99
|
+
"required": True
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
@app.get_prompt()
|
|
106
|
+
async def get_prompt(name: str, arguments: dict) -> str:
|
|
107
|
+
"""Get a prompt by name"""
|
|
108
|
+
if name == "summarize":
|
|
109
|
+
text = arguments.get("text", "")
|
|
110
|
+
return f"Summary of the text: {text}"
|
|
111
|
+
else:
|
|
112
|
+
raise ValueError(f"Unknown prompt: {name}")
|
|
113
|
+
|
|
114
|
+
def main():
|
|
115
|
+
"""Main entry point for the MCP server"""
|
|
116
|
+
import asyncio
|
|
117
|
+
from mcp.server.stdio import stdio_server
|
|
118
|
+
|
|
119
|
+
async def run_server():
|
|
120
|
+
async with stdio_server() as (read_stream, write_stream):
|
|
121
|
+
capabilities = ServerCapabilities(
|
|
122
|
+
resources={},
|
|
123
|
+
tools={},
|
|
124
|
+
prompts={}
|
|
125
|
+
)
|
|
126
|
+
init_options = InitializationOptions(
|
|
127
|
+
server_name="mcp-server-docker",
|
|
128
|
+
server_version="0.1.0",
|
|
129
|
+
capabilities=capabilities
|
|
130
|
+
)
|
|
131
|
+
await app.run(read_stream, write_stream, init_options)
|
|
132
|
+
|
|
133
|
+
asyncio.run(run_server())
|
|
134
|
+
|
|
135
|
+
if __name__ == "__main__":
|
|
136
|
+
main()
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: iflow-mcp_chuckwilliams37-mcp-server-docker
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP Server with Docker, Redis, and TimescaleDB
|
|
5
|
+
Project-URL: Homepage, https://github.com/chuckwilliams37/mcp-server-docker
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: fastapi
|
|
8
|
+
Requires-Dist: mcp
|
|
9
|
+
Requires-Dist: psycopg2-binary
|
|
10
|
+
Requires-Dist: python-dotenv
|
|
11
|
+
Requires-Dist: redis
|
|
12
|
+
Requires-Dist: torch
|
|
13
|
+
Requires-Dist: uvicorn[standard]
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# ๐ MCP Server with Docker, Redis, and TimescaleDB
|
|
17
|
+
|
|
18
|
+
This repository sets up a **Model Context Protocol (MCP) Server** using Docker, integrating Redis and TimescaleDB for efficient data management.
|
|
19
|
+
|
|
20
|
+
## ๐ ๏ธ Features
|
|
21
|
+
|
|
22
|
+
- **FastAPI**: Serves as the web framework for the MCP server.
|
|
23
|
+
- **Redis**: Provides caching mechanisms.
|
|
24
|
+
- **TimescaleDB**: A time-series database built on PostgreSQL.
|
|
25
|
+
- **Docker Compose**: Orchestrates multi-container Docker applications.
|
|
26
|
+
- **Environment Variables**: Configurable via `.env` file.
|
|
27
|
+
- **Systemd Service**: Ensures the server auto-starts on reboot.
|
|
28
|
+
|
|
29
|
+
## ๐ Prerequisites
|
|
30
|
+
|
|
31
|
+
- **Docker** and **Docker Compose** installed on your system.
|
|
32
|
+
- **Git** for version control.
|
|
33
|
+
- **Zsh** with **Oh-My-Zsh** (optional, for enhanced shell experience).
|
|
34
|
+
|
|
35
|
+
## ๐ Repository Structure
|
|
36
|
+
|
|
37
|
+
```plaintext
|
|
38
|
+
mcp-server-docker/
|
|
39
|
+
โโโ app/
|
|
40
|
+
โ โโโ app.py
|
|
41
|
+
โโโ .env.example
|
|
42
|
+
โโโ docker-compose.yml
|
|
43
|
+
โโโ Dockerfile
|
|
44
|
+
โโโ requirements.txt
|
|
45
|
+
โโโ scripts/
|
|
46
|
+
โ โโโ bootstrap-mcp.sh
|
|
47
|
+
โ โโโ full-bootstrap-mcp.sh
|
|
48
|
+
โ โโโ init-repo.sh
|
|
49
|
+
โ โโโ push-repo.sh
|
|
50
|
+
โ โโโ setup-mcpserver.sh
|
|
51
|
+
โโโ README.md
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## ๐ Setup Instructions
|
|
55
|
+
|
|
56
|
+
1. **Clone the Repository**:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/chuckwilliams37/mcp-server-docker.git
|
|
60
|
+
cd mcp-server-docker
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
2. **Configure Environment Variables**:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cp .env.example .env
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Modify `.env` as needed.
|
|
70
|
+
|
|
71
|
+
3. **Build and Start the Containers**:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
docker compose build
|
|
75
|
+
docker compose up -d
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
4. **Access the MCP Server**:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
http://localhost:8080
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## ๐ Auto-Restart on Reboot
|
|
85
|
+
|
|
86
|
+
Create a systemd service to keep your app alive:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
sudo nano /etc/systemd/system/mcp-docker.service
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Paste:
|
|
93
|
+
|
|
94
|
+
```ini
|
|
95
|
+
[Unit]
|
|
96
|
+
Description=MCP Docker Compose App
|
|
97
|
+
Requires=docker.service
|
|
98
|
+
After=docker.service
|
|
99
|
+
|
|
100
|
+
[Service]
|
|
101
|
+
WorkingDirectory=/home/youruser/mcp-server-docker
|
|
102
|
+
ExecStart=/usr/bin/docker compose up -d
|
|
103
|
+
ExecStop=/usr/bin/docker compose down
|
|
104
|
+
Restart=always
|
|
105
|
+
TimeoutStartSec=0
|
|
106
|
+
|
|
107
|
+
[Install]
|
|
108
|
+
WantedBy=multi-user.target
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Enable it:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
sudo systemctl daemon-reload
|
|
115
|
+
sudo systemctl enable mcp-docker
|
|
116
|
+
sudo systemctl start mcp-docker
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## ๐งช Scripts
|
|
122
|
+
|
|
123
|
+
The `scripts/` directory contains utility scripts to automate infrastructure tasks.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### ๐ ๏ธ `scripts/full-bootstrap-mcp.sh`
|
|
128
|
+
|
|
129
|
+
๐ก **Use this on a fresh Ubuntu VM** to fully prepare it for MCP deployment. It:
|
|
130
|
+
|
|
131
|
+
- Installs system dependencies (Docker, Git, Zsh, UFW, Fail2Ban, etc.)
|
|
132
|
+
- Sets up `oh-my-zsh` with the `jonathan` theme
|
|
133
|
+
- Configures Remote Desktop with XFCE + XRDP
|
|
134
|
+
- Clones the MCP repo
|
|
135
|
+
- Builds and launches the app with `docker compose`
|
|
136
|
+
- Adds a systemd service to relaunch containers on reboot
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
chmod +x scripts/full-bootstrap-mcp.sh
|
|
140
|
+
./scripts/full-bootstrap-mcp.sh
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### ๐ `scripts/init-repo.sh`
|
|
146
|
+
|
|
147
|
+
Initializes a new local Git repository and commits the current directory:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
chmod +x scripts/init-repo.sh
|
|
151
|
+
./scripts/init-repo.sh
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
### ๐ค `scripts/push-repo.sh`
|
|
157
|
+
|
|
158
|
+
Pushes your local repo to a remote (update URL first):
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
chmod +x scripts/push-repo.sh
|
|
162
|
+
./scripts/push-repo.sh
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
### ๐ง `scripts/setup-mcpserver.sh`
|
|
168
|
+
|
|
169
|
+
Configures your local SSH environment to access a remote MCP server:
|
|
170
|
+
|
|
171
|
+
- Pushes your public key
|
|
172
|
+
- Adds an SSH alias
|
|
173
|
+
- Prints a sample A-record
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
chmod +x scripts/setup-mcpserver.sh
|
|
177
|
+
./scripts/setup-mcpserver.sh
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
> โ ๏ธ Edit placeholder values (e.g., IPs, usernames, repo URLs) before executing.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## ๐ค Contributions
|
|
187
|
+
|
|
188
|
+
Feel free to fork this repository, submit issues, or create pull requests.
|
|
189
|
+
|
|
190
|
+
## ๐ License
|
|
191
|
+
|
|
192
|
+
This project is licensed under the MIT License.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
app/app.py,sha256=CT7rLeBvzOQ-xVdZztZ39QXEyuJcNqL2qw09ErA7j_M,4088
|
|
2
|
+
iflow_mcp_chuckwilliams37_mcp_server_docker-0.1.0.dist-info/METADATA,sha256=OXWaAMraXGoQIDGOj6rHg2pR-EAdakP2GAi4A1WVe0I,4177
|
|
3
|
+
iflow_mcp_chuckwilliams37_mcp_server_docker-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
4
|
+
iflow_mcp_chuckwilliams37_mcp_server_docker-0.1.0.dist-info/entry_points.txt,sha256=bnSUUmv3WMGj291fmU4hFTh2wYukv5zacbxWNiPjLBo,51
|
|
5
|
+
iflow_mcp_chuckwilliams37_mcp_server_docker-0.1.0.dist-info/RECORD,,
|