mcp-server-framework 1.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.
- mcp_server_framework-1.1.0/LICENSE +21 -0
- mcp_server_framework-1.1.0/PKG-INFO +429 -0
- mcp_server_framework-1.1.0/README.md +397 -0
- mcp_server_framework-1.1.0/pyproject.toml +53 -0
- mcp_server_framework-1.1.0/setup.cfg +4 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/__init__.py +11 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/commands.py +80 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/factory.py +113 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/loader.py +10 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/plugins/__init__.py +1 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/plugins/logging.py +121 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/plugins/management.py +52 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/py.typed +0 -0
- mcp_server_framework-1.1.0/src/mcp_server_factory/tracker.py +8 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/__init__.py +36 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/config.py +109 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/health.py +153 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/logging.py +60 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/oauth.py +179 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/plugins/__init__.py +16 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/plugins/loader.py +205 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/plugins/models.py +21 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/plugins/tracker.py +160 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/py.typed +0 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/server.py +116 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework/utils/__init__.py +1 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework.egg-info/PKG-INFO +429 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework.egg-info/SOURCES.txt +41 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework.egg-info/dependency_links.txt +1 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework.egg-info/entry_points.txt +3 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework.egg-info/requires.txt +10 -0
- mcp_server_framework-1.1.0/src/mcp_server_framework.egg-info/top_level.txt +3 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/__init__.py +11 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/cli.py +54 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/client.py +74 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/commands.py +21 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/management.py +129 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/plugins/__init__.py +0 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/plugins/management.py +136 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/proxy.py +237 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/py.typed +0 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/serve.py +118 -0
- mcp_server_framework-1.1.0/src/mcp_server_proxy/tool_log.py +104 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 cuber-it
|
|
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,429 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp-server-framework
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: MCP Server Toolkit — Framework, Factory and Proxy for building MCP servers
|
|
5
|
+
Author-email: cuber IT service <info@uc-it.de>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://www.uc-it.de
|
|
8
|
+
Project-URL: Repository, https://github.com/cuber-it/mcp_server_toolkit
|
|
9
|
+
Project-URL: Issues, https://github.com/cuber-it/mcp_server_toolkit/issues
|
|
10
|
+
Keywords: mcp,model-context-protocol,framework,factory,proxy,llm,ai,plugins
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: mcp>=1.26.0
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Requires-Dist: fastapi>=0.100.0
|
|
25
|
+
Requires-Dist: uvicorn>=0.20.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
29
|
+
Requires-Dist: httpx>=0.24; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# MCP Server Toolkit
|
|
34
|
+
|
|
35
|
+
A Python toolkit for building MCP (Model Context Protocol) servers.
|
|
36
|
+
|
|
37
|
+
Three packages, one ecosystem:
|
|
38
|
+
|
|
39
|
+
| Package | Role |
|
|
40
|
+
|---------|------|
|
|
41
|
+
| **mcp_server_framework** | Shared library: config, transport, health, plugin infrastructure |
|
|
42
|
+
| **mcp_server_factory** | Static plugin loading at startup (CLI tool) |
|
|
43
|
+
| **mcp_server_proxy** | Dynamic plugin loading at runtime (daemon with management API) |
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install -e ".[dev]"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Factory — Build a static server from plugins
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
mcp-factory --plugins echo --http 12201 --plugin-dir ./plugins
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Proxy — Dynamic server with runtime plugin management
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Start proxy with echo plugin on HTTP
|
|
61
|
+
mcp-proxy serve --autoload echo --http 12200 --plugin-dir ./plugins
|
|
62
|
+
|
|
63
|
+
# Manage plugins at runtime (separate terminal)
|
|
64
|
+
mcp-proxy status
|
|
65
|
+
mcp-proxy load shell
|
|
66
|
+
mcp-proxy unload echo
|
|
67
|
+
mcp-proxy reload shell
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Framework — Build a standalone server
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from mcp_server_framework import load_config, create_server, run_server
|
|
74
|
+
|
|
75
|
+
config = load_config()
|
|
76
|
+
mcp = create_server(config)
|
|
77
|
+
|
|
78
|
+
@mcp.tool()
|
|
79
|
+
def hello(name: str) -> str:
|
|
80
|
+
"""Says hello."""
|
|
81
|
+
return f"Hello, {name}!"
|
|
82
|
+
|
|
83
|
+
run_server(mcp, config)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Plugin Interface
|
|
87
|
+
|
|
88
|
+
Every plugin implements one function:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
def register(mcp, config: dict) -> None:
|
|
92
|
+
@mcp.tool()
|
|
93
|
+
def my_tool(param: str) -> str:
|
|
94
|
+
"""Tool description for the LLM."""
|
|
95
|
+
return do_something(param)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Works with Factory and Proxy without changes.
|
|
99
|
+
|
|
100
|
+
### Create a New Plugin
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
./scripts/new-plugin.sh myservice # creates plugins/myservice/
|
|
104
|
+
./scripts/new-plugin.sh myservice ./src # custom target directory
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Generates `__init__.py` (MCP wiring) and `tools.py` (pure logic) with annotated
|
|
108
|
+
examples — start editing `tools.py`, restart the proxy, done.
|
|
109
|
+
|
|
110
|
+
### Recommended Plugin Structure
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
plugins/myservice/
|
|
114
|
+
├── __init__.py # register(mcp, config) — thin MCP wrapper
|
|
115
|
+
├── client.py # HTTP client (pure Python, no MCP)
|
|
116
|
+
└── tools.py # Tool logic (pure Python, no MCP)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This separation keeps your business logic testable and reusable
|
|
120
|
+
without MCP dependencies.
|
|
121
|
+
|
|
122
|
+
## Included Plugins
|
|
123
|
+
|
|
124
|
+
| Plugin | Tools | Description |
|
|
125
|
+
|--------|-------|-------------|
|
|
126
|
+
| `echo` | 2 | Minimal example — echo and echo_upper |
|
|
127
|
+
| `greet` | 1 | Minimal example — greet by name |
|
|
128
|
+
| `mattermost` | 5 | Mattermost REST API (send, channels, posts, search, user) |
|
|
129
|
+
| `wekan` | 18 | Wekan Kanban REST API (boards, cards, checklists, labels) |
|
|
130
|
+
| `shell` | 33 | Filesystem, editor, search, shell, git, systemd, HTTP, packages, diagnostics |
|
|
131
|
+
|
|
132
|
+
## Proxy Features
|
|
133
|
+
|
|
134
|
+
### Management API
|
|
135
|
+
|
|
136
|
+
The proxy runs a FastAPI management server on a separate port (default: 12299):
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
GET /proxy/status All plugins and tools
|
|
140
|
+
GET /proxy/plugins Plugin name list
|
|
141
|
+
POST /proxy/load {"plugin": "name"}
|
|
142
|
+
POST /proxy/unload {"plugin": "name"}
|
|
143
|
+
POST /proxy/reload {"plugin": "name"}
|
|
144
|
+
GET /proxy/commands Registered management extensions
|
|
145
|
+
POST /proxy/command/{name} Run a management extension
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Management API Authentication
|
|
149
|
+
|
|
150
|
+
Optionally protect the management API with a Bearer token:
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
# proxy.yaml
|
|
154
|
+
management_token: "${MCP_MGMT_TOKEN}"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Or via CLI
|
|
159
|
+
mcp-proxy serve --mgmt-token "my-secret" --autoload echo
|
|
160
|
+
|
|
161
|
+
# Client commands with token
|
|
162
|
+
mcp-proxy status --token "my-secret"
|
|
163
|
+
mcp-proxy load shell --token "my-secret"
|
|
164
|
+
|
|
165
|
+
# Or via environment variable (works for both server and client)
|
|
166
|
+
export MCP_MGMT_TOKEN="my-secret"
|
|
167
|
+
mcp-proxy serve --autoload echo
|
|
168
|
+
mcp-proxy status
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Without a token configured, no authentication is required (development default).
|
|
172
|
+
|
|
173
|
+
### Auto-Prefix
|
|
174
|
+
|
|
175
|
+
Avoid tool name collisions when loading multiple plugins:
|
|
176
|
+
|
|
177
|
+
```yaml
|
|
178
|
+
# proxy.yaml
|
|
179
|
+
auto_prefix: true # tool "send" from plugin "mm" becomes "mm_send"
|
|
180
|
+
|
|
181
|
+
plugins:
|
|
182
|
+
mattermost:
|
|
183
|
+
prefix: "mm" # custom prefix (overrides plugin name)
|
|
184
|
+
echo:
|
|
185
|
+
prefix: false # disable prefix for this plugin
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Tools that already start with their plugin's prefix are not double-prefixed.
|
|
189
|
+
|
|
190
|
+
### Health Endpoint
|
|
191
|
+
|
|
192
|
+
When running on HTTP, the health server includes plugin status:
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
GET /health Simple status
|
|
196
|
+
GET /health/detailed Uptime, requests, errors
|
|
197
|
+
GET /health/ready Readiness check (verifies plugins loaded)
|
|
198
|
+
GET /health/plugins Current plugin and tool inventory
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Management Command Extensions
|
|
202
|
+
|
|
203
|
+
Extend the proxy with custom management commands:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
def register(mcp, config: dict) -> None:
|
|
207
|
+
proxy = config.get("_proxy")
|
|
208
|
+
if proxy:
|
|
209
|
+
proxy.register_command("stats", lambda p: f"{len(p.plugins)} plugins")
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Commands are available via MCP tools and the REST management API.
|
|
213
|
+
|
|
214
|
+
## OAuth Authentication
|
|
215
|
+
|
|
216
|
+
OAuth is **enabled by default** for HTTP transport (ignored for stdio).
|
|
217
|
+
Uses RFC 7662 Token Introspection — no extra dependencies needed (uses httpx from MCP SDK).
|
|
218
|
+
Valid tokens are cached for 8 hours (configurable via `oauth_cache_ttl`) to reduce introspection load.
|
|
219
|
+
|
|
220
|
+
Configure via YAML or environment variables:
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
# config.yaml
|
|
224
|
+
oauth_enabled: true # default: true
|
|
225
|
+
oauth_server_url: "https://auth.example.com" # OAuth introspection endpoint
|
|
226
|
+
oauth_public_url: "https://mcp.example.com" # Public URL of this server
|
|
227
|
+
oauth_cache_ttl: 28800 # token cache in seconds (default: 8h)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Or via environment
|
|
232
|
+
export MCP_OAUTH_ENABLED=true
|
|
233
|
+
export MCP_OAUTH_SERVER_URL=https://auth.example.com
|
|
234
|
+
export MCP_PUBLIC_URL=https://mcp.example.com
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Behavior:**
|
|
238
|
+
- HTTP + OAuth configured → full token verification via introspection
|
|
239
|
+
- HTTP + OAuth enabled but URLs missing → **warning**, runs without auth
|
|
240
|
+
- HTTP + `oauth_enabled: false` → no auth, no warning
|
|
241
|
+
- stdio → OAuth ignored regardless of config
|
|
242
|
+
|
|
243
|
+
To explicitly disable:
|
|
244
|
+
```yaml
|
|
245
|
+
oauth_enabled: false
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Security
|
|
249
|
+
|
|
250
|
+
### Shell Plugin Boundaries
|
|
251
|
+
|
|
252
|
+
The shell plugin supports configurable security boundaries:
|
|
253
|
+
|
|
254
|
+
```yaml
|
|
255
|
+
plugins:
|
|
256
|
+
shell:
|
|
257
|
+
enabled: true
|
|
258
|
+
allowed_paths: # restrict filesystem access
|
|
259
|
+
- "/home/user/projects"
|
|
260
|
+
- "/tmp"
|
|
261
|
+
blocked_commands: # block dangerous commands
|
|
262
|
+
- "sudo"
|
|
263
|
+
- "rm -rf /"
|
|
264
|
+
- "chmod"
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Without boundaries configured, the shell plugin has unrestricted access
|
|
268
|
+
(suitable for local development). For shared or production deployments,
|
|
269
|
+
configure `allowed_paths` and `blocked_commands`.
|
|
270
|
+
|
|
271
|
+
### Pre-Call Validation
|
|
272
|
+
|
|
273
|
+
Register a custom validator that runs before every tool invocation:
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
from mcp_server_framework.plugins import set_pre_call_validator
|
|
277
|
+
|
|
278
|
+
def my_validator(tool_name: str, params: dict) -> str | None:
|
|
279
|
+
"""Return error string to reject, None to allow."""
|
|
280
|
+
if len(str(params)) > 100_000:
|
|
281
|
+
return "Input too large"
|
|
282
|
+
return None
|
|
283
|
+
|
|
284
|
+
set_pre_call_validator(my_validator)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Logging
|
|
288
|
+
|
|
289
|
+
Configure log format via config or environment:
|
|
290
|
+
|
|
291
|
+
```yaml
|
|
292
|
+
log_level: INFO
|
|
293
|
+
log_format: json # "json" for machine-readable, "text" (default) for humans
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
JSON output example:
|
|
297
|
+
```json
|
|
298
|
+
{"ts": "2026-03-11T10:30:00+00:00", "level": "INFO", "logger": "mcp_server_proxy.proxy", "msg": "Plugin 'echo' loaded: 2 tools ['echo', 'echo_upper']"}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Tool Call Logging (Proxy)
|
|
302
|
+
|
|
303
|
+
The proxy automatically logs every tool call to `~/.mcp_proxy/logs/tool_calls.jsonl`:
|
|
304
|
+
|
|
305
|
+
```json
|
|
306
|
+
{"ts": "2026-03-11T14:30:00", "tool": "shell_exec", "params": {"command": "ls"}, "result": "...", "ok": true}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
- Daily rotation with gzip compression (`YYYY-MM-DD.jsonl.gz`)
|
|
310
|
+
- 90-day retention with automatic cleanup
|
|
311
|
+
- Safe — never raises, never blocks tool execution
|
|
312
|
+
|
|
313
|
+
## Interactive Test Client
|
|
314
|
+
|
|
315
|
+
Debug and explore any MCP server from the terminal:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# Connect via stdio
|
|
319
|
+
python examples/mcp_client.py -v stdio -- mcp-proxy --autoload echo
|
|
320
|
+
|
|
321
|
+
# Connect via HTTP
|
|
322
|
+
python examples/mcp_client.py http http://localhost:12200/mcp
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
REPL commands: `tools`, `call <name>`, `resources`, `prompts`, `info`, `quit`
|
|
326
|
+
|
|
327
|
+
Tool shorthand — call tools directly by name:
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
mcp> echo hello # single-arg shorthand
|
|
331
|
+
mcp> echo_upper world
|
|
332
|
+
mcp> greet Claude
|
|
333
|
+
mcp> proxy__status # no-arg tools work too
|
|
334
|
+
mcp> call echo # interactive mode (prompts for args)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Examples
|
|
338
|
+
|
|
339
|
+
Ready-to-run scripts in `examples/`:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
./examples/run_factory_echo.sh # Factory + Echo (stdio, all-in-one)
|
|
343
|
+
./examples/run_proxy_http.sh # Proxy + Echo (HTTP)
|
|
344
|
+
./examples/run_proxy_shell.sh # Proxy + Shell (HTTP)
|
|
345
|
+
./examples/run_proxy_full.sh # Proxy + Echo + Shell (HTTP)
|
|
346
|
+
./examples/connect_proxy_http.sh # Client → running proxy
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
See [examples/README.md](examples/README.md) for details.
|
|
350
|
+
|
|
351
|
+
## Configuration
|
|
352
|
+
|
|
353
|
+
YAML config with environment variable overrides (`MCP_*`):
|
|
354
|
+
|
|
355
|
+
```yaml
|
|
356
|
+
server_name: "My Proxy"
|
|
357
|
+
transport: http # stdio | http
|
|
358
|
+
host: "0.0.0.0"
|
|
359
|
+
port: 12200
|
|
360
|
+
health_port: 12201
|
|
361
|
+
management_port: 12299
|
|
362
|
+
log_level: INFO
|
|
363
|
+
log_format: text # text | json
|
|
364
|
+
auto_prefix: true
|
|
365
|
+
|
|
366
|
+
# OAuth (enabled by default for HTTP, set false to disable)
|
|
367
|
+
oauth_server_url: "https://auth.example.com"
|
|
368
|
+
oauth_public_url: "https://mcp.example.com"
|
|
369
|
+
oauth_cache_ttl: 28800 # token cache seconds (default: 8h, 0 = disabled)
|
|
370
|
+
|
|
371
|
+
# Management API auth (separate from OAuth, optional)
|
|
372
|
+
management_token: "${MCP_MGMT_TOKEN}"
|
|
373
|
+
|
|
374
|
+
autoload:
|
|
375
|
+
- echo
|
|
376
|
+
- shell
|
|
377
|
+
|
|
378
|
+
plugins:
|
|
379
|
+
echo:
|
|
380
|
+
enabled: true
|
|
381
|
+
shell:
|
|
382
|
+
enabled: true
|
|
383
|
+
timeout: 60
|
|
384
|
+
allowed_paths:
|
|
385
|
+
- "/home/user/projects"
|
|
386
|
+
blocked_commands:
|
|
387
|
+
- "sudo"
|
|
388
|
+
mattermost:
|
|
389
|
+
enabled: true
|
|
390
|
+
url: "https://mm.example.com"
|
|
391
|
+
token: "${MM_TOKEN}"
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Example configs in `config/` and `examples/configs/`.
|
|
395
|
+
|
|
396
|
+
## Tests
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
pytest # 159 tests
|
|
400
|
+
pytest -v # verbose
|
|
401
|
+
pytest tests/proxy/ # proxy only
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Project Structure
|
|
405
|
+
|
|
406
|
+
```
|
|
407
|
+
src/
|
|
408
|
+
├── mcp_server_framework/ # Shared: config, server, health, logging, plugins
|
|
409
|
+
├── mcp_server_factory/ # Static loader + CLI
|
|
410
|
+
└── mcp_server_proxy/ # Dynamic loader + management API + CLI
|
|
411
|
+
plugins/
|
|
412
|
+
├── echo.py # Minimal example
|
|
413
|
+
├── greet.py # Minimal example
|
|
414
|
+
├── mattermost/ # REST adapter (Mattermost)
|
|
415
|
+
├── wekan/ # REST adapter (Wekan Kanban)
|
|
416
|
+
└── shell/ # 33 workstation tools (filesystem, editor, search, shell, git, system, HTTP, packages)
|
|
417
|
+
examples/
|
|
418
|
+
├── mcp_client.py # Interactive test client
|
|
419
|
+
├── configs/ # Ready-to-use YAML configs
|
|
420
|
+
└── *.sh # Launch scripts
|
|
421
|
+
scripts/
|
|
422
|
+
└── new-plugin.sh # Plugin scaffold generator
|
|
423
|
+
tests/ # 159 tests (framework, factory, proxy, plugins)
|
|
424
|
+
config/ # Example configs + systemd service
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## License
|
|
428
|
+
|
|
429
|
+
MIT
|