FlowState MCP
by tobiasGuta
README.md
# FlowState MCP
FlowState MCP is a local Model Context Protocol server for **persistent business-workflow and application-state analysis** during authorized web security testing.
It is not a vulnerability scanner and it does not send requests.
V1 imports local Burp XML or HAR traffic, assigns each import to a human-defined actor, strips authentication secrets, extracts workflow-relevant identifiers and state fields, builds an actor/entity/action/state graph, proposes **hypotheses** for manual validation, can persist structured validation outcomes, and can prioritize the highest-value unresolved hypotheses.
## Why it exists
Burp MCP is excellent at exposing HTTP traffic and controlled Burp actions to an AI client.
FlowState solves a different problem:
> What does the traffic mean in the application's workflow?
Examples:
```text
Owner creates invitation
↓
Member accepts invitation
↓
Membership becomes active
↓
Owner removes member
```
FlowState can remember the actors, objects, transitions, and evidence behind those actions and then suggest questions such as:
- Was an accepted invitation actually made unusable?
- Can another registered actor perform the same state-changing action?
- Did a field change from `pending` to `accepted`, and are invalid adjacent transitions still untested?
- Where did one object identifier appear across multiple requests?
Those are hypotheses, not vulnerability findings.
## Design principle: no target-specific heuristics
A lab or real target may reveal a weakness in FlowState's model, but the production fix must describe a **general web-workflow property**, not the target's route names or known solution.
FlowState must not special-case paths such as `/account`, `/checkout`, `/dashboard`, or any lab-specific endpoint. Instead, it should reason from evidence such as:
- chronological timestamps;
- session continuity and session rotation;
- redirects and sanitized Referer relationships;
- HTTP method and response semantics;
- observed state fields;
- the same endpoint changing from a redirect/denial-like response to a successful response.
Regression fixtures are allowed to resemble bugs that exposed a weakness. Production code is not.
## v0.1.3 workflow intelligence
v0.1.3 adds generic workflow-span reasoning on top of the v0.1.2 chronology model:
- redirect-follow GET/HEAD observations are identified as navigation edges;
- navigation that also rotates a session or carries state evidence remains a meaningful state boundary;
- the same endpoint changing from redirect to success is surfaced as an access-gate candidate;
- transition hypotheses are ranked by bug-hunting value;
- whole-span checkpoint hypotheses target the protected destination instead of only examining adjacent triples;
- low-value local skip hypotheses whose destination is merely a redirect-follow navigation request are suppressed.
For an observed span like:
```text
resource denied
↓
workflow step A
↓
workflow step B
↓
resource succeeds
```
FlowState can ask whether the resource becomes accessible immediately after A, before B is completed, without knowing anything about the application's path names.
## v0.1.4 evidence lifecycle
v0.1.4 keeps FlowState passive but lets it remember what happened when a human manually validates a generated hypothesis.
Generated hypotheses receive stable campaign-local IDs plus a validation state:
```text
untested
↓
supported | falsified | inconclusive
```
`flow_record_hypothesis_validation` stores only structured, sanitized evidence such as:
- the hypothesis ID;
- manual outcome (`supported`, `falsified`, or `inconclusive`);
- test method and path;
- observed HTTP status;
- sanitized redirect path;
- a bounded note with obvious secret assignments redacted.
Query values are not persisted in validation paths. Cookies, session values, credentials, CSRF values, and token material are not required or intentionally stored.
A `supported` hypothesis still does **not** mean "confirmed vulnerability". It means manual evidence supported the security concern represented by that hypothesis. Reporting impact and vulnerability status remain separate human decisions.
The lifecycle becomes:
```text
passive traffic
↓
workflow model
↓
hypothesis (untested)
↓
manual validation outside FlowState
↓
record structured result
↓
supported / falsified / inconclusive
↓
regenerated hypothesis keeps that history
```
## v0.1.5 validation-aware queue
v0.1.5 uses the persisted validation history to answer a new question:
> Given what has already been tested, what should I test next?
`flow_next_hypotheses` combines current transition and actor-comparison hypotheses, attaches their persisted validation status, and returns only actionable unresolved work.
Queue behavior is intentionally conservative:
- `untested` hypotheses keep their normal hunting priority;
- `inconclusive` hypotheses remain actionable but receive a small retry penalty;
- `supported` and `falsified` hypotheses remain visible in normal hypothesis/history output but are excluded from the next-action queue;
- an `intermediate_state_access` umbrella hypothesis does not compete with concrete `workflow_checkpoint_access` children for the same actor and destination;
- resolving one child hypothesis does **not** automatically mark its broader parent supported or falsified.
This is prioritization only. FlowState still does not send validation traffic.
## v0.1.6 workflow dominance and subsumption
v0.1.6 prevents the next-action queue from recommending redundant workflow tests when a **stronger earlier checkpoint** has already been directly supported.
The rule is structural, not path-specific. For the same actor and destination, if a supported `workflow_checkpoint_access` hypothesis shows that the destination was already reachable at checkpoint A, then FlowState can safely treat certain later questions as queue-only `subsumed` work:
- a later `workflow_checkpoint_access` hypothesis whose checkpoint was still listed as a remaining prerequisite after A;
- a `skip_step` hypothesis for a prerequisite that was also still listed after A.
Example:
```text
resource denied
↓
checkpoint A ← directly tested: resource succeeds here
↓
checkpoint B ← later checkpoint question is subsumed
↓
step C ← skip-C question is subsumed for earliest-access reasoning
↓
resource succeeds
```
The important distinction is preserved:
```text
validation_status: untested
queue_status: subsumed
subsumed_by: hyp-...
```
FlowState does **not** rewrite the later hypothesis to `supported`, because it was never directly tested. Subsumption only says another stronger result already answered the same earliest-access question well enough that another request would be redundant.
Subsumption is directional and scoped. A later supported checkpoint does not subsume an earlier checkpoint, and evidence does not cross actors or destinations.
`flow_next_hypotheses` now returns a separate `subsumed` collection and `subsumed_count` alongside the actionable queue.
## V1 safety boundary
FlowState V1:
- uses local `stdio` MCP only;
- has no HTTP client;
- has no browser automation;
- has no scanner;
- has no exploit runner;
- does not replay requests;
- does not store Authorization, Cookie, Set-Cookie, API-key, password, or token values from imported traffic;
- filters imports to the campaign target host and its subdomains;
- uses bounded import sizes and bounded observation counts;
- labels hypotheses as requiring manual validation;
- records validation outcomes only after an external/manual test has already occurred;
- prioritizes unresolved hypotheses without changing their evidence state;
- can suppress redundant later workflow questions without marking them directly validated.
Use your existing Burp MCP separately when you intentionally want the AI client to inspect or replay a request.
## Tools
| Tool | Purpose |
| --- | --- |
| `flow_health` | Server status, limits, and safety boundary |
| `flow_create_campaign` | Create one target-scoped workflow campaign |
| `flow_list_campaigns` | List local campaigns |
| `flow_get_campaign` | Read one campaign |
| `flow_register_actor` | Register Owner, Member, Outsider, Anonymous, etc. |
| `flow_list_actors` | List campaign actors |
| `flow_import_har` | Import a HAR for one actor |
| `flow_import_burp_xml` | Import Burp XML for one actor |
| `flow_list_observations` | Inspect sanitized stored observations |
| `flow_build_state_graph` | Build actor/entity/action/state relationships |
| `flow_show_actor_permissions` | Compare observed behavior by actor |
| `flow_show_object_history` | Trace one identifier across observations |
| `flow_generate_transition_hypotheses` | Generate ranked transition questions with persistent validation status |
| `flow_generate_actor_swap_hypotheses` | Generate actor-comparison questions with persistent validation status |
| `flow_record_hypothesis_validation` | Persist a structured manual validation outcome for a generated hypothesis |
| `flow_list_hypothesis_validations` | List validation history for a campaign or one hypothesis |
| `flow_next_hypotheses` | Return the highest-value unresolved hypotheses and identify redundant subsumed workflow questions |
## Install
Python 3.11+:
```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
pytest -q
```
Linux/macOS:
```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
pytest -q
```
## Run manually
```bash
python server.py
```
The server speaks MCP over stdin/stdout, so manual launch normally appears to wait for protocol input.
## Codex registration
Windows example:
```powershell
codex mcp add flowstate -- D:/Tools/FlowState-MCP/.venv/Scripts/python.exe D:/Tools/FlowState-MCP/server.py
codex mcp get flowstate
```
Linux/macOS:
```bash
codex mcp add flowstate -- /absolute/path/FlowState-MCP/.venv/bin/python /absolute/path/FlowState-MCP/server.py
```
## Claude Code registration
```bash
claude mcp add flowstate --scope user -- /absolute/path/FlowState-MCP/.venv/bin/python /absolute/path/FlowState-MCP/server.py
```
## Suggested workflow with Burp MCP
```text
ScopeNest containers
├─ Owner
├─ Member
└─ Anonymous
│
↓
Burp
│
├──────────────→ Burp MCP
│ │
│ └─ inspect/replay intentionally
│
└─ export HAR/XML
│
↓
FlowState MCP
│
┌────────┼─────────┐
↓ ↓ ↓
actors objects states
└────────┼─────────┘
↓
hypotheses
↓
manual validation
↓
record safe result
↓
supported / falsified /
inconclusive
↓
resolve + subsume work
↓
next unresolved work
```
## Example session
```text
1. flow_create_campaign
name="Target SaaS"
target_host="app.example.com"
2. flow_register_actor
actor_id="owner"
name="Owner"
roles=["organization_owner"]
3. Export Owner traffic from Burp as XML or HAR.
4. flow_import_burp_xml
5. flow_build_state_graph
6. flow_generate_transition_hypotheses
# note the hypothesis_id of the question you manually test
7. Perform the controlled validation separately.
8. flow_record_hypothesis_validation
hypothesis_id="hyp-..."
outcome="supported"
test_method="GET"
test_path="/protected-resource"
observed_status=200
9. flow_generate_transition_hypotheses
# the same hypothesis now reports validation_status="supported"
10. flow_next_hypotheses
# supported/falsified work is retained as history
# later questions may be queue_status="subsumed" when stronger earlier evidence covers them
11. flow_list_hypothesis_validations
```
## What V1 deliberately does not do
V1 does not try to infer a complete business ontology from every API field.
It uses deterministic heuristics for:
- action verbs in paths;
- HTTP method semantics;
- path identifiers;
- common ID-like JSON fields;
- common state/status/role fields.
The graph is evidence-backed and intentionally imperfect. A future version can add explicit human corrections such as:
```text
"mem_912 represents user_22"
"workspace_id is a tenant boundary"
"accepted invitations must never be reusable"
```
without turning guesses into facts.
## V1 success test
FlowState V1 is successful only if, on a real bug-bounty session, it produces at least one hypothesis that you would genuinely test and that you did not immediately notice from raw Burp history alone.
The next bar is stronger: the hypothesis should survive controlled manual validation, FlowState should preserve that evidence without turning a hypothesis into a vulnerability claim automatically, and later prioritization should avoid spending requests on workflow questions already covered by stronger evidence.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues