proofflow-mcp 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,24 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .venv/
5
+ .pytest_cache/
6
+
7
+ # Local data
8
+ *.sqlite3
9
+ *.db
10
+ backend/data/demo/
11
+ sample_data/work/
12
+ sample_data/repos/
13
+
14
+ # Frontend
15
+ node_modules/
16
+ dist/
17
+ .vite/
18
+ *.tsbuildinfo
19
+
20
+ # OS and editor files
21
+ .DS_Store
22
+ Thumbs.db
23
+ .idea/
24
+ .vscode/
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.4
2
+ Name: proofflow-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for ProofFlow – audit infrastructure for AI coding agents
5
+ Project-URL: Homepage, https://github.com/Hyperion-GPU/ProofFlow-v0.1
6
+ Project-URL: Repository, https://github.com/Hyperion-GPU/ProofFlow-v0.1
7
+ Project-URL: Issues, https://github.com/Hyperion-GPU/ProofFlow-v0.1/issues
8
+ Author: Hyperion-GPU
9
+ License-Expression: MIT
10
+ Keywords: ai-agent,audit,claude-code,codex,mcp,proofflow
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Quality Assurance
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: httpx>=0.27.0
19
+ Requires-Dist: mcp>=1.0.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
22
+ Requires-Dist: pytest>=8.0; extra == 'dev'
23
+ Requires-Dist: respx>=0.21; extra == 'dev'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # ProofFlow MCP Server
27
+
28
+ MCP (Model Context Protocol) server that exposes ProofFlow's audit capabilities as tools for Claude Code and Codex.
29
+
30
+ ## What it does
31
+
32
+ Lets AI coding assistants trigger ProofFlow workflows directly:
33
+
34
+ - **Scan folders** — index files with SHA-256 hashes, create audit Cases
35
+ - **Code review** — analyze git diffs, generate evidence-backed risk claims
36
+ - **Suggest actions** — generate file organization suggestions
37
+ - **Approve & execute** — run pending actions (with policy gate awareness)
38
+ - **Export Proof Packets** — generate shareable markdown audit reports
39
+ - **Search** — full-text search across indexed artifacts
40
+ - **Undo** — reverse executed actions
41
+
42
+ ## Prerequisites
43
+
44
+ - Python 3.11+
45
+ - ProofFlow backend running on `http://127.0.0.1:8787`
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ cd mcp-server
51
+ pip install -e .
52
+ ```
53
+
54
+ For development (includes test dependencies):
55
+
56
+ ```bash
57
+ pip install -e ".[dev]"
58
+ ```
59
+
60
+ > Note: Install in a separate virtualenv from the backend to avoid starlette version conflicts between FastAPI and the MCP SDK.
61
+
62
+ ## Configuration
63
+
64
+ ### Claude Code
65
+
66
+ Add to your project's `.mcp.json` or `~/.claude/settings.json`:
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "proofflow": {
72
+ "command": "python",
73
+ "args": ["-m", "proofflow_mcp"],
74
+ "env": {
75
+ "PROOFFLOW_BASE_URL": "http://127.0.0.1:8787"
76
+ }
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Claude Desktop
83
+
84
+ Add to `claude_desktop_config.json`:
85
+ - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
86
+ - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
87
+
88
+ ```json
89
+ {
90
+ "mcpServers": {
91
+ "proofflow": {
92
+ "command": "proofflow-mcp",
93
+ "env": {
94
+ "PROOFFLOW_BASE_URL": "http://127.0.0.1:8787"
95
+ }
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### Codex
102
+
103
+ Add to your Codex MCP configuration with the same command/args pattern.
104
+
105
+ ### Environment Variables
106
+
107
+ | Variable | Default | Description |
108
+ |----------|---------|-------------|
109
+ | `PROOFFLOW_BASE_URL` | `http://127.0.0.1:8787` | ProofFlow backend URL |
110
+ | `PROOFFLOW_TIMEOUT` | `30` | HTTP request timeout in seconds |
111
+ | `PROOFFLOW_API_KEY` | *(unset)* | API key for backend auth (optional) |
112
+ | `PROOFFLOW_MCP_MAX_CONCURRENT` | `5` | Max concurrent MCP tool calls |
113
+
114
+ ## Available Tools
115
+
116
+ | Tool | Description |
117
+ |------|-------------|
118
+ | `proofflow_health` | Check backend connectivity |
119
+ | `proofflow_scan` | Scan a folder, create Case + Artifacts |
120
+ | `proofflow_suggest` | Generate cleanup suggestions for a scanned Case |
121
+ | `proofflow_review` | AgentGuard code review on a git repo |
122
+ | `proofflow_status` | Get full Case status (artifacts, claims, actions) |
123
+ | `proofflow_approve_execute` | Approve and execute a pending action |
124
+ | `proofflow_export_packet` | Export Case as Proof Packet (markdown) |
125
+ | `proofflow_search` | Full-text search across artifacts |
126
+ | `proofflow_list_cases` | List all Cases |
127
+ | `proofflow_list_actions` | List actions for a Case |
128
+ | `proofflow_undo` | Undo an executed action |
129
+ | `proofflow_decide` | Create a decision to approve/reject a policy gate |
130
+
131
+ ## Usage Example
132
+
133
+ In Claude Code, once configured:
134
+
135
+ ```
136
+ > Review the code changes in this repo for safety
137
+
138
+ Claude will call proofflow_review with the current repo path,
139
+ creating an AgentGuard Case with evidence-backed claims.
140
+ ```
141
+
142
+ ## Running Tests
143
+
144
+ ```bash
145
+ cd mcp-server
146
+ python -m pytest tests/ -v
147
+ ```
148
+
149
+ ## Running the Server Directly
150
+
151
+ ```bash
152
+ python -m proofflow_mcp
153
+ ```
154
+
155
+ The server communicates via stdio (stdin/stdout) per the MCP protocol.
156
+
157
+ ## Architecture
158
+
159
+ ```
160
+ Claude Code / Codex
161
+ ↓ (MCP stdio)
162
+ ProofFlow MCP Server
163
+ ↓ (HTTP)
164
+ ProofFlow Backend (localhost:8787)
165
+
166
+ SQLite DB + Local Files
167
+ ```
168
+
169
+ The MCP server is a thin adapter — all business logic lives in the ProofFlow backend.
@@ -0,0 +1,144 @@
1
+ # ProofFlow MCP Server
2
+
3
+ MCP (Model Context Protocol) server that exposes ProofFlow's audit capabilities as tools for Claude Code and Codex.
4
+
5
+ ## What it does
6
+
7
+ Lets AI coding assistants trigger ProofFlow workflows directly:
8
+
9
+ - **Scan folders** — index files with SHA-256 hashes, create audit Cases
10
+ - **Code review** — analyze git diffs, generate evidence-backed risk claims
11
+ - **Suggest actions** — generate file organization suggestions
12
+ - **Approve & execute** — run pending actions (with policy gate awareness)
13
+ - **Export Proof Packets** — generate shareable markdown audit reports
14
+ - **Search** — full-text search across indexed artifacts
15
+ - **Undo** — reverse executed actions
16
+
17
+ ## Prerequisites
18
+
19
+ - Python 3.11+
20
+ - ProofFlow backend running on `http://127.0.0.1:8787`
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ cd mcp-server
26
+ pip install -e .
27
+ ```
28
+
29
+ For development (includes test dependencies):
30
+
31
+ ```bash
32
+ pip install -e ".[dev]"
33
+ ```
34
+
35
+ > Note: Install in a separate virtualenv from the backend to avoid starlette version conflicts between FastAPI and the MCP SDK.
36
+
37
+ ## Configuration
38
+
39
+ ### Claude Code
40
+
41
+ Add to your project's `.mcp.json` or `~/.claude/settings.json`:
42
+
43
+ ```json
44
+ {
45
+ "mcpServers": {
46
+ "proofflow": {
47
+ "command": "python",
48
+ "args": ["-m", "proofflow_mcp"],
49
+ "env": {
50
+ "PROOFFLOW_BASE_URL": "http://127.0.0.1:8787"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### Claude Desktop
58
+
59
+ Add to `claude_desktop_config.json`:
60
+ - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
61
+ - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
62
+
63
+ ```json
64
+ {
65
+ "mcpServers": {
66
+ "proofflow": {
67
+ "command": "proofflow-mcp",
68
+ "env": {
69
+ "PROOFFLOW_BASE_URL": "http://127.0.0.1:8787"
70
+ }
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ ### Codex
77
+
78
+ Add to your Codex MCP configuration with the same command/args pattern.
79
+
80
+ ### Environment Variables
81
+
82
+ | Variable | Default | Description |
83
+ |----------|---------|-------------|
84
+ | `PROOFFLOW_BASE_URL` | `http://127.0.0.1:8787` | ProofFlow backend URL |
85
+ | `PROOFFLOW_TIMEOUT` | `30` | HTTP request timeout in seconds |
86
+ | `PROOFFLOW_API_KEY` | *(unset)* | API key for backend auth (optional) |
87
+ | `PROOFFLOW_MCP_MAX_CONCURRENT` | `5` | Max concurrent MCP tool calls |
88
+
89
+ ## Available Tools
90
+
91
+ | Tool | Description |
92
+ |------|-------------|
93
+ | `proofflow_health` | Check backend connectivity |
94
+ | `proofflow_scan` | Scan a folder, create Case + Artifacts |
95
+ | `proofflow_suggest` | Generate cleanup suggestions for a scanned Case |
96
+ | `proofflow_review` | AgentGuard code review on a git repo |
97
+ | `proofflow_status` | Get full Case status (artifacts, claims, actions) |
98
+ | `proofflow_approve_execute` | Approve and execute a pending action |
99
+ | `proofflow_export_packet` | Export Case as Proof Packet (markdown) |
100
+ | `proofflow_search` | Full-text search across artifacts |
101
+ | `proofflow_list_cases` | List all Cases |
102
+ | `proofflow_list_actions` | List actions for a Case |
103
+ | `proofflow_undo` | Undo an executed action |
104
+ | `proofflow_decide` | Create a decision to approve/reject a policy gate |
105
+
106
+ ## Usage Example
107
+
108
+ In Claude Code, once configured:
109
+
110
+ ```
111
+ > Review the code changes in this repo for safety
112
+
113
+ Claude will call proofflow_review with the current repo path,
114
+ creating an AgentGuard Case with evidence-backed claims.
115
+ ```
116
+
117
+ ## Running Tests
118
+
119
+ ```bash
120
+ cd mcp-server
121
+ python -m pytest tests/ -v
122
+ ```
123
+
124
+ ## Running the Server Directly
125
+
126
+ ```bash
127
+ python -m proofflow_mcp
128
+ ```
129
+
130
+ The server communicates via stdio (stdin/stdout) per the MCP protocol.
131
+
132
+ ## Architecture
133
+
134
+ ```
135
+ Claude Code / Codex
136
+ ↓ (MCP stdio)
137
+ ProofFlow MCP Server
138
+ ↓ (HTTP)
139
+ ProofFlow Backend (localhost:8787)
140
+
141
+ SQLite DB + Local Files
142
+ ```
143
+
144
+ The MCP server is a thin adapter — all business logic lives in the ProofFlow backend.
@@ -0,0 +1,48 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "proofflow-mcp"
7
+ version = "0.1.0"
8
+ description = "MCP server for ProofFlow – audit infrastructure for AI coding agents"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ authors = [
13
+ { name = "Hyperion-GPU" },
14
+ ]
15
+ keywords = ["mcp", "proofflow", "audit", "ai-agent", "claude-code", "codex"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Topic :: Software Development :: Quality Assurance",
23
+ ]
24
+ dependencies = [
25
+ "mcp>=1.0.0",
26
+ "httpx>=0.27.0",
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/Hyperion-GPU/ProofFlow-v0.1"
31
+ Repository = "https://github.com/Hyperion-GPU/ProofFlow-v0.1"
32
+ Issues = "https://github.com/Hyperion-GPU/ProofFlow-v0.1/issues"
33
+
34
+ [project.scripts]
35
+ proofflow-mcp = "proofflow_mcp.server:main"
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["src/proofflow_mcp"]
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = ["tests"]
42
+
43
+ [project.optional-dependencies]
44
+ dev = [
45
+ "pytest>=8.0",
46
+ "pytest-asyncio>=0.23",
47
+ "respx>=0.21",
48
+ ]
@@ -0,0 +1,3 @@
1
+ """ProofFlow MCP Server – exposes ProofFlow audit tools via Model Context Protocol."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,5 @@
1
+ """Allow running as python -m proofflow_mcp."""
2
+
3
+ from proofflow_mcp.server import main
4
+
5
+ main()
@@ -0,0 +1,175 @@
1
+ """HTTP client wrapper for the ProofFlow backend REST API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from typing import Any
7
+
8
+ import httpx
9
+
10
+
11
+ class ProofFlowError(Exception):
12
+ """Raised when a ProofFlow API call fails."""
13
+
14
+ def __init__(self, message: str, status_code: int | None = None):
15
+ super().__init__(message)
16
+ self.status_code = status_code
17
+
18
+
19
+ class ProofFlowClient:
20
+ """Async HTTP client for the ProofFlow backend."""
21
+
22
+ def __init__(self) -> None:
23
+ self._base_url = os.getenv("PROOFFLOW_BASE_URL", "http://127.0.0.1:8787")
24
+ self._timeout = float(os.getenv("PROOFFLOW_TIMEOUT", "30"))
25
+ self._http: httpx.AsyncClient | None = None
26
+
27
+ async def _get_http(self) -> httpx.AsyncClient:
28
+ if self._http is None or self._http.is_closed:
29
+ headers: dict[str, str] = {}
30
+ api_key = os.getenv("PROOFFLOW_API_KEY")
31
+ if api_key:
32
+ headers["X-ProofFlow-Token"] = api_key
33
+ self._http = httpx.AsyncClient(
34
+ base_url=self._base_url, timeout=self._timeout, headers=headers
35
+ )
36
+ return self._http
37
+
38
+ async def close(self) -> None:
39
+ if self._http and not self._http.is_closed:
40
+ await self._http.aclose()
41
+
42
+ async def _request(
43
+ self, method: str, path: str, **kwargs: Any
44
+ ) -> dict[str, Any] | list[dict[str, Any]]:
45
+ http = await self._get_http()
46
+ try:
47
+ response = await http.request(method, path, **kwargs)
48
+ except httpx.ConnectError:
49
+ raise ProofFlowError(
50
+ "ProofFlow backend is not running. "
51
+ "Start it with: cd backend && python -m uvicorn proofflow.main:app --port 8787"
52
+ )
53
+ except httpx.TimeoutException:
54
+ raise ProofFlowError(
55
+ f"ProofFlow backend timed out after {self._timeout}s"
56
+ )
57
+
58
+ if response.status_code >= 400:
59
+ try:
60
+ detail = response.json().get("detail", response.text)
61
+ except Exception:
62
+ detail = response.text
63
+ raise ProofFlowError(
64
+ f"ProofFlow API error ({response.status_code}): {detail}",
65
+ status_code=response.status_code,
66
+ )
67
+
68
+ return response.json()
69
+
70
+ # --- Health ---
71
+
72
+ async def health(self) -> dict[str, Any]:
73
+ return await self._request("GET", "/health")
74
+
75
+ # --- Cases ---
76
+
77
+ async def list_cases(self) -> list[dict[str, Any]]:
78
+ return await self._request("GET", "/cases")
79
+
80
+ async def get_case_packet(self, case_id: str) -> dict[str, Any]:
81
+ return await self._request("GET", f"/cases/{case_id}/packet")
82
+
83
+ # --- LocalProof ---
84
+
85
+ async def scan(
86
+ self,
87
+ folder_path: str,
88
+ recursive: bool = True,
89
+ max_files: int = 500,
90
+ ) -> dict[str, Any]:
91
+ return await self._request(
92
+ "POST",
93
+ "/localproof/scan",
94
+ json={"folder_path": folder_path, "recursive": recursive, "max_files": max_files},
95
+ )
96
+
97
+ async def suggest_actions(
98
+ self, case_id: str, target_root: str
99
+ ) -> dict[str, Any]:
100
+ return await self._request(
101
+ "POST",
102
+ "/localproof/suggest-actions",
103
+ json={"case_id": case_id, "target_root": target_root},
104
+ )
105
+
106
+ # --- AgentGuard ---
107
+
108
+ async def review(
109
+ self,
110
+ repo_path: str,
111
+ base_ref: str = "HEAD",
112
+ include_untracked: bool = True,
113
+ test_command: str | None = None,
114
+ ) -> dict[str, Any]:
115
+ body: dict[str, Any] = {
116
+ "repo_path": repo_path,
117
+ "base_ref": base_ref,
118
+ "include_untracked": include_untracked,
119
+ }
120
+ if test_command is not None:
121
+ body["test_command"] = test_command
122
+ return await self._request("POST", "/agentguard/review", json=body)
123
+
124
+ # --- Actions ---
125
+
126
+ async def list_actions(self, case_id: str) -> list[dict[str, Any]]:
127
+ return await self._request("GET", f"/cases/{case_id}/actions")
128
+
129
+ async def approve_action(self, action_id: str) -> dict[str, Any]:
130
+ return await self._request("POST", f"/actions/{action_id}/approve")
131
+
132
+ async def execute_action(self, action_id: str) -> dict[str, Any]:
133
+ return await self._request("POST", f"/actions/{action_id}/execute")
134
+
135
+ async def undo_action(self, action_id: str) -> dict[str, Any]:
136
+ return await self._request("POST", f"/actions/{action_id}/undo")
137
+
138
+ # --- Reports ---
139
+
140
+ async def export_report(self, case_id: str) -> dict[str, Any]:
141
+ return await self._request(
142
+ "POST",
143
+ f"/reports/cases/{case_id}/export",
144
+ json={"format": "markdown"},
145
+ )
146
+
147
+ # --- Search ---
148
+
149
+ async def search(self, query: str, limit: int = 25) -> dict[str, Any]:
150
+ return await self._request(
151
+ "GET", "/search", params={"q": query, "limit": limit}
152
+ )
153
+
154
+ # --- Decisions ---
155
+
156
+ async def create_decision(
157
+ self,
158
+ case_id: str,
159
+ title: str,
160
+ status: str,
161
+ rationale: str,
162
+ result: str,
163
+ metadata: dict[str, Any] | None = None,
164
+ ) -> dict[str, Any]:
165
+ body: dict[str, Any] = {
166
+ "title": title,
167
+ "status": status,
168
+ "rationale": rationale,
169
+ "result": result,
170
+ }
171
+ if metadata:
172
+ body["metadata"] = metadata
173
+ return await self._request(
174
+ "POST", f"/cases/{case_id}/decisions", json=body
175
+ )