@unson/brainbase-mcp 0.44.0 → 0.44.1

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.
Files changed (72) hide show
  1. package/contracts/canonical-task/operation-schema.sql +58 -0
  2. package/contracts/canonical-task/search-indexes.sql +10 -0
  3. package/contracts/canonical-task/store-schema.sql +77 -0
  4. package/dist/automation-run.d.ts +213 -0
  5. package/dist/automation-run.js +479 -0
  6. package/dist/canonical-task-operations.d.ts +205 -0
  7. package/dist/canonical-task-operations.js +700 -0
  8. package/dist/canonical-task-postgres.d.ts +139 -0
  9. package/dist/canonical-task-postgres.js +554 -0
  10. package/dist/canonical-task-service.d.ts +13 -0
  11. package/dist/canonical-task-service.js +55 -3
  12. package/dist/canonical-task-store-config.d.ts +31 -0
  13. package/dist/canonical-task-store-config.js +53 -0
  14. package/dist/config-parser.d.ts +298 -0
  15. package/dist/config-parser.js +593 -0
  16. package/dist/connected-onboarding.d.ts +57 -0
  17. package/dist/connected-onboarding.js +37 -0
  18. package/dist/durable-wait-http.d.ts +3 -1
  19. package/dist/durable-wait-http.js +73 -6
  20. package/dist/durable-waits.d.ts +93 -3
  21. package/dist/durable-waits.js +320 -8
  22. package/dist/honcho.d.ts +25 -0
  23. package/dist/honcho.js +81 -0
  24. package/dist/judgment-event-adapter.d.ts +72 -0
  25. package/dist/judgment-event-adapter.js +114 -0
  26. package/dist/judgment-event-outbox.d.ts +182 -0
  27. package/dist/judgment-event-outbox.js +568 -0
  28. package/dist/judgment-execution-outcome.d.ts +46 -0
  29. package/dist/judgment-execution-outcome.js +149 -0
  30. package/dist/judgment-host.d.ts +18 -7
  31. package/dist/judgment-host.js +82 -34
  32. package/dist/judgment-lifecycle-core.d.ts +198 -0
  33. package/dist/judgment-lifecycle-core.js +464 -0
  34. package/dist/judgment-node-evidence.d.ts +57 -0
  35. package/dist/judgment-node-evidence.js +297 -0
  36. package/dist/judgment-runtime-resolution.d.ts +264 -0
  37. package/dist/judgment-runtime-resolution.js +1248 -0
  38. package/dist/judgment-runtime-resolution.public.d.ts +255 -0
  39. package/dist/knowledge-event.d.ts +28 -0
  40. package/dist/knowledge-event.js +114 -0
  41. package/dist/mcp-runtime.d.ts +75 -0
  42. package/dist/mcp-runtime.js +188 -0
  43. package/dist/meeting-automation-runtime.d.ts +102 -0
  44. package/dist/meeting-automation-runtime.js +249 -0
  45. package/dist/meeting-automation.d.ts +155 -0
  46. package/dist/meeting-automation.js +341 -0
  47. package/dist/meeting-minutes-context-receipt.d.ts +91 -0
  48. package/dist/meeting-minutes-context-receipt.js +280 -0
  49. package/dist/meeting-source-sync.d.ts +89 -0
  50. package/dist/meeting-source-sync.js +230 -0
  51. package/dist/mesh.d.ts +58 -0
  52. package/dist/mesh.js +134 -0
  53. package/dist/onboarding-runtime.d.ts +47 -0
  54. package/dist/onboarding-runtime.js +4719 -0
  55. package/dist/routine-cycle.d.ts +51 -0
  56. package/dist/routine-cycle.js +153 -0
  57. package/dist/routine-liveness.d.ts +49 -0
  58. package/dist/routine-liveness.js +227 -0
  59. package/dist/routine-runtime.d.ts +101 -0
  60. package/dist/routine-runtime.js +237 -0
  61. package/dist/routines.d.ts +3 -0
  62. package/dist/routines.js +3 -0
  63. package/dist/run-receipt.d.ts +40 -0
  64. package/dist/run-receipt.js +635 -0
  65. package/dist/runtime-host.d.ts +64 -0
  66. package/dist/runtime-host.js +70 -0
  67. package/dist/world-work.d.ts +16 -0
  68. package/package.json +115 -3
  69. package/ui/objective-editor.js +47 -11
  70. package/ui/world/world-district.js +18 -3
  71. package/ui/world/world-placement.js +13 -0
  72. package/ui/world/world-work-rail.js +7 -1
@@ -0,0 +1,255 @@
1
+ export { JudgmentResolutionError, canonicalJson, computeRequestDigest, sha256Hex } from './judgment-resolution-contract.js';
2
+
3
+ export type JudgmentRuntimeIntent =
4
+ | 'answer'
5
+ | 'investigate'
6
+ | 'diagnose'
7
+ | 'design'
8
+ | 'implement'
9
+ | 'review'
10
+ | 'operate';
11
+ export type JudgmentRuntimeDomain =
12
+ | 'general'
13
+ | 'knowledge'
14
+ | 'personal_judgment'
15
+ | 'engineering'
16
+ | 'organization'
17
+ | 'operations';
18
+ export type JudgmentRuntimeSignal =
19
+ | 'cumulative_effect'
20
+ | 'complexity_growth'
21
+ | 'threshold_proposal'
22
+ | 'parallel_exploration'
23
+ | 'authority_boundary'
24
+ | 'problem_frame_uncertain'
25
+ | 'external_outcome';
26
+ export type JudgmentRuntimeActionKind = 'none' | 'read' | 'write' | 'external';
27
+ export type JudgmentRuntimeRisk = 'low' | 'medium' | 'high' | 'critical';
28
+ export type JudgmentRuntimeConfidence = 'confirmed' | 'inferred' | 'unknown';
29
+ export type JudgmentRuntimeStatus = 'resolved' | 'needs_classification' | 'needs_policy_resolution';
30
+ export type JudgmentRuntimeAutonomyDecision = 'continue' | 'escalate';
31
+
32
+ export interface JudgmentRuntimeClassification {
33
+ intent: JudgmentRuntimeIntent;
34
+ domains: JudgmentRuntimeDomain[];
35
+ action_kind: JudgmentRuntimeActionKind;
36
+ risk: JudgmentRuntimeRisk;
37
+ confidence: JudgmentRuntimeConfidence;
38
+ signals: JudgmentRuntimeSignal[];
39
+ }
40
+
41
+ export interface JudgmentRuntimeMessage {
42
+ sequence: number;
43
+ turn_id: string | null;
44
+ role: 'user' | 'assistant';
45
+ phase: string | null;
46
+ text: string;
47
+ }
48
+
49
+ export interface JudgmentRuntimePriorReceipt {
50
+ turn_id: string;
51
+ resolution_id: string;
52
+ request_digest: string;
53
+ context_digest: string | null;
54
+ plan_digest: string;
55
+ classification: JudgmentRuntimeClassification;
56
+ selected_dag_ids: string[];
57
+ }
58
+
59
+ export interface JudgmentRuntimeRuntimeContext {
60
+ host: 'codex' | 'claude-code';
61
+ entrypoint?: 'codex' | 'claude_code' | 'mana' | 'company_os' | 'unknown';
62
+ model: string | null;
63
+ permission_mode: string | null;
64
+ project_binding: string | null;
65
+ }
66
+
67
+ export interface JudgmentRuntimeConversationContext {
68
+ schema_version: 'brainbase-conversation-context-v1';
69
+ session_ref: string;
70
+ messages: JudgmentRuntimeMessage[];
71
+ prior_receipts: JudgmentRuntimePriorReceipt[];
72
+ runtime: JudgmentRuntimeRuntimeContext;
73
+ instruction_bindings: Array<{ scope: string; source_ref: string; digest: string }>;
74
+ completeness: 'complete' | 'partial';
75
+ source_digest: string;
76
+ }
77
+
78
+ export interface JudgmentRuntimeInput {
79
+ request: string;
80
+ turn_id: string;
81
+ project_code: string | null;
82
+ conversation_context: JudgmentRuntimeConversationContext;
83
+ model_interpretation: JudgmentRuntimeClassification | null;
84
+ }
85
+
86
+ export interface JudgmentRuntimeManifestLock {
87
+ schema_version: 'brainbase-judgment-manifest-lock-v1';
88
+ entries: Array<{ runtime_version: string; manifest_digest: string }>;
89
+ }
90
+
91
+ export interface JudgmentRuntimePolicy {
92
+ id: string;
93
+ version: string;
94
+ priority: number;
95
+ strength: 'hard' | 'soft';
96
+ scope: { type: 'global' | 'organization' | 'project' | 'owner'; id: string | null };
97
+ visibility: 'organization' | 'owner';
98
+ owner_person_id: string | null;
99
+ evidence_requirement: string;
100
+ effect: { target: string; decision: 'require' | 'forbid' | 'prefer' };
101
+ instruction: string;
102
+ human_approval?: {
103
+ action_kinds?: JudgmentRuntimeActionKind[];
104
+ risks?: JudgmentRuntimeRisk[];
105
+ };
106
+ [key: string]: unknown;
107
+ }
108
+
109
+ export interface JudgmentRuntimeManifest {
110
+ schema_version: 'brainbase-judgment-runtime-v1';
111
+ runtime_version: string;
112
+ host_bindings: Array<{ adapter_id: string; adapter_version: string; status?: string; [key: string]: unknown }>;
113
+ policies: JudgmentRuntimePolicy[];
114
+ nodes: Array<{
115
+ id: string;
116
+ kind: 'common' | 'judgment' | 'capability' | 'constraint' | 'fail_closed';
117
+ instruction: string;
118
+ required_capability_template: string | null;
119
+ execution_contract?: string;
120
+ [key: string]: unknown;
121
+ }>;
122
+ dags: Array<{
123
+ id: string;
124
+ kind: 'domain' | 'constraint' | 'fail_closed';
125
+ path: string[];
126
+ policy_ids: string[];
127
+ [key: string]: unknown;
128
+ }>;
129
+ composition_edges: Array<[string, string]>;
130
+ selectors: {
131
+ domain_order: JudgmentRuntimeDomain[];
132
+ signal_order: JudgmentRuntimeSignal[];
133
+ domain_dags: Record<JudgmentRuntimeDomain, string>;
134
+ signal_dags: Record<JudgmentRuntimeSignal, string>;
135
+ engineering_implementation_dag?: string;
136
+ authority_dag: string;
137
+ clarification_dag: string;
138
+ [key: string]: unknown;
139
+ };
140
+ semantic_matchers: {
141
+ intents: Record<JudgmentRuntimeIntent, string[]>;
142
+ domains: Record<Exclude<JudgmentRuntimeDomain, 'general'>, string[]>;
143
+ signals: Record<JudgmentRuntimeSignal, string[]>;
144
+ safety: Record<'write' | 'external' | 'critical', string[]>;
145
+ positive_commands: string[];
146
+ follow_up: string[];
147
+ [key: string]: unknown;
148
+ };
149
+ autonomy: {
150
+ schema_version: 'brainbase-autonomy-policy-v1';
151
+ continue_risks: JudgmentRuntimeRisk[];
152
+ escalate_risks: JudgmentRuntimeRisk[];
153
+ escalate_action_kinds: JudgmentRuntimeActionKind[];
154
+ runtime_escalation_reasons: string[];
155
+ [key: string]: unknown;
156
+ };
157
+ [key: string]: unknown;
158
+ }
159
+
160
+ export interface JudgmentRuntimeReconciliation {
161
+ status: 'resolved' | 'needs_classification';
162
+ classification: JudgmentRuntimeClassification | null;
163
+ assurance: 'verified' | 'bounded' | 'unknown';
164
+ reasons: string[];
165
+ evidence: Record<string, unknown>;
166
+ }
167
+
168
+ export interface JudgmentRuntimeResolutionPlan {
169
+ status: JudgmentRuntimeStatus;
170
+ autonomy_decision: JudgmentRuntimeAutonomyDecision;
171
+ autonomy_reason_code: 'routine_in_scope' | 'classification_missing' | 'policy_conflict' | 'risk_or_external';
172
+ allowed_runtime_escalation_reasons: string[];
173
+ autonomy_policy_ids: string[];
174
+ reconciliation: JudgmentRuntimeReconciliation;
175
+ selected_dag_ids: string[];
176
+ applicable_policies: JudgmentRuntimePolicy[];
177
+ suppressed_policies: Array<{ policy_id: string; suppressed_by_policy_id: string; reason: string }>;
178
+ policy_conflict: boolean;
179
+ required_capabilities: Array<{
180
+ capability: string;
181
+ status: string;
182
+ input: Record<string, unknown>;
183
+ receipt_required: boolean;
184
+ [key: string]: unknown;
185
+ }>;
186
+ active_nodes: string[];
187
+ active_edges: Array<[string, string]>;
188
+ active_node_definitions: JudgmentRuntimeManifest['nodes'];
189
+ unresolved: string[];
190
+ rationale: string[];
191
+ }
192
+
193
+ export interface JudgmentRuntimeCoreInput {
194
+ input: JudgmentRuntimeInput;
195
+ manifest: JudgmentRuntimeManifest;
196
+ /** Policies already filtered by the Organization/Host authorization adapter. */
197
+ applicablePolicies?: JudgmentRuntimePolicy[];
198
+ ownerPersonId?: string | null;
199
+ clientCapabilities?: string[];
200
+ }
201
+
202
+ export declare function validateManifestLock(
203
+ lock: JudgmentRuntimeManifestLock,
204
+ previous?: JudgmentRuntimeManifestLock | null,
205
+ current?: { runtimeVersion: string; manifestDigest: string } | null,
206
+ ): true;
207
+ export declare function validateManifest(manifest: JudgmentRuntimeManifest, lock: JudgmentRuntimeManifestLock): string;
208
+ export declare function validateRuntimeInput(rawInput: unknown, manifest: JudgmentRuntimeManifest): JudgmentRuntimeInput;
209
+ export declare function autonomyResolution(
210
+ status: JudgmentRuntimeStatus,
211
+ classification: JudgmentRuntimeClassification | null,
212
+ manifest: JudgmentRuntimeManifest,
213
+ applicablePolicies?: JudgmentRuntimePolicy[],
214
+ ): {
215
+ autonomy_decision: JudgmentRuntimeAutonomyDecision;
216
+ autonomy_reason_code: JudgmentRuntimeResolutionPlan['autonomy_reason_code'];
217
+ allowed_runtime_escalation_reasons: string[];
218
+ autonomy_policy_ids: string[];
219
+ };
220
+ export declare function reconcileModelInterpretation(
221
+ input: JudgmentRuntimeInput,
222
+ manifest: JudgmentRuntimeManifest,
223
+ ): JudgmentRuntimeReconciliation;
224
+ export declare function classify(input: JudgmentRuntimeInput, manifest: JudgmentRuntimeManifest): JudgmentRuntimeReconciliation;
225
+ export declare function materializePolicy(policy: JudgmentRuntimePolicy, ownerPersonId: string | null): JudgmentRuntimePolicy;
226
+ export declare function mergePolicies(policies: JudgmentRuntimePolicy[]): {
227
+ applicable: JudgmentRuntimePolicy[];
228
+ suppressed: Array<{ policy_id: string; suppressed_by_policy_id: string; reason: string }>;
229
+ conflict: boolean;
230
+ };
231
+ export declare function selectedDags(classification: JudgmentRuntimeClassification, manifest: JudgmentRuntimeManifest): string[];
232
+ export declare function buildGraph(
233
+ dagIds: string[],
234
+ manifest: JudgmentRuntimeManifest,
235
+ options?: { clarification?: boolean },
236
+ ): { active_nodes: string[]; active_edges: Array<[string, string]> };
237
+ export declare function materializeActiveNodeDefinitions(
238
+ activeNodes: string[],
239
+ manifest: JudgmentRuntimeManifest,
240
+ options?: { evidenceRequired?: boolean },
241
+ ): JudgmentRuntimeManifest['nodes'];
242
+ export declare function topologicallySortNodes(nodes: string[], edges: Array<[string, string]>): string[];
243
+ export declare const JUDGMENT_FRAME_CAPABILITY: 'judgment.frame';
244
+ export declare function isJudgmentBearing(classification: JudgmentRuntimeClassification | null): boolean;
245
+ export declare function frameCapabilities(
246
+ input: JudgmentRuntimeInput,
247
+ classification: JudgmentRuntimeClassification | null,
248
+ clientCapabilities: ReadonlySet<string>,
249
+ status: JudgmentRuntimeStatus,
250
+ ): JudgmentRuntimeResolutionPlan['required_capabilities'];
251
+ export declare function knowledgeCapabilities(
252
+ input: JudgmentRuntimeInput,
253
+ classification: JudgmentRuntimeClassification | null,
254
+ ): JudgmentRuntimeResolutionPlan['required_capabilities'];
255
+ export declare function resolveJudgmentRuntimeCore(args: JudgmentRuntimeCoreInput): JudgmentRuntimeResolutionPlan;
@@ -0,0 +1,28 @@
1
+ /** Stable common boundary for host-provided knowledge-event adapters. */
2
+ export declare const KNOWLEDGE_EVENT_CONTRACT_VERSION: "knowledge_event.v1";
3
+ export declare const KNOWLEDGE_EVENT_REQUIRED_FIELDS: readonly ["schema_version", "event_id", "occurred_at", "captured_at", "source", "subject", "decision_authority", "applicability_scope", "permission_snapshot", "source_pointer", "body_hash", "parent_episode_id"];
4
+ export type KnowledgeEventRequiredField = typeof KNOWLEDGE_EVENT_REQUIRED_FIELDS[number];
5
+ export type KnowledgeEventRecord = Record<string, unknown>;
6
+ export declare class KnowledgeEventContractError extends Error {
7
+ readonly field: string;
8
+ readonly code = "knowledge_event_invalid";
9
+ constructor(field: string, message?: string);
10
+ }
11
+ /**
12
+ * Canonical JSON used for idempotency and conflict checks. Host repositories
13
+ * may store additional fields, but the common identity never depends on
14
+ * property insertion order.
15
+ */
16
+ export declare function canonicalKnowledgeEventJson(value: unknown): string;
17
+ export declare function knowledgeEventSha256(value: string): string;
18
+ /**
19
+ * Validate only the portable event envelope. Subject semantics, decision
20
+ * authority, tenant identity, and persistence remain host responsibilities.
21
+ */
22
+ export declare function normalizeKnowledgeEvent(value: unknown): KnowledgeEventRecord;
23
+ declare const IDENTITY_FIELDS: readonly ["body_hash", "source_pointer", "subject", "decision_authority", "applicability_scope", "permission_snapshot", "parent_episode_id", "organization_id", "sensitivity", "role_min", "venue"];
24
+ export type KnowledgeEventIdentity = Pick<KnowledgeEventRecord, typeof IDENTITY_FIELDS[number]>;
25
+ export declare function knowledgeEventIdentity(value: unknown): KnowledgeEventIdentity;
26
+ export declare function knowledgeEventFingerprint(value: unknown): string;
27
+ export declare function sameKnowledgeEventIdentity(left: unknown, right: unknown): boolean;
28
+ export {};
@@ -0,0 +1,114 @@
1
+ import { createHash } from 'node:crypto';
2
+ /** Stable common boundary for host-provided knowledge-event adapters. */
3
+ export const KNOWLEDGE_EVENT_CONTRACT_VERSION = 'knowledge_event.v1';
4
+ export const KNOWLEDGE_EVENT_REQUIRED_FIELDS = [
5
+ 'schema_version',
6
+ 'event_id',
7
+ 'occurred_at',
8
+ 'captured_at',
9
+ 'source',
10
+ 'subject',
11
+ 'decision_authority',
12
+ 'applicability_scope',
13
+ 'permission_snapshot',
14
+ 'source_pointer',
15
+ 'body_hash',
16
+ 'parent_episode_id'
17
+ ];
18
+ export class KnowledgeEventContractError extends Error {
19
+ field;
20
+ code = 'knowledge_event_invalid';
21
+ constructor(field, message = `knowledge_event.v1 field is required: ${field}`) {
22
+ super(message);
23
+ this.field = field;
24
+ this.name = 'KnowledgeEventContractError';
25
+ }
26
+ }
27
+ function isRecord(value) {
28
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
29
+ }
30
+ function clone(value) {
31
+ if (Array.isArray(value))
32
+ return value.map(clone);
33
+ if (isRecord(value)) {
34
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, clone(child)]));
35
+ }
36
+ return value;
37
+ }
38
+ function hasValue(value) {
39
+ return value !== undefined && value !== null && value !== '';
40
+ }
41
+ /**
42
+ * Canonical JSON used for idempotency and conflict checks. Host repositories
43
+ * may store additional fields, but the common identity never depends on
44
+ * property insertion order.
45
+ */
46
+ export function canonicalKnowledgeEventJson(value) {
47
+ if (Array.isArray(value))
48
+ return `[${value.map(canonicalKnowledgeEventJson).join(',')}]`;
49
+ if (isRecord(value)) {
50
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalKnowledgeEventJson(value[key])}`).join(',')}}`;
51
+ }
52
+ return JSON.stringify(value);
53
+ }
54
+ export function knowledgeEventSha256(value) {
55
+ return createHash('sha256').update(value, 'utf8').digest('hex');
56
+ }
57
+ /**
58
+ * Validate only the portable event envelope. Subject semantics, decision
59
+ * authority, tenant identity, and persistence remain host responsibilities.
60
+ */
61
+ export function normalizeKnowledgeEvent(value) {
62
+ if (!isRecord(value))
63
+ throw new KnowledgeEventContractError('event', 'knowledge event must be an object');
64
+ for (const field of KNOWLEDGE_EVENT_REQUIRED_FIELDS) {
65
+ if (!hasValue(value[field]))
66
+ throw new KnowledgeEventContractError(field);
67
+ }
68
+ if (value.schema_version !== KNOWLEDGE_EVENT_CONTRACT_VERSION) {
69
+ throw new KnowledgeEventContractError('schema_version', `schema_version must be ${KNOWLEDGE_EVENT_CONTRACT_VERSION}`);
70
+ }
71
+ if (typeof value.event_id !== 'string' || !value.event_id.trim()) {
72
+ throw new KnowledgeEventContractError('event_id', 'event_id must be a non-empty string');
73
+ }
74
+ for (const field of ['occurred_at', 'captured_at']) {
75
+ if (typeof value[field] !== 'string' || !Number.isFinite(Date.parse(value[field]))) {
76
+ throw new KnowledgeEventContractError(field, `${field} must be an ISO timestamp`);
77
+ }
78
+ }
79
+ if (typeof value.body_hash !== 'string' || !/^(?:sha256:)?[a-f0-9]{64}$/u.test(value.body_hash)) {
80
+ throw new KnowledgeEventContractError('body_hash', 'body_hash must be a SHA-256 digest');
81
+ }
82
+ return clone(value);
83
+ }
84
+ const IDENTITY_FIELDS = [
85
+ 'body_hash',
86
+ 'source_pointer',
87
+ 'subject',
88
+ 'decision_authority',
89
+ 'applicability_scope',
90
+ 'permission_snapshot',
91
+ 'parent_episode_id',
92
+ 'organization_id',
93
+ 'sensitivity',
94
+ 'role_min',
95
+ 'venue'
96
+ ];
97
+ export function knowledgeEventIdentity(value) {
98
+ const event = normalizeKnowledgeEvent(value);
99
+ return Object.fromEntries(IDENTITY_FIELDS
100
+ .filter((field) => event[field] !== undefined)
101
+ .map((field) => [field, event[field]]));
102
+ }
103
+ export function knowledgeEventFingerprint(value) {
104
+ return knowledgeEventSha256(canonicalKnowledgeEventJson(knowledgeEventIdentity(value)));
105
+ }
106
+ export function sameKnowledgeEventIdentity(left, right) {
107
+ try {
108
+ return canonicalKnowledgeEventJson(knowledgeEventIdentity(left))
109
+ === canonicalKnowledgeEventJson(knowledgeEventIdentity(right));
110
+ }
111
+ catch {
112
+ return false;
113
+ }
114
+ }
@@ -0,0 +1,75 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
3
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
4
+ import { type CallToolResult, type ServerNotification, type ServerRequest, type Tool } from '@modelcontextprotocol/sdk/types.js';
5
+ export declare const MCP_RUNTIME_CONTRACT_VERSION: "mcp_runtime.v1";
6
+ export interface LocalMcpRuntimeDescriptor {
7
+ packageName: string;
8
+ command: string;
9
+ transport: 'stdio';
10
+ storage: 'local';
11
+ hostedDependency: false;
12
+ }
13
+ export interface McpToolCall {
14
+ name: string;
15
+ arguments: Record<string, unknown>;
16
+ }
17
+ export interface McpToolReceipt {
18
+ tool: string;
19
+ status: 'accepted' | 'completed' | 'failed' | 'unknown';
20
+ receiptKind: 'tool_result' | 'send_ack' | 'error';
21
+ verified: boolean;
22
+ }
23
+ export type LocalMcpToolHandler = (arguments_: Record<string, unknown>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult>;
24
+ /**
25
+ * Optional host-owned fallback for calls that are intentionally absent from
26
+ * the advertised tools/list surface. The runtime only performs the SDK
27
+ * dispatch; the host decides whether the call is a retired tool, an unknown
28
+ * name, or an authenticated request that must be rejected.
29
+ */
30
+ export type LocalMcpUnknownToolHandler = (name: string, arguments_: Record<string, unknown>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult>;
31
+ export interface LocalMcpRuntimeTool {
32
+ definition: Tool;
33
+ handler: LocalMcpToolHandler;
34
+ }
35
+ export interface LocalMcpRuntimeOptions {
36
+ name: string;
37
+ version: string;
38
+ instructions?: string;
39
+ tools: readonly LocalMcpRuntimeTool[];
40
+ /** The host may observe the exact SDK tools/list surface for its audit trail. */
41
+ onListTools?: (tools: readonly Tool[]) => void | Promise<void>;
42
+ /** The host may preserve behavior for calls outside the advertised surface. */
43
+ onUnknownTool?: LocalMcpUnknownToolHandler;
44
+ /** The host may inject HTTP, stdio, or an in-memory SDK transport. */
45
+ transport?: Transport;
46
+ }
47
+ export interface LocalMcpRuntimeHandle {
48
+ readonly server: Server;
49
+ readonly transport: Transport;
50
+ close(): Promise<void>;
51
+ }
52
+ export declare class McpRuntimeContractError extends Error {
53
+ readonly code = "mcp_runtime_contract_invalid";
54
+ constructor(field: string, message?: string);
55
+ }
56
+ /**
57
+ * Create an SDK MCP server with a host-independent tool registry.
58
+ *
59
+ * The returned Server is intentionally transport agnostic. A host can connect
60
+ * it to stdio, Streamable HTTP, or an in-memory transport without the OSS
61
+ * package importing auth, tenant, deployment, or provider code.
62
+ */
63
+ export declare function createLocalMcpServer(options: LocalMcpRuntimeOptions): Server;
64
+ /**
65
+ * Start a local SDK runtime and return an explicit lifecycle handle.
66
+ *
67
+ * The default is stdio for local clients. Hosts that own HTTP/auth may inject
68
+ * their transport and retain the same engine and tool contract.
69
+ */
70
+ export declare function runLocalMcpServer(options: LocalMcpRuntimeOptions): Promise<LocalMcpRuntimeHandle>;
71
+ export declare const createMcpRuntimeServer: typeof createLocalMcpServer;
72
+ export declare const startLocalMcpRuntime: typeof runLocalMcpServer;
73
+ export declare function normalizeLocalMcpRuntimeDescriptor(value: unknown): LocalMcpRuntimeDescriptor;
74
+ export declare function normalizeMcpToolCall(value: unknown): McpToolCall;
75
+ export declare function createMcpToolReceipt(input: Pick<McpToolReceipt, 'tool' | 'status' | 'receiptKind' | 'verified'>): McpToolReceipt;
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Local MCP process and tool-call contracts.
3
+ *
4
+ * The runtime in this module deliberately owns only the SDK server and its
5
+ * tool dispatch. HTTP, bearer tokens, tenant selection, graph/index access,
6
+ * and provider I/O stay in the host and are supplied through tool callbacks
7
+ * or an injected SDK transport.
8
+ */
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
12
+ export const MCP_RUNTIME_CONTRACT_VERSION = 'mcp_runtime.v1';
13
+ export class McpRuntimeContractError extends Error {
14
+ code = 'mcp_runtime_contract_invalid';
15
+ constructor(field, message = `MCP runtime field is invalid: ${field}`) {
16
+ super(message);
17
+ this.name = 'McpRuntimeContractError';
18
+ }
19
+ }
20
+ function cloneToolDefinition(definition) {
21
+ if (!definition || typeof definition !== 'object' || Array.isArray(definition)) {
22
+ throw new McpRuntimeContractError('tool.definition');
23
+ }
24
+ if (typeof definition.name !== 'string' || !definition.name.trim()) {
25
+ throw new McpRuntimeContractError('tool.definition.name');
26
+ }
27
+ if (!definition.inputSchema || definition.inputSchema.type !== 'object') {
28
+ throw new McpRuntimeContractError('tool.definition.inputSchema');
29
+ }
30
+ try {
31
+ return structuredClone(definition);
32
+ }
33
+ catch {
34
+ throw new McpRuntimeContractError('tool.definition', 'tool definition must be structured-cloneable');
35
+ }
36
+ }
37
+ function textResult(text, isError = false) {
38
+ return {
39
+ content: [{ type: 'text', text }],
40
+ ...(isError ? { isError: true } : {})
41
+ };
42
+ }
43
+ function normalizeRuntimeOptions(options) {
44
+ const name = text(options.name, 'name');
45
+ const version = text(options.version, 'version');
46
+ if (!Array.isArray(options.tools))
47
+ throw new McpRuntimeContractError('tools');
48
+ const tools = [];
49
+ const names = new Set();
50
+ for (const tool of options.tools) {
51
+ if (!tool || typeof tool !== 'object' || typeof tool.handler !== 'function') {
52
+ throw new McpRuntimeContractError('tool.handler');
53
+ }
54
+ const definition = cloneToolDefinition(tool.definition);
55
+ if (names.has(definition.name)) {
56
+ throw new McpRuntimeContractError('tools', `duplicate MCP tool name: ${definition.name}`);
57
+ }
58
+ names.add(definition.name);
59
+ tools.push({ definition, handler: tool.handler });
60
+ }
61
+ return {
62
+ name,
63
+ version,
64
+ ...(options.instructions === undefined ? {} : { instructions: text(options.instructions, 'instructions') }),
65
+ tools,
66
+ ...(options.onListTools === undefined ? {} : { onListTools: options.onListTools }),
67
+ ...(options.onUnknownTool === undefined ? {} : { onUnknownTool: options.onUnknownTool }),
68
+ transport: options.transport
69
+ };
70
+ }
71
+ /**
72
+ * Create an SDK MCP server with a host-independent tool registry.
73
+ *
74
+ * The returned Server is intentionally transport agnostic. A host can connect
75
+ * it to stdio, Streamable HTTP, or an in-memory transport without the OSS
76
+ * package importing auth, tenant, deployment, or provider code.
77
+ */
78
+ export function createLocalMcpServer(options) {
79
+ const normalized = normalizeRuntimeOptions(options);
80
+ const toolsByName = new Map(normalized.tools.map((tool) => [tool.definition.name, tool]));
81
+ const server = new Server({ name: normalized.name, version: normalized.version }, {
82
+ capabilities: { tools: {} },
83
+ ...(normalized.instructions ? { instructions: normalized.instructions } : {})
84
+ });
85
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
86
+ const tools = normalized.tools.map((tool) => structuredClone(tool.definition));
87
+ await normalized.onListTools?.(tools);
88
+ return { tools };
89
+ });
90
+ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
91
+ const registered = toolsByName.get(request.params.name);
92
+ const arguments_ = request.params.arguments ?? {};
93
+ if (!registered) {
94
+ if (normalized.onUnknownTool) {
95
+ try {
96
+ return await normalized.onUnknownTool(request.params.name, structuredClone(arguments_), extra);
97
+ }
98
+ catch {
99
+ return textResult(`Tool execution failed: ${request.params.name}`, true);
100
+ }
101
+ }
102
+ return textResult(`Unknown tool: ${request.params.name}`, true);
103
+ }
104
+ try {
105
+ return await registered.handler(structuredClone(arguments_), extra);
106
+ }
107
+ catch {
108
+ return textResult(`Tool execution failed: ${request.params.name}`, true);
109
+ }
110
+ });
111
+ return server;
112
+ }
113
+ /**
114
+ * Start a local SDK runtime and return an explicit lifecycle handle.
115
+ *
116
+ * The default is stdio for local clients. Hosts that own HTTP/auth may inject
117
+ * their transport and retain the same engine and tool contract.
118
+ */
119
+ export async function runLocalMcpServer(options) {
120
+ const normalized = normalizeRuntimeOptions(options);
121
+ const server = createLocalMcpServer(normalized);
122
+ const transport = normalized.transport ?? new StdioServerTransport();
123
+ try {
124
+ await server.connect(transport);
125
+ }
126
+ catch (error) {
127
+ await transport.close().catch(() => undefined);
128
+ throw error;
129
+ }
130
+ let closed = false;
131
+ return {
132
+ server,
133
+ transport,
134
+ async close() {
135
+ if (closed)
136
+ return;
137
+ closed = true;
138
+ await server.close();
139
+ }
140
+ };
141
+ }
142
+ export const createMcpRuntimeServer = createLocalMcpServer;
143
+ export const startLocalMcpRuntime = runLocalMcpServer;
144
+ function text(value, field) {
145
+ if (typeof value !== 'string' || !value.trim())
146
+ throw new McpRuntimeContractError(field);
147
+ return value.trim();
148
+ }
149
+ export function normalizeLocalMcpRuntimeDescriptor(value) {
150
+ if (!value || typeof value !== 'object' || Array.isArray(value))
151
+ throw new McpRuntimeContractError('descriptor');
152
+ const candidate = value;
153
+ if (candidate.transport !== 'stdio')
154
+ throw new McpRuntimeContractError('transport', 'local MCP transport must be stdio');
155
+ if (candidate.storage !== 'local')
156
+ throw new McpRuntimeContractError('storage', 'local MCP storage must be local');
157
+ if (candidate.hostedDependency !== false)
158
+ throw new McpRuntimeContractError('hostedDependency', 'local MCP must not require a hosted dependency');
159
+ return {
160
+ packageName: text(candidate.packageName, 'packageName'),
161
+ command: text(candidate.command, 'command'),
162
+ transport: 'stdio',
163
+ storage: 'local',
164
+ hostedDependency: false
165
+ };
166
+ }
167
+ export function normalizeMcpToolCall(value) {
168
+ if (!value || typeof value !== 'object' || Array.isArray(value))
169
+ throw new McpRuntimeContractError('call');
170
+ const candidate = value;
171
+ if (!candidate.arguments || typeof candidate.arguments !== 'object' || Array.isArray(candidate.arguments)) {
172
+ throw new McpRuntimeContractError('arguments');
173
+ }
174
+ return {
175
+ name: text(candidate.name, 'name'),
176
+ arguments: structuredClone(candidate.arguments)
177
+ };
178
+ }
179
+ export function createMcpToolReceipt(input) {
180
+ const tool = text(input.tool, 'tool');
181
+ if (!['accepted', 'completed', 'failed', 'unknown'].includes(input.status))
182
+ throw new McpRuntimeContractError('status');
183
+ if (!['tool_result', 'send_ack', 'error'].includes(input.receiptKind))
184
+ throw new McpRuntimeContractError('receiptKind');
185
+ if (typeof input.verified !== 'boolean')
186
+ throw new McpRuntimeContractError('verified');
187
+ return { tool, status: input.status, receiptKind: input.receiptKind, verified: input.verified };
188
+ }