fireweed-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fireweed_mcp-0.1.0/.github/workflows/publish.yml +67 -0
- fireweed_mcp-0.1.0/.gitignore +7 -0
- fireweed_mcp-0.1.0/LICENSE.md +105 -0
- fireweed_mcp-0.1.0/PKG-INFO +222 -0
- fireweed_mcp-0.1.0/README.md +99 -0
- fireweed_mcp-0.1.0/open_format/SPEC.md +114 -0
- fireweed_mcp-0.1.0/open_format/conformance.py +159 -0
- fireweed_mcp-0.1.0/open_format/reference_reader.py +168 -0
- fireweed_mcp-0.1.0/open_format/verify_bundle.py +110 -0
- fireweed_mcp-0.1.0/pyproject.toml +39 -0
- fireweed_mcp-0.1.0/src/fireweed/__init__.py +16 -0
- fireweed_mcp-0.1.0/src/fireweed/claim.py +47 -0
- fireweed_mcp-0.1.0/src/fireweed/consolidation_ops.py +460 -0
- fireweed_mcp-0.1.0/src/fireweed/consolidator.py +284 -0
- fireweed_mcp-0.1.0/src/fireweed/constants.py +261 -0
- fireweed_mcp-0.1.0/src/fireweed/constitutional.py +68 -0
- fireweed_mcp-0.1.0/src/fireweed/coreference.py +60 -0
- fireweed_mcp-0.1.0/src/fireweed/crypto.py +166 -0
- fireweed_mcp-0.1.0/src/fireweed/decay.py +215 -0
- fireweed_mcp-0.1.0/src/fireweed/domain_classifier.py +104 -0
- fireweed_mcp-0.1.0/src/fireweed/entity_linker.py +390 -0
- fireweed_mcp-0.1.0/src/fireweed/erasure.py +274 -0
- fireweed_mcp-0.1.0/src/fireweed/extractor.py +139 -0
- fireweed_mcp-0.1.0/src/fireweed/fabric.py +292 -0
- fireweed_mcp-0.1.0/src/fireweed/field_edges.py +177 -0
- fireweed_mcp-0.1.0/src/fireweed/firewall.py +115 -0
- fireweed_mcp-0.1.0/src/fireweed/graph.py +562 -0
- fireweed_mcp-0.1.0/src/fireweed/grounding.py +292 -0
- fireweed_mcp-0.1.0/src/fireweed/ledger.py +241 -0
- fireweed_mcp-0.1.0/src/fireweed/ledger_sqlite.py +134 -0
- fireweed_mcp-0.1.0/src/fireweed/perceiver.py +329 -0
- fireweed_mcp-0.1.0/src/fireweed/percept_buffer.py +258 -0
- fireweed_mcp-0.1.0/src/fireweed/pipeline.py +306 -0
- fireweed_mcp-0.1.0/src/fireweed/query_parser.py +143 -0
- fireweed_mcp-0.1.0/src/fireweed/read_gate.py +404 -0
- fireweed_mcp-0.1.0/src/fireweed/reader.py +266 -0
- fireweed_mcp-0.1.0/src/fireweed/receipts.py +115 -0
- fireweed_mcp-0.1.0/src/fireweed/reinforcement.py +73 -0
- fireweed_mcp-0.1.0/src/fireweed/resolver.py +600 -0
- fireweed_mcp-0.1.0/src/fireweed/retrieval.py +463 -0
- fireweed_mcp-0.1.0/src/fireweed/scoring.py +212 -0
- fireweed_mcp-0.1.0/src/fireweed/self_model.py +158 -0
- fireweed_mcp-0.1.0/src/fireweed/semantic_encoder.py +89 -0
- fireweed_mcp-0.1.0/src/fireweed/significance.py +254 -0
- fireweed_mcp-0.1.0/src/fireweed/speaker.py +36 -0
- fireweed_mcp-0.1.0/src/fireweed_mcp/__init__.py +2 -0
- fireweed_mcp-0.1.0/src/fireweed_mcp/server.py +385 -0
- fireweed_mcp-0.1.0/tests/test_mcp_server.py +161 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Publish fireweed-mcp to PyPI via Trusted Publishing (OIDC) — no API token stored anywhere.
|
|
2
|
+
#
|
|
3
|
+
# PyPI publisher configuration this must match EXACTLY:
|
|
4
|
+
# PyPI Project Name : fireweed-mcp
|
|
5
|
+
# Owner : Starksood
|
|
6
|
+
# Repository name : fireweed-mcp
|
|
7
|
+
# Workflow name : publish.yml
|
|
8
|
+
# Environment name : pypi
|
|
9
|
+
#
|
|
10
|
+
# Triggered by publishing a GitHub Release, so a push to main can never ship a version by accident.
|
|
11
|
+
name: publish
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
release:
|
|
15
|
+
types: [published]
|
|
16
|
+
workflow_dispatch: # manual re-run if a publish fails after the release is cut
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
test:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
strategy:
|
|
22
|
+
matrix:
|
|
23
|
+
python-version: ["3.9", "3.12"] # 3.9 is the floor the engine actually runs on
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
- run: pip install pytest
|
|
30
|
+
- run: PYTHONPATH=src python -m pytest -q tests/
|
|
31
|
+
|
|
32
|
+
build:
|
|
33
|
+
needs: test
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.12"
|
|
40
|
+
- run: pip install build
|
|
41
|
+
- run: python -m build
|
|
42
|
+
# Fail the release rather than ship a package that installs but cannot import — the exact
|
|
43
|
+
# failure this project shipped once already and caught only by installing the wheel.
|
|
44
|
+
- name: smoke-test the built wheel in a clean venv
|
|
45
|
+
run: |
|
|
46
|
+
python -m venv /tmp/smoke
|
|
47
|
+
/tmp/smoke/bin/pip install dist/*.whl
|
|
48
|
+
/tmp/smoke/bin/python -c "import fireweed, fireweed_mcp.server as s; assert s.TOOLS; print('import-ok')"
|
|
49
|
+
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}' \
|
|
50
|
+
| /tmp/smoke/bin/fireweed-mcp | grep -q '"serverInfo"' && echo "protocol-ok"
|
|
51
|
+
- uses: actions/upload-artifact@v4
|
|
52
|
+
with:
|
|
53
|
+
name: dist
|
|
54
|
+
path: dist/
|
|
55
|
+
|
|
56
|
+
publish:
|
|
57
|
+
needs: build
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
environment: pypi # must match the Environment name in the PyPI publisher
|
|
60
|
+
permissions:
|
|
61
|
+
id-token: write # required for Trusted Publishing; no token secret needed
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/download-artifact@v4
|
|
64
|
+
with:
|
|
65
|
+
name: dist
|
|
66
|
+
path: dist/
|
|
67
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Functional Source License, Version 1.1, ALv2 Future License
|
|
2
|
+
|
|
3
|
+
## Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-ALv2
|
|
6
|
+
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 Sanyam Sood
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available under
|
|
20
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
+
Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
27
|
+
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
28
|
+
and redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
+
means making the Software available to others in a commercial product or
|
|
34
|
+
service that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the Software
|
|
39
|
+
that exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a licensee
|
|
52
|
+
using the Software in accordance with these Terms and Conditions.
|
|
53
|
+
|
|
54
|
+
### Patents
|
|
55
|
+
|
|
56
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
+
patents, the license grant above includes a license under our patents. If you
|
|
58
|
+
make a claim against any party that the Software infringes or contributes to
|
|
59
|
+
the infringement of any patent, then your patent license to the Software ends
|
|
60
|
+
immediately.
|
|
61
|
+
|
|
62
|
+
### Redistribution
|
|
63
|
+
|
|
64
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
+
the Software.
|
|
66
|
+
|
|
67
|
+
If you redistribute any copies, modifications or derivatives of the Software,
|
|
68
|
+
you must include a copy of or a link to these Terms and Conditions and not
|
|
69
|
+
remove any copyright notices provided in or with the Software.
|
|
70
|
+
|
|
71
|
+
### Disclaimer
|
|
72
|
+
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
74
|
+
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
75
|
+
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
76
|
+
|
|
77
|
+
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
78
|
+
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
79
|
+
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
80
|
+
|
|
81
|
+
### Trademarks
|
|
82
|
+
|
|
83
|
+
Except for displaying the License Details and identifying us as the origin of
|
|
84
|
+
the Software, you have no right under these Terms and Conditions to use our
|
|
85
|
+
trademarks, trade names, service marks or product names.
|
|
86
|
+
|
|
87
|
+
## Grant of Future License
|
|
88
|
+
|
|
89
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
90
|
+
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
91
|
+
the date we make the Software available. On or after that date, you may use the
|
|
92
|
+
Software under the Apache License, Version 2.0, in which case the following
|
|
93
|
+
will apply:
|
|
94
|
+
|
|
95
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
96
|
+
this file except in compliance with the License.
|
|
97
|
+
|
|
98
|
+
You may obtain a copy of the License at
|
|
99
|
+
|
|
100
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
101
|
+
|
|
102
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
|
103
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
104
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
105
|
+
specific language governing permissions and limitations under the License.
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: fireweed-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agent memory where every fact carries a receipt — a deterministic gate decides what is remembered, and erasure issues a signed certificate.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Starksood/fireweed-mcp
|
|
6
|
+
Project-URL: Source, https://github.com/Starksood/fireweed-mcp
|
|
7
|
+
Author: Sanyam Sood
|
|
8
|
+
License: # Functional Source License, Version 1.1, ALv2 Future License
|
|
9
|
+
|
|
10
|
+
## Abbreviation
|
|
11
|
+
|
|
12
|
+
FSL-1.1-ALv2
|
|
13
|
+
|
|
14
|
+
## Notice
|
|
15
|
+
|
|
16
|
+
Copyright 2026 Sanyam Sood
|
|
17
|
+
|
|
18
|
+
## Terms and Conditions
|
|
19
|
+
|
|
20
|
+
### Licensor ("We")
|
|
21
|
+
|
|
22
|
+
The party offering the Software under these Terms and Conditions.
|
|
23
|
+
|
|
24
|
+
### The Software
|
|
25
|
+
|
|
26
|
+
The "Software" is each version of the software that we make available under
|
|
27
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
28
|
+
Conditions with the Software.
|
|
29
|
+
|
|
30
|
+
### License Grant
|
|
31
|
+
|
|
32
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
33
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
34
|
+
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
35
|
+
and redistribute the Software for any Permitted Purpose identified below.
|
|
36
|
+
|
|
37
|
+
### Permitted Purpose
|
|
38
|
+
|
|
39
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
40
|
+
means making the Software available to others in a commercial product or
|
|
41
|
+
service that:
|
|
42
|
+
|
|
43
|
+
1. substitutes for the Software;
|
|
44
|
+
|
|
45
|
+
2. substitutes for any other product or service we offer using the Software
|
|
46
|
+
that exists as of the date we make the Software available; or
|
|
47
|
+
|
|
48
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
49
|
+
|
|
50
|
+
Permitted Purposes specifically include using the Software:
|
|
51
|
+
|
|
52
|
+
1. for your internal use and access;
|
|
53
|
+
|
|
54
|
+
2. for non-commercial education;
|
|
55
|
+
|
|
56
|
+
3. for non-commercial research; and
|
|
57
|
+
|
|
58
|
+
4. in connection with professional services that you provide to a licensee
|
|
59
|
+
using the Software in accordance with these Terms and Conditions.
|
|
60
|
+
|
|
61
|
+
### Patents
|
|
62
|
+
|
|
63
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
64
|
+
patents, the license grant above includes a license under our patents. If you
|
|
65
|
+
make a claim against any party that the Software infringes or contributes to
|
|
66
|
+
the infringement of any patent, then your patent license to the Software ends
|
|
67
|
+
immediately.
|
|
68
|
+
|
|
69
|
+
### Redistribution
|
|
70
|
+
|
|
71
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
72
|
+
the Software.
|
|
73
|
+
|
|
74
|
+
If you redistribute any copies, modifications or derivatives of the Software,
|
|
75
|
+
you must include a copy of or a link to these Terms and Conditions and not
|
|
76
|
+
remove any copyright notices provided in or with the Software.
|
|
77
|
+
|
|
78
|
+
### Disclaimer
|
|
79
|
+
|
|
80
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
81
|
+
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
82
|
+
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
83
|
+
|
|
84
|
+
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
85
|
+
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
86
|
+
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
87
|
+
|
|
88
|
+
### Trademarks
|
|
89
|
+
|
|
90
|
+
Except for displaying the License Details and identifying us as the origin of
|
|
91
|
+
the Software, you have no right under these Terms and Conditions to use our
|
|
92
|
+
trademarks, trade names, service marks or product names.
|
|
93
|
+
|
|
94
|
+
## Grant of Future License
|
|
95
|
+
|
|
96
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
97
|
+
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
98
|
+
the date we make the Software available. On or after that date, you may use the
|
|
99
|
+
Software under the Apache License, Version 2.0, in which case the following
|
|
100
|
+
will apply:
|
|
101
|
+
|
|
102
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
103
|
+
this file except in compliance with the License.
|
|
104
|
+
|
|
105
|
+
You may obtain a copy of the License at
|
|
106
|
+
|
|
107
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
108
|
+
|
|
109
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
|
110
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
111
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
112
|
+
specific language governing permissions and limitations under the License.
|
|
113
|
+
License-File: LICENSE.md
|
|
114
|
+
Keywords: agent-memory,audit,erasure,gdpr,llm,mcp,model-context-protocol,provenance
|
|
115
|
+
Classifier: Development Status :: 4 - Beta
|
|
116
|
+
Classifier: Intended Audience :: Developers
|
|
117
|
+
Classifier: Programming Language :: Python :: 3
|
|
118
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
119
|
+
Requires-Python: >=3.9
|
|
120
|
+
Provides-Extra: semantic
|
|
121
|
+
Requires-Dist: sentence-transformers>=3.0; extra == 'semantic'
|
|
122
|
+
Description-Content-Type: text/markdown
|
|
123
|
+
|
|
124
|
+
# fireweed-mcp
|
|
125
|
+
|
|
126
|
+
Agent memory where every fact carries a receipt.
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
remember(claim = "Priya joined Acme in 2019 under duress.",
|
|
130
|
+
evidence = "Priya Raman joined Acme in 2019 as a logistics analyst.")
|
|
131
|
+
|
|
132
|
+
REFUSED (asserts_more_than_evidence) — the claim adds something the evidence does not say.
|
|
133
|
+
claim : Priya joined Acme in 2019 under duress.
|
|
134
|
+
evidence: Priya Raman joined Acme in 2019 as a logistics analyst.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
recall("Priya's salary")
|
|
139
|
+
|
|
140
|
+
ABSTAINED (unknown_predicate) — no claims ground "salary"; 1 claim about Priya Raman exists
|
|
141
|
+
This is a refusal, not an empty result.
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
forget("Priya")
|
|
146
|
+
|
|
147
|
+
ERASED Priya Raman — certificate issued
|
|
148
|
+
signature : hmac-sha256:f4d0768ef3b0fec624afec12f25bfd91…
|
|
149
|
+
nodes in closure : 1
|
|
150
|
+
every probe abstains : True
|
|
151
|
+
bystanders surviving : 1
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
That last one is the artifact behind *"delete me from your agent's memory — and prove it."*
|
|
155
|
+
|
|
156
|
+
## Install
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
uvx fireweed-mcp # try it
|
|
160
|
+
pip install fireweed-mcp # keep it
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
claude mcp add fireweed -- uvx fireweed-mcp
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
No dependencies. No API keys. No model — nothing in this server calls an LLM.
|
|
168
|
+
|
|
169
|
+
## What it does
|
|
170
|
+
|
|
171
|
+
| tool | |
|
|
172
|
+
|---|---|
|
|
173
|
+
| `remember` | admits a claim **only if the evidence you cite supports it**. Refusals are typed and say what to fix. |
|
|
174
|
+
| `recall` | grounded claims **with the byte range they came from**; abstains and names the term it could not ground |
|
|
175
|
+
| `verify_receipts` | re-hash every source, re-slice every range — **tamper-evident** |
|
|
176
|
+
| `forget` | erasure with exact closure and a **signed certificate**; bystanders survive |
|
|
177
|
+
| `export_memory` | the whole substrate as a portable open-format blob |
|
|
178
|
+
|
|
179
|
+
## Why the refusals are the point
|
|
180
|
+
|
|
181
|
+
Most memory servers store what the model says and return what's nearest. This one **adjudicates**.
|
|
182
|
+
|
|
183
|
+
The rule is *the model proposes, deterministic code decides.* Across an RPC boundary that stops
|
|
184
|
+
being a slogan: **your agent is the proposer**, and it cannot talk its way past the gate, because
|
|
185
|
+
the gate is not a prompt. Pass a claim and the text you're quoting; pure functions check that the
|
|
186
|
+
evidence names the subject, preserves the relation, invents no numbers, and asserts nothing the
|
|
187
|
+
span doesn't say. What survives is stored with a byte range into the source.
|
|
188
|
+
|
|
189
|
+
Then anyone can check it afterwards — including someone who trusts neither your agent nor this
|
|
190
|
+
server. That is the whole product.
|
|
191
|
+
|
|
192
|
+
## What it does NOT do
|
|
193
|
+
|
|
194
|
+
Stated up front, because this project's last headline number turned out to be measuring nothing
|
|
195
|
+
(see [the retraction](https://github.com/Starksood/Fireweed_Fabric/blob/main/RETRACTION.md), which
|
|
196
|
+
ships with a script that proves it):
|
|
197
|
+
|
|
198
|
+
- **It does not extract memories from free text.** You supply the claim and the evidence.
|
|
199
|
+
Automatic extraction needs a perceiver model; this server deliberately has none.
|
|
200
|
+
- **It does not make an LLM truthful.** It governs what enters the *record* and what can be proven
|
|
201
|
+
about it. Your model can still say whatever it likes in its own prose.
|
|
202
|
+
- **Conversational recall is weak, and measured.** On a 1,200-item adversarial corpus the retrieval
|
|
203
|
+
gate abstains on only **40%** of questions whose answer is genuinely absent — it checks that the
|
|
204
|
+
question's *topic* is grounded, not that the asked-for *value* exists. The write path, receipts
|
|
205
|
+
and erasure are unaffected and are the parts to rely on.
|
|
206
|
+
|
|
207
|
+
## Your data
|
|
208
|
+
|
|
209
|
+
`~/.fireweed/mcp/` (`FIREWEED_MCP_STORE` to change). The substrate is an open format — see
|
|
210
|
+
[`open_format/SPEC.md`](open_format/SPEC.md) — and `open_format/reference_reader.py` reads it with
|
|
211
|
+
the standard library alone. Your memory outlives this server, this engine, and any model. A test
|
|
212
|
+
asserts that round trip.
|
|
213
|
+
|
|
214
|
+
Optional: `pip install "fireweed-mcp[semantic]"` enables paraphrase matching in `recall`. Without
|
|
215
|
+
it the gate refuses *more* — the safe direction — and `memory_stats` tells you which mode you're in.
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
**FSL-1.1-ALv2** — source-available. Free for everything except building a competing product;
|
|
220
|
+
converts to **Apache 2.0 on 2028-01-01**. Full text in [`LICENSE.md`](LICENSE.md).
|
|
221
|
+
|
|
222
|
+
Want to use Fireweed in a commercial product or competing service? → **snymsood@icloud.com**
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# fireweed-mcp
|
|
2
|
+
|
|
3
|
+
Agent memory where every fact carries a receipt.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
remember(claim = "Priya joined Acme in 2019 under duress.",
|
|
7
|
+
evidence = "Priya Raman joined Acme in 2019 as a logistics analyst.")
|
|
8
|
+
|
|
9
|
+
REFUSED (asserts_more_than_evidence) — the claim adds something the evidence does not say.
|
|
10
|
+
claim : Priya joined Acme in 2019 under duress.
|
|
11
|
+
evidence: Priya Raman joined Acme in 2019 as a logistics analyst.
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
recall("Priya's salary")
|
|
16
|
+
|
|
17
|
+
ABSTAINED (unknown_predicate) — no claims ground "salary"; 1 claim about Priya Raman exists
|
|
18
|
+
This is a refusal, not an empty result.
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
forget("Priya")
|
|
23
|
+
|
|
24
|
+
ERASED Priya Raman — certificate issued
|
|
25
|
+
signature : hmac-sha256:f4d0768ef3b0fec624afec12f25bfd91…
|
|
26
|
+
nodes in closure : 1
|
|
27
|
+
every probe abstains : True
|
|
28
|
+
bystanders surviving : 1
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
That last one is the artifact behind *"delete me from your agent's memory — and prove it."*
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uvx fireweed-mcp # try it
|
|
37
|
+
pip install fireweed-mcp # keep it
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
claude mcp add fireweed -- uvx fireweed-mcp
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
No dependencies. No API keys. No model — nothing in this server calls an LLM.
|
|
45
|
+
|
|
46
|
+
## What it does
|
|
47
|
+
|
|
48
|
+
| tool | |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `remember` | admits a claim **only if the evidence you cite supports it**. Refusals are typed and say what to fix. |
|
|
51
|
+
| `recall` | grounded claims **with the byte range they came from**; abstains and names the term it could not ground |
|
|
52
|
+
| `verify_receipts` | re-hash every source, re-slice every range — **tamper-evident** |
|
|
53
|
+
| `forget` | erasure with exact closure and a **signed certificate**; bystanders survive |
|
|
54
|
+
| `export_memory` | the whole substrate as a portable open-format blob |
|
|
55
|
+
|
|
56
|
+
## Why the refusals are the point
|
|
57
|
+
|
|
58
|
+
Most memory servers store what the model says and return what's nearest. This one **adjudicates**.
|
|
59
|
+
|
|
60
|
+
The rule is *the model proposes, deterministic code decides.* Across an RPC boundary that stops
|
|
61
|
+
being a slogan: **your agent is the proposer**, and it cannot talk its way past the gate, because
|
|
62
|
+
the gate is not a prompt. Pass a claim and the text you're quoting; pure functions check that the
|
|
63
|
+
evidence names the subject, preserves the relation, invents no numbers, and asserts nothing the
|
|
64
|
+
span doesn't say. What survives is stored with a byte range into the source.
|
|
65
|
+
|
|
66
|
+
Then anyone can check it afterwards — including someone who trusts neither your agent nor this
|
|
67
|
+
server. That is the whole product.
|
|
68
|
+
|
|
69
|
+
## What it does NOT do
|
|
70
|
+
|
|
71
|
+
Stated up front, because this project's last headline number turned out to be measuring nothing
|
|
72
|
+
(see [the retraction](https://github.com/Starksood/Fireweed_Fabric/blob/main/RETRACTION.md), which
|
|
73
|
+
ships with a script that proves it):
|
|
74
|
+
|
|
75
|
+
- **It does not extract memories from free text.** You supply the claim and the evidence.
|
|
76
|
+
Automatic extraction needs a perceiver model; this server deliberately has none.
|
|
77
|
+
- **It does not make an LLM truthful.** It governs what enters the *record* and what can be proven
|
|
78
|
+
about it. Your model can still say whatever it likes in its own prose.
|
|
79
|
+
- **Conversational recall is weak, and measured.** On a 1,200-item adversarial corpus the retrieval
|
|
80
|
+
gate abstains on only **40%** of questions whose answer is genuinely absent — it checks that the
|
|
81
|
+
question's *topic* is grounded, not that the asked-for *value* exists. The write path, receipts
|
|
82
|
+
and erasure are unaffected and are the parts to rely on.
|
|
83
|
+
|
|
84
|
+
## Your data
|
|
85
|
+
|
|
86
|
+
`~/.fireweed/mcp/` (`FIREWEED_MCP_STORE` to change). The substrate is an open format — see
|
|
87
|
+
[`open_format/SPEC.md`](open_format/SPEC.md) — and `open_format/reference_reader.py` reads it with
|
|
88
|
+
the standard library alone. Your memory outlives this server, this engine, and any model. A test
|
|
89
|
+
asserts that round trip.
|
|
90
|
+
|
|
91
|
+
Optional: `pip install "fireweed-mcp[semantic]"` enables paraphrase matching in `recall`. Without
|
|
92
|
+
it the gate refuses *more* — the safe direction — and `memory_stats` tells you which mode you're in.
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
**FSL-1.1-ALv2** — source-available. Free for everything except building a competing product;
|
|
97
|
+
converts to **Apache 2.0 on 2028-01-01**. Full text in [`LICENSE.md`](LICENSE.md).
|
|
98
|
+
|
|
99
|
+
Want to use Fireweed in a commercial product or competing service? → **snymsood@icloud.com**
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# The Fireweed Memory Protocol (FMP) — normalization spec v1
|
|
2
|
+
|
|
3
|
+
**Status:** the open half of the open-core boundary. This document, `reference_reader.py`,
|
|
4
|
+
`conformance.py` and the trap corpus are permanently open; the engine that DECIDES what enters a
|
|
5
|
+
substrate is not. The split is exact: **everything that describes is here, everything that
|
|
6
|
+
adjudicates is private.**
|
|
7
|
+
|
|
8
|
+
**Why it exists:** weights obsolesce in a decade. A record that can only be read by the vendor that
|
|
9
|
+
wrote it is not a record, it is a rental. An FMP snapshot must stay readable with nothing but a JSON
|
|
10
|
+
parser and this document — which is why the reference reader imports only the standard library, and
|
|
11
|
+
why that constraint is a conformance check rather than a preference.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. Container
|
|
16
|
+
|
|
17
|
+
A snapshot is one UTF-8 JSON object. Top level:
|
|
18
|
+
|
|
19
|
+
| field | type | meaning |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `snapshot_version` | int | format version. **2** is current. A reader MUST refuse a version it does not know. |
|
|
22
|
+
| `fireweed_version` | string | the writer's engine version. Informational; never load-bearing. |
|
|
23
|
+
| `nodes` | array | the claims. §2 |
|
|
24
|
+
| `entities` | array | the things claims are about. §3 |
|
|
25
|
+
| `relations` | array | typed edges. §4 |
|
|
26
|
+
| `sessions_seen`, `total_sessions`, `seen_domains`, `session_timestamp`, `session_anchor`, `ingested_session_ids` | — | writer bookkeeping. A reader MAY ignore all of it. |
|
|
27
|
+
|
|
28
|
+
**Refusing is mandatory, not optional.** A reader that silently reads an unknown version is how a
|
|
29
|
+
format rots: it will misinterpret fields that changed meaning and report the result as fact.
|
|
30
|
+
|
|
31
|
+
## 2. Nodes (claims)
|
|
32
|
+
|
|
33
|
+
Required: `node_id` (unique), `claim`. Load-bearing optional fields:
|
|
34
|
+
|
|
35
|
+
| field | meaning |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `normalized_claim` | canonical form used for matching. Derived; never authoritative over `claim`. |
|
|
38
|
+
| `node_type` | `fact` \| `event` \| `state` \| `preference` \| `constraint` \| `inference` \| `reflection` \| `summary` |
|
|
39
|
+
| `status.memory_state` | `active` \| `disputed` \| `superseded` \| `quarantined` \| `frozen` |
|
|
40
|
+
| `entities[].entity_id` | references §3 |
|
|
41
|
+
| `domains` | topical tags, unordered |
|
|
42
|
+
| `provenance` | §5 |
|
|
43
|
+
|
|
44
|
+
**The memory-state contract.**
|
|
45
|
+
|
|
46
|
+
- `active` and `disputed` are both READABLE. A `disputed` node is held in standing contradiction,
|
|
47
|
+
not retired: both sides of an unresolved conflict stay answerable, because silently picking a
|
|
48
|
+
winner is a decision the format must not make on the reader's behalf.
|
|
49
|
+
- `superseded` nodes are **retained in the file, never deleted.** A reader can always reconstruct
|
|
50
|
+
what was once believed and when it stopped being believed. Belief revision is part of the record.
|
|
51
|
+
- Erasure is the one exception: erased content is genuinely gone, replaced by a tombstone. That is a
|
|
52
|
+
deliberate asymmetry — supersession is history, erasure is a promise.
|
|
53
|
+
|
|
54
|
+
## 3. Entities
|
|
55
|
+
|
|
56
|
+
`entity_id` (unique), `canonical_name`, `entity_type`
|
|
57
|
+
(`person` \| `place` \| `organization` \| `object` \| `concept` \| `event`), `aliases`.
|
|
58
|
+
|
|
59
|
+
> **Known defect, stated rather than hidden:** writers at time of writing emit `person` for nearly
|
|
60
|
+
> every entity, including organizations and objects. `entity_type` is therefore NOT yet trustworthy
|
|
61
|
+
> and a reader must not build behaviour on it. Tracked in `docs/DESIGN_read_gate.md` §5, where it is
|
|
62
|
+
> the blocker for object typing.
|
|
63
|
+
|
|
64
|
+
## 4. Relations
|
|
65
|
+
|
|
66
|
+
`relation_id`, `relation_type`, `source_id`, `target_id`.
|
|
67
|
+
|
|
68
|
+
**The list is heterogeneous, and the endpoint domain depends on the type.** This is the one place a
|
|
69
|
+
naive reader will get it wrong — the first run of the conformance suite reported four "dangling"
|
|
70
|
+
relations that were simply entity edges:
|
|
71
|
+
|
|
72
|
+
| relation_type | `source_id` / `target_id` refer to |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `supersedes`, `contradicts`, `supports`, `derived_from`, `causes`, `motivates`, `before` | **node** ids |
|
|
75
|
+
| `co_occurs` | **entity** ids |
|
|
76
|
+
|
|
77
|
+
A reader MUST resolve endpoints in the domain the type declares.
|
|
78
|
+
|
|
79
|
+
## 5. Provenance and receipts
|
|
80
|
+
|
|
81
|
+
| field | meaning |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `source_turn_id` | the turn or document-derived id the claim came from |
|
|
84
|
+
| `source_span` | the **verbatim** evidence the claim was admitted on |
|
|
85
|
+
| `confidence` | the proposer's confidence. Never a gate; informational only. |
|
|
86
|
+
| `grounding_class` | `grounded_verbatim` (subject named in the cited span) or `grounded_resolved` (subject resolved from outside it) |
|
|
87
|
+
| `doc_hash`, `byte_start`, `byte_end` | the receipt coordinate, when the claim is document-bound |
|
|
88
|
+
|
|
89
|
+
**A receipt exists only when `doc_hash`, `byte_start` and `byte_end` are ALL present.** A partial
|
|
90
|
+
coordinate is not a weak receipt — it is no receipt. Reporting one would be exactly the fabrication
|
|
91
|
+
the format exists to prevent, and the conformance suite checks it.
|
|
92
|
+
|
|
93
|
+
**Verification** is two steps, and both must pass:
|
|
94
|
+
|
|
95
|
+
1. `"sha256:" + sha256(document)` equals `doc_hash`
|
|
96
|
+
2. `document[byte_start:byte_end]` decodes to `source_span`
|
|
97
|
+
|
|
98
|
+
Change any byte of the source and one of the two fails. That is the whole provenance guarantee, and
|
|
99
|
+
it is checkable by anyone holding the document — no engine, no network, no trust.
|
|
100
|
+
|
|
101
|
+
## 6. Conformance
|
|
102
|
+
|
|
103
|
+
python open_format/conformance.py <snapshot.json>
|
|
104
|
+
|
|
105
|
+
20 checks. It does not trust the reference reader: it states properties of the FORMAT and runs them
|
|
106
|
+
against whatever reader it is handed, so passing with your own implementation means yours conforms.
|
|
107
|
+
Three of the checks assert the reader REFUSES malformed input, and two assert receipts FAIL on a
|
|
108
|
+
tampered source — a suite that can only pass is not evidence.
|
|
109
|
+
|
|
110
|
+
## 7. Stability
|
|
111
|
+
|
|
112
|
+
Within a major version: fields may be ADDED; existing field meanings never change. A reader must
|
|
113
|
+
ignore fields it does not recognise. Removing or repurposing a field requires a version bump, which
|
|
114
|
+
existing readers are required to refuse.
|