switch-trust-mcp
A local MCP server (stdio) that gives a coding agent read-only access to a Switch Trust backend's AI-SPM issues, inventory, guardrails, cost optimization 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):
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.):
{
"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_sizecapped at 100.get_issue(issue_id, page_size?, cursor?)— issue detail + assembled rule-level remediation guidance + a page of affected objects;objectsis paginated the same way aslist_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_issuesis capped at 500 and the call at 300 backend requests — and returns ascanblock reportingcomplete,issues_scanned,requestsanderrors.complete: falsemeans the caps were hit and the file may have findings this result omits; treat it as "unknown", not as "clean", and narrow the search withlist_issuesfilters 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_sizecapped 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_sizecapped 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_sizecapped at 100.get_llm_session(session_id)— one session's aggregate cost/tokens/turns plus the full per-turn list.
ROI / cost-optimization
list_roi_agents(page?, page_size?)— per-agent LLM activity summaries (latest_interaction_time,interaction_count).page_sizecapped at 100.list_roi_interactions(agent_id, since?, until?, page?, page_size?, order?)— one agent's raw LLM interaction rows (with computedcost_usd) — the source data the cost-optimization analyses read.agent_idrequired;since/untilare RFC3339 timestamps.page_sizecapped at 100.list_roi_analyses(agent_id?, analysis_type?, page?, page_size?, order?)— cost-optimization analysis results (findings + estimated$savings), latest first.analysis_typeis one oftool_bloat,model_optimizer,verbosity,context_cache_waste,retry_loop_waste.page_sizecapped at 100.get_latest_roi_analyses(agent_id, analysis_types)— the latest finished result per type for one agent, i.e. its current recommendations. Both arguments are required; a type with no finished run is simply absent from the result.get_roi_analysis(analysis_id)— one analysis result's full detail.
Red-teaming / eval
list_evaluations(search?, approach?, page?, page_size?, order?)— evaluation definitions (probes/metrics), including red-teaming adversarial probes;approachisprobeormetric. Page-numbered;page_sizecapped at 100.get_evaluation(evaluation_id)— full definition detail, includingattack_techniques/adversarial_goals/num_prompts/max_turnsfor adversarial-probe evaluations.list_agent_evaluations(agent_id?, evaluation_id?, search?, page?, page_size?, order?)— agent↔evaluation assignments, each withlatest_run_status/progress/summaryand ascore_trend(last 5 scores). Page-numbered;page_sizecapped 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;statusisqueued/running/finished/error. Page-numbered;page_sizecapped 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;statusispassed/failed/error/scored. There is no single-result detail endpoint, soconversationtranscripts are trimmed rather than dropped: every turn is kept but each turn's text is truncated to 300 characters. Page-numbered;page_sizecapped 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 undertest/. - Editable install:
pip install -e '.[dev]', then runswitch-trust-mcp. - Docs are fetched from your instance at runtime; for offline work point
SWITCH_TRUST_REMEDIATION_DIRat a local copy of the docs directory.
Tests
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.
Metadata
Release files for switch-trust-mcp 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| switch_trust_mcp-0.2.0.tar.gz | 129.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| switch_trust_mcp-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 507.3 kB
Release files / switch_trust_mcp-0.2.0.tar.gz
| Download URL | switch_trust_mcp-0.2.0.tar.gz |
|---|---|
| Size | 129.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d3543dd378abc0151ddf64ba3b065cc0848cc9ad92725560a289f472ecacebb6
|
|
BLAKE2b-256 checksum How to use checksums |
19dbce5f582e6bccb1ba7553325438857d5e5d1f29804caadf3a2ec30cbd09e7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logRelease files / switch_trust_mcp-0.2.0-py3-none-any.whl
| Download URL | switch_trust_mcp-0.2.0-py3-none-any.whl |
|---|---|
| Size | 377.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6ad57af2d19553dfb5300ee1cdfddc91010271d24f7bdbc643163cbeaabb6daa
|
|
BLAKE2b-256 checksum How to use checksums |
4e8b013c02f88b2f0f233fad9fa8a62ad44d8381469cc051fa95e64c1a219722
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency log