Secure Reports MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Secure Reports MCP get the monthly visits report for September 2026"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-secure-reports
An MCP server that lets an AI agent export reports from a system that has no API, without handing the agent more access than the person using it.
I built the first version for a hospital whose information system only has a web interface. This repository is a cleaned up public version: same design, synthetic data, no hospital names or real credentials.

What it does
The agent (Claude Desktop, Claude Code or any MCP client) can list reports, start an export, poll until the file is ready, and look up insurance claims. Behind the server, a backend logs in to the legacy system and downloads the file.
Three things make it safe to point at sensitive data:
Tools depend on the role. One server process serves one role. Tools that role may not use are never registered, so the model does not see them in tools/list at all. Report types are filtered the same way. Permissions live in config/roles.json, so a change is a reviewed pull request, not a code change.
Every call is audited. Each tool call, allowed or denied, goes to an append only JSONL log with the role, user, parameters and duration. Fields such as patient_id are masked before they are written, including inside nested objects.
Credentials never reach the model. The login for the legacy system is stored in a Fernet encrypted vault. Only the backend reads it. No tool returns it, and each read is itself an audit event.
Related MCP server: Governed MCP Gateway
Roles in the sample config
Tool | reporting_staff | unit_manager | finance |
| ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ |
| ✓ | ✓ | |
| ✓ |
Try it
Requires Python 3.10 or newer.
python -m venv .venv
.venv/bin/pip install -e ".[dev]" # Windows: .venv\Scripts\pip
.venv/bin/python scripts/demo.pyThe demo starts the server twice over stdio, once as reporting_staff and once as finance, and prints what each role sees:
=== Connected as reporting_staff ===
tools/list: download_report, get_report_job_status, list_available_reports
> download_report({"report_type": "monthly_visits", ...})
ok: {"job_id": "f1cf76f6...", "status": "queued", "next": "poll get_report_job_status"}
> download_report({"report_type": "insurance_claims", ...})
error: Error executing tool download_report: Report type 'insurance_claims' is not allowed for this role
=== Connected as finance ===
tools/list: check_claim_status, download_billing_statement, download_report, get_report_job_status, list_available_reports
=== audit.jsonl ===
reporting_staff download_report failed {"report_type": "insurance_claims", ...}
finance check_claim_status success {"claim_id": null, "patient_id": "00******78"}Run the tests:
.venv/bin/python -m pytestUse it from Claude Desktop
Generate a vault key once:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"Then add the server to claude_desktop_config.json:
{
"mcpServers": {
"secure-reports": {
"command": "/path/to/mcp-secure-reports/.venv/bin/secure-reports-mcp",
"env": {
"MCP_ROLE": "reporting_staff",
"VAULT_MASTER_KEY": "paste the key here",
"DATA_DIR": "/path/to/mcp-secure-reports/data"
}
}
}
}Ask Claude for "the monthly visits report for September 2026" and it will start the export, poll the job and tell you where the file is. Open data/audit.jsonl to see what was logged.
Configuration
Variable | Default | Purpose |
|
| Role served by this process |
|
| User id written to the audit log |
| none, required | Fernet key for the credential vault |
|
|
|
|
| How long a mock export takes |
|
| Audit log, vault file and exports |
|
| Role and tool definitions |
Project layout
src/secure_reports_mcp/
server.py registers tools for the active role, audits every call
tools.py tool logic, no MCP or logging concerns
backend.py MockBackend (synthetic data) and the PlaywrightBackend interface
vault.py Fernet encrypted credential store
audit.py append only JSONL log with field masking
config.py loads and validates config/roles.json
scripts/demo.py end to end run over the MCP protocol
tests/ 35 tests: masking, vault, config, role filtering, job lifecycleWhat is mocked
MockBackend runs the full flow, including the vault read and the async job, but writes a small CSV of made up numbers instead of logging in anywhere. PlaywrightBackend defines where real browser automation goes and raises NotImplementedError, because selectors depend on the target system. In the hospital deployment the next step is a read only database backend with a fixed set of queries per domain, rather than free form SQL.
Role selection by environment variable is fine for a single user on a desktop. A shared deployment should take the role from an authenticated session instead.
License
MIT
Available Tools
3 toolsdownload_reportB
Start exporting a report. date_range is {"from": "YYYY-MM-DD", "to": "YYYY-MM-DD"}. Returns a job_id.
Inputs: date_range (required), report_type (required).
get_report_job_statusB
Check whether an export job has finished and where the file is.
Inputs: job_id (required).
list_available_reportsA
List the report types this role may download. domain is 'management' or 'billing'.
Inputs: domain (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 3 tools
Each tool has a clearly distinct purpose: listing available reports, initiating an export job, and polling job status. There is no overlap in resource or action, so an agent can easily choose the right tool.
All three tools use consistent snake_case with verb-led names (list_..., download_..., get_...). The pattern is predictable and readable across the set.
Three tools are well-scoped for a focused report-export server. Each earns its place in the core workflow without being excessive.
The set covers listing, starting an export, and checking job status, which forms a complete minimal lifecycle. Minor gaps exist (no cancel job or list jobs operation), but agents can work around them for the stated purpose.
Maintenance
Related MCP Connectors
Context and control for any AI. Agent identity, scoped access, and proof across tools.
Credential broker for AI agents: scoped, revocable API access with policy enforcement and audit.
Security gateway for AI agents: policy, approval, and audited execution, no secrets shared.
Every AI tool call runs as the person who asked, under your rules, fully audited.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables controlled AI-agent access to enterprise-shaped tools with a deny-by-default gated write path, human approval, dry-run execution, and append-only audit logging.1-
- AlicenseNot gradedqualityCmaintenanceEnforces authenticated identity on every tool call and SSE frame, rotates vaulted credentials in place, and restricts tools via allowlists.71 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to securely query a synthetic health-insurance claims database through read-only, parameterized tools for claims, member histories, coverage rules, and year-to-date summaries. Includes API-key authentication, per-tool authorization, rate limiting, untrusted-text sanitization, and fail-closed audit logging.MIT
- FlicenseNot gradedqualityCmaintenanceEnables a locally hosted AI, running entirely inside the client's building with no outside network access, to reach line-of-business systems, document stores and email through a small set of narrow, task-specific and schema-validated tools. It applies least-privilege per-tool credentials, personal-data masking, output leak checks and tamper-evident audit logging, keeping actions read-only by default and gating any write behind human approval so untrusted document content cannot trigger privileged operations.-