MCP Event Intelligence について
MCP Event Intelligenceは、複数のイベントソースにまたがる将来条件を待つエージェントホスト向けの実験的なイベントランタイムです。モデルから独立して条件を保存し、成立時にタスクを起動します。
主な機能
- 01将来のイベント条件を永続化
- 02複数ソースの時間パターンとウィンドウ
- 03セマンティック述語と派生イベント
- 04トリガーのライフサイクル管理
- 05テナント単位の分離と永続ストレージ
活用シーン
- 01複数イベントの成立後にタスクを起動
- 02イベント時刻に基づく複雑な系列の検出
- 03共有ホストでテナントごとのトリガーを分離
MCP 対応
ホストに接続済みのEvents対応MCPクライアントを検出し、実験的なEvents拡張を通じてイベントを受け取ります。MCPサーバーがイベントソースを公開するためのプロバイダーインターフェースも備えています。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y mcp-event-intelligenceDATA_DIRPersistent Event Intelligence state directory.MCP_WRITE_ENABLEDSet to true to expose persistent trigger mutation tools. Read-only by default.RUNTIME_WAKE_TARGETS_JSONシークレットOptional operator-configured signed runtime wake targets.TYPESAFE_API_KEYシークレットOptional TypeSafe Jev API key for explicit semantic Pattern AST nodes.TYPESAFE_MODELOptional TypeSafe Jev model override. Defaults to jev-latest.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
MCP Event Intelligence
スリープ中のエージェント向けの、永続性を備えた時間的イベントインテリジェンスです。
MCP Event Intelligence は、LLM やエージェントのループを稼働させ続けることなく、複数のイベントソースにまたがる将来の条件に反応する必要があるエージェント向けの、実験的なイベントランタイムです。
主な統合モデルは、ホストに組み込まれ、ホストが所有する方式です。エージェントホストは既存の MCP クライアント、トランスポート、OAuth セッション、プロバイダーの認証情報をそのまま保持します。Event Intelligence はホストの MCP レジストリへの参照を受け取り、すでに接続されているクライアントを自動的に検出し、Events に対応したクライアントのみを使用します。
エージェントは、次のような意図を表現できます。
この PR がマージされ、本番環境へのデプロイが成功し、10 分間エラーが観測されなかったら、このタスクを起動してリリースをレビューしてください。
Event Intelligence は、モデルとは独立して将来の条件を永続化し、世界がその条件を満たすまで待機します。そして、その条件に起動対象がある場合にのみホストを起動します。エージェントの継続処理を伴わない条件も設定でき、より高次の事実は派生イベントトリガーを通じて個別に合成されます。
既存のエージェントホストに組み込む
npm からインストールします:
npm install mcp-event-intelligence
公開パッケージ:npm · 公式 MCP Registry
ほとんどのランタイムでは、まずランタイムに依存しない統合インターフェースを使用します:
import {
createEmbeddedRuntimeIntegration,
createEventSourceRegistry,
} from 'mcp-event-intelligence/embedded';
const ei = await createEmbeddedRuntimeIntegration({
dataDir: './data/event-intelligence',
// The host owns transports, auth and connection lifecycle.
eventSources: createEventSourceRegistry({
list: () => runtime.events.connections(),
subscribe: (refresh) => runtime.events.onConnectionsChanged(refresh),
}),
// EI emits an activation. The host decides what "resume" means.
activation: {
resolveTarget: (target) => runtime.resolveContinuation(target),
hasReceipt: (receiptId) => runtime.hasWakeReceipt(receiptId),
deliver: ({ activation, target, receiptId }) =>
runtime.resumeFromEvent({ activation, target, receiptId }),
},
// Optional. Runtimes without an agent-tool surface can omit tooling entirely.
tooling: {
resolveContext: (ctx) => ({
target: runtime.currentContinuation(ctx),
actor: runtime.currentActor(ctx),
owner: runtime.currentOwner(ctx),
}),
// Host-owned control. EI does not reduce authorization/approval/interrupt
// semantics to a boolean.
control: (request) => runtime.policy.control(request),
// Optional host-owned result projection. Large results may be externalized
// behind a runtime-specific reference instead of entering model context.
projectResult: (request) => runtime.results.project(request),
},
});
継続先は、{ runtime, kind, id } 以外については、EI から意図的に不透明なものとして扱われます。ホストはこれを Turn、Execution、スレッド、グラフのチェックポイント、ワークフロー、Case、またはその他の永続的な継続プリミティブに対応付けることができます。
返されるツールは、EI に依存しない機能メタデータを持つ中立的な記述子です:
for (const tool of ei.toolCatalog.all) {
// The host translates this descriptor into its own tool/capability system.
runtime.tools.register(tool);
}
組み込みカタログには、ソースの検出に加えて、永続的なトリガーのライフサイクル全体が含まれます:trigger_create、trigger_list、trigger_inspect、trigger_pause、trigger_resume、trigger_update、trigger_delete。トリガーの読み取りは、resolveContext() が返す ID によって所有者の範囲に限定されます。永続的な変更は引き続きホストのcontrol()境界を通ります。
EI には、toOpenAI()、toAnthropic()、toMuffin()、toArtemis()のような、ランタイムごとのアダプター一覧は意図的に含まれていません。ランタイムの種類が多すぎるため、新しいランタイムの追加に EI コアの変更が必要になることは決してありません。ホストは同じ中立的な契約を使用し、最終的な変換を自身の境界で行います。
ツールを公開するかどうかもホストが管理します。toolCatalog.list({ capabilityIds })を使うと、ホストが公開を決定した機能だけを抽出できます。EI は読み取りか永続的な変更かといったメタデータを提供しますが、ホストの RBAC、リスクレベル、承認フロー、割り込み UX は決定しません。
永続的な変更の場合、tooling.control()は次のいずれかを返します:
{ action: 'execute', execution?: ... }— 続行します。必要に応じて、ホストのポリシーや承認の来歴を付与できます。または{ action: 'return', result: ... }— 停止し、ホストが所有する不透明な結果を返します。この結果は、拒否、承認が必要、割り込み、延期、またはホストランタイムがサポートするその他の状態を意味する場合があります。
EI は後者のケースを解釈しません。これにより、認可、人による承認、割り込みのセマンティクスはすべてイベントエンジンの外部に保たれます。
結果の処理も同じ境界に従います。projectResult()は、小さな値をインラインで保持することも、ホストが所有する参照に置き換えることもできます。EI が BLOB ストア、アーティファクトシステム、またはモデルコンテキストマネージャーになることはありません。
パッケージには、if (runtime === "muffin")、"artemis"、"openai"、"anthropic"のような、名前付きランタイムに基づくディスパッチは含まれていません。新しいランタイムには、EI コアの外部にあるホスト境界のコードだけが必要です。
ランタイムで直接制御する必要がある場合は、低レベルのホスト API も引き続き利用できます:
ハーネスレベルの MCP レジストリは、一度だけ渡してください。MCP ごとに渡す必要はありません:
import {
createEventIntelligenceHost,
createMcpRegistryAdapter,
} from 'mcp-event-intelligence/host';
const ei = await createEventIntelligenceHost({
dataDir: './data',
mcpRegistry: createMcpRegistryAdapter({
listConnections: () => host.mcp.listConnections(),
subscribe: (refresh) => host.mcp.onConnectionsChanged(refresh),
}),
wake: async (packet, activation) => {
const receipt = await host.resume(packet.target, {
packet,
activation,
});
return { runtimeReceiptId: receipt.id };
},
});
Event Intelligence はホストレジストリを自動的に列挙します。GitHub、Gmail、非公開/社内 MCP、および今後の接続を EI 内で再設定する必要はありません。ツールのみの MCP はエージェントから引き続き利用でき、Events レイヤーでは無視されます。Events 対応の MCP は自動的に接続されます。
エージェント優先のトリガーフロー
エージェントに、別の DSL やモデル固有のプランナーは必要ありません。公開されている作成方法は次のとおりです。
event_sources_list
↓
trigger_language_describe (only when grammar discovery is useful)
↓
trigger_plan
↓
Pattern AST definition
↓
trigger_create
planTrigger() は決定論的に動作します。稼働中のイベントソースを解決し、serverId を設定し、サブスクリプション引数と述語/パターンのフィールドパスを公開スキーマに照らして検証し、標準形式のトリガー定義と必要な接続 ID を返します。
シンプルな条件では、pattern を省略すると、宣言されたイベントを対象とする allOf パターンが生成されます。
const plan = await ei.planTrigger({
events: [{
id: 'invoice',
event: 'erpnext.sales_invoice.submitted',
where: [
{ path: 'grand_total', op: 'gt', value: 10000 },
],
}],
withinMs: 60 * 60 * 1000,
target: {
runtime: 'agent',
kind: 'conversation',
id: 'chat-42',
},
continuation: {
instruction:
'Check the submitted invoice for anomalies and report back in this conversation.',
},
});
高度な CEP では、同じ標準形式の pattern を直接記述します。
const language = ei.describeTriggerLanguage({ category: 'pattern' });
const plan = await ei.planTrigger({
events: [
{ id: 'order', event: 'erpnext.sales_order.created' },
{ id: 'failure', event: 'payments.failed' },
{ id: 'ticket', event: 'support.ticket.created' },
],
withinMs: 30 * 60 * 1000,
pattern: {
version: '2',
partitionBy: [{
key: 'customer',
fields: [
{ ref: 'order', path: 'customer' },
{ ref: 'failure', path: 'customer' },
{ ref: 'ticket', path: 'customer' },
],
}],
root: {
kind: 'aggregate',
function: 'sum',
ref: 'order',
path: 'grand_total',
op: 'gte',
value: 10000,
child: {
kind: 'sequence',
contiguity: 'followedBy',
children: [
{ kind: 'event', ref: 'order' },
{
kind: 'repeat',
child: { kind: 'event', ref: 'failure' },
min: 2,
max: 5,
mode: 'greedy',
},
{
kind: 'optional',
child: { kind: 'event', ref: 'ticket' },
mode: 'greedy',
},
],
},
},
},
target: {
runtime: 'agent',
kind: 'conversation',
id: 'chat-42',
},
continuation: {
instruction: 'Review this customer payment-risk pattern.',
},
});
パターン AST は、トリガー実行モデルの唯一の標準形式です。ネストされたブールパターンとシーケンスパターン、連続性、繰り返し/省略可能な量指定子、上限付き否定パターン、カレンダー/不在/デバウンス/レート/重複排除の各セマンティクス、イベント時刻ウィンドウ、イベント間の比較と算術演算、集計、状態遷移、パーティショニング、マッチ選択ポリシー、決定論的な派生指標に対応します。
ワイヤースキーマでは現在、この文法を version: "2" として識別します。これはスキーマのバージョンであり、別の実行アーキテクチャを意味するものではありません。
ランタイムは決定論を優先します。構造化データでは条件を確実に表現できない場合に限り、第一級の semantic ノードを利用できます。これはベンダーに依存せず、設定された SemanticEvaluator を呼び出します。TYPESAFE_API_KEY が設定されている場合は、同梱の TypeSafe Jev アダプターを任意で使用できます。セマンティック呼び出しは明示的に行われ、回数と時間に上限が設けられ、タイムアウト、キャッシュ、監査記録に対応します。通常の CEP 実行にモデル API は必要ありません。
永続化される continuation は、トリガー条件とは別の問いに答えるものです。将来、条件が成立した後にエージェントは何をすべきか? トリガーに conditionOnly: true を設定すれば、ランタイムターゲットや継続処理を指定せず、条件の状態だけを永続化できます。
ワイヤー上の wake は、意図的に小さく、参照情報のみを含みます。組み込みホストには、2 番目の wake 引数として Activation Envelope も渡されます。同じエンベロープは後から再構築できます。
const activation = await ei.hydrateWake(wakeId);
エンベロープには、設定済みの継続処理、標準形式の Pattern、マッチ状態、マッチした証拠が含まれます。イベントペイロードは信頼できない外部シグナルとしてラベル付けされ、トリガーの continuation.contextPolicy に従ってのみ含まれます。
共有ホスト、テナント分離、ストレージ
1 つの EI ホストで、トリガー状態を共有せずに複数のテナント/ワークスペースに対応できます。ホストが所有する各 MCP 接続に scopeId を付与し、テナント向けコードには対応するスコープ付きビューだけを渡します。
const tenant = await ei.scope('tenant-acme');
await tenant.triggerControl.createTrigger({
definition,
connectionIds: ['acme-erp'],
actor,
owner,
});
const acmeConnections = await tenant.mcpStatus();
デフォルトの参照ストアは、デフォルト以外のスコープを、それぞれ別個の永続ストアパーティション内に物理的に名前空間化します。そのため、トリガー ID、マッチ ID、カーソル、イベントソース、期限、派生イベント、wake 配信状態は、結果を後からグローバルな結果から除外するのではなく、スコープ内で解決されます。ルートホストオブジェクトは、信頼された運用者/コントロールプレーンの権限です。テナントコードにはスコープ付きビューを渡してください。
ストレージは差し替え可能です。
const ei = await createEventIntelligenceHost({
store: myEventIntelligenceStore,
mcpRegistry,
wake,
});
PersistentEventStore は引き続き、依存関係不要の単一プロセス向けデフォルトです。水平スケールするワーカーには、任意で利用できる PostgreSQL アダプターを使用してください。
import pg from 'pg';
import {
PostgresEventStore,
} from 'mcp-event-intelligence/storage/postgres';
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
const store = new PostgresEventStore({
pool,
dispatchPoolIdentity: pool, // required for fenced host dispatch
ownsPool: true,
});
共有デプロイでは、EVENT_INTELLIGENCE_REQUIRE_SHARED_STORE=true と、グローバルに一意な EVENT_INTELLIGENCE_WORKER_ID を設定してください。PostgreSQL パスは、データベースを信頼できる情報源とするスコープ分離、分散環境でのアトミックな wake の取得、トリガー/バージョン/パーティションのリースに加え、共有された再試行/デッドレター状態とクラッシュ復旧状態を提供します。同梱の JSONL ストアは参照実装としての品質にとどまり、複数レプリカで安全であるかのようには扱いません。ストレージと共有状態を参照してください。
MCP プロバイダーにイベントを追加する
プロバイダーは、汎用的な JSON-RPC の接続処理を再実装することなく、実験的な Events 境界を公開できます。
import { createMcpEventsProvider } from 'mcp-event-intelligence/provider';
const events = createMcpEventsProvider({
events: [
{
descriptor: {
name: 'erpnext.sales_invoice.submitted',
description: 'A submitted Sales Invoice was observed.',
delivery: ['poll'],
inputSchema: { type: 'object' },
payloadSchema: {
type: 'object',
required: ['name', 'company', 'grand_total'],
properties: {
name: { type: 'string' },
company: { type: 'string' },
grand_total: { type: 'number' },
},
},
},
poll: async ({ cursor, maxEvents, context }) => {
return providerRuntime.pollInvoices({ cursor, maxEvents, context });
},
},
],
});
このパッケージは、現在のドラフト版 Events 拡張の識別子と設定、events/list、events/poll、共通の検証処理とレスポンス形式を管理します。組み込む MCP サーバーは capabilities.extensions["io.modelcontextprotocol/events"] を通知し、プロバイダーはドメイン固有のイベント定義、認証、データクエリ、発生 ID、不透明なカーソルのセマンティクスを管理します。
このアダプターは、現在の実験的な MCP Events ドラフトに対応しています。確定した MCP Events 準拠をうたうものではありません。v0.4 の互換性スナップショットは、2026-09-25 時点での experimental-ext-triggers-events PR #7 における io.modelcontextprotocol/events 拡張ネゴシエーションの方向性と、conformance PR #521 で検証された検出/ポーリングの契約に準拠しています。
ERPNext を想定した プロバイダーファクトリー もエクスポートされています。
import {
createErpNextEventsProvider,
} from 'mcp-event-intelligence/provider/erpnext';
const events = createErpNextEventsProvider({
pollSalesInvoices: ({ cursor, maxEvents }) =>
erp.pollSubmittedInvoices({ cursor, maxEvents }),
pollSalesOrders: ({ cursor, maxEvents }) =>
erp.pollCreatedSalesOrders({ cursor, maxEvents }),
});
このヘルパーは、erpnext.sales_invoice.submitted と erpnext.sales_order.created の MCP Events ディスクリプター、スキーマ、レスポンス検証を管理します。認証情報を管理する ERPNext コネクターではありません。ホスト/プロバイダーが実際のデータアクセス関数を提供する必要があります。この分離は意図的なものであり、Event Intelligence がプロバイダーの認証を重複して実装することを防ぎます。
実際の ERP データレイヤーでこの抽象化が機能することを示す本番環境での実証は、sarooo17/world-capability-mcp にあります。その ERP Events 実装は、認証済みの ERPNext/Frappe レコードクエリ、テナント/会社フィルター、不透明で再生安全なカーソル、ページネーション/hasMore、タイムゾーンの正規化、決定論的な発生 ID とともに createMcpEventsProvider を使用します。したがって、このパッケージのローカルファクトリーは、本番環境用の ERP コネクターそのものではなく、型付きの便利な API として捉えてください。
v0.7 の実装内容
ホストが管理するイベントソース
- ホストの既存 MCP レジストリーからの自動検出;
- 重複する認証情報を使わず、すでに接続済みの MCP クライアントを再利用;
capabilities.extensions["io.modelcontextprotocol/events"]による MCP 拡張の直接ネゴシエーション;- ページネーションに対応した
events/listによる検出; (connection, event name, arguments)に基づく永続的な EventSubscription ID;- サーバー指定の
nextPollMs、null 許容のカーソル、上限付きページ取得に対応したevents/poll; - ホストが管理するプッシュおよび webhook 配信アダプターから、同じ EventOccurrence パイプラインにイベントを送信;
- 永続的な不透明カーソルとサブスクリプションごとの配信状態;
- 共有された上流サブスクリプションから、同じ
(connection, event, arguments)の組を使用するすべてのアクティブなトリガーにイベントを配信; - 共有ホスト向けのスコープごとのソース/カーソル分離;
- 接続ごとのポーリングの単一実行と、上限付きの
hasMoreバッチ取得; - イベントソースの自動登録;
- ホスト MCP クライアントの動的な接続/切断;
- GitHub webhook など、プロバイダー固有の互換アダプター。
複合トリガーと時間ベースのトリガー
allOf、anyOf、sequence、count;- 同じ値に基づく決定論的な相関付け;
- オプションの意味的相関付け;
absence、not、unless、after、until;debounce、threshold、rate、distinct;- IANA タイムゾーンに対応したカレンダー条件;
- プロバイダーから新しいイベントが届かない場合も継続する永続的な期限。
イベントソースとサブスクリプション
events/list は EventSource 記述子を検出します。永続的な EventSubscription は別個のランタイムオブジェクトであり、ホスト接続、イベント名、正規化されたサブスクリプションの arguments によって識別されます。各サブスクリプションは、それぞれ独立したカーソル/配信状態を持ちます。
これにより、MCP 側のフィルタリングと Event Intelligence の条件を分離できます。arguments はプロバイダーの inputSchema に対して検証され、トリガーの where 述語は、配信されたペイロードに対して EI が評価します。したがって、2 つのトリガーが異なる arguments で同じイベント名をサブスクライブしても、カーソルは共有されません。
ポーリング、プッシュ、Webhook は、配信メカニズムとしてのみ扱われます。相関処理、時間的推論、派生イベント、ウェイク処理の前に、3 つすべてが同じ EventOccurrence 取り込み経路に正規化されます。
エージェントが作成する継続処理
- イベントソースの検出;
- エージェントに使いやすい、決定的なトリガー計画/コンパイル;
- 各ソースの
inputSchemaに対して検証され、EI のペイロード述語とは区別される MCP サブスクリプションのarguments; eq、neq、contains、startsWith、endsWith、regex、in、notIn、between、exists、isNull、type、gt、gte、lt、lteを含む構造化述語;- トリガー条件とは分けて保持される、永続化された継続契約;
- 一致したイベントの証拠を用いた Activation Envelope の水和;
- 埋め込み型ウェイクコールバックが
(packet, activation)を受け取ること; - 実際のソーススキーマと公開フィールドに対する決定的な検証;
- 承認を経た永続的な変更;
- 1 回限りの実行、クールダウン、最大発火回数、有効期限、リース、更新、削除。
派生イベントと合成
トリガーは、エージェントを起動する代わりに、不変の高次イベントを出力できます。
pr.merged + deploy.succeeded
↓
release.ready@1
+
manager.approved
↓
rollout.allowed@1
↓
runtime wake
派生イベントでは、直接の親イベントへの参照のみの来歴と、フラット化されたルート証拠が保持されます。
バージョン管理された契約
派生イベント名は、release.ready@1 のようなバージョン管理された契約です。
- 最初のプロデューサーが正規スキーマを確立します;
- 互換性のあるプロデューサーは同じ契約バージョンに参加できます;
- 互換性のないスキーマは、トリガーの永続化前にエラーになります;
- 複数のバージョンを共存させることができます;
- バージョンが指定されていないために曖昧になるコンシューマーは、フェイルクローズします;
- すべてのイベント発生にはスキーマフィンガープリントが含まれます。
ホストまたはコールバックによるウェイク
埋め込み型ハーネスでは、target.runtime、target.kind、target.id に基づいてルーティングする単一のインプロセスウェイクディスパッチャーを提供できます。ランタイム固有のハンドラーは、より低レベルの選択肢として引き続き利用できます。代わりに、スタンドアロンのデプロイでは署名付き HMAC コールバックを使用できます。どちらの経路も、安定した runtimeReceiptId を返します。
ランタイム配信は永続的です。安定したウェイク ID に対して永続化された配信レコードが作成され、ワーカーはリースを使ってそのレコードを取得します。一時的な失敗は上限付き指数バックオフで再試行され、期限切れの取得状態は再起動後に回復できます。再試行回数の上限に達した場合にのみ、デッドレターになります。これにより、同じアトミックストアを共有する 2 つのワーカーが、同じ配信を同時に所有することを意図する事態を防げます。それでも、受信側の協力なしに、任意の外部副作用をトランザクション的に厳密な 1 回限りで実行できるシステムは存在しないため、ランタイムでは安定したウェイク ID を冪等性キーとして扱う必要があります。
これが存在する理由
MCP Events が扱うのは、イベントの転送/サブスクリプション境界です。Event Intelligence は、転送の上位層を探ります。
- エージェントが将来の条件をどのように宣言するか;
- エージェントがスリープしている間に、複数イベントの状態をどのように維持するか;
- 不在や時間がどのようにイベントになるか;
- モデルを呼び出さずに、より高次の事実をどのように導出するか;
- そうした事実を安全にどのように合成するか;
- 検証済みのシナリオで、ホストがエージェントを実質的に一度だけ再開する方法。
このプロジェクトは MCP Events の置き換えを提案するものではなく、MCP の公式拡張を標榜するものでもありません。
AI と API キー
Event Intelligence における AI の境界は、任意の 明示的なセマンティック評価 だけです。
- Pattern AST では、ベンダーに依存しない
semanticノードを、セマンティック条件を表す唯一の形式として公開します。 TYPESAFE_API_KEYを設定すると、トリガーがセマンティック評価を明示的に要求した場合に、同梱の TypeSafe Jev 評価器が有効になります。- 埋め込みホストは、代わりに互換性のある
semanticEvaluatorを注入できます。 - 決定論的な述語、パターン、ウィンドウ、集計、状態変更、期限、派生指標には、AI 評価器は不要です。
- OpenAI のプランナーは同梱されておらず、OpenAI API への依存もありません。
自然言語による推論は、すでにエージェント/ハーネスが担います。エージェントは trigger_plan / planTrigger() を使って、検出したソーススキーマに基づき一般的なリクエストを決定論的にコンパイルするか、高度なケースでは正規形式のトリガー定義を直接送信できます。決定論的な相関、時間論理、永続化、派生イベント、ウェイク配信にモデル API は不要です。
システム全体の受け入れテスト
v0.6 の受け入れテストスイートでは、以下を検証します。
- ホスト所有の MCP クライアント → 拡張機能の検出 → 永続サブスクリプション → ポーリング/プッシュ/Webhook による発生 → 複合マッチ → プロセス内ウェイク;
- ベンダーに依存しないイベント → 複合マッチ → 派生イベント → 派生イベントの合成 → 署名付きランタイムウェイク;
- コントラクトのスキーマ進化と曖昧さの拒否;
- refs のみのルート来歴;
- 派生イベントやウェイクを重複させない再生;
- 時間的な期限が保留中の状態でのプロセス終了;
- 期限経過後、同じデータストアでの再起動;
- 新たなプロバイダーイベントなしでのウェイク復旧;
- プロセス再起動後のリトライ状態復旧と、リースに基づく同時ワーカーの排他制御;
- スコープが異なり、同一のトリガー ID を持つ場合の共有ホストにおけるテナント分離;
- 上限付き/単一フライトのプロバイダーポーリング;
- ERPNext 形式の請求書/注文イベントによるプロバイダー汎化のカバレッジ;
- ハッシュリンク付き監査の検証。
別途実施したライブ回帰テストでは、実際の GitHub Webhook の受信から MCP EventOccurrence/複合ファンイン経路までを検証しました。
リファレンス/デバッグサービス
HTTP サービスは、ローカル開発、適合性検証、プロバイダー固有の回帰テストに引き続き便利です。これは主要な統合モデルではなく、前述の埋め込み型ホスト所有パッケージの利用方法に代わるものでもありません。
要件
- Node.js 22 以降
- リファレンス構成では外部データベースは不要です
git clone https://github.com/sarooo17/event-intelligence.git
cd event-intelligence
npm ci
npm run check
export SERVICE_AUTH_TOKEN="$(openssl rand -hex 32)"
npm start
次に:
curl http://127.0.0.1:3000/readyz
スタンドアロンサービスは、手動/プロバイダー固有のイベント受信に対応します。任意の MCP 接続は所有しません。ホスト所有の MCP の再利用には、前述のパッケージ統合を使用します。
Docker
docker build -t mcp-event-intelligence:0.6.1 .
docker run --rm \
-p 3000:3000 \
-v mcp-event-intelligence-data:/data \
-e SERVICE_AUTH_TOKEN="$(openssl rand -hex 32)" \
mcp-event-intelligence:0.6.1
任意の MCP コントロールプレーン
このパッケージは、公式 TypeScript SDK v2 を通じて、標準の MCP stdio コントロールプレーンも公開します。
npx mcp-event-intelligence mcp
読み取り専用/変更を伴わないツールは、デフォルトで公開されます。これには event_sources_list、trigger_plan、検査、シミュレーション、wake_hydrate、コントラクト、ランタイム状態が含まれます。trigger_create は、生の正規形式の定義、または同じエージェント向けプラン形式のどちらでも受け付けます。EI は後者を通常の変更制御に適用する前にコンパイルします。
永続的なトリガー変更用ツールは、オペレーターが MCP_WRITE_ENABLED=true を明示的に有効にした場合にのみ登録されます。また、各変更には引き続き confirmationId が必要です。MCP サーバーはコントロールプレーンアダプターであり、ホストが他の MCP サーバーへ再接続するためのゲートウェイではありません。
docs/QUICKSTART.md と docs/MCP-REGISTRY.md を参照してください。
設定
スタンドアロン/コア環境変数:
| 変数 | 必須 | 用途 |
|---|---|---|
SERVICE_AUTH_TOKEN | 保護された HTTP API では必須 | コントロールプレーンのエンドポイント用ベアラートークン |
DATA_DIR | いいえ | 永続化用 JSONL ディレクトリ。既定値は ./data |
PORT | いいえ | HTTP ポート。既定値は 3000 |
ENVIRONMENT_ID | いいえ | 環境の境界 |
RUNTIME_WAKE_TARGETS_JSON | いいえ | スタンドアロンランタイムの署名付きコールバック |
GITHUB_WEBHOOK_SECRET | いいえ | GitHub webhook の受信を検証 |
TYPESAFE_API_KEY | いいえ | バンドルされた TypeSafe Jev セマンティック評価器 |
WAKE_DELIVERY_MAX_ATTEMPTS | いいえ | wake 配信の最大試行回数。既定値は 5 |
WAKE_DELIVERY_LEASE_MS | いいえ | claim リース期間。既定値は 30000 |
WAKE_RETRY_BASE_DELAY_MS | いいえ | 初回リトライの遅延。既定値は 1000 |
WAKE_RETRY_MAX_DELAY_MS | いいえ | リトライのバックオフ上限。既定値は 60000 |
WAKE_RETRY_TICK_MS | いいえ | リトライスケジューラーの間隔。既定値は 1000 |
組み込みホストは MCP レジストリアダプターを 1 つ渡します。Event Intelligence はそのレジストリから、すでに接続されているクライアントを検出します。プロバイダーの MCP 接続設定を EI 内に重複して定義することはありません。
アーキテクチャ
詳細な実行モデル、クロック、ライフサイクル、永続化、信頼境界については、docs/ARCHITECTURE.md を参照してください。
重要なセマンティクス
イベント時刻と処理時刻
通常のイベントウィンドウではイベントの occurredAt を使用します。MCP 受信時には、利用可能な場合、ホストの receivedAt も保持します。配信順序はイベントの順序を定義しません。
順序が前後したイベントは、互換性のあるイベント時刻ウィンドウと照合されます。遅れて到着したイベントは、イベント時刻の全体の範囲が引き続き withinMs に収まる場合に限り、部分一致をより早い occurredAt に再アンカーできます。それ以外の場合は別の部分ウィンドウを開始し、誤ったシーケンスを作成することはありません。
トリガーでは eventTime.allowedLatenessMs を設定できます(既定値は 0)。EI はトリガー/相関ストリームごとにイベント時刻ウォーターマークを維持します。古い部分ウィンドウは、その有効期限が maxObservedEventTime - allowedLatenessMs を過ぎるまで保持されます。ウォーターマークより古いイベントでも、保持されている互換性のある部分一致を完了できますが、古くなった新しいウィンドウの開始には使用できません。
不在/期限の進行には Event Intelligence の処理時刻を使用します。この分離は明示され、テストされています。
実質的に一度だけのランタイム起動
この実装は、理論上の分散環境における厳密な一度だけの配信を保証するものではありません。
安定した wake ID、永続化された配信状態、アトミックな claim リース、上限のあるリトライ、ランタイムの受領確認、リプレイ処理を使用し、検証済みの参照シナリオで実質的に一度だけのランタイム起動を実現します。
派生イベントと現在の状態
派生イベントは、履歴上のある時点で何が真になったかを示します。
Event Intelligence は、変更可能な現在状態/ファクトデータベースを意図的に実装していません。
セキュリティ
SECURITY.md と docs/SECURITY-MODEL.md をお読みください。
組み込みモードでは、ホストが MCP の認可と認証情報を保持します。Event Intelligence は、ホストから提供された MCP レジストリを通じて公開されるクライアントオブジェクトのみを検出します。テナント向けの呼び出し元には、host.scope(scopeId) のみを提供してください。参照用 JSONL ストアはスコープごとに分割され、単一プロセスで動作します。分散型のカスタムストアでは、スコープの分離とアトミックな wake の claim を維持する必要があります。
MCP 互換性の状況
MCP には、独立した 2 つの境界があります。
- イベントの受信:実験的な
io.modelcontextprotocol/events拡張機能を公開する、ホストが所有する接続済みの MCP クライアントと、プロバイダー固有のアダプターです。参照プロバイダーアダプターではポーリングがネイティブでサポートされていますが、プッシュ/Webhook の受信機は引き続きホストが所有する配信アダプターです。 - コントロールプレーン:公式 TypeScript SDK v2 で構築され、プロトコルリビジョン 2026-07-28 を対象とする、オプションの標準 MCP stdio サーバーです。
レジストリの識別子:
io.github.sarooo17/event-intelligence
server.json は、CI で公式の mcp-publisher validate コマンドを使用して検証されます。MCP Events 自体は引き続き実験段階であり、Triggers & Events の取り組みの進展に伴って変更される可能性があります。
プロジェクトの状況
v0.6.x の参照実装/実験段階です。
アーキテクチャは実装され、エンドツーエンドで動作検証済みです。ストレージは現在、注入可能でスコープ化されていますが、同梱の JSONL バックエンドは単一プロセスの参照実装のままです。残作業の中心は、本番用データベースアダプター/HA 検証、スケーラビリティベンチマーク、上流へのフィードバックです。
例
永続的な時間、派生イベント、対象を絞ったウェイクを使用する、将来条件フローを組み合わせた例については、リリースゲートの例を参照してください。
コントリビュート
CONTRIBUTING.md を参照してください。
ホストアダプター、MCP Events との互換性、時間に関するセマンティクス、本番環境向けの永続化、セキュリティレビュー、再現可能なプロバイダー統合に関するコントリビュートが特に役立ちます。
ライセンス
Apache License 2.0 です。LICENSE を参照してください。
免責事項
これは独立したオープンソースプロジェクトです。公式の Model Context Protocol 仕様ではなく、MCP メンテナーとの提携関係も、MCP メンテナーによる推奨もありません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。