Skip to main content

Python implementation of the FortiSOAR REST API

Reason this release was yanked:

leaked internal ip

Project description

pyfsr

PyPI version Tests Documentation Status codecov

Documentation · Installation · Quick start · AI / agents

pyfsr is a batteries-included Python client for the FortiSOAR REST API. It gives you a typed query/CRUD layer over any module, picklist resolution, connector execution, playbook-run history, safe deletes — and a ready-made AI/agent surface (tool-schema registry + an optional MCP server) so an agent can drive FortiSOAR with no glue code.

Python 3.10+ · Pydantic v2 · MIT.

Installation

pip install pyfsr
# with the optional generic MCP server:
pip install 'pyfsr[mcp]'

Quick start

from pyfsr import FortiSOAR, Query

# API-key auth, or ("username", "password")
client = FortiSOAR("soar.example.com", "your-api-key")

# Generic, typed CRUD for ANY module via client.records(module)
incidents = client.records("incidents")

inc = incidents.get("0d2c...")          # by uuid, "module:uuid", or full IRI
inc["name"], inc.uuid                    # records are dict- AND attribute-accessible

# Structured queries with a fluent builder -> a HydraPage you can iterate
page = incidents.query(
    Query().eq("status.itemValue", "Open").like("name", "phish").limit(50)
)
for inc in incidents.iterate(Query().eq("status.itemValue", "Open")):
    ...                                  # lazily walks every page

# Create / update / delete (soft by default; hard= for permanent)
new = incidents.create({"name": "Suspicious login", "severity": "High"},
                       resolve_picklists=True)   # friendly values -> IRIs
incidents.update(new.uuid, {"status": "Closed"}, resolve_picklists=True)
incidents.delete(new.uuid)               # delete(..., hard=True) to purge

Configure from the environment

from pyfsr import EnvConfig

# reads FSR_BASE_URL (+ FSR_API_KEY or FSR_USERNAME/FSR_PASSWORD),
# FSR_PORT, FSR_VERIFY_SSL, FSR_TIMEOUT
client = EnvConfig.from_env().client()

Features

  • Generic record accessclient.records(module) for CRUD on any module; no hand-built /api/3/... URLs or Hydra unwrapping.
  • Query DSLQuery().eq(...).in_(...).group(...).sort(...).limit(...), compiled to the FortiSOAR query-body shape (pagination handled for you).
  • Typed models — Alert/Incident/Task/Comment come back as Pydantic v2 models that are also dict-compatible; unknown modules fall back to a lenient BaseRecord, so custom fields/modules never break.
  • Picklistsclient.picklists resolves friendly values ("High") to IRIs and discovers which picklist a (module, field) binds to.
  • Connectorsclient.connectors lists configured connectors, runs healthchecks, and executes operations.
  • Playbooksclient.playbooks merges live + historical run history and resumes manual-input steps.
  • Safe deletes — soft-delete/restore + guarded single-row hard delete.
  • Schema discoveryclient.list_modules() / client.describe_module().
  • Resilient transport — configurable timeout=, automatic retry with backoff on idempotent requests (429/5xx), and secrets masked in verbose logs.
  • Bundled OpenAPI specpyfsr.spec.load_spec() for offline reference and drift(client) to compare the spec against a live appliance.

AI / agent-friendly

pyfsr ships a transport-neutral tool registry for the core operations, with token-efficient results and structured (never-raised) errors — feed it to Anthropic tool-use, OpenAI function calling, your own agent loop, or the bundled MCP server.

from pyfsr.tools import to_anthropic_tools, to_openai_tools, dispatch

tools = to_anthropic_tools()             # or to_openai_tools(), or tool_schemas()

# ... your model picks a tool ...
result = dispatch(client, "search_records",
                  {"module": "alerts", "summary": True, "limit": 10})
# result is JSON-safe and trimmed; failures come back as {"error": {...}}

Reads accept summary=True or fields=[...] to keep payloads small:

client.records("alerts").query(Query().limit(20), summary=True)

Generic MCP server

Point any MCP-capable agent at any FortiSOAR with one command:

pip install 'pyfsr[mcp]'
FSR_BASE_URL=soar.example.com FSR_API_KEY=... python -m pyfsr.mcp

It exposes the same registry (record CRUD, schema discovery, picklists, connectors, playbook runs) as MCP tools — generic and dependency-light, distinct from any domain-specific FortiSOAR MCP.

Development

uv sync --extra dev
uv run pytest -q                 # unit tests (live tests deselected by default)
uvx ruff check src tests

Live integration tests run with pytest -m integration and need an examples/config.toml pointing at a FortiSOAR instance.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyfsr-0.5.1.tar.gz (519.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyfsr-0.5.1-py3-none-any.whl (347.4 kB view details)

Uploaded Python 3

File details

Details for the file pyfsr-0.5.1.tar.gz.

File metadata

  • Download URL: pyfsr-0.5.1.tar.gz
  • Upload date:
  • Size: 519.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyfsr-0.5.1.tar.gz
Algorithm Hash digest
SHA256 30b7d49fa3b8d1f493c84a7e0c8f5c3ec87ac979a4ce29c49c74ce6f3e193cc6
MD5 6b85b65256c35426e45bc00ca9d06d0d
BLAKE2b-256 661595974b4333fcc8eb0dd2426636c2f8b45f1159a49aa411a851f6009fe771

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyfsr-0.5.1.tar.gz:

Publisher: publish.yml on ftnt-dspille/pyfsr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyfsr-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: pyfsr-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 347.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyfsr-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2e9bcfcee3add0814d75a41aa0f6ac7f767553b07a7545053b68e3f645568680
MD5 8ecd14fc1752fbe8f1efbbe606f69fe9
BLAKE2b-256 c6ceba5a87d03fe7b0b8a7685dd0330196e3e4bb97d098af3d38ca3082082569

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyfsr-0.5.1-py3-none-any.whl:

Publisher: publish.yml on ftnt-dspille/pyfsr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page