@crediolabs/policy-builder-mcp 0.1.6 → 0.1.7
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/LICENSE +21 -0
- package/README.md +7 -2
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +2 -2
- package/dist/src/schemas.d.ts +58 -2058
- package/dist/src/schemas.js +26 -213
- package/dist/src/server.js +3 -3
- package/dist-cjs/package.json +3 -0
- package/dist-cjs/src/index.d.ts +7 -0
- package/dist-cjs/src/index.js +20 -0
- package/dist-cjs/src/schemas.d.ts +447 -0
- package/dist-cjs/src/schemas.js +58 -0
- package/dist-cjs/src/server.d.ts +6 -0
- package/dist-cjs/src/server.js +42 -0
- package/dist-cjs/src/tools/result.d.ts +24 -0
- package/dist-cjs/src/tools/result.js +39 -0
- package/dist-cjs/src/transports/http.d.ts +15 -0
- package/dist-cjs/src/transports/http.js +140 -0
- package/dist-cjs/src/transports/stdio.d.ts +1 -0
- package/dist-cjs/src/transports/stdio.js +18 -0
- package/package.json +36 -3
- package/src/index.ts +6 -10
- package/src/schemas.ts +47 -239
- package/src/server.ts +3 -3
- package/dist/src/tools/run.d.ts +0 -15
- package/dist/src/tools/run.js +0 -98
- package/src/tools/run.ts +0 -134
package/dist/src/tools/run.js
DELETED
|
@@ -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
|
-
}
|