Metadata-Version: 2.4
Name: switch-trust-mcp
Version: 0.1.0
Summary: Switch Trust platform MCP server: read-only AI-SPM issues, inventory, and remediation guidance for coding agents
Author: SandboxAQ
License: Apache-2.0
Project-URL: Repository, https://github.com/sandbox-quantum/switch-trust-mcp
Keywords: ai,mcp,security,ai-spm,switch-trust
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1,>=0.28
Requires-Dist: mcp<2,>=1.27
Requires-Dist: attrs<27,>=25
Requires-Dist: python-dateutil<3,>=2.9
Provides-Extra: dev
Requires-Dist: pytest<9,>=8; extra == "dev"
Provides-Extra: audit
Requires-Dist: pip-licenses>=5.0; extra == "audit"
Requires-Dist: cyclonedx-bom>=6.0; extra == "audit"
Requires-Dist: pip-audit>=2.7; extra == "audit"
Requires-Dist: pip-tools==7.6.2; extra == "audit"
Dynamic: license-file

# switch-trust-mcp

A local [MCP](https://modelcontextprotocol.io) server (stdio) that gives a coding
agent read-only access to a Switch Trust backend's **AI-SPM issues, inventory, and
remediation guidance** so it can fix the flagged code.

It is a thin, authenticated REST client over the Switch Trust API — no scanner runs
locally and no backend changes are required. Everything valuable (AI-reasoned
findings, rule-based issues, public-asset vuln enrichment, remediation guidance)
is already computed server-side and served over the existing API / static assets.

## Install & run

The idiomatic way is via the published wheel with `uvx` (no clone, no build step):

```bash
uvx switch-trust-mcp
```

## Configuration

Set two environment variables:

| Variable                 | Meaning                                                        |
| ------------------------ | --------------------------------------------------------------- |
| `SWITCH_TRUST_API_KEY`   | Switch Trust API key (`sk_...`).                                |
| `SWITCH_TRUST_INSTANCE`  | Switch Trust instance base URL, e.g. `https://app.flintai.dev`. |

The instance URL is validated against a fail-closed host allowlist before any
credential is attached.

The **tenant and workspace are auto-discovered** from the API key at startup —
you do not configure any IDs. A key is pinned to exactly one tenant + active
workspace by the backend.

The API key is only ever sent in the `Authorization: ApiKey ...` header and is
never logged.

## Wiring into a coding agent

Add to your MCP client config (Claude Code `.mcp.json`, Cursor, etc.):

```jsonc
{
  "mcpServers": {
    "switch-trust-mcp": {
      "command": "uvx",
      "args": ["switch-trust-mcp"],
      "env": {
        "SWITCH_TRUST_API_KEY": "sk_...",
        "SWITCH_TRUST_INSTANCE": "https://app.flintai.dev"
      }
    }
  }
}
```

## Tools

**Fix-focused**

- `get_context` — show the resolved instance / tenant / workspace.
- `list_issues(severity?, rule_id?, category?, search?, page_size?, cursor?)` —
  list issues; paginated, `page_size` capped at 100.
- `get_issue(issue_id, page_size?, cursor?)` — issue detail + assembled
  rule-level remediation guidance + a page of affected objects; `objects` is
  paginated the same way as `list_issues`.
- `get_finding_detail(issue_id, object_id, detail_id?)` — per-finding file path,
  code snippet, evidence, and inline remediation.
- `find_issues_for_file(path, max_issues?)` — issues whose findings reference a
  given working-tree file (client-side scan; matches by shared path suffix).
  The scan follows pagination but is bounded — `max_issues` is capped at 500 and
  the call at 300 backend requests — and returns a `scan` block reporting
  `complete`, `issues_scanned`, `requests` and `errors`. **`complete: false`
  means the caps were hit and the file may have findings this result omits**;
  treat it as "unknown", not as "clean", and narrow the search with
  `list_issues` filters instead.
- `get_remediation_guidance(rule_name)` — rule-level remediation markdown.

**Inventory browse**

- `list_models | list_agents | list_tools | list_mcp_servers(name?, severity?, supplier?, library?, page_size?, cursor?)`
- `get_model | get_agent | get_tool | get_mcp_server(asset_id)` — detail plus
  attached issues, related assets, and code locations.

**Guardrails & LLM-interaction analytics**

- `list_guardrail_policies(search?, page?, page_size?)` — page-numbered (not
  cursor-based); `page_size` capped at 100.
- `get_guardrail_policy(policy_id)` — policy detail: name, description,
  user/assistant detector configuration.
- `get_guardrail_interaction_counts | get_guardrail_outcomes | get_guardrail_categories(agent_id?)`
  — guardrail-decision dashboards across LLM interactions, optionally scoped
  to one agent.
- `list_llm_interactions(search?, agent_id?, page_size?, cursor?)` — prompt/
  response pairs with guardrail outcomes; rows are trimmed (long text
  truncated, per-turn events omitted) for context budget. `page_size` capped
  at 100.
- `get_interaction(interaction_id)` — one interaction's full detail.
- `list_llm_sessions(agent_id, sort?, sort_dir?, page_size?, cursor?)` —
  grouped conversation turns for one agent (required). `page_size` capped at 100.
- `get_llm_session(session_id)` — one session's aggregate cost/tokens/turns
  plus the full per-turn list.

**Red-teaming / eval**

- `list_evaluations(search?, approach?, page?, page_size?, order?)` —
  evaluation definitions (probes/metrics), including red-teaming adversarial
  probes; `approach` is `probe` or `metric`. Page-numbered; `page_size`
  capped at 100.
- `get_evaluation(evaluation_id)` — full definition detail, including
  `attack_techniques` / `adversarial_goals` / `num_prompts` / `max_turns` for
  adversarial-probe evaluations.
- `list_agent_evaluations(agent_id?, evaluation_id?, search?, page?, page_size?, order?)`
  — agent↔evaluation assignments, each with `latest_run_status`/`progress`/
  `summary` and a `score_trend` (last 5 scores). Page-numbered; `page_size`
  capped at 100.
- `get_agent_evaluation(agent_evaluation_id)` — one assignment's full detail.
- `get_agent_evaluation_summary(agent_id)` — one agent's evaluation health
  rollup: health score, per-category OWASP coverage, and score trend.
- `list_evaluation_runs(evaluation_id?, agent_evaluation_id?, page?, page_size?, order?)`
  — runs; `status` is `queued`/`running`/`finished`/`error`. Page-numbered;
  `page_size` capped at 100.
- `get_evaluation_run(evaluation_run_id)` — one run's detail.
- `list_evaluation_run_results(evaluation_run_id, page?, page_size?, order?)`
  — one run's per-prompt results; `status` is `passed`/`failed`/`error`/
  `scored`. There is no single-result detail endpoint, so `conversation`
  transcripts are trimmed rather than dropped: every turn is kept but each
  turn's text is truncated to 300 characters. Page-numbered; `page_size`
  capped at 100.
- `get_agent_endpoint(agent_id)` — an agent's red-teaming target-endpoint
  config (`endpoint_url`, `endpoint_auth_type`, `model_type`, `config`);
  secrets are redacted server-side and always come back empty.

## Remediation guidance

Rule-level remediation markdown has **no dedicated API** — it is served by the
instance's web server as static assets at `{instance}/assets/docs-remediations/…`
(the same origin and files the web UI reads). This server fetches them at runtime
over HTTP through the shared client and caches them per session; nothing is
bundled into the package. When a rule has no docs (or the assets origin is
unreachable), fall back to the per-finding `remediation` text from
`get_finding_detail`.

For offline development or tests, set `SWITCH_TRUST_REMEDIATION_DIR` to a local directory
laid out like the assets (`rule-name-to-remediation-folder-map.json` + per-rule
folders); the loader then reads from disk and never touches the network.

## Development

- Layout: `src/switch_trust_mcp/` (`src/` layout), tests under `test/`.
- Editable install: `pip install -e '.[dev]'`, then run `switch-trust-mcp`.
- Docs are fetched from your instance at runtime; for offline work point
  `SWITCH_TRUST_REMEDIATION_DIR` at a local copy of the docs directory.

## Tests

```bash
pytest
```

Tests are hermetic (httpx `MockTransport` for the client and the remediation-docs
fetch, a fake client + `SWITCH_TRUST_REMEDIATION_DIR` for the tools), so they need no
network or live backend.
