mcpField
F
factstore

factstore

ローカル
github.comメモリ・ナレッジ04 週間前に更新

factstore について

factstoreは、企業システムや文書に由来する追跡可能な記録を必要とするAIエージェント、開発者、チーム向けのPostgresベースのファクトストアです。属性を事前登録し、根拠付きで記録して変更不能な履歴を保つため、特定時点で把握していた内容を照会できます。

主な機能

  1. 01登録済みの型付き属性
  2. 02根拠にひも付いたファクト取引
  3. 03指定時点読み取り対応の不変履歴
  4. 04MCPサーバーとPython SDK
  5. 05カタログ作成と文書取り込み用スキル

活用シーン

  1. 01請求書やメールをファクトとして取り込む
  2. 02業務システムのエクスポートをカタログ化
  3. 03日付を指定してファクトと履歴を照会

MCP 対応

MCPサーバーはstdio経由でfactstoreの操作をツールとして公開し、認証情報は環境変数から取得します。MCPクライアントがファクトにアクセスでき、削除ツールは別の認証情報がある場合にのみ利用できます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"victor-eu-factstore": {
"command": "uvx",
"args": [
"factstore"
],
"env": {
"FACTSTORE_DSN": "<FACTSTORE_DSN>",
"FACTSTORE_EXCISE_DSN": "<FACTSTORE_EXCISE_DSN>"
}
}
}
}
起動コマンドuvx factstore
設定が必要な環境変数
FACTSTORE_DSNシークレットThe credential `factstore actor STORE NAME` prints: a Postgres connection string for one actor of one store.
FACTSTORE_EXCISE_DSNシークレットAn excision credential (`factstore actor --excise`). Only then is the excise tool listed.

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypifactstore0.1.0

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

factstore

Postgres 上の AI エージェント向けファクトストアです。エージェントは、企業のシステムやドキュメントに記載された内容をファクトとして記録します。ファクトは、登録済み属性の値であり、誰が書き込んだか、どのドキュメントに由来するかを記したトランザクションに保存されます。上書きはされないため、どの日付時点で何を把握していたかをストアから確認できます。エージェントは MCP サーバー経由で、スクリプトは Python SDK 経由で利用します。

エージェントが実行する手順であるスキルも付属しています。1つはエクスポートデータから企業のシステムをインデックス化し、もう1つはドキュメントやメールを読み取ってファクトにします。設計ではこの方式を採用した理由を、評価ではテスト対象を説明しています。MIT ライセンスです。

インストール

Postgres 16 以降、Python 3.12 以降、および uvx 用の uv が必要です。

1. Postgres。 自分のものを使うか、起動してください。factstore init にはスーパーユーザーが必要です。

docker run -d --name factstore-pg -e POSTGRES_PASSWORD=postgres -p 5432:5432 --shm-size=1g postgres:17

2. ストアと、エージェント用の認証情報。

pip install factstore
export FACTSTORE_ADMIN_DSN=postgresql://postgres:postgres@localhost:5432/postgres
factstore init acme                        # a store, with factstore-core
factstore install acme factstore-skills    # the vocabulary the skills use
factstore actor acme "ingest agent"        # prints the actor's ID and its credential

3. エージェントを接続します。 Claude Code では、プラグインが MCP サーバーとスキルを導入し、認証情報を尋ねます。

/plugin marketplace add Victor-EU/factstore
/plugin install factstore@factstore

その他の MCP クライアントでは、認証情報を環境変数に設定してサーバーを実行します。

{"mcpServers": {"factstore": {"command": "uvx", "args": ["factstore", "mcp"],
                              "env": {"FACTSTORE_DSN": "<credential>"}}}}

factstore skills DIR は、スキルを .claude/skills などのエージェントのスキルディレクトリにコピーします。カタログ作成スキルと取り込みスキルは SDK を使って一括書き込みも行うため、エージェントのシェルに pip install factstore が必要です。

4. 質問します。 「./invoices の請求書をストアに読み込んで」は factstore-ingest を使います。「Shopify と QuickBooks のエクスポートをインデックス化して」は factstore-catalogue を使います。「ストアにはどんな種類のものが入っている?」は factstore-ontology を使います。

リリースに含まれるもの

factstore install STORE NAME は、名前を指定してパッケージをインストールし、その依存パッケージもインストールします。

パッケージ内容
factstore-coreエビデンス、ドキュメント、確信度、通貨、統合、ドメイン時間です。init がインストールします。
factstore-skillsカタログ作成、オントロジー、取り込みのスキルと、オントロジースキルが形状に名前を付ける際に使う語彙です。
factstore-ecom-ops中国で製造しオンラインで販売するブランドの供給側を扱います。サプライヤー、SKU、発注書、検査、出荷、通関申告が含まれます。付属のスキルはサプライヤーの PDF、チャット、出荷メールを読み取ります。
factstore-ecom-indexカタログ作成スキル用に、Shopify、Amazon、3PL、QuickBooks が管理するデータの ID と結合キーを扱います。

個人データ。 サーバーのルールにより、氏名、住所、電話番号はストアに保存されず、ドキュメント内に留まります。属性にこれらを保持させたい企業は、core/personal で許可します。

開発

git clone https://github.com/Victor-EU/factstore && cd factstore
docker compose up -d                      # Postgres 17 on port 54329
cd factstore
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pytest

テストでは、テストごとにストアを作成し、削除します。ソースチェックアウトからは、factstore install にパッケージのディレクトリ(../packages/ecom-ops など)を指定することもできます。packages/ では、パッケージ形式とパッケージについて説明しています。パッケージの新しいバージョンは、追加する内容を登録します。また、カーネルで許可されている2種類の変更である、属性を多値にする変更と ID にする変更を行うこともできます。factstore-skills/ にスキルがあります。

import factstore

store = factstore.connect("<credential from above>")
store.register_attribute({"ident": "shopify/order_id", "type": "string", "cardinality": "one",
                          "unique": "identity", "doc": "Shopify's ID for an order."})
store.transact([{"e": ["shopify/order_id", "1234"], "a": "shopify/order_id", "v": "1234"}])
store.query('select e, v from "shopify/order_id"').rows

FACTSTORE_DSN が設定されていれば、同じ呼び出しをモジュールレベルでも実行できます:factstore.transact([...])、factstore.query(...)。

MCP サーバー

factstore mcp または factstore-mcp は、stdio 経由で呼び出しをツールとして提供します。認証情報は環境変数(FACTSTORE_DSN)から取得され、ツール呼び出しから渡されることはありません。FACTSTORE_EXCISE_DSN に消去用認証情報も設定されている場合に限り、excise が一覧に表示されます。tools.py のツール説明は、モデルが読むドキュメントです。

レイアウト

ファイル内容
schema.sqlPostgres で不変条件を強制するテーブル、ロール、トリガー
kernel.py書き込みロック、スキーマの読み込み、採番、ログと派生テーブルへの変更の適用
store.py呼び出し:transact、query、stats、register_attribute、search_attributes、excise
read.py安全に読み取りを実行する処理:読み取り専用、ロールバック、単一ステートメント、タイムアウト、行数上限
stats.py属性の使用状況、シグネチャ、参照の接続性
server.pyMCP サーバー
admin.py、cli.pyストア、アクター、認証情報の作成、パッケージのインストール
packages.pyパッケージマニフェスト、リリースに含まれるパッケージ、インストール順序
tools.pyMCP ツールの説明と入力スキーマ:モデル向けのドキュメント
fs.pyカーネル独自の fs/ 属性
tests/reference.py参照リーダー:ログを単純に畳み込む処理。テストのオラクルとして使用

不変条件の強制方法

不変条件を強制するのは Python コードだけではなく、Postgres です。

  • 不変性。 書き込み側が fact テーブルに対して持つ権限は INSERT と SELECT のみで、それ以外の権限はありません。トリガーは、fs_excise() 外での UPDATE、TRUNCATE、およびあらゆる DELETE を、所有者からの操作であっても拒否します。
  • 書き込み者をカーネルが決定します。 認証情報は Postgres のログインです。トリガーは各トランザクションのアクターを session_user から、時刻をシステムクロックから設定し、クライアントが送信した値は上書きします。カーネル独自の関数だけが fs/actor、fs/at、fs/excised_* のファクトを書き込めます。
  • 登録済みの型付き属性。 すべてのファクトには登録済みの属性を指定する必要があり(外部キーで強制)、トリガーが値とその属性の型が一致することを確認します。別のトリガーは、属性の変更が許可されていない方向(型の変更、多対一への変更、一意性の削除)に進むのを防ぎます。
  • コミット順序。 各書き込みはストアごとに1つのアドバイザリロックを取得し、そのロック内でトランザクション ID を割り当てます。トリガーも同じロックを取得し、最新の ID より後でない ID を拒否します。

読み取り

query はビューに対して1つの SQL ステートメントを実行します(設計上の未解決事項1。 スパイクで決定):

  • 各属性は、その属性名を付けたビューです。スキーマ current の "po/status"(e, v, tx) と、ログ全体を対象とする history."po/status"(e, v, tx, op) があります。
  • 登録時にトリガーがビューを作成します。
  • as-of 読み取りでは factstore.as_of を設定し、すべてのビューがその値を尊重します。

モデルが SQL を記述するため、read.py は別の接続で実行します。

  • 常にロールバックされる READ ONLY トランザクション内で実行するため、SET ROLE を含め、ステートメントによる変更はすべて取り消されます。
  • プリペアドステートメントとして実行するため、Postgres が2つ目のステートメントを拒否します。
  • 10秒のタイムアウトと1,000行の上限を設けます。

アドバイザリロックはロールバック後も保持されるため、各読み取りの後に解放されます。クエリが書き込みロックを保持することはありません。

stats はエンティティをシグネチャ、つまりそれぞれが持つ属性の正確な集合ごとにグループ化し、シグネチャ間の参照数を数えます。これはオントロジースキルが必要とする形式での共起です。ある種類のものは通常、1つのシグネチャを持つか、オプション属性だけが異なる少数のシグネチャを持ちます。

実装時に行った決定

  • カーディナリティ 1 は書き込み時に適用します。 新しい値をアサートすると、古い値の明示的な撤回がログに書き込まれます。その後の現在の状態は、属性のカーディナリティが当時どう設定されていたかにかかわらず、アサーションと撤回を単純に畳み込んで求められます。
  • 冗長な書き込みは破棄します。 エンティティがすでに持っている値のアサートや、持っていない値の撤回は、変更なしとして報告され、ログには記録されません。何も変更しない呼び出しではトランザクションが書き込まれないため、取り込みを再実行してもログは変わりません。
  • ルックアップによる作成はアサーションがある場合に限ります。 ルックアップで何も見つからず、呼び出しが何かをアサートする場合は、エンティティが作成されます。ルックアップが撤回のみに使われる場合、呼び出しはエラーになります。
  • 文字列の等価性にはハッシュインデックスを使います。 文字列値の B ツリーは先頭 200 文字にインデックスを付けるため、長い値でも挿入が失敗することはありません。等価性の判定では値全体に対するハッシュインデックスを使うため、どのビューでも v = 'x' を利用できます。
  • カーネルのテストは何も入っていないストアで実行します。 init は factstore-core をインストールしますが、カーネルのテストでは core=False を指定します。カーネルは名前を認識しないため、そのテストが core に依存すべきではありません。各パッケージにはそれぞれ独自のテストがあります。
  • 近似一致のしきい値。 これらはサンプル属性を使った初期調整値で、store.py の先頭に設定されています。tests/test_register.py には、しきい値の検証に使ったケースが記録されています。M5 の「登録済み属性」指標を使って、しきい値を調整します。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。