@crediolabs/policy-builder-mcp 0.1.18 → 0.2.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/README.md CHANGED
@@ -54,8 +54,11 @@ branch on them.
54
54
  non-loopback host; it serves `127.0.0.1`, `::1` or `localhost` unless the
55
55
  embedding caller explicitly opts out (`allowExternalHost: true` via the
56
56
  programmatic API), because the surface is unauthenticated by design.
57
- - The on-chain interpreter the policies target is **unaudited**; see the
58
- [architecture document](https://github.com/untangledfinance/octogate/blob/main/docs/architecture.md).
57
+ - See the
58
+ [architecture document](https://github.com/untangledfinance/octogate/blob/main/docs/architecture.md)
59
+ for what the on-chain interpreter does and does not enforce, and the
60
+ [repository README](https://github.com/untangledfinance/octogate#readme)
61
+ for the contracts' audit status.
59
62
 
60
63
  ## License
61
64
 
@@ -427,18 +427,66 @@ export declare const SynthesizePolicyToolShape: {
427
427
  limitAmount: z.ZodOptional<z.ZodString>;
428
428
  invocationLimit: z.ZodOptional<z.ZodNumber>;
429
429
  swapRecipientAllowlist: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">>;
430
+ oraclePriceBound: z.ZodOptional<z.ZodArray<z.ZodObject<{
431
+ asset: z.ZodEffects<z.ZodString, string, string>;
432
+ operator: z.ZodEnum<["eq", "lt", "lte", "gt", "gte"]>;
433
+ value: z.ZodString;
434
+ decimals: z.ZodNumber;
435
+ }, "strip", z.ZodTypeAny, {
436
+ value: string;
437
+ operator: "eq" | "lt" | "lte" | "gt" | "gte";
438
+ asset: string;
439
+ decimals: number;
440
+ }, {
441
+ value: string;
442
+ operator: "eq" | "lt" | "lte" | "gt" | "gte";
443
+ asset: string;
444
+ decimals: number;
445
+ }>, "many">>;
430
446
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
431
447
  windowSeconds: z.ZodOptional<z.ZodNumber>;
432
448
  validUntilLedger: z.ZodOptional<z.ZodNumber>;
433
449
  limitAmount: z.ZodOptional<z.ZodString>;
434
450
  invocationLimit: z.ZodOptional<z.ZodNumber>;
435
451
  swapRecipientAllowlist: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">>;
452
+ oraclePriceBound: z.ZodOptional<z.ZodArray<z.ZodObject<{
453
+ asset: z.ZodEffects<z.ZodString, string, string>;
454
+ operator: z.ZodEnum<["eq", "lt", "lte", "gt", "gte"]>;
455
+ value: z.ZodString;
456
+ decimals: z.ZodNumber;
457
+ }, "strip", z.ZodTypeAny, {
458
+ value: string;
459
+ operator: "eq" | "lt" | "lte" | "gt" | "gte";
460
+ asset: string;
461
+ decimals: number;
462
+ }, {
463
+ value: string;
464
+ operator: "eq" | "lt" | "lte" | "gt" | "gte";
465
+ asset: string;
466
+ decimals: number;
467
+ }>, "many">>;
436
468
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
437
469
  windowSeconds: z.ZodOptional<z.ZodNumber>;
438
470
  validUntilLedger: z.ZodOptional<z.ZodNumber>;
439
471
  limitAmount: z.ZodOptional<z.ZodString>;
440
472
  invocationLimit: z.ZodOptional<z.ZodNumber>;
441
473
  swapRecipientAllowlist: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">>;
474
+ oraclePriceBound: z.ZodOptional<z.ZodArray<z.ZodObject<{
475
+ asset: z.ZodEffects<z.ZodString, string, string>;
476
+ operator: z.ZodEnum<["eq", "lt", "lte", "gt", "gte"]>;
477
+ value: z.ZodString;
478
+ decimals: z.ZodNumber;
479
+ }, "strip", z.ZodTypeAny, {
480
+ value: string;
481
+ operator: "eq" | "lt" | "lte" | "gt" | "gte";
482
+ asset: string;
483
+ decimals: number;
484
+ }, {
485
+ value: string;
486
+ operator: "eq" | "lt" | "lte" | "gt" | "gte";
487
+ asset: string;
488
+ decimals: number;
489
+ }>, "many">>;
442
490
  }, z.ZodTypeAny, "passthrough">>>;
443
491
  readonly confidenceOverride: z.ZodOptional<z.ZodObject<{
444
492
  threshold: z.ZodNumber;
@@ -1103,6 +1151,17 @@ export declare const RevokePolicyToolShape: {
1103
1151
  readonly rpcUrl: z.ZodOptional<z.ZodString>;
1104
1152
  readonly baseFee: z.ZodOptional<z.ZodNumber>;
1105
1153
  };
1154
+ /** Flat ZodRawShape for `merge_policy`: the tightening remedy when two rules
1155
+ * our interpreter polices can serve the same calls. Two steps, in order. */
1156
+ export declare const MergePolicyToolShape: {
1157
+ readonly ruleId: z.ZodNumber;
1158
+ readonly incomingPredicateBlobBase64: z.ZodString;
1159
+ readonly step: z.ZodEnum<["detach", "reinstall"]>;
1160
+ readonly smartAccount: z.ZodOptional<z.ZodString>;
1161
+ readonly sourceAccount: z.ZodOptional<z.ZodString>;
1162
+ readonly rpcUrl: z.ZodOptional<z.ZodString>;
1163
+ readonly baseFee: z.ZodOptional<z.ZodNumber>;
1164
+ };
1106
1165
  /** Flat ZodRawShape for `get_interpreter_info`. `verifyLive` triggers an
1107
1166
  * optional RPC `grammar_version()` call so the caller can verify the
1108
1167
  * deployed contract matches the pin. */
@@ -112,6 +112,14 @@ export const RevokePolicyToolShape = {
112
112
  ruleId: z.number().int().nonnegative().optional(),
113
113
  interpreterAddress: z.string().optional(),
114
114
  };
115
+ /** Flat ZodRawShape for `merge_policy`: the tightening remedy when two rules
116
+ * our interpreter polices can serve the same calls. Two steps, in order. */
117
+ export const MergePolicyToolShape = {
118
+ ...SmartAccountToolShape,
119
+ ruleId: z.number().int().nonnegative(),
120
+ incomingPredicateBlobBase64: z.string().min(1),
121
+ step: z.enum(['detach', 'reinstall']),
122
+ };
115
123
  /** Flat ZodRawShape for `get_interpreter_info`. `verifyLive` triggers an
116
124
  * optional RPC `grammar_version()` call so the caller can verify the
117
125
  * deployed contract matches the pin. */
@@ -10,9 +10,9 @@
10
10
  // Stateless: a fresh McpServer is constructed per transport (stdio/HTTP). No
11
11
  // shared mutable state across calls; nothing here caches, queues, or holds
12
12
  // key material.
13
- import { runGetInterpreterInfo, runInstallPolicy, runRecordTransaction, runRevokePolicy, runSimulatePolicy, runSynthesizePolicy, runVerifyPolicy, } from '@crediolabs/policy-synth/run';
13
+ import { runGetInterpreterInfo, runInstallPolicy, runMergePolicy, runRecordTransaction, runRevokePolicy, runSimulatePolicy, runSynthesizePolicy, runVerifyPolicy, } from '@crediolabs/policy-synth/run';
14
14
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
15
- import { GetInterpreterInfoToolShape, InstallPolicyToolShape, RecordTransactionToolShape, RevokePolicyToolShape, SimulatePolicyToolShape, SynthesizePolicyToolShape, VerifyPolicyToolShape, } from "./schemas.js";
15
+ import { GetInterpreterInfoToolShape, InstallPolicyToolShape, MergePolicyToolShape, RecordTransactionToolShape, RevokePolicyToolShape, SimulatePolicyToolShape, SynthesizePolicyToolShape, VerifyPolicyToolShape, } from "./schemas.js";
16
16
  import { mcpResultFromCore } from "./tools/result.js";
17
17
  /** Our envelope types `structuredContent` precisely (T / ToolError); the SDK's
18
18
  * CallToolResult widens it to Record<string, unknown>, so the nominal types
@@ -34,5 +34,6 @@ export function registerTools(server) {
34
34
  server.tool('verify_policy', 'Run the static minimality check on a proposed PredicateNode against a RecordedTransaction (no conjunct is load-bearing-free). Returns VERIFICATION_FAILED with the dropped-constraint fingerprints when the predicate is over-broad.', VerifyPolicyToolShape, (args) => runVerifyPolicy(args).then(toCallToolResult));
35
35
  server.tool('install_policy', 'Build an UNSIGNED Soroban transaction XDR for `account.add_context_rule(...)` that installs a new policy rule on the given smart account. The wallet signs the returned XDR - the signature IS the user-confirmation step (this server is stateless and holds no key material, so there is no two-call confirm pair). Only CALL 1 is emitted; the interpreter `install` follow-up needs the rule id the account assigns in call 1 and is documented in `followUp` in the response.', InstallPolicyToolShape, (args) => runInstallPolicy(args).then(toCallToolResult));
36
36
  server.tool('revoke_policy', 'Build an UNSIGNED Soroban transaction XDR for `account.remove_context_rule(ruleId)` that removes a policy rule from the given smart account. The smart account handles uninstalling each attached policy itself. Auth is master-only - the source account MUST be the master signer set; delegated signers cannot uninstall.', RevokePolicyToolShape, (args) => runRevokePolicy(args).then(toCallToolResult));
37
+ server.tool('merge_policy', "Tighten a rule by replacing its predicate with the conjunction of the installed one and a new one. This is the remedy for the overlap `install_policy` reports between two rules the interpreter polices: because OpenZeppelin enforces only the rule a signer names, adding a second, tighter rule restricts nothing, so the restriction has to become one predicate. TWO transactions, in order: call with step 'detach' to remove the current attachment, wait for it to confirm, then call with step 'reinstall'. Detaching uninstalls the policy, which RESETS every counter on the rule, and the rule is unpoliced in between - both are reported in `warnings`.", MergePolicyToolShape, (args) => runMergePolicy(args).then(toCallToolResult));
37
38
  server.tool('get_interpreter_info', 'Read-only fingerprint lookup for the policy interpreter contract: returns the pinned address, grammar version, and wasm sha256 (from the pinned constants + SELF_VERSION). When `verifyLive=true`, performs an additional `grammar_version()` RPC call against the pinned address and reports whether the deployed contract matches the pin - a live mismatch check is more useful than a fabricated audit field.', GetInterpreterInfoToolShape, (args) => runGetInterpreterInfo(args).then(toCallToolResult));
38
39
  }
@@ -2,8 +2,13 @@
2
2
  //
3
3
  // Streamable HTTP transport (hosted). Uses the Node http module directly so
4
4
  // the package stays thin - no express / hono dep. We run in STATELESS mode
5
- // (sessionIdGenerator: undefined) so each POST /mcp is its own transaction:
6
- // this matches the brief's "stateless across calls" invariant.
5
+ // (no `sessionIdGenerator` option), and the SDK 1.26+ requires a FRESH
6
+ // transport per request in stateless mode: reusing one across requests lets
7
+ // concurrent clients share internal message-id state, which is exactly the
8
+ // cross-client data leak GHSA-345p-7cg4-v4c7 warns about. We therefore build
9
+ // a transport inside the request handler, connect it, dispatch the request,
10
+ // then close it (close() resets the McpServer's transport slot so the next
11
+ // request can reconnect cleanly).
7
12
  //
8
13
  // Single endpoint: POST /mcp (the SDK also accepts GET for SSE streaming, but
9
14
  // the T1 surface does not emit server-initiated messages so we omit it).
@@ -34,13 +39,11 @@ export async function startHttpServer(opts) {
34
39
  if (!LOOPBACK_HOSTS.has(host) && opts.allowExternalHost !== true) {
35
40
  throw new Error(`startHttpServer: refusing to bind host ${host}: the MCP surface is unauthenticated, so only loopback (127.0.0.1, ::1, localhost) is permitted by default. Pass \`allowExternalHost: true\` to opt in to a non-loopback bind.`);
36
41
  }
42
+ // The McpServer is stateless and per-process; we keep ONE instance alive
43
+ // for the lifetime of the listener, but each request creates + connects a
44
+ // fresh StreamableHTTPServerTransport (SDK 1.26+ refuses to reuse a
45
+ // stateless transport across requests).
37
46
  const server = createMcpServer();
38
- // One transport per server (the SDK reuses the transport for every request
39
- // in stateless mode). We connect it once at startup and reuse it.
40
- const transport = new StreamableHTTPServerTransport({
41
- sessionIdGenerator: undefined,
42
- });
43
- await server.connect(transport);
44
47
  const httpServer = createServer(async (req, res) => {
45
48
  if (!req.url) {
46
49
  sendJson(res, 400, { error: 'missing url' });
@@ -86,6 +89,20 @@ export async function startHttpServer(opts) {
86
89
  });
87
90
  return;
88
91
  }
92
+ // One transport per request. Omitting `sessionIdGenerator` selects
93
+ // stateless mode in SDK 1.26+ (the previous `sessionIdGenerator:
94
+ // undefined` form is rejected because the option type no longer
95
+ // includes `undefined` under `exactOptionalPropertyTypes`).
96
+ //
97
+ // The cast `as unknown as Transport` is narrowly scoped to the SDK
98
+ // boundary: the Node wrapper exposes `onclose` via getter/setter with
99
+ // type `(() => void) | undefined`, while the `Transport` interface
100
+ // declares `onclose?: () => void`. Under `exactOptionalPropertyTypes:
101
+ // true` those are not structurally assignable. The runtime contract is
102
+ // the same (the setter accepts `() => void`), so we cast once here.
103
+ const transport = new StreamableHTTPServerTransport();
104
+ const sdkTransport = transport;
105
+ await server.connect(sdkTransport);
89
106
  try {
90
107
  // `handleRequest` writes the response and returns once the message has
91
108
  // been dispatched. No shared state across calls in stateless mode.
@@ -107,6 +124,14 @@ export async function startHttpServer(opts) {
107
124
  sendJson(res, 500, { error });
108
125
  }
109
126
  }
127
+ finally {
128
+ // Closing the transport fires its `onclose`, which resets
129
+ // `server._transport` to undefined so the next request can connect
130
+ // a fresh transport. We swallow the close error: a request that
131
+ // already wrote its response does not care whether the close path
132
+ // threw.
133
+ await transport.close().catch(() => { });
134
+ }
110
135
  });
111
136
  await new Promise((resolve, reject) => {
112
137
  httpServer.once('error', reject);
@@ -121,7 +146,6 @@ export async function startHttpServer(opts) {
121
146
  path,
122
147
  close: async () => {
123
148
  await new Promise((resolve) => httpServer.close(() => resolve()));
124
- await transport.close().catch(() => { });
125
149
  await server.close().catch(() => { });
126
150
  },
127
151
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crediolabs/policy-builder-mcp",
3
- "version": "0.1.18",
3
+ "version": "0.2.0",
4
4
  "license": "MIT",
5
5
  "description": "MCP server exposing the OZ policy-synth core (record_transaction + synthesize_policy) over stdio and Streamable HTTP transports.",
6
6
  "type": "module",
@@ -37,7 +37,6 @@
37
37
  "types": "./dist/src/index.d.ts",
38
38
  "bun": "./src/index.ts",
39
39
  "import": "./dist/src/index.js",
40
- "require": "./dist-cjs/src/index.js",
41
40
  "default": "./dist/src/index.js"
42
41
  },
43
42
  "./package.json": "./package.json"
@@ -47,7 +46,6 @@
47
46
  },
48
47
  "files": [
49
48
  "dist",
50
- "dist-cjs",
51
49
  "src",
52
50
  "!src/**/*.test.ts"
53
51
  ],
@@ -56,15 +54,13 @@
56
54
  },
57
55
  "scripts": {
58
56
  "test": "bun test",
59
- "build": "tsc -p tsconfig.build.json && tsc -p tsconfig.build.cjs.json && node scripts/write-cjs-package-json.cjs",
60
- "build:esm": "tsc -p tsconfig.build.json",
61
- "build:cjs": "tsc -p tsconfig.build.cjs.json && node scripts/write-cjs-package-json.cjs",
57
+ "build": "tsc -p tsconfig.build.json",
62
58
  "prepublishOnly": "bun run build && bun test",
63
59
  "prepack": "bun run build"
64
60
  },
65
61
  "dependencies": {
66
- "@crediolabs/policy-synth": "0.1.18",
67
- "@modelcontextprotocol/sdk": "1.18.1",
62
+ "@crediolabs/policy-synth": "0.2.0",
63
+ "@modelcontextprotocol/sdk": "1.26.0",
68
64
  "@stellar/stellar-sdk": "14.4.0",
69
65
  "zod": "3.25.76"
70
66
  },
package/src/schemas.ts CHANGED
@@ -167,6 +167,15 @@ export const RevokePolicyToolShape = {
167
167
  interpreterAddress: z.string().optional(),
168
168
  } as const
169
169
 
170
+ /** Flat ZodRawShape for `merge_policy`: the tightening remedy when two rules
171
+ * our interpreter polices can serve the same calls. Two steps, in order. */
172
+ export const MergePolicyToolShape = {
173
+ ...SmartAccountToolShape,
174
+ ruleId: z.number().int().nonnegative(),
175
+ incomingPredicateBlobBase64: z.string().min(1),
176
+ step: z.enum(['detach', 'reinstall']),
177
+ } as const
178
+
170
179
  /** Flat ZodRawShape for `get_interpreter_info`. `verifyLive` triggers an
171
180
  * optional RPC `grammar_version()` call so the caller can verify the
172
181
  * deployed contract matches the pin. */
package/src/server.ts CHANGED
@@ -15,6 +15,7 @@ import type { ToolResponse } from '@crediolabs/policy-synth'
15
15
  import {
16
16
  runGetInterpreterInfo,
17
17
  runInstallPolicy,
18
+ runMergePolicy,
18
19
  runRecordTransaction,
19
20
  runRevokePolicy,
20
21
  runSimulatePolicy,
@@ -26,6 +27,7 @@ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'
26
27
  import {
27
28
  GetInterpreterInfoToolShape,
28
29
  InstallPolicyToolShape,
30
+ MergePolicyToolShape,
29
31
  RecordTransactionToolShape,
30
32
  RevokePolicyToolShape,
31
33
  SimulatePolicyToolShape,
@@ -97,6 +99,13 @@ export function registerTools(server: McpServer): void {
97
99
  (args) => runRevokePolicy(args).then(toCallToolResult)
98
100
  )
99
101
 
102
+ server.tool(
103
+ 'merge_policy',
104
+ "Tighten a rule by replacing its predicate with the conjunction of the installed one and a new one. This is the remedy for the overlap `install_policy` reports between two rules the interpreter polices: because OpenZeppelin enforces only the rule a signer names, adding a second, tighter rule restricts nothing, so the restriction has to become one predicate. TWO transactions, in order: call with step 'detach' to remove the current attachment, wait for it to confirm, then call with step 'reinstall'. Detaching uninstalls the policy, which RESETS every counter on the rule, and the rule is unpoliced in between - both are reported in `warnings`.",
105
+ MergePolicyToolShape,
106
+ (args) => runMergePolicy(args).then(toCallToolResult)
107
+ )
108
+
100
109
  server.tool(
101
110
  'get_interpreter_info',
102
111
  'Read-only fingerprint lookup for the policy interpreter contract: returns the pinned address, grammar version, and wasm sha256 (from the pinned constants + SELF_VERSION). When `verifyLive=true`, performs an additional `grammar_version()` RPC call against the pinned address and reports whether the deployed contract matches the pin - a live mismatch check is more useful than a fabricated audit field.',
@@ -2,8 +2,13 @@
2
2
  //
3
3
  // Streamable HTTP transport (hosted). Uses the Node http module directly so
4
4
  // the package stays thin - no express / hono dep. We run in STATELESS mode
5
- // (sessionIdGenerator: undefined) so each POST /mcp is its own transaction:
6
- // this matches the brief's "stateless across calls" invariant.
5
+ // (no `sessionIdGenerator` option), and the SDK 1.26+ requires a FRESH
6
+ // transport per request in stateless mode: reusing one across requests lets
7
+ // concurrent clients share internal message-id state, which is exactly the
8
+ // cross-client data leak GHSA-345p-7cg4-v4c7 warns about. We therefore build
9
+ // a transport inside the request handler, connect it, dispatch the request,
10
+ // then close it (close() resets the McpServer's transport slot so the next
11
+ // request can reconnect cleanly).
7
12
  //
8
13
  // Single endpoint: POST /mcp (the SDK also accepts GET for SSE streaming, but
9
14
  // the T1 surface does not emit server-initiated messages so we omit it).
@@ -22,6 +27,7 @@
22
27
  import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http'
23
28
  import type { ToolError } from '@crediolabs/policy-synth'
24
29
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
30
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'
25
31
  import { createMcpServer } from '../server.ts'
26
32
 
27
33
  const LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost'])
@@ -60,13 +66,11 @@ export async function startHttpServer(opts: StartHttpServerOptions): Promise<Run
60
66
  `startHttpServer: refusing to bind host ${host}: the MCP surface is unauthenticated, so only loopback (127.0.0.1, ::1, localhost) is permitted by default. Pass \`allowExternalHost: true\` to opt in to a non-loopback bind.`
61
67
  )
62
68
  }
69
+ // The McpServer is stateless and per-process; we keep ONE instance alive
70
+ // for the lifetime of the listener, but each request creates + connects a
71
+ // fresh StreamableHTTPServerTransport (SDK 1.26+ refuses to reuse a
72
+ // stateless transport across requests).
63
73
  const server = createMcpServer()
64
- // One transport per server (the SDK reuses the transport for every request
65
- // in stateless mode). We connect it once at startup and reuse it.
66
- const transport = new StreamableHTTPServerTransport({
67
- sessionIdGenerator: undefined,
68
- })
69
- await server.connect(transport)
70
74
 
71
75
  const httpServer: Server = createServer(async (req, res) => {
72
76
  if (!req.url) {
@@ -114,6 +118,21 @@ export async function startHttpServer(opts: StartHttpServerOptions): Promise<Run
114
118
  return
115
119
  }
116
120
 
121
+ // One transport per request. Omitting `sessionIdGenerator` selects
122
+ // stateless mode in SDK 1.26+ (the previous `sessionIdGenerator:
123
+ // undefined` form is rejected because the option type no longer
124
+ // includes `undefined` under `exactOptionalPropertyTypes`).
125
+ //
126
+ // The cast `as unknown as Transport` is narrowly scoped to the SDK
127
+ // boundary: the Node wrapper exposes `onclose` via getter/setter with
128
+ // type `(() => void) | undefined`, while the `Transport` interface
129
+ // declares `onclose?: () => void`. Under `exactOptionalPropertyTypes:
130
+ // true` those are not structurally assignable. The runtime contract is
131
+ // the same (the setter accepts `() => void`), so we cast once here.
132
+ const transport = new StreamableHTTPServerTransport()
133
+ const sdkTransport = transport as unknown as Transport
134
+ await server.connect(sdkTransport)
135
+
117
136
  try {
118
137
  // `handleRequest` writes the response and returns once the message has
119
138
  // been dispatched. No shared state across calls in stateless mode.
@@ -132,6 +151,13 @@ export async function startHttpServer(opts: StartHttpServerOptions): Promise<Run
132
151
  }
133
152
  sendJson(res, 500, { error })
134
153
  }
154
+ } finally {
155
+ // Closing the transport fires its `onclose`, which resets
156
+ // `server._transport` to undefined so the next request can connect
157
+ // a fresh transport. We swallow the close error: a request that
158
+ // already wrote its response does not care whether the close path
159
+ // threw.
160
+ await transport.close().catch(() => {})
135
161
  }
136
162
  })
137
163
 
@@ -149,7 +175,6 @@ export async function startHttpServer(opts: StartHttpServerOptions): Promise<Run
149
175
  path,
150
176
  close: async () => {
151
177
  await new Promise<void>((resolve) => httpServer.close(() => resolve()))
152
- await transport.close().catch(() => {})
153
178
  await server.close().catch(() => {})
154
179
  },
155
180
  }
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }
@@ -1,7 +0,0 @@
1
- export { type RunRecordTransactionInput, type RunSynthesizePolicyInput, runRecordTransaction, runSynthesizePolicy, } from '@crediolabs/policy-synth/run';
2
- export { RecordTransactionToolShape, SynthesizePolicyToolShape, } from './schemas.ts';
3
- export { createMcpServer, registerTools } from './server.ts';
4
- export type { McpToolError, McpToolResult } from './tools/result.ts';
5
- export { mcpErrorFromCore, mcpResultFromCore } from './tools/result.ts';
6
- export { startHttpServer } from './transports/http.ts';
7
- export { startStdioServer } from './transports/stdio.ts';
@@ -1,20 +0,0 @@
1
- "use strict";
2
- // packages/policy-builder-mcp/src/index.ts - public re-exports for the MCP server package.
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.startStdioServer = exports.startHttpServer = exports.mcpResultFromCore = exports.mcpErrorFromCore = exports.registerTools = exports.createMcpServer = exports.SynthesizePolicyToolShape = exports.RecordTransactionToolShape = exports.runSynthesizePolicy = exports.runRecordTransaction = void 0;
5
- var run_1 = require("@crediolabs/policy-synth/run");
6
- Object.defineProperty(exports, "runRecordTransaction", { enumerable: true, get: function () { return run_1.runRecordTransaction; } });
7
- Object.defineProperty(exports, "runSynthesizePolicy", { enumerable: true, get: function () { return run_1.runSynthesizePolicy; } });
8
- var schemas_ts_1 = require("./schemas.js");
9
- Object.defineProperty(exports, "RecordTransactionToolShape", { enumerable: true, get: function () { return schemas_ts_1.RecordTransactionToolShape; } });
10
- Object.defineProperty(exports, "SynthesizePolicyToolShape", { enumerable: true, get: function () { return schemas_ts_1.SynthesizePolicyToolShape; } });
11
- var server_ts_1 = require("./server.js");
12
- Object.defineProperty(exports, "createMcpServer", { enumerable: true, get: function () { return server_ts_1.createMcpServer; } });
13
- Object.defineProperty(exports, "registerTools", { enumerable: true, get: function () { return server_ts_1.registerTools; } });
14
- var result_ts_1 = require("./tools/result.js");
15
- Object.defineProperty(exports, "mcpErrorFromCore", { enumerable: true, get: function () { return result_ts_1.mcpErrorFromCore; } });
16
- Object.defineProperty(exports, "mcpResultFromCore", { enumerable: true, get: function () { return result_ts_1.mcpResultFromCore; } });
17
- var http_ts_1 = require("./transports/http.js");
18
- Object.defineProperty(exports, "startHttpServer", { enumerable: true, get: function () { return http_ts_1.startHttpServer; } });
19
- var stdio_ts_1 = require("./transports/stdio.js");
20
- Object.defineProperty(exports, "startStdioServer", { enumerable: true, get: function () { return stdio_ts_1.startStdioServer; } });