mcp-event-intelligence 0.1.0
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.
- package/CHANGELOG.md +80 -0
- package/LICENSE +201 -0
- package/README.md +298 -0
- package/SECURITY.md +42 -0
- package/bin/mcp-event-intelligence.mjs +52 -0
- package/dist/src/composite/engine.d.ts +87 -0
- package/dist/src/composite/engine.js +667 -0
- package/dist/src/composite/temporal.d.ts +32 -0
- package/dist/src/composite/temporal.js +317 -0
- package/dist/src/intelligenceProtocol/audit.d.ts +19 -0
- package/dist/src/intelligenceProtocol/audit.js +56 -0
- package/dist/src/intelligenceProtocol/canonical.d.ts +2 -0
- package/dist/src/intelligenceProtocol/canonical.js +21 -0
- package/dist/src/intelligenceProtocol/index.d.ts +12 -0
- package/dist/src/intelligenceProtocol/index.js +8 -0
- package/dist/src/intelligenceProtocol/invariants.d.ts +3 -0
- package/dist/src/intelligenceProtocol/invariants.js +36 -0
- package/dist/src/intelligenceProtocol/lifecycle.d.ts +4 -0
- package/dist/src/intelligenceProtocol/lifecycle.js +24 -0
- package/dist/src/intelligenceProtocol/mapper.d.ts +14 -0
- package/dist/src/intelligenceProtocol/mapper.js +28 -0
- package/dist/src/intelligenceProtocol/schemas.d.ts +325 -0
- package/dist/src/intelligenceProtocol/schemas.js +182 -0
- package/dist/src/intelligenceProtocol/triggerSchemas.d.ts +488 -0
- package/dist/src/intelligenceProtocol/triggerSchemas.js +379 -0
- package/dist/src/intelligenceProtocol/version.d.ts +7 -0
- package/dist/src/intelligenceProtocol/version.js +7 -0
- package/dist/src/mcpEvents/consumer.d.ts +7 -0
- package/dist/src/mcpEvents/consumer.js +14 -0
- package/dist/src/mcpEvents/server.d.ts +41 -0
- package/dist/src/mcpEvents/server.js +122 -0
- package/dist/src/protocol/types.d.ts +37 -0
- package/dist/src/protocol/types.js +1 -0
- package/dist/src/semantic/conditionEngine.d.ts +7 -0
- package/dist/src/semantic/conditionEngine.js +65 -0
- package/dist/src/semantic/types.d.ts +31 -0
- package/dist/src/semantic/types.js +1 -0
- package/dist/src/semantic/typesafeJevEvaluator.d.ts +23 -0
- package/dist/src/semantic/typesafeJevEvaluator.js +95 -0
- package/package.json +85 -0
- package/scripts/host-integration.d.mts +86 -0
- package/scripts/host-integration.mjs +216 -0
- package/scripts/lib/composite-event-consumer.mjs +172 -0
- package/scripts/lib/composite-wake-coordinator.mjs +185 -0
- package/scripts/lib/derived-contract-registry.mjs +210 -0
- package/scripts/lib/derived-event-coordinator.mjs +242 -0
- package/scripts/lib/event-processor.mjs +409 -0
- package/scripts/lib/generic-runtime-wake.mjs +76 -0
- package/scripts/lib/github-mcp-events-adapter.mjs +66 -0
- package/scripts/lib/github-webhook.mjs +88 -0
- package/scripts/lib/http-wake-deliverer.mjs +31 -0
- package/scripts/lib/local-event-intelligence-runtime.mjs +193 -0
- package/scripts/lib/mcp-events-client.mjs +519 -0
- package/scripts/lib/persistent-event-store.mjs +769 -0
- package/scripts/lib/temporal-deadline-scheduler.mjs +111 -0
- package/scripts/lib/trigger-control-plane.mjs +939 -0
- package/scripts/lib/trigger-inspector.mjs +631 -0
- package/scripts/lib/wake-signature.mjs +10 -0
- package/scripts/mcp-stdio-server.mjs +380 -0
- package/scripts/mcp-stdio.mjs +3 -0
- package/scripts/run-tests.mjs +51 -0
- package/scripts/service.mjs +756 -0
- package/server.json +68 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/server';
|
|
2
|
+
import { serveStdio } from '@modelcontextprotocol/server/stdio';
|
|
3
|
+
import * as z from 'zod/v4';
|
|
4
|
+
import {
|
|
5
|
+
parseCompositeTriggerDefinition,
|
|
6
|
+
} from '../dist/src/intelligenceProtocol/index.js';
|
|
7
|
+
import {
|
|
8
|
+
simulateTrigger,
|
|
9
|
+
} from './lib/trigger-inspector.mjs';
|
|
10
|
+
import {
|
|
11
|
+
createLocalEventIntelligenceRuntime,
|
|
12
|
+
} from './lib/local-event-intelligence-runtime.mjs';
|
|
13
|
+
|
|
14
|
+
function jsonResult(value) {
|
|
15
|
+
return {
|
|
16
|
+
content: [
|
|
17
|
+
{
|
|
18
|
+
type: 'text',
|
|
19
|
+
text: JSON.stringify(value, null, 2),
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
structuredContent: value,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function errorResult(error) {
|
|
27
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
28
|
+
const code =
|
|
29
|
+
error && typeof error === 'object' && 'code' in error
|
|
30
|
+
? String(error.code)
|
|
31
|
+
: 'EVENT_INTELLIGENCE_ERROR';
|
|
32
|
+
return {
|
|
33
|
+
isError: true,
|
|
34
|
+
content: [
|
|
35
|
+
{
|
|
36
|
+
type: 'text',
|
|
37
|
+
text: JSON.stringify({ error: message, code }, null, 2),
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
structuredContent: { error: message, code },
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function actorFromEnv(env) {
|
|
45
|
+
return {
|
|
46
|
+
type: 'agent',
|
|
47
|
+
principal_id: env.MCP_ACTOR_ID ?? 'mcp-agent',
|
|
48
|
+
...(env.MCP_TENANT_ID ? { tenant_id: env.MCP_TENANT_ID } : {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function ownerFromEnv(env) {
|
|
53
|
+
return {
|
|
54
|
+
type: 'user',
|
|
55
|
+
principal_id: env.MCP_OWNER_ID ?? 'local-user',
|
|
56
|
+
...(env.MCP_TENANT_ID ? { tenant_id: env.MCP_TENANT_ID } : {}),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function registerReadTools(server, runtime) {
|
|
61
|
+
server.registerTool(
|
|
62
|
+
'event_sources_list',
|
|
63
|
+
{
|
|
64
|
+
description:
|
|
65
|
+
'List active event sources currently available to Event Intelligence.',
|
|
66
|
+
inputSchema: z.object({
|
|
67
|
+
connectionIds: z.array(z.string()).optional(),
|
|
68
|
+
}),
|
|
69
|
+
},
|
|
70
|
+
async ({ connectionIds }) => {
|
|
71
|
+
try {
|
|
72
|
+
return jsonResult({
|
|
73
|
+
sources: runtime.triggerControl.listEventSources({
|
|
74
|
+
...(connectionIds ? { connectionIds } : {}),
|
|
75
|
+
}),
|
|
76
|
+
});
|
|
77
|
+
} catch (error) {
|
|
78
|
+
return errorResult(error);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
server.registerTool(
|
|
84
|
+
'trigger_list',
|
|
85
|
+
{
|
|
86
|
+
description:
|
|
87
|
+
'List durable triggers and lifecycle state, optionally scoped to the configured owner.',
|
|
88
|
+
inputSchema: z.object({
|
|
89
|
+
ownerOnly: z.boolean().default(true),
|
|
90
|
+
}),
|
|
91
|
+
},
|
|
92
|
+
async ({ ownerOnly }) => {
|
|
93
|
+
try {
|
|
94
|
+
return jsonResult({
|
|
95
|
+
triggers: runtime.triggerControl.listTriggers(
|
|
96
|
+
ownerOnly ? { owner: ownerFromEnv(process.env) } : {},
|
|
97
|
+
),
|
|
98
|
+
});
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return errorResult(error);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
server.registerTool(
|
|
106
|
+
'trigger_inspect',
|
|
107
|
+
{
|
|
108
|
+
description:
|
|
109
|
+
'Explain a trigger deterministically, including missing clauses, temporal state, deadlines, lineage, derived outputs and wake receipt.',
|
|
110
|
+
inputSchema: z.object({
|
|
111
|
+
triggerId: z.string().min(1),
|
|
112
|
+
version: z.string().min(1).optional(),
|
|
113
|
+
matchId: z.string().min(1).optional(),
|
|
114
|
+
}),
|
|
115
|
+
},
|
|
116
|
+
async (input) => {
|
|
117
|
+
try {
|
|
118
|
+
return jsonResult(runtime.triggerInspector.inspect(input));
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return errorResult(error);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
server.registerTool(
|
|
126
|
+
'trigger_simulate',
|
|
127
|
+
{
|
|
128
|
+
description:
|
|
129
|
+
'Run a trigger definition against an isolated event sequence without mutating live state.',
|
|
130
|
+
inputSchema: z.object({
|
|
131
|
+
definition: z.record(z.string(), z.unknown()),
|
|
132
|
+
events: z.array(z.record(z.string(), z.unknown())),
|
|
133
|
+
until: z.string().optional(),
|
|
134
|
+
order: z.enum(['provided', 'event_time']).default('provided'),
|
|
135
|
+
}),
|
|
136
|
+
},
|
|
137
|
+
async (input) => {
|
|
138
|
+
try {
|
|
139
|
+
return jsonResult(await simulateTrigger(input));
|
|
140
|
+
} catch (error) {
|
|
141
|
+
return errorResult(error);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
server.registerTool(
|
|
147
|
+
'derived_contracts_list',
|
|
148
|
+
{
|
|
149
|
+
description:
|
|
150
|
+
'List versioned derived-event contracts, canonical schemas, fingerprints and registered producers.',
|
|
151
|
+
inputSchema: z.object({
|
|
152
|
+
eventName: z.string().min(1).optional(),
|
|
153
|
+
}),
|
|
154
|
+
},
|
|
155
|
+
async ({ eventName }) => {
|
|
156
|
+
try {
|
|
157
|
+
return jsonResult({
|
|
158
|
+
contracts: runtime.store.listDerivedContracts(eventName),
|
|
159
|
+
});
|
|
160
|
+
} catch (error) {
|
|
161
|
+
return errorResult(error);
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
server.registerTool(
|
|
167
|
+
'runtime_status',
|
|
168
|
+
{
|
|
169
|
+
description:
|
|
170
|
+
'Return local Event Intelligence runtime status, restored counts, host-managed MCP event connections and pending temporal deadlines.',
|
|
171
|
+
inputSchema: z.object({}),
|
|
172
|
+
},
|
|
173
|
+
async () => {
|
|
174
|
+
try {
|
|
175
|
+
return jsonResult({
|
|
176
|
+
restored: runtime.restored,
|
|
177
|
+
hostMcpEventConnections: runtime.mcpEventsClient.status(),
|
|
178
|
+
pendingTemporalDeadlines:
|
|
179
|
+
runtime.store.listTemporalDeadlines({ status: 'pending' }).length,
|
|
180
|
+
derivedEvents: runtime.store.listDerivedEvents().length,
|
|
181
|
+
derivedContracts: runtime.store.listDerivedContracts().length,
|
|
182
|
+
writeEnabled: process.env.MCP_WRITE_ENABLED === 'true',
|
|
183
|
+
});
|
|
184
|
+
} catch (error) {
|
|
185
|
+
return errorResult(error);
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function registerWriteTools(server, runtime) {
|
|
192
|
+
const actor = () => actorFromEnv(process.env);
|
|
193
|
+
const owner = () => ownerFromEnv(process.env);
|
|
194
|
+
|
|
195
|
+
server.registerTool(
|
|
196
|
+
'trigger_create',
|
|
197
|
+
{
|
|
198
|
+
description:
|
|
199
|
+
'Create a durable trigger. Persistent MCP mutations require explicit confirmationId and MCP_WRITE_ENABLED=true.',
|
|
200
|
+
inputSchema: z.object({
|
|
201
|
+
definition: z.record(z.string(), z.unknown()),
|
|
202
|
+
connectionIds: z.array(z.string()).min(1),
|
|
203
|
+
confirmationId: z.string().min(1),
|
|
204
|
+
}),
|
|
205
|
+
},
|
|
206
|
+
async ({ definition, connectionIds, confirmationId }) => {
|
|
207
|
+
try {
|
|
208
|
+
return jsonResult(
|
|
209
|
+
await runtime.triggerControl.createTrigger({
|
|
210
|
+
definition,
|
|
211
|
+
connectionIds,
|
|
212
|
+
actor: actor(),
|
|
213
|
+
owner: owner(),
|
|
214
|
+
confirmationId,
|
|
215
|
+
}),
|
|
216
|
+
);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
return errorResult(error);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
const lifecycleSchema = z.object({
|
|
224
|
+
triggerId: z.string().min(1),
|
|
225
|
+
version: z.string().min(1),
|
|
226
|
+
confirmationId: z.string().min(1),
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
server.registerTool(
|
|
230
|
+
'trigger_pause',
|
|
231
|
+
{
|
|
232
|
+
description: 'Pause a durable trigger after explicit confirmation.',
|
|
233
|
+
inputSchema: lifecycleSchema,
|
|
234
|
+
},
|
|
235
|
+
async ({ triggerId, version, confirmationId }) => {
|
|
236
|
+
try {
|
|
237
|
+
return jsonResult(
|
|
238
|
+
await runtime.triggerControl.pauseTrigger({
|
|
239
|
+
triggerId,
|
|
240
|
+
version,
|
|
241
|
+
actor: actor(),
|
|
242
|
+
owner: owner(),
|
|
243
|
+
confirmationId,
|
|
244
|
+
}),
|
|
245
|
+
);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
return errorResult(error);
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
server.registerTool(
|
|
253
|
+
'trigger_resume',
|
|
254
|
+
{
|
|
255
|
+
description: 'Resume a paused durable trigger after explicit confirmation.',
|
|
256
|
+
inputSchema: lifecycleSchema,
|
|
257
|
+
},
|
|
258
|
+
async ({ triggerId, version, confirmationId }) => {
|
|
259
|
+
try {
|
|
260
|
+
return jsonResult(
|
|
261
|
+
await runtime.triggerControl.resumeTrigger({
|
|
262
|
+
triggerId,
|
|
263
|
+
version,
|
|
264
|
+
actor: actor(),
|
|
265
|
+
owner: owner(),
|
|
266
|
+
confirmationId,
|
|
267
|
+
}),
|
|
268
|
+
);
|
|
269
|
+
} catch (error) {
|
|
270
|
+
return errorResult(error);
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
server.registerTool(
|
|
276
|
+
'trigger_delete',
|
|
277
|
+
{
|
|
278
|
+
description: 'Delete a durable trigger after explicit confirmation.',
|
|
279
|
+
inputSchema: lifecycleSchema,
|
|
280
|
+
},
|
|
281
|
+
async ({ triggerId, version, confirmationId }) => {
|
|
282
|
+
try {
|
|
283
|
+
return jsonResult(
|
|
284
|
+
await runtime.triggerControl.deleteTrigger({
|
|
285
|
+
triggerId,
|
|
286
|
+
version,
|
|
287
|
+
actor: actor(),
|
|
288
|
+
owner: owner(),
|
|
289
|
+
confirmationId,
|
|
290
|
+
}),
|
|
291
|
+
);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
return errorResult(error);
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
server.registerTool(
|
|
299
|
+
'trigger_update',
|
|
300
|
+
{
|
|
301
|
+
description:
|
|
302
|
+
'Create a new immutable version of an existing durable trigger after explicit confirmation.',
|
|
303
|
+
inputSchema: z.object({
|
|
304
|
+
triggerId: z.string().min(1),
|
|
305
|
+
expectedVersion: z.string().min(1),
|
|
306
|
+
definition: z.record(z.string(), z.unknown()),
|
|
307
|
+
connectionIds: z.array(z.string()).optional(),
|
|
308
|
+
confirmationId: z.string().min(1),
|
|
309
|
+
}),
|
|
310
|
+
},
|
|
311
|
+
async ({
|
|
312
|
+
triggerId,
|
|
313
|
+
expectedVersion,
|
|
314
|
+
definition,
|
|
315
|
+
connectionIds,
|
|
316
|
+
confirmationId,
|
|
317
|
+
}) => {
|
|
318
|
+
try {
|
|
319
|
+
return jsonResult(
|
|
320
|
+
await runtime.triggerControl.updateTrigger({
|
|
321
|
+
triggerId,
|
|
322
|
+
expectedVersion,
|
|
323
|
+
definition,
|
|
324
|
+
connectionIds,
|
|
325
|
+
actor: actor(),
|
|
326
|
+
owner: owner(),
|
|
327
|
+
confirmationId,
|
|
328
|
+
}),
|
|
329
|
+
);
|
|
330
|
+
} catch (error) {
|
|
331
|
+
return errorResult(error);
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export async function buildEventIntelligenceMcpServer({
|
|
338
|
+
env = process.env,
|
|
339
|
+
} = {}) {
|
|
340
|
+
const runtime = await createLocalEventIntelligenceRuntime({ env });
|
|
341
|
+
const server = new McpServer(
|
|
342
|
+
{
|
|
343
|
+
name: 'mcp-event-intelligence',
|
|
344
|
+
version: '0.1.0',
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
instructions:
|
|
348
|
+
'Use Event Intelligence to discover event sources, inspect/simulate durable trigger programs, and govern continuations. The agent authors structured trigger definitions using the discovered source schemas. Persistent mutations are unavailable unless the operator enables MCP_WRITE_ENABLED=true, and each mutation requires confirmationId.',
|
|
349
|
+
},
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
registerReadTools(server, runtime);
|
|
353
|
+
if (env.MCP_WRITE_ENABLED === 'true') {
|
|
354
|
+
registerWriteTools(server, runtime);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return { server, runtime };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export async function serveEventIntelligenceStdio({
|
|
361
|
+
env = process.env,
|
|
362
|
+
} = {}) {
|
|
363
|
+
const { server, runtime } = await buildEventIntelligenceMcpServer({ env });
|
|
364
|
+
const close = async () => {
|
|
365
|
+
await runtime.close();
|
|
366
|
+
};
|
|
367
|
+
process.once('SIGTERM', close);
|
|
368
|
+
process.once('SIGINT', close);
|
|
369
|
+
|
|
370
|
+
console.error(
|
|
371
|
+
JSON.stringify({
|
|
372
|
+
message: 'mcp_event_intelligence_stdio_ready',
|
|
373
|
+
dataDir: env.DATA_DIR ?? './data',
|
|
374
|
+
writeEnabled: env.MCP_WRITE_ENABLED === 'true',
|
|
375
|
+
mcpProtocolTarget: '2026-07-28',
|
|
376
|
+
}),
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
await serveStdio(() => server, { legacy: 'reject' });
|
|
380
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
|
|
4
|
+
const timeoutMs = Number(process.env.TEST_FILE_TIMEOUT_MS ?? 60000);
|
|
5
|
+
const tests = (await readdir('test'))
|
|
6
|
+
.filter((name) => name.endsWith('.test.mjs'))
|
|
7
|
+
.sort()
|
|
8
|
+
.map((name) => `test/${name}`);
|
|
9
|
+
|
|
10
|
+
for (const file of tests) {
|
|
11
|
+
console.log(`\n=== ${file} ===`);
|
|
12
|
+
|
|
13
|
+
const child = spawn(process.execPath, ['--test', file], {
|
|
14
|
+
stdio: 'inherit',
|
|
15
|
+
env: process.env,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
let timedOut = false;
|
|
19
|
+
const timer = setTimeout(() => {
|
|
20
|
+
timedOut = true;
|
|
21
|
+
console.error(`\nTEST_FILE_TIMEOUT: ${file} exceeded ${timeoutMs}ms`);
|
|
22
|
+
child.kill('SIGTERM');
|
|
23
|
+
|
|
24
|
+
const hardKill = setTimeout(() => child.kill('SIGKILL'), 5000);
|
|
25
|
+
hardKill.unref?.();
|
|
26
|
+
}, timeoutMs);
|
|
27
|
+
timer.unref?.();
|
|
28
|
+
|
|
29
|
+
const code = await new Promise((resolve, reject) => {
|
|
30
|
+
child.once('error', reject);
|
|
31
|
+
child.once('exit', (exitCode, signal) => {
|
|
32
|
+
if (timedOut) {
|
|
33
|
+
resolve(124);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (signal) {
|
|
37
|
+
console.error(`Test process terminated by signal ${signal}: ${file}`);
|
|
38
|
+
resolve(1);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
resolve(exitCode ?? 1);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
|
|
47
|
+
if (code !== 0) {
|
|
48
|
+
process.exitCode = code;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|