dopesecurity-mcp-server 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.
Files changed (28) hide show
  1. dopesecurity_mcp_server-0.1.0/.gitignore +15 -0
  2. dopesecurity_mcp_server-0.1.0/CHANGELOG.md +7 -0
  3. dopesecurity_mcp_server-0.1.0/LICENSE +21 -0
  4. dopesecurity_mcp_server-0.1.0/PKG-INFO +241 -0
  5. dopesecurity_mcp_server-0.1.0/README.md +211 -0
  6. dopesecurity_mcp_server-0.1.0/VERSION +1 -0
  7. dopesecurity_mcp_server-0.1.0/pyproject.toml +94 -0
  8. dopesecurity_mcp_server-0.1.0/src/dopesecurity/__init__.py +1 -0
  9. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/__init__.py +5 -0
  10. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/__main__.py +135 -0
  11. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/auth.py +209 -0
  12. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/config.py +172 -0
  13. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/errors.py +236 -0
  14. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/flightdeck/__init__.py +1 -0
  15. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/flightdeck/client.py +437 -0
  16. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/flightdeck/models.py +27 -0
  17. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/instructions.py +69 -0
  18. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/py.typed +1 -0
  19. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/schemas.py +578 -0
  20. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/server.py +139 -0
  21. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/services/__init__.py +1 -0
  22. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/services/custom_categories.py +93 -0
  23. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/services/endpoints.py +43 -0
  24. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/services/policies.py +433 -0
  25. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/tools/__init__.py +17 -0
  26. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/tools/custom_categories.py +158 -0
  27. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/tools/endpoints.py +69 -0
  28. dopesecurity_mcp_server-0.1.0/src/dopesecurity/mcp_server/tools/policies.py +438 -0
@@ -0,0 +1,15 @@
1
+ .venv/
2
+ .pytest_cache/
3
+ .ruff_cache/
4
+ .mypy_cache/
5
+ .amp/
6
+ .ropeproject/
7
+ dist/
8
+ *.egg-info/
9
+ __pycache__/
10
+ *.pyc
11
+ .DS_Store
12
+
13
+ # Scratch file used to capture failing tool runs during development.
14
+ # Repo-root only; intentionally not docs/failures.md.
15
+ /failures.md
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.1.0] — 2026-05-29
6
+
7
+ Initial public release.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dope.security
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,241 @@
1
+ Metadata-Version: 2.4
2
+ Name: dopesecurity-mcp-server
3
+ Version: 0.1.0
4
+ Summary: Local MCP server for the dope.security Flightdeck partner API
5
+ Project-URL: Homepage, https://dope.security
6
+ Project-URL: Repository, https://github.com/dopesecurity/mcp
7
+ Project-URL: Changelog, https://github.com/dopesecurity/mcp/blob/main/CHANGELOG.md
8
+ Author: dope.security
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai,dope.security,mcp,model-context-protocol,security,swg
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Information Technology
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: Topic :: Security
21
+ Classifier: Topic :: System :: Systems Administration
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: httpx>=0.27.0
25
+ Requires-Dist: mcp>=1.2.0
26
+ Requires-Dist: pydantic-settings>=2.2
27
+ Requires-Dist: pydantic>=2.6
28
+ Requires-Dist: structlog>=24.1.0
29
+ Description-Content-Type: text/markdown
30
+
31
+ # dopesecurity-mcp-server
32
+
33
+ The Dope MCP is a local [Model Context Protocol](https://modelcontextprotocol.io)
34
+ server that lets an AI assistant talk to your dope.security tenant —
35
+ look at endpoints, read and tweak policies, and curate custom URL
36
+ categories. It wraps most of the Flightdeck partner API, runs on your
37
+ machine, and is **read-only out of the box**: nothing changes in your
38
+ tenant until you explicitly turn writes on. It's currently in beta, we
39
+ hope you enjoy using it.
40
+
41
+ ## Installation
42
+
43
+ Installation is via `uvx`.
44
+
45
+ Runs the server on demand. Nothing is installed globally.
46
+
47
+ **Prerequisites**
48
+
49
+ 1. Install `uv` — see [Astral's install guide](https://docs.astral.sh/uv/getting-started/installation/).
50
+ 2. Install a Python runtime with `uv`:
51
+
52
+ ```sh
53
+ uv python install 3.11
54
+ ```
55
+
56
+ **MCP client config**
57
+
58
+ Add the server to your MCP client configuration:
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "dope-security": {
64
+ "command": "uvx",
65
+ "args": ["dopesecurity-mcp-server"],
66
+ "env": {
67
+ "DOPE_CLIENT_ID": "your-client-id",
68
+ "DOPE_CLIENT_SECRET": "your-client-secret",
69
+ "DOPE_ENABLE_MUTATIONS": "false",
70
+ "DOPE_ENABLE_DESTRUCTIVE": "false"
71
+ }
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ ## Three tiers of access
78
+
79
+ The tool surface is gated by two environment variables, both `false`
80
+ by default. Tools that aren't enabled by the active combination are
81
+ **not registered** at all — they don't exist on the MCP wire.
82
+
83
+ | `DOPE_ENABLE_MUTATIONS` | `DOPE_ENABLE_DESTRUCTIVE` | What the agent can do |
84
+ | ----------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
85
+ | `false` | `false` | **Read-only.** Inspect endpoints, policies, custom categories. Cannot modify the tenant. |
86
+ | `true` | `false` | **Read + write.** Per-entry creates, updates, upserts, assigns, unassigns, and per-entry deletes. Cannot drop a whole policy or wipe a section. |
87
+ | `true` | `true` | **Read + write + destructive.** Adds whole-policy drops, whole-section resets to base, whole-custom-category deletes, and wipe-all-URLs. |
88
+ | `false` | `true` | Invalid — the server refuses to start. |
89
+
90
+ Flightdeck RBAC still applies on top of whichever tier you enable:
91
+ even when a tool is registered, Flightdeck may reject the call because
92
+ your OAuth client's role doesn't permit it. Start with read-only,
93
+ flip to mutations when you trust the agent's workflow, and only enable
94
+ destructive when you explicitly want the agent to be able to start
95
+ over.
96
+
97
+ ## Configuration reference
98
+
99
+ | Env var | CLI flag | Default | Description |
100
+ | ------------------------ | ---------------------- | ------- | -------------------------------------------------------------------------------------------- |
101
+ | `DOPE_CLIENT_ID` | — | — | API client ID issued from the dope console. **Required.** |
102
+ | `DOPE_CLIENT_SECRET` | — | — | API client secret issued from the dope console. **Required.** |
103
+ | `DOPE_ENABLE_MUTATIONS` | `--enable-mutations` | `false` | Expose write tools that modify tenant state. |
104
+ | `DOPE_ENABLE_DESTRUCTIVE`| `--enable-destructive` | `false` | Additionally expose destructive tools (whole-policy drops, whole-section resets). Requires mutations. |
105
+ | `DOPE_TIMEOUT_SECONDS` | `--timeout-seconds` | `30` | HTTP timeout for Flightdeck calls. |
106
+ | `DOPE_LOG_LEVEL` | `--log-level` | `INFO` | Log verbosity (logs go to stderr only). |
107
+
108
+ `DOPE_CLIENT_ID` and `DOPE_CLIENT_SECRET` should be provided as
109
+ environment variables. You can grab the credentials from the
110
+ [dope console](https://inflight.dope.security/dope.console/settings/api-client-credentials).
111
+
112
+ ## Available tools
113
+
114
+ ### Endpoints (read-only)
115
+
116
+ | Tool | Description |
117
+ | ------------------- | ---------------------------------------- |
118
+ | `search_endpoints` | List or search endpoints (cursor paged). |
119
+
120
+ ### Policies (read)
121
+
122
+ | Tool | Description |
123
+ | ---------------------------------------- | ---------------------------------------- |
124
+ | `list_policies` | List all policies. |
125
+ | `get_policy_assignments` | Show users/groups assigned to a policy. |
126
+ | `get_policy_restrictions` | Show per-category restrictions. |
127
+ | `get_policy_exceptions` | Show per-category exceptions. |
128
+ | `get_policy_url_bypass` | List URL bypass entries. |
129
+ | `get_policy_application_bypass_entries` | List application bypass entries. |
130
+
131
+ ### Policies (write — only when mutations enabled)
132
+
133
+ | Tool | Description |
134
+ | --------------------------------------------- | ---------------------------------------------- |
135
+ | `create_policy` | Create a new policy. |
136
+ | `assign_policy_principals` | Add users/groups to a policy. |
137
+ | `unassign_policy_principals` | Remove users/groups from a policy. |
138
+ | `update_policy_restrictions` | Update per-category restrictions. |
139
+ | `replace_policy_category_exceptions` | Replace exceptions for the submitted category. |
140
+ | `upsert_policy_url_bypass` | Add or update URL bypass entries. |
141
+ | `delete_policy_url_bypass_entries` | Delete named URL bypass entries. |
142
+ | `upsert_policy_application_bypass` | Add or update application bypass entries. |
143
+ | `delete_policy_application_bypass_entries` | Delete named application bypass entries. |
144
+
145
+ ### Policies (destructive — only when both mutations and destructive are enabled)
146
+
147
+ | Tool | Description |
148
+ | ------------------------------------------ | ---------------------------------------- |
149
+ | `delete_policy` | Delete a whole policy. |
150
+ | `reset_policy_restrictions_to_base` | Reset all restrictions to Base. |
151
+ | `reset_policy_url_bypass_to_base` | Reset URL bypass to Base. |
152
+ | `reset_policy_application_bypass_to_base` | Reset application bypass to Base. |
153
+
154
+ ### Custom categories (read)
155
+
156
+ | Tool | Description |
157
+ | -------------------------- | --------------------------------- |
158
+ | `list_custom_categories` | List all custom categories. |
159
+ | `get_custom_category_urls` | List URLs in a custom category. |
160
+
161
+ ### Custom categories (write — only when mutations enabled)
162
+
163
+ | Tool | Description |
164
+ | ------------------------------------- | ------------------------------------ |
165
+ | `create_custom_category` | Create a new custom category. |
166
+ | `add_urls_to_custom_category` | Add URLs to a custom category. |
167
+ | `delete_single_url_from_custom_category` | Remove one URL from a category. |
168
+
169
+ ### Custom categories (destructive — only when both mutations and destructive are enabled)
170
+
171
+ | Tool | Description |
172
+ | ------------------------------------- | ------------------------------------ |
173
+ | `delete_custom_category` | Delete a whole custom category. |
174
+ | `delete_all_urls_from_custom_category`| Wipe every URL from a category. |
175
+
176
+ ## Developing
177
+
178
+ ### Setup and verification
179
+
180
+ From the repository root:
181
+
182
+ ```sh
183
+ make install # uv sync --locked
184
+ make check # lint + typecheck + unit tests
185
+ make integration-tests # requires DOPE_MCP_TESTS_CLIENT_SECRET
186
+ uv run dopesecurity-mcp-server --help
187
+ ```
188
+
189
+ Run `make help` to see all available targets.
190
+
191
+ ### Known limitations
192
+
193
+ - `assign_policy_principals` and `unassign_policy_principals` are
194
+ read-merge-write on top of Flightdeck's overwrite-only assignments
195
+ endpoint, so concurrent edits to the same policy may be clobbered.
196
+ - Pagination is cursor-based; the mcp server does not auto-fetch all pages.
197
+
198
+ ### Flightdeck routes deliberately omitted from MCP
199
+
200
+ Some Flightdeck partner API routes are intentionally **not** exposed as
201
+ MCP tools and will not be added. This is the list — treat it as a
202
+ "don't bother proposing this" register.
203
+
204
+ - `PUT /custom_categories/{name}/urls` — overwrite-all semantics. An
205
+ agent calling this with a partial list silently destroys every URL it
206
+ didn't mention. Use `add_urls_to_custom_category`,
207
+ `delete_single_url_from_custom_category`, and
208
+ `delete_all_urls_from_custom_category` instead, which force the agent
209
+ to state intent explicitly.
210
+
211
+ ### Running a local checkout from an MCP client
212
+
213
+ To point an MCP client (Amp, Claude Desktop, etc.) at your local checkout
214
+ instead of the published `uvx` package, replace the `command`/`args` so the
215
+ client launches the server through `uv run --directory`:
216
+
217
+ ```json
218
+ {
219
+ "mcpServers": {
220
+ "dope-security-dev": {
221
+ "command": "uv",
222
+ "args": [
223
+ "run",
224
+ "--directory",
225
+ "/absolute/path/to/dopemcp",
226
+ "dopesecurity-mcp-server"
227
+ ],
228
+ "env": {
229
+ "DOPE_CLIENT_ID": "your-client-id",
230
+ "DOPE_CLIENT_SECRET": "your-client-secret",
231
+ "DOPE_ENABLE_MUTATIONS": "true",
232
+ "DOPE_ENABLE_DESTRUCTIVE": "true",
233
+ "DOPE_LOG_LEVEL": "DEBUG"
234
+ }
235
+ }
236
+ }
237
+ }
238
+ ```
239
+
240
+ Replace `/absolute/path/to/dopemcp` with the path to your clone. The MCP
241
+ client spawns the server over stdio on demand.
@@ -0,0 +1,211 @@
1
+ # dopesecurity-mcp-server
2
+
3
+ The Dope MCP is a local [Model Context Protocol](https://modelcontextprotocol.io)
4
+ server that lets an AI assistant talk to your dope.security tenant —
5
+ look at endpoints, read and tweak policies, and curate custom URL
6
+ categories. It wraps most of the Flightdeck partner API, runs on your
7
+ machine, and is **read-only out of the box**: nothing changes in your
8
+ tenant until you explicitly turn writes on. It's currently in beta, we
9
+ hope you enjoy using it.
10
+
11
+ ## Installation
12
+
13
+ Installation is via `uvx`.
14
+
15
+ Runs the server on demand. Nothing is installed globally.
16
+
17
+ **Prerequisites**
18
+
19
+ 1. Install `uv` — see [Astral's install guide](https://docs.astral.sh/uv/getting-started/installation/).
20
+ 2. Install a Python runtime with `uv`:
21
+
22
+ ```sh
23
+ uv python install 3.11
24
+ ```
25
+
26
+ **MCP client config**
27
+
28
+ Add the server to your MCP client configuration:
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "dope-security": {
34
+ "command": "uvx",
35
+ "args": ["dopesecurity-mcp-server"],
36
+ "env": {
37
+ "DOPE_CLIENT_ID": "your-client-id",
38
+ "DOPE_CLIENT_SECRET": "your-client-secret",
39
+ "DOPE_ENABLE_MUTATIONS": "false",
40
+ "DOPE_ENABLE_DESTRUCTIVE": "false"
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Three tiers of access
48
+
49
+ The tool surface is gated by two environment variables, both `false`
50
+ by default. Tools that aren't enabled by the active combination are
51
+ **not registered** at all — they don't exist on the MCP wire.
52
+
53
+ | `DOPE_ENABLE_MUTATIONS` | `DOPE_ENABLE_DESTRUCTIVE` | What the agent can do |
54
+ | ----------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
55
+ | `false` | `false` | **Read-only.** Inspect endpoints, policies, custom categories. Cannot modify the tenant. |
56
+ | `true` | `false` | **Read + write.** Per-entry creates, updates, upserts, assigns, unassigns, and per-entry deletes. Cannot drop a whole policy or wipe a section. |
57
+ | `true` | `true` | **Read + write + destructive.** Adds whole-policy drops, whole-section resets to base, whole-custom-category deletes, and wipe-all-URLs. |
58
+ | `false` | `true` | Invalid — the server refuses to start. |
59
+
60
+ Flightdeck RBAC still applies on top of whichever tier you enable:
61
+ even when a tool is registered, Flightdeck may reject the call because
62
+ your OAuth client's role doesn't permit it. Start with read-only,
63
+ flip to mutations when you trust the agent's workflow, and only enable
64
+ destructive when you explicitly want the agent to be able to start
65
+ over.
66
+
67
+ ## Configuration reference
68
+
69
+ | Env var | CLI flag | Default | Description |
70
+ | ------------------------ | ---------------------- | ------- | -------------------------------------------------------------------------------------------- |
71
+ | `DOPE_CLIENT_ID` | — | — | API client ID issued from the dope console. **Required.** |
72
+ | `DOPE_CLIENT_SECRET` | — | — | API client secret issued from the dope console. **Required.** |
73
+ | `DOPE_ENABLE_MUTATIONS` | `--enable-mutations` | `false` | Expose write tools that modify tenant state. |
74
+ | `DOPE_ENABLE_DESTRUCTIVE`| `--enable-destructive` | `false` | Additionally expose destructive tools (whole-policy drops, whole-section resets). Requires mutations. |
75
+ | `DOPE_TIMEOUT_SECONDS` | `--timeout-seconds` | `30` | HTTP timeout for Flightdeck calls. |
76
+ | `DOPE_LOG_LEVEL` | `--log-level` | `INFO` | Log verbosity (logs go to stderr only). |
77
+
78
+ `DOPE_CLIENT_ID` and `DOPE_CLIENT_SECRET` should be provided as
79
+ environment variables. You can grab the credentials from the
80
+ [dope console](https://inflight.dope.security/dope.console/settings/api-client-credentials).
81
+
82
+ ## Available tools
83
+
84
+ ### Endpoints (read-only)
85
+
86
+ | Tool | Description |
87
+ | ------------------- | ---------------------------------------- |
88
+ | `search_endpoints` | List or search endpoints (cursor paged). |
89
+
90
+ ### Policies (read)
91
+
92
+ | Tool | Description |
93
+ | ---------------------------------------- | ---------------------------------------- |
94
+ | `list_policies` | List all policies. |
95
+ | `get_policy_assignments` | Show users/groups assigned to a policy. |
96
+ | `get_policy_restrictions` | Show per-category restrictions. |
97
+ | `get_policy_exceptions` | Show per-category exceptions. |
98
+ | `get_policy_url_bypass` | List URL bypass entries. |
99
+ | `get_policy_application_bypass_entries` | List application bypass entries. |
100
+
101
+ ### Policies (write — only when mutations enabled)
102
+
103
+ | Tool | Description |
104
+ | --------------------------------------------- | ---------------------------------------------- |
105
+ | `create_policy` | Create a new policy. |
106
+ | `assign_policy_principals` | Add users/groups to a policy. |
107
+ | `unassign_policy_principals` | Remove users/groups from a policy. |
108
+ | `update_policy_restrictions` | Update per-category restrictions. |
109
+ | `replace_policy_category_exceptions` | Replace exceptions for the submitted category. |
110
+ | `upsert_policy_url_bypass` | Add or update URL bypass entries. |
111
+ | `delete_policy_url_bypass_entries` | Delete named URL bypass entries. |
112
+ | `upsert_policy_application_bypass` | Add or update application bypass entries. |
113
+ | `delete_policy_application_bypass_entries` | Delete named application bypass entries. |
114
+
115
+ ### Policies (destructive — only when both mutations and destructive are enabled)
116
+
117
+ | Tool | Description |
118
+ | ------------------------------------------ | ---------------------------------------- |
119
+ | `delete_policy` | Delete a whole policy. |
120
+ | `reset_policy_restrictions_to_base` | Reset all restrictions to Base. |
121
+ | `reset_policy_url_bypass_to_base` | Reset URL bypass to Base. |
122
+ | `reset_policy_application_bypass_to_base` | Reset application bypass to Base. |
123
+
124
+ ### Custom categories (read)
125
+
126
+ | Tool | Description |
127
+ | -------------------------- | --------------------------------- |
128
+ | `list_custom_categories` | List all custom categories. |
129
+ | `get_custom_category_urls` | List URLs in a custom category. |
130
+
131
+ ### Custom categories (write — only when mutations enabled)
132
+
133
+ | Tool | Description |
134
+ | ------------------------------------- | ------------------------------------ |
135
+ | `create_custom_category` | Create a new custom category. |
136
+ | `add_urls_to_custom_category` | Add URLs to a custom category. |
137
+ | `delete_single_url_from_custom_category` | Remove one URL from a category. |
138
+
139
+ ### Custom categories (destructive — only when both mutations and destructive are enabled)
140
+
141
+ | Tool | Description |
142
+ | ------------------------------------- | ------------------------------------ |
143
+ | `delete_custom_category` | Delete a whole custom category. |
144
+ | `delete_all_urls_from_custom_category`| Wipe every URL from a category. |
145
+
146
+ ## Developing
147
+
148
+ ### Setup and verification
149
+
150
+ From the repository root:
151
+
152
+ ```sh
153
+ make install # uv sync --locked
154
+ make check # lint + typecheck + unit tests
155
+ make integration-tests # requires DOPE_MCP_TESTS_CLIENT_SECRET
156
+ uv run dopesecurity-mcp-server --help
157
+ ```
158
+
159
+ Run `make help` to see all available targets.
160
+
161
+ ### Known limitations
162
+
163
+ - `assign_policy_principals` and `unassign_policy_principals` are
164
+ read-merge-write on top of Flightdeck's overwrite-only assignments
165
+ endpoint, so concurrent edits to the same policy may be clobbered.
166
+ - Pagination is cursor-based; the mcp server does not auto-fetch all pages.
167
+
168
+ ### Flightdeck routes deliberately omitted from MCP
169
+
170
+ Some Flightdeck partner API routes are intentionally **not** exposed as
171
+ MCP tools and will not be added. This is the list — treat it as a
172
+ "don't bother proposing this" register.
173
+
174
+ - `PUT /custom_categories/{name}/urls` — overwrite-all semantics. An
175
+ agent calling this with a partial list silently destroys every URL it
176
+ didn't mention. Use `add_urls_to_custom_category`,
177
+ `delete_single_url_from_custom_category`, and
178
+ `delete_all_urls_from_custom_category` instead, which force the agent
179
+ to state intent explicitly.
180
+
181
+ ### Running a local checkout from an MCP client
182
+
183
+ To point an MCP client (Amp, Claude Desktop, etc.) at your local checkout
184
+ instead of the published `uvx` package, replace the `command`/`args` so the
185
+ client launches the server through `uv run --directory`:
186
+
187
+ ```json
188
+ {
189
+ "mcpServers": {
190
+ "dope-security-dev": {
191
+ "command": "uv",
192
+ "args": [
193
+ "run",
194
+ "--directory",
195
+ "/absolute/path/to/dopemcp",
196
+ "dopesecurity-mcp-server"
197
+ ],
198
+ "env": {
199
+ "DOPE_CLIENT_ID": "your-client-id",
200
+ "DOPE_CLIENT_SECRET": "your-client-secret",
201
+ "DOPE_ENABLE_MUTATIONS": "true",
202
+ "DOPE_ENABLE_DESTRUCTIVE": "true",
203
+ "DOPE_LOG_LEVEL": "DEBUG"
204
+ }
205
+ }
206
+ }
207
+ }
208
+ ```
209
+
210
+ Replace `/absolute/path/to/dopemcp` with the path to your clone. The MCP
211
+ client spawns the server over stdio on demand.
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,94 @@
1
+ [project]
2
+ name = "dopesecurity-mcp-server"
3
+ dynamic = ["version"]
4
+ description = "Local MCP server for the dope.security Flightdeck partner API"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ authors = [{ name = "dope.security" }]
10
+ keywords = ["mcp", "model-context-protocol", "ai", "dope.security", "security", "swg"]
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Intended Audience :: System Administrators",
14
+ "Intended Audience :: Information Technology",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Topic :: Security",
21
+ "Topic :: System :: Systems Administration",
22
+ "Typing :: Typed",
23
+ ]
24
+ dependencies = [
25
+ "mcp>=1.2.0",
26
+ "httpx>=0.27.0",
27
+ "pydantic>=2.6",
28
+ "pydantic-settings>=2.2",
29
+ "structlog>=24.1.0",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://dope.security"
34
+ Repository = "https://github.com/dopesecurity/mcp"
35
+ Changelog = "https://github.com/dopesecurity/mcp/blob/main/CHANGELOG.md"
36
+
37
+ [project.scripts]
38
+ dopesecurity-mcp-server = "dopesecurity.mcp_server.__main__:main"
39
+
40
+ [build-system]
41
+ requires = ["hatchling"]
42
+ build-backend = "hatchling.build"
43
+
44
+ [tool.hatch.version]
45
+ path = "VERSION"
46
+ pattern = "^(?P<version>.+)$"
47
+
48
+ [tool.hatch.build.targets.wheel]
49
+ packages = ["src/dopesecurity"]
50
+ exclude = ["**/tests/**"]
51
+
52
+ [tool.hatch.build.targets.sdist]
53
+ include = [
54
+ "/src/dopesecurity",
55
+ "/README.md",
56
+ "/CHANGELOG.md",
57
+ "/LICENSE",
58
+ "/VERSION",
59
+ "/pyproject.toml",
60
+ ]
61
+ exclude = ["**/tests/**"]
62
+
63
+ [dependency-groups]
64
+ dev = [
65
+ "pytest>=8.0",
66
+ "pytest-asyncio>=0.23",
67
+ "ruff>=0.5.0",
68
+ "mypy>=1.10",
69
+ ]
70
+
71
+ [tool.ruff]
72
+ target-version = "py311"
73
+ src = ["src"]
74
+ line-length = 100
75
+
76
+ [tool.ruff.lint]
77
+ select = ["E", "F", "W", "I", "B", "UP", "N"]
78
+ ignore = ["E501"]
79
+
80
+ [tool.mypy]
81
+ python_version = "3.11"
82
+ strict = true
83
+ packages = ["dopesecurity.mcp_server"]
84
+ mypy_path = "src"
85
+ explicit_package_bases = true
86
+
87
+ [[tool.mypy.overrides]]
88
+ module = "mcp.*"
89
+ ignore_missing_imports = true
90
+
91
+ [tool.pytest.ini_options]
92
+ testpaths = ["src"]
93
+ asyncio_mode = "auto"
94
+ filterwarnings = ["error"]
@@ -0,0 +1 @@
1
+ """dope.security Python packages."""
@@ -0,0 +1,5 @@
1
+ """dope.security MCP server."""
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.1.0"