node804-mcp-toolkit 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.
@@ -0,0 +1,28 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - name: Install
20
+ run: |
21
+ python -m pip install --upgrade pip
22
+ pip install -e ".[dev]"
23
+ - name: Lint
24
+ run: ruff check .
25
+ - name: Type check
26
+ run: mypy src
27
+ - name: Test
28
+ run: pytest -v
@@ -0,0 +1,35 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.13"
15
+ - name: Build sdist and wheel
16
+ run: |
17
+ python -m pip install --upgrade pip build
18
+ python -m build
19
+ - uses: actions/upload-artifact@v4
20
+ with:
21
+ name: dist
22
+ path: dist/
23
+
24
+ publish:
25
+ needs: build
26
+ runs-on: ubuntu-latest
27
+ environment: pypi
28
+ permissions:
29
+ id-token: write # required for PyPI Trusted Publishing (OIDC)
30
+ steps:
31
+ - uses: actions/download-artifact@v4
32
+ with:
33
+ name: dist
34
+ path: dist/
35
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .pytest_cache/
5
+ .mypy_cache/
6
+ .ruff_cache/
7
+ .venv/
8
+ dist/
9
+ build/
10
+ *.log
11
+ .coverage
12
+ htmlcov/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Michael Pope
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,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: node804-mcp-toolkit
3
+ Version: 0.1.0
4
+ Summary: Shared utilities for token-efficient MCP servers — RBAC, audit logging, lean response shaping, TLS config
5
+ Project-URL: Homepage, https://github.com/Node804/node804-mcp-toolkit
6
+ Project-URL: Repository, https://github.com/Node804/node804-mcp-toolkit
7
+ Project-URL: Issues, https://github.com/Node804/node804-mcp-toolkit/issues
8
+ Author-email: Michael Pope <me@michaelpope.cv>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: audit,mcp,model-context-protocol,rbac,tls
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: pydantic>=2.10.6
24
+ Provides-Extra: dev
25
+ Requires-Dist: mypy>=1.10; extra == 'dev'
26
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
27
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
28
+ Requires-Dist: pytest>=8.0; extra == 'dev'
29
+ Requires-Dist: ruff>=0.6; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # node804-mcp-toolkit
33
+
34
+ [![CI](https://github.com/Node804/node804-mcp-toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/Node804/node804-mcp-toolkit/actions/workflows/ci.yml)
35
+ [![PyPI](https://img.shields.io/pypi/v/node804-mcp-toolkit)](https://pypi.org/project/node804-mcp-toolkit/)
36
+ [![Python](https://img.shields.io/pypi/pyversions/node804-mcp-toolkit)](https://pypi.org/project/node804-mcp-toolkit/)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
38
+
39
+ Shared utilities for building token-efficient, security-conscious [MCP](https://modelcontextprotocol.io) servers for IT operations. Provides the cross-cutting concerns every ops MCP needs — permission gating, audit logging, response shaping, TLS config — so each server in a suite implements them the same way.
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ pip install node804-mcp-toolkit
45
+ ```
46
+
47
+ ## What's in here
48
+
49
+ | Module | Purpose |
50
+ |---|---|
51
+ | `rbac` | Hierarchical permission modes (`read` / `standard` / `full` / `admin`); a gate decorator that only registers tools with the MCP server when the active mode qualifies — ungated tools are invisible to the AI client, not just blocked |
52
+ | `audit` | JSON-lines audit logging of every tool call with timing, success/error state, sensitive-key redaction, and long-value truncation |
53
+ | `lean` | Pure response-shaping helpers: field whitelisting, internal-key stripping, pagination, server-side pattern filtering |
54
+ | `tls` | Verify-by-default TLS config from env vars, with custom CA bundle support for internal PKI |
55
+ | `params` | Shared Pydantic parameter types (`VerboseFlag`, `FieldsList`, `Pagination`, `Pattern`) so every tool uses the same names, defaults, and descriptions |
56
+
57
+ ## Quick start
58
+
59
+ Gate tools by permission mode, with audit logging composed in:
60
+
61
+ ```python
62
+ from mcp.server.fastmcp import FastMCP
63
+ from node804_mcp_toolkit import Mode, ModeGate, open_sink
64
+
65
+ mcp = FastMCP("panos-mcp")
66
+
67
+ # Audit sink: writes JSONL when PANOS_AUDIT_LOG is set, no-op otherwise.
68
+ sink = open_sink(env_var="PANOS_AUDIT_LOG")
69
+
70
+ # Mode comes from env. Missing or invalid values fail safe to read-only.
71
+ gate = ModeGate.from_env(env_var="PANOS_MODE", audit_sink=sink)
72
+
73
+ @gate.tool(mcp, required=Mode.READ)
74
+ async def get_security_rules(...): ...
75
+
76
+ @gate.tool(mcp, required=Mode.ADMIN)
77
+ async def commit(...): ... # not registered at all unless PANOS_MODE=admin
78
+ ```
79
+
80
+ Shape responses for token efficiency:
81
+
82
+ ```python
83
+ from node804_mcp_toolkit import filter_by_pattern, paginate, strip_keys, whitelist
84
+
85
+ rules = strip_keys(raw_rules, ["@uuid", "@loc"]) # drop SDK internals
86
+ rules = filter_by_pattern(rules, pattern, name_field="name")
87
+ rules = paginate(rules, limit=100, offset=0)
88
+ rules = whitelist(rules, ["name", "action", "source", "destination"])
89
+ ```
90
+
91
+ Resolve TLS settings from environment (verify-by-default):
92
+
93
+ ```python
94
+ from node804_mcp_toolkit import resolve_tls_config
95
+ import httpx, os
96
+
97
+ tls = resolve_tls_config(dict(os.environ), prefix="PRTG")
98
+ # PRTG_TLS_VERIFY=false → verify off, with a loud stderr warning
99
+ # PRTG_TLS_CA=/path.pem → custom CA bundle for internal PKI
100
+ client = httpx.Client(verify=str(tls.ca_path) if tls.ca_bundle else tls.verify)
101
+ ```
102
+
103
+ ## Design philosophy
104
+
105
+ - **One toolkit, one set of patterns.** A user who learns the parameter conventions in any one MCP — `verbose`, `fields`, `limit`, `offset`, `pattern` — gets the same conventions in all of them.
106
+ - **Default deny.** Unset or misconfigured mode env vars fall back to read-only. Tools above the active mode are never registered, so the AI client can't even see them.
107
+ - **Token-lean by default.** Responses expose the fields the AI actually reasons over; `verbose=true` opts into the full payload.
108
+ - **Best-effort observability.** Audit logging never breaks a tool call — sink failures warn once to stderr and move on.
109
+
110
+ ## Used by
111
+
112
+ - [`node804-panos-mcp`](https://github.com/Node804) — Palo Alto firewall management
113
+ - [`node804-freshservice-mcp`](https://github.com/Node804) — Freshservice ticketing
114
+ - Planned: PRTG and Veeam MCPs
115
+
116
+ ## Development
117
+
118
+ ```bash
119
+ pip install -e ".[dev]"
120
+ pytest
121
+ ruff check .
122
+ mypy src
123
+ ```
124
+
125
+ Requires Python 3.11+. Fully typed (`py.typed` included), `mypy --strict` clean.
126
+
127
+ ## License
128
+
129
+ [MIT](LICENSE)
@@ -0,0 +1,98 @@
1
+ # node804-mcp-toolkit
2
+
3
+ [![CI](https://github.com/Node804/node804-mcp-toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/Node804/node804-mcp-toolkit/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/node804-mcp-toolkit)](https://pypi.org/project/node804-mcp-toolkit/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/node804-mcp-toolkit)](https://pypi.org/project/node804-mcp-toolkit/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ Shared utilities for building token-efficient, security-conscious [MCP](https://modelcontextprotocol.io) servers for IT operations. Provides the cross-cutting concerns every ops MCP needs — permission gating, audit logging, response shaping, TLS config — so each server in a suite implements them the same way.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ pip install node804-mcp-toolkit
14
+ ```
15
+
16
+ ## What's in here
17
+
18
+ | Module | Purpose |
19
+ |---|---|
20
+ | `rbac` | Hierarchical permission modes (`read` / `standard` / `full` / `admin`); a gate decorator that only registers tools with the MCP server when the active mode qualifies — ungated tools are invisible to the AI client, not just blocked |
21
+ | `audit` | JSON-lines audit logging of every tool call with timing, success/error state, sensitive-key redaction, and long-value truncation |
22
+ | `lean` | Pure response-shaping helpers: field whitelisting, internal-key stripping, pagination, server-side pattern filtering |
23
+ | `tls` | Verify-by-default TLS config from env vars, with custom CA bundle support for internal PKI |
24
+ | `params` | Shared Pydantic parameter types (`VerboseFlag`, `FieldsList`, `Pagination`, `Pattern`) so every tool uses the same names, defaults, and descriptions |
25
+
26
+ ## Quick start
27
+
28
+ Gate tools by permission mode, with audit logging composed in:
29
+
30
+ ```python
31
+ from mcp.server.fastmcp import FastMCP
32
+ from node804_mcp_toolkit import Mode, ModeGate, open_sink
33
+
34
+ mcp = FastMCP("panos-mcp")
35
+
36
+ # Audit sink: writes JSONL when PANOS_AUDIT_LOG is set, no-op otherwise.
37
+ sink = open_sink(env_var="PANOS_AUDIT_LOG")
38
+
39
+ # Mode comes from env. Missing or invalid values fail safe to read-only.
40
+ gate = ModeGate.from_env(env_var="PANOS_MODE", audit_sink=sink)
41
+
42
+ @gate.tool(mcp, required=Mode.READ)
43
+ async def get_security_rules(...): ...
44
+
45
+ @gate.tool(mcp, required=Mode.ADMIN)
46
+ async def commit(...): ... # not registered at all unless PANOS_MODE=admin
47
+ ```
48
+
49
+ Shape responses for token efficiency:
50
+
51
+ ```python
52
+ from node804_mcp_toolkit import filter_by_pattern, paginate, strip_keys, whitelist
53
+
54
+ rules = strip_keys(raw_rules, ["@uuid", "@loc"]) # drop SDK internals
55
+ rules = filter_by_pattern(rules, pattern, name_field="name")
56
+ rules = paginate(rules, limit=100, offset=0)
57
+ rules = whitelist(rules, ["name", "action", "source", "destination"])
58
+ ```
59
+
60
+ Resolve TLS settings from environment (verify-by-default):
61
+
62
+ ```python
63
+ from node804_mcp_toolkit import resolve_tls_config
64
+ import httpx, os
65
+
66
+ tls = resolve_tls_config(dict(os.environ), prefix="PRTG")
67
+ # PRTG_TLS_VERIFY=false → verify off, with a loud stderr warning
68
+ # PRTG_TLS_CA=/path.pem → custom CA bundle for internal PKI
69
+ client = httpx.Client(verify=str(tls.ca_path) if tls.ca_bundle else tls.verify)
70
+ ```
71
+
72
+ ## Design philosophy
73
+
74
+ - **One toolkit, one set of patterns.** A user who learns the parameter conventions in any one MCP — `verbose`, `fields`, `limit`, `offset`, `pattern` — gets the same conventions in all of them.
75
+ - **Default deny.** Unset or misconfigured mode env vars fall back to read-only. Tools above the active mode are never registered, so the AI client can't even see them.
76
+ - **Token-lean by default.** Responses expose the fields the AI actually reasons over; `verbose=true` opts into the full payload.
77
+ - **Best-effort observability.** Audit logging never breaks a tool call — sink failures warn once to stderr and move on.
78
+
79
+ ## Used by
80
+
81
+ - [`node804-panos-mcp`](https://github.com/Node804) — Palo Alto firewall management
82
+ - [`node804-freshservice-mcp`](https://github.com/Node804) — Freshservice ticketing
83
+ - Planned: PRTG and Veeam MCPs
84
+
85
+ ## Development
86
+
87
+ ```bash
88
+ pip install -e ".[dev]"
89
+ pytest
90
+ ruff check .
91
+ mypy src
92
+ ```
93
+
94
+ Requires Python 3.11+. Fully typed (`py.typed` included), `mypy --strict` clean.
95
+
96
+ ## License
97
+
98
+ [MIT](LICENSE)
@@ -0,0 +1,77 @@
1
+ [project]
2
+ name = "node804-mcp-toolkit"
3
+ dynamic = ["version"]
4
+ description = "Shared utilities for token-efficient MCP servers — RBAC, audit logging, lean response shaping, TLS config"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ keywords = ["mcp", "model-context-protocol", "rbac", "audit", "tls"]
10
+ classifiers = [
11
+ "Development Status :: 4 - Beta",
12
+ "Intended Audience :: System Administrators",
13
+ "Intended Audience :: Developers",
14
+ "Operating System :: OS Independent",
15
+ "Programming Language :: Python :: 3",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Programming Language :: Python :: 3.14",
20
+ "Typing :: Typed",
21
+ ]
22
+ dependencies = [
23
+ "pydantic>=2.10.6",
24
+ ]
25
+
26
+ [[project.authors]]
27
+ name = "Michael Pope"
28
+ email = "me@michaelpope.cv"
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/Node804/node804-mcp-toolkit"
32
+ Repository = "https://github.com/Node804/node804-mcp-toolkit"
33
+ Issues = "https://github.com/Node804/node804-mcp-toolkit/issues"
34
+
35
+ [project.optional-dependencies]
36
+ dev = [
37
+ "pytest>=8.0",
38
+ "pytest-asyncio>=0.23",
39
+ "pytest-cov>=5.0",
40
+ "ruff>=0.6",
41
+ "mypy>=1.10",
42
+ ]
43
+
44
+ [build-system]
45
+ requires = ["hatchling"]
46
+ build-backend = "hatchling.build"
47
+
48
+ # Single source of truth for the version: __version__ in __init__.py.
49
+ [tool.hatch.version]
50
+ path = "src/node804_mcp_toolkit/__init__.py"
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["src/node804_mcp_toolkit"]
54
+
55
+ # Include py.typed marker so type checkers (mypy, pyright) consume the
56
+ # inline annotations. Without this, downstream MCPs see "missing library
57
+ # stubs" errors when they import from node804_mcp_toolkit.
58
+ [tool.hatch.build.targets.wheel.force-include]
59
+ "src/node804_mcp_toolkit/py.typed" = "node804_mcp_toolkit/py.typed"
60
+
61
+ [tool.ruff]
62
+ line-length = 100
63
+ target-version = "py311"
64
+
65
+ [tool.ruff.lint]
66
+ select = ["E", "F", "I", "B", "UP", "SIM", "RUF"]
67
+ ignore = ["E501"] # long lines handled by formatter
68
+
69
+ [tool.mypy]
70
+ python_version = "3.11"
71
+ strict = true
72
+ warn_unused_ignores = true
73
+ disallow_untyped_defs = true
74
+
75
+ [tool.pytest.ini_options]
76
+ testpaths = ["tests"]
77
+ asyncio_mode = "auto"
@@ -0,0 +1,45 @@
1
+ """Shared utilities for token-efficient MCP servers.
2
+
3
+ Public API re-exported here for convenience::
4
+
5
+ from node804_mcp_toolkit import Mode, ModeGate, audit, open_sink, whitelist, ...
6
+ """
7
+
8
+ from .audit import (
9
+ AuditCategory,
10
+ AuditEvent,
11
+ AuditSink,
12
+ JsonlSink,
13
+ audit,
14
+ open_sink,
15
+ sanitize_args,
16
+ )
17
+ from .lean import filter_by_pattern, paginate, strip_keys, whitelist
18
+ from .params import FieldsList, Pagination, Pattern, VerboseFlag
19
+ from .rbac import Mode, ModeGate
20
+ from .tls import TlsConfig, describe_tls, resolve_tls_config
21
+
22
+ __version__ = "0.1.0"
23
+
24
+ __all__ = [
25
+ "AuditCategory",
26
+ "AuditEvent",
27
+ "AuditSink",
28
+ "FieldsList",
29
+ "JsonlSink",
30
+ "Mode",
31
+ "ModeGate",
32
+ "Pagination",
33
+ "Pattern",
34
+ "TlsConfig",
35
+ "VerboseFlag",
36
+ "audit",
37
+ "describe_tls",
38
+ "filter_by_pattern",
39
+ "open_sink",
40
+ "paginate",
41
+ "resolve_tls_config",
42
+ "sanitize_args",
43
+ "strip_keys",
44
+ "whitelist",
45
+ ]