@crediolabs/policy-builder-mcp 0.1.11 → 0.1.13
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/dist/src/schemas.d.ts +607 -2
- package/dist/src/schemas.js +67 -2
- package/dist/src/server.js +22 -2
- package/dist-cjs/src/schemas.d.ts +607 -2
- package/dist-cjs/src/schemas.js +73 -1
- package/dist-cjs/src/server.js +20 -0
- package/package.json +3 -2
- package/src/schemas.ts +95 -0
- package/src/server.ts +68 -2
package/dist/src/schemas.js
CHANGED
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
// `ZodEffects`, which has no `.shape`). They MUST stay in lockstep with
|
|
21
21
|
// the strict schemas - a drift in field type or optionality breaks the
|
|
22
22
|
// SDK's emitted JSON Schema.
|
|
23
|
-
import { ComposeUserResponsesSchema, InterpreterOptionsSchema, MandateSpecSchema, NetworkSchema, OzAdapterConfigSchema, RecordedTransactionSchema, RecordTransactionInputSchema, SynthesizePolicyInputSchema, ToolErrorSchema, } from '@crediolabs/policy-synth/run';
|
|
23
|
+
import { ComposeUserResponsesSchema, GetInterpreterInfoInputSchema, InstallPolicyInputSchema, InterpreterOptionsSchema, MandateSpecSchema, NetworkSchema, OraclePriceFixtureSchema, OzAdapterConfigSchema, PredicateNodeSchema, RecordedTransactionSchema, RecordTransactionInputSchema, RevokePolicyInputSchema, SimulatePolicyInputSchema, SynthesizePolicyInputSchema, ToolErrorSchema, VerifyPolicyInputSchema, } from '@crediolabs/policy-synth/run';
|
|
24
24
|
import { z } from 'zod';
|
|
25
25
|
// Re-export the strict schemas so MCP package consumers (and existing tests)
|
|
26
26
|
// still get them from this module. The canonical home is
|
|
27
27
|
// `@crediolabs/policy-synth/run`; the re-exports here are a shim kept for
|
|
28
28
|
// backward compatibility with downstream callers that imported from the MCP
|
|
29
29
|
// package directly.
|
|
30
|
-
export { ComposeUserResponsesSchema, InterpreterOptionsSchema, MandateSpecSchema, NetworkSchema, OzAdapterConfigSchema, RecordedTransactionSchema, RecordTransactionInputSchema, SynthesizePolicyInputSchema, ToolErrorSchema, };
|
|
30
|
+
export { ComposeUserResponsesSchema, GetInterpreterInfoInputSchema, InstallPolicyInputSchema, InterpreterOptionsSchema, MandateSpecSchema, NetworkSchema, OraclePriceFixtureSchema, OzAdapterConfigSchema, PredicateNodeSchema, RecordedTransactionSchema, RecordTransactionInputSchema, RevokePolicyInputSchema, SimulatePolicyInputSchema, SynthesizePolicyInputSchema, ToolErrorSchema, VerifyPolicyInputSchema, };
|
|
31
31
|
/** Flat ZodRawShape used for the MCP SDK tool registration. The body
|
|
32
32
|
* re-validates against `RecordTransactionInputSchema` so the mutual-exclusion
|
|
33
33
|
* rule still fires (the SDK does not invoke `.refine()` at registration time). */
|
|
@@ -49,4 +49,69 @@ export const SynthesizePolicyToolShape = {
|
|
|
49
49
|
confidenceOverride: z.object({ threshold: z.number().min(0).max(1) }).optional(),
|
|
50
50
|
interpreter: InterpreterOptionsSchema.optional(),
|
|
51
51
|
ozConfig: OzAdapterConfigSchema.optional(),
|
|
52
|
+
// Without this the tool chain has no join. A ProposedPolicy carries
|
|
53
|
+
// `policyDocuments[].encodedPredicate` (canonical ScVal bytes), while
|
|
54
|
+
// `simulate_policy` and `verify_policy` both want the PredicateNode TREE,
|
|
55
|
+
// and the tree is only returned under `explain`. Omitting it here left an
|
|
56
|
+
// MCP client able to synthesize a policy and then unable to prove anything
|
|
57
|
+
// about it - the two checks were reachable only with `predicate: null`,
|
|
58
|
+
// which skips the interpreter predicate entirely.
|
|
59
|
+
explain: z.boolean().optional(),
|
|
60
|
+
};
|
|
61
|
+
/** Flat ZodRawShape for `simulate_policy`. The `predicate` is typed as
|
|
62
|
+
* `z.unknown()` at the tool boundary because the recursive
|
|
63
|
+
* `PredicateNodeSchema` is a `z.lazy()` union (the SDK does not accept
|
|
64
|
+
* unions at the tool-registration boundary); the body re-validates
|
|
65
|
+
* against `SimulatePolicyInputSchema`, which fails closed on a
|
|
66
|
+
* malformed predicate. `predicate` is nullable here (vs required for
|
|
67
|
+
* verify_policy) so the SDK-emitted JSON Schema mirrors the engine's
|
|
68
|
+
* "OZ-only / no interpreter predicate" contract. */
|
|
69
|
+
export const SimulatePolicyToolShape = {
|
|
70
|
+
predicate: z.unknown().nullable().optional(),
|
|
71
|
+
permitTx: RecordedTransactionSchema,
|
|
72
|
+
validUntilLedger: z.number().int().positive().optional(),
|
|
73
|
+
oraclePricesByAsset: z.record(z.string(), OraclePriceFixtureSchema).optional(),
|
|
74
|
+
};
|
|
75
|
+
/** Flat ZodRawShape for `verify_policy`. Same `z.unknown()` boundary
|
|
76
|
+
* trick for `predicate` as `SimulatePolicyToolShape`; `predicate` is
|
|
77
|
+
* required at the strict-schema level (`VerifyPolicyInputSchema`) so
|
|
78
|
+
* the body fails closed on a missing predicate. */
|
|
79
|
+
export const VerifyPolicyToolShape = {
|
|
80
|
+
predicate: z.unknown(),
|
|
81
|
+
permitTx: RecordedTransactionSchema,
|
|
82
|
+
validUntilLedger: z.number().int().positive().optional(),
|
|
83
|
+
oraclePricesByAsset: z.record(z.string(), OraclePriceFixtureSchema).optional(),
|
|
84
|
+
};
|
|
85
|
+
/** Flat ZodRawShape for `install_policy`. `rule` is typed as `z.unknown()`
|
|
86
|
+
* at the tool boundary because the rule schema is a discriminated union
|
|
87
|
+
* the SDK does not accept at registration; the body re-validates
|
|
88
|
+
* against `InstallPolicyInputSchema`. `encodedPredicate` /
|
|
89
|
+
* `predicateHash` live INSIDE `rule.policies[].predicateBlobBase64`
|
|
90
|
+
* (the policy already carries the encoded predicate); the run-layer
|
|
91
|
+
* extracts them from there. */
|
|
92
|
+
export const InstallPolicyToolShape = {
|
|
93
|
+
smartAccount: z.string().min(1).optional(),
|
|
94
|
+
sourceAccount: z.string().min(1).optional(),
|
|
95
|
+
rule: z.unknown().optional(),
|
|
96
|
+
installNonce: z.number().int().positive().optional(),
|
|
97
|
+
interpreterAddress: z.string().optional(),
|
|
98
|
+
rpcUrl: z.string().url().optional(),
|
|
99
|
+
baseFee: z.number().int().positive().optional(),
|
|
100
|
+
};
|
|
101
|
+
/** Flat ZodRawShape for `revoke_policy`. */
|
|
102
|
+
export const RevokePolicyToolShape = {
|
|
103
|
+
smartAccount: z.string().min(1).optional(),
|
|
104
|
+
sourceAccount: z.string().min(1).optional(),
|
|
105
|
+
ruleId: z.number().int().nonnegative().optional(),
|
|
106
|
+
interpreterAddress: z.string().optional(),
|
|
107
|
+
rpcUrl: z.string().url().optional(),
|
|
108
|
+
baseFee: z.number().int().positive().optional(),
|
|
109
|
+
};
|
|
110
|
+
/** Flat ZodRawShape for `get_interpreter_info`. `verifyLive` triggers an
|
|
111
|
+
* optional RPC `grammar_version()` call so the caller can verify the
|
|
112
|
+
* deployed contract matches the pin. */
|
|
113
|
+
export const GetInterpreterInfoToolShape = {
|
|
114
|
+
network: z.enum(['mainnet', 'testnet']).optional(),
|
|
115
|
+
verifyLive: z.boolean().optional(),
|
|
116
|
+
rpcUrl: z.string().url().optional(),
|
|
52
117
|
};
|
package/dist/src/server.js
CHANGED
|
@@ -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 { runRecordTransaction, runSynthesizePolicy } from '@crediolabs/policy-synth/run';
|
|
13
|
+
import { runGetInterpreterInfo, runInstallPolicy, runRecordTransaction, runRevokePolicy, runSimulatePolicy, runSynthesizePolicy, runVerifyPolicy, } from '@crediolabs/policy-synth/run';
|
|
14
14
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
15
|
-
import { RecordTransactionToolShape, SynthesizePolicyToolShape } from "./schemas.js";
|
|
15
|
+
import { GetInterpreterInfoToolShape, InstallPolicyToolShape, RecordTransactionToolShape, RevokePolicyToolShape, SimulatePolicyToolShape, SynthesizePolicyToolShape, VerifyPolicyToolShape, } from "./schemas.js";
|
|
16
16
|
import { mcpResultFromCore } from "./tools/result.js";
|
|
17
17
|
/** Build a fresh, stateless MCP server. The caller owns the returned object
|
|
18
18
|
* and connects it to a single transport (stdio or Streamable HTTP). */
|
|
@@ -35,4 +35,24 @@ export function registerTools(server) {
|
|
|
35
35
|
const res = await runSynthesizePolicy(args);
|
|
36
36
|
return mcpResultFromCore(res);
|
|
37
37
|
});
|
|
38
|
+
server.tool('simulate_policy', 'Replay a RecordedTransaction against a proposed PredicateNode (or null for an OZ-only policy) and emit the SimulationResult envelope (permit verdict + deny-case battery). Returns a SIMULATION_ERROR ToolError on runtime evaluation failure.', SimulatePolicyToolShape, async (args) => {
|
|
39
|
+
const res = await runSimulatePolicy(args);
|
|
40
|
+
return mcpResultFromCore(res);
|
|
41
|
+
});
|
|
42
|
+
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, async (args) => {
|
|
43
|
+
const res = await runVerifyPolicy(args);
|
|
44
|
+
return mcpResultFromCore(res);
|
|
45
|
+
});
|
|
46
|
+
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, async (args) => {
|
|
47
|
+
const res = await runInstallPolicy(args);
|
|
48
|
+
return mcpResultFromCore(res);
|
|
49
|
+
});
|
|
50
|
+
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, async (args) => {
|
|
51
|
+
const res = await runRevokePolicy(args);
|
|
52
|
+
return mcpResultFromCore(res);
|
|
53
|
+
});
|
|
54
|
+
server.tool('get_interpreter_info', 'Read-only fingerprint lookup for the policy interpreter contract: returns the pinned address, grammar version, and wasm sha256 (from DEPLOYMENTS.md + 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, async (args) => {
|
|
55
|
+
const res = await runGetInterpreterInfo(args);
|
|
56
|
+
return mcpResultFromCore(res);
|
|
57
|
+
});
|
|
38
58
|
}
|