@crediolabs/policy-builder-mcp 0.1.6 → 0.1.8

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.
@@ -1,98 +0,0 @@
1
- // apps/policy-builder-mcp/src/tools/run.ts
2
- //
3
- // Tool bodies for `record_transaction` and `synthesize_policy`. Each body is a
4
- // THIN adapter over the pure core:
5
- //
6
- // 1. Re-validate the parsed input via Zod. This is a defence-in-depth check -
7
- // the SDK has already parsed it through the registered schema, but we never
8
- // want a tool body to throw on garbage (the SDK treats uncaught throws as
9
- // transport errors and the agent loses the machine-readable ToolError).
10
- // 2. Dispatch to the matching core entry point with the minimum required
11
- // inputs.
12
- // 3. Return the core's ToolResponse<T> unchanged. The server layer maps it
13
- // to the MCP envelope; nothing here knows about MCP.
14
- //
15
- // No business logic. No retries. No session state. The same call shape can
16
- // drive the CLI (which calls into the same core directly without MCP).
17
- import { placeholderOzConfig, recordTransaction, synthesizeFromMandate, synthesizeFromRecording, } from '@crediolabs/policy-synth';
18
- import { RecordTransactionInputSchema, SynthesizePolicyInputSchema, } from "../schemas.js";
19
- /** `record_transaction` body - wraps `recordTransaction`. The tool input
20
- * matches the core RecordInput minus the injected `fetcher` (the transport
21
- * layer does not own the RPC). Returns the core ToolResponse unchanged. */
22
- export async function runRecordTransaction(raw) {
23
- const parsed = RecordTransactionInputSchema.safeParse(raw);
24
- if (!parsed.success) {
25
- return {
26
- ok: false,
27
- error: validationError('record_transaction', parsed.error.issues),
28
- };
29
- }
30
- const input = parsed.data;
31
- // Strip the wire-only `confidenceOverride` and pass the rest straight through.
32
- const coreInput = {
33
- network: input.network,
34
- ...(input.hash !== undefined ? { hash: input.hash } : {}),
35
- ...(input.xdr !== undefined ? { xdr: input.xdr } : {}),
36
- ...(input.confidenceOverride !== undefined
37
- ? { confidenceOverride: input.confidenceOverride }
38
- : {}),
39
- };
40
- return recordTransaction(coreInput);
41
- }
42
- /** `synthesize_policy` body - discriminated union on `source`:
43
- * - `mandate` -> synthesizeFromMandate
44
- * - `recording` -> synthesizeFromRecording
45
- * Exposing BOTH front-ends through ONE tool keeps the MCP surface tiny while
46
- * letting the agent pick the deterministic or the inferred path. The CLI
47
- * routes the same way. */
48
- export async function runSynthesizePolicy(raw) {
49
- const parsed = SynthesizePolicyInputSchema.safeParse(raw);
50
- if (!parsed.success) {
51
- return {
52
- ok: false,
53
- error: validationError('synthesize_policy', parsed.error.issues),
54
- };
55
- }
56
- const input = parsed.data;
57
- const ozConfig = resolveOzConfig(input);
58
- if (input.source === 'mandate') {
59
- // Zod's optional fields widen to `T | undefined`, which the core's
60
- // exact-optional MandateSpec rejects; the schema already validated the
61
- // shape, so assert it (same pattern as the recordedTx cast below).
62
- return synthesizeFromMandate(input.mandate, ozConfig);
63
- }
64
- // recording source
65
- const recorded = input.recordedTx;
66
- return synthesizeFromRecording(recorded, {
67
- network: input.network,
68
- ...(input.userResponses !== undefined ? { userResponses: input.userResponses } : {}),
69
- ...(input.confidenceOverride !== undefined
70
- ? { confidenceOverride: input.confidenceOverride }
71
- : {}),
72
- ...(input.interpreter !== undefined ? { interpreter: input.interpreter } : {}),
73
- }, ozConfig);
74
- }
75
- function resolveOzConfig(input) {
76
- if (input.ozConfig)
77
- return input.ozConfig;
78
- // The mandate path is network-agnostic; fall back to mainnet so the
79
- // placeholder OZ instance addresses are deterministic.
80
- return placeholderOzConfig('mainnet');
81
- }
82
- /** Build a canonical ToolError for a Zod validation failure. The remediation
83
- * hint points the agent back at the right tool with an empty arg bag - the
84
- * tool name IS the machine-readable hint. */
85
- function validationError(toolName, issues) {
86
- const code = toolName === 'record_transaction' ? 'RECORDING_FAILED' : 'SYNTHESIS_ERROR';
87
- return {
88
- code,
89
- message: `${toolName}: invalid input: ${issues
90
- .map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)
91
- .join('; ')}`,
92
- severity: 'error',
93
- retryable: false,
94
- remediation: {
95
- toolCall: { name: toolName, args: {} },
96
- },
97
- };
98
- }
package/src/tools/run.ts DELETED
@@ -1,134 +0,0 @@
1
- // apps/policy-builder-mcp/src/tools/run.ts
2
- //
3
- // Tool bodies for `record_transaction` and `synthesize_policy`. Each body is a
4
- // THIN adapter over the pure core:
5
- //
6
- // 1. Re-validate the parsed input via Zod. This is a defence-in-depth check -
7
- // the SDK has already parsed it through the registered schema, but we never
8
- // want a tool body to throw on garbage (the SDK treats uncaught throws as
9
- // transport errors and the agent loses the machine-readable ToolError).
10
- // 2. Dispatch to the matching core entry point with the minimum required
11
- // inputs.
12
- // 3. Return the core's ToolResponse<T> unchanged. The server layer maps it
13
- // to the MCP envelope; nothing here knows about MCP.
14
- //
15
- // No business logic. No retries. No session state. The same call shape can
16
- // drive the CLI (which calls into the same core directly without MCP).
17
-
18
- import {
19
- type ErrorCode,
20
- type MandateSpec,
21
- type OzAdapterConfig,
22
- type ProposedPolicy,
23
- placeholderOzConfig,
24
- type RecordedTransaction,
25
- recordTransaction,
26
- type SynthesizeFromRecordingOptions,
27
- synthesizeFromMandate,
28
- synthesizeFromRecording,
29
- type ToolError,
30
- type ToolResponse,
31
- } from '@crediolabs/policy-synth'
32
- import {
33
- type RecordTransactionInput,
34
- RecordTransactionInputSchema,
35
- type SynthesizePolicyInput,
36
- SynthesizePolicyInputSchema,
37
- } from '../schemas.ts'
38
-
39
- export type RunRecordTransactionInput = RecordTransactionInput
40
-
41
- export type RunSynthesizePolicyInput = SynthesizePolicyInput
42
-
43
- /** `record_transaction` body - wraps `recordTransaction`. The tool input
44
- * matches the core RecordInput minus the injected `fetcher` (the transport
45
- * layer does not own the RPC). Returns the core ToolResponse unchanged. */
46
- export async function runRecordTransaction(
47
- raw: unknown
48
- ): Promise<ToolResponse<RecordedTransaction>> {
49
- const parsed = RecordTransactionInputSchema.safeParse(raw)
50
- if (!parsed.success) {
51
- return {
52
- ok: false,
53
- error: validationError('record_transaction', parsed.error.issues),
54
- }
55
- }
56
- const input: RecordTransactionInput = parsed.data
57
- // Strip the wire-only `confidenceOverride` and pass the rest straight through.
58
- const coreInput = {
59
- network: input.network,
60
- ...(input.hash !== undefined ? { hash: input.hash } : {}),
61
- ...(input.xdr !== undefined ? { xdr: input.xdr } : {}),
62
- ...(input.confidenceOverride !== undefined
63
- ? { confidenceOverride: input.confidenceOverride }
64
- : {}),
65
- }
66
- return recordTransaction(coreInput)
67
- }
68
-
69
- /** `synthesize_policy` body - discriminated union on `source`:
70
- * - `mandate` -> synthesizeFromMandate
71
- * - `recording` -> synthesizeFromRecording
72
- * Exposing BOTH front-ends through ONE tool keeps the MCP surface tiny while
73
- * letting the agent pick the deterministic or the inferred path. The CLI
74
- * routes the same way. */
75
- export async function runSynthesizePolicy(raw: unknown): Promise<ToolResponse<ProposedPolicy>> {
76
- const parsed = SynthesizePolicyInputSchema.safeParse(raw)
77
- if (!parsed.success) {
78
- return {
79
- ok: false,
80
- error: validationError('synthesize_policy', parsed.error.issues),
81
- }
82
- }
83
- const input = parsed.data
84
- const ozConfig: OzAdapterConfig = resolveOzConfig(input)
85
-
86
- if (input.source === 'mandate') {
87
- // Zod's optional fields widen to `T | undefined`, which the core's
88
- // exact-optional MandateSpec rejects; the schema already validated the
89
- // shape, so assert it (same pattern as the recordedTx cast below).
90
- return synthesizeFromMandate(input.mandate as MandateSpec, ozConfig)
91
- }
92
- // recording source
93
- const recorded: RecordedTransaction = input.recordedTx as RecordedTransaction
94
- return synthesizeFromRecording(
95
- recorded,
96
- {
97
- network: input.network,
98
- ...(input.userResponses !== undefined ? { userResponses: input.userResponses } : {}),
99
- ...(input.confidenceOverride !== undefined
100
- ? { confidenceOverride: input.confidenceOverride }
101
- : {}),
102
- ...(input.interpreter !== undefined ? { interpreter: input.interpreter } : {}),
103
- } as SynthesizeFromRecordingOptions,
104
- ozConfig
105
- )
106
- }
107
-
108
- function resolveOzConfig(input: SynthesizePolicyInput): OzAdapterConfig {
109
- if (input.ozConfig) return input.ozConfig
110
- // The mandate path is network-agnostic; fall back to mainnet so the
111
- // placeholder OZ instance addresses are deterministic.
112
- return placeholderOzConfig('mainnet')
113
- }
114
-
115
- /** Build a canonical ToolError for a Zod validation failure. The remediation
116
- * hint points the agent back at the right tool with an empty arg bag - the
117
- * tool name IS the machine-readable hint. */
118
- function validationError(
119
- toolName: 'record_transaction' | 'synthesize_policy',
120
- issues: ReadonlyArray<{ path: ReadonlyArray<string | number>; message: string }>
121
- ): ToolError {
122
- const code: ErrorCode = toolName === 'record_transaction' ? 'RECORDING_FAILED' : 'SYNTHESIS_ERROR'
123
- return {
124
- code,
125
- message: `${toolName}: invalid input: ${issues
126
- .map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)
127
- .join('; ')}`,
128
- severity: 'error',
129
- retryable: false,
130
- remediation: {
131
- toolCall: { name: toolName, args: {} },
132
- },
133
- }
134
- }