@crediolabs/policy-builder-mcp 0.1.12 → 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-cjs/src/schemas.js
CHANGED
|
@@ -22,17 +22,24 @@
|
|
|
22
22
|
// the strict schemas - a drift in field type or optionality breaks the
|
|
23
23
|
// SDK's emitted JSON Schema.
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.SynthesizePolicyToolShape = exports.RecordTransactionToolShape = exports.ToolErrorSchema = exports.SynthesizePolicyInputSchema = exports.RecordTransactionInputSchema = exports.RecordedTransactionSchema = exports.OzAdapterConfigSchema = exports.NetworkSchema = exports.MandateSpecSchema = exports.InterpreterOptionsSchema = exports.ComposeUserResponsesSchema = void 0;
|
|
25
|
+
exports.GetInterpreterInfoToolShape = exports.RevokePolicyToolShape = exports.InstallPolicyToolShape = exports.VerifyPolicyToolShape = exports.SimulatePolicyToolShape = exports.SynthesizePolicyToolShape = exports.RecordTransactionToolShape = exports.VerifyPolicyInputSchema = exports.ToolErrorSchema = exports.SynthesizePolicyInputSchema = exports.SimulatePolicyInputSchema = exports.RevokePolicyInputSchema = exports.RecordTransactionInputSchema = exports.RecordedTransactionSchema = exports.PredicateNodeSchema = exports.OzAdapterConfigSchema = exports.OraclePriceFixtureSchema = exports.NetworkSchema = exports.MandateSpecSchema = exports.InterpreterOptionsSchema = exports.InstallPolicyInputSchema = exports.GetInterpreterInfoInputSchema = exports.ComposeUserResponsesSchema = void 0;
|
|
26
26
|
const run_1 = require("@crediolabs/policy-synth/run");
|
|
27
27
|
Object.defineProperty(exports, "ComposeUserResponsesSchema", { enumerable: true, get: function () { return run_1.ComposeUserResponsesSchema; } });
|
|
28
|
+
Object.defineProperty(exports, "GetInterpreterInfoInputSchema", { enumerable: true, get: function () { return run_1.GetInterpreterInfoInputSchema; } });
|
|
29
|
+
Object.defineProperty(exports, "InstallPolicyInputSchema", { enumerable: true, get: function () { return run_1.InstallPolicyInputSchema; } });
|
|
28
30
|
Object.defineProperty(exports, "InterpreterOptionsSchema", { enumerable: true, get: function () { return run_1.InterpreterOptionsSchema; } });
|
|
29
31
|
Object.defineProperty(exports, "MandateSpecSchema", { enumerable: true, get: function () { return run_1.MandateSpecSchema; } });
|
|
30
32
|
Object.defineProperty(exports, "NetworkSchema", { enumerable: true, get: function () { return run_1.NetworkSchema; } });
|
|
33
|
+
Object.defineProperty(exports, "OraclePriceFixtureSchema", { enumerable: true, get: function () { return run_1.OraclePriceFixtureSchema; } });
|
|
31
34
|
Object.defineProperty(exports, "OzAdapterConfigSchema", { enumerable: true, get: function () { return run_1.OzAdapterConfigSchema; } });
|
|
35
|
+
Object.defineProperty(exports, "PredicateNodeSchema", { enumerable: true, get: function () { return run_1.PredicateNodeSchema; } });
|
|
32
36
|
Object.defineProperty(exports, "RecordedTransactionSchema", { enumerable: true, get: function () { return run_1.RecordedTransactionSchema; } });
|
|
33
37
|
Object.defineProperty(exports, "RecordTransactionInputSchema", { enumerable: true, get: function () { return run_1.RecordTransactionInputSchema; } });
|
|
38
|
+
Object.defineProperty(exports, "RevokePolicyInputSchema", { enumerable: true, get: function () { return run_1.RevokePolicyInputSchema; } });
|
|
39
|
+
Object.defineProperty(exports, "SimulatePolicyInputSchema", { enumerable: true, get: function () { return run_1.SimulatePolicyInputSchema; } });
|
|
34
40
|
Object.defineProperty(exports, "SynthesizePolicyInputSchema", { enumerable: true, get: function () { return run_1.SynthesizePolicyInputSchema; } });
|
|
35
41
|
Object.defineProperty(exports, "ToolErrorSchema", { enumerable: true, get: function () { return run_1.ToolErrorSchema; } });
|
|
42
|
+
Object.defineProperty(exports, "VerifyPolicyInputSchema", { enumerable: true, get: function () { return run_1.VerifyPolicyInputSchema; } });
|
|
36
43
|
const zod_1 = require("zod");
|
|
37
44
|
/** Flat ZodRawShape used for the MCP SDK tool registration. The body
|
|
38
45
|
* re-validates against `RecordTransactionInputSchema` so the mutual-exclusion
|
|
@@ -55,4 +62,69 @@ exports.SynthesizePolicyToolShape = {
|
|
|
55
62
|
confidenceOverride: zod_1.z.object({ threshold: zod_1.z.number().min(0).max(1) }).optional(),
|
|
56
63
|
interpreter: run_1.InterpreterOptionsSchema.optional(),
|
|
57
64
|
ozConfig: run_1.OzAdapterConfigSchema.optional(),
|
|
65
|
+
// Without this the tool chain has no join. A ProposedPolicy carries
|
|
66
|
+
// `policyDocuments[].encodedPredicate` (canonical ScVal bytes), while
|
|
67
|
+
// `simulate_policy` and `verify_policy` both want the PredicateNode TREE,
|
|
68
|
+
// and the tree is only returned under `explain`. Omitting it here left an
|
|
69
|
+
// MCP client able to synthesize a policy and then unable to prove anything
|
|
70
|
+
// about it - the two checks were reachable only with `predicate: null`,
|
|
71
|
+
// which skips the interpreter predicate entirely.
|
|
72
|
+
explain: zod_1.z.boolean().optional(),
|
|
73
|
+
};
|
|
74
|
+
/** Flat ZodRawShape for `simulate_policy`. The `predicate` is typed as
|
|
75
|
+
* `z.unknown()` at the tool boundary because the recursive
|
|
76
|
+
* `PredicateNodeSchema` is a `z.lazy()` union (the SDK does not accept
|
|
77
|
+
* unions at the tool-registration boundary); the body re-validates
|
|
78
|
+
* against `SimulatePolicyInputSchema`, which fails closed on a
|
|
79
|
+
* malformed predicate. `predicate` is nullable here (vs required for
|
|
80
|
+
* verify_policy) so the SDK-emitted JSON Schema mirrors the engine's
|
|
81
|
+
* "OZ-only / no interpreter predicate" contract. */
|
|
82
|
+
exports.SimulatePolicyToolShape = {
|
|
83
|
+
predicate: zod_1.z.unknown().nullable().optional(),
|
|
84
|
+
permitTx: run_1.RecordedTransactionSchema,
|
|
85
|
+
validUntilLedger: zod_1.z.number().int().positive().optional(),
|
|
86
|
+
oraclePricesByAsset: zod_1.z.record(zod_1.z.string(), run_1.OraclePriceFixtureSchema).optional(),
|
|
87
|
+
};
|
|
88
|
+
/** Flat ZodRawShape for `verify_policy`. Same `z.unknown()` boundary
|
|
89
|
+
* trick for `predicate` as `SimulatePolicyToolShape`; `predicate` is
|
|
90
|
+
* required at the strict-schema level (`VerifyPolicyInputSchema`) so
|
|
91
|
+
* the body fails closed on a missing predicate. */
|
|
92
|
+
exports.VerifyPolicyToolShape = {
|
|
93
|
+
predicate: zod_1.z.unknown(),
|
|
94
|
+
permitTx: run_1.RecordedTransactionSchema,
|
|
95
|
+
validUntilLedger: zod_1.z.number().int().positive().optional(),
|
|
96
|
+
oraclePricesByAsset: zod_1.z.record(zod_1.z.string(), run_1.OraclePriceFixtureSchema).optional(),
|
|
97
|
+
};
|
|
98
|
+
/** Flat ZodRawShape for `install_policy`. `rule` is typed as `z.unknown()`
|
|
99
|
+
* at the tool boundary because the rule schema is a discriminated union
|
|
100
|
+
* the SDK does not accept at registration; the body re-validates
|
|
101
|
+
* against `InstallPolicyInputSchema`. `encodedPredicate` /
|
|
102
|
+
* `predicateHash` live INSIDE `rule.policies[].predicateBlobBase64`
|
|
103
|
+
* (the policy already carries the encoded predicate); the run-layer
|
|
104
|
+
* extracts them from there. */
|
|
105
|
+
exports.InstallPolicyToolShape = {
|
|
106
|
+
smartAccount: zod_1.z.string().min(1).optional(),
|
|
107
|
+
sourceAccount: zod_1.z.string().min(1).optional(),
|
|
108
|
+
rule: zod_1.z.unknown().optional(),
|
|
109
|
+
installNonce: zod_1.z.number().int().positive().optional(),
|
|
110
|
+
interpreterAddress: zod_1.z.string().optional(),
|
|
111
|
+
rpcUrl: zod_1.z.string().url().optional(),
|
|
112
|
+
baseFee: zod_1.z.number().int().positive().optional(),
|
|
113
|
+
};
|
|
114
|
+
/** Flat ZodRawShape for `revoke_policy`. */
|
|
115
|
+
exports.RevokePolicyToolShape = {
|
|
116
|
+
smartAccount: zod_1.z.string().min(1).optional(),
|
|
117
|
+
sourceAccount: zod_1.z.string().min(1).optional(),
|
|
118
|
+
ruleId: zod_1.z.number().int().nonnegative().optional(),
|
|
119
|
+
interpreterAddress: zod_1.z.string().optional(),
|
|
120
|
+
rpcUrl: zod_1.z.string().url().optional(),
|
|
121
|
+
baseFee: zod_1.z.number().int().positive().optional(),
|
|
122
|
+
};
|
|
123
|
+
/** Flat ZodRawShape for `get_interpreter_info`. `verifyLive` triggers an
|
|
124
|
+
* optional RPC `grammar_version()` call so the caller can verify the
|
|
125
|
+
* deployed contract matches the pin. */
|
|
126
|
+
exports.GetInterpreterInfoToolShape = {
|
|
127
|
+
network: zod_1.z.enum(['mainnet', 'testnet']).optional(),
|
|
128
|
+
verifyLive: zod_1.z.boolean().optional(),
|
|
129
|
+
rpcUrl: zod_1.z.string().url().optional(),
|
|
58
130
|
};
|
package/dist-cjs/src/server.js
CHANGED
|
@@ -39,4 +39,24 @@ function registerTools(server) {
|
|
|
39
39
|
const res = await (0, run_1.runSynthesizePolicy)(args);
|
|
40
40
|
return (0, result_ts_1.mcpResultFromCore)(res);
|
|
41
41
|
});
|
|
42
|
+
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.', schemas_ts_1.SimulatePolicyToolShape, async (args) => {
|
|
43
|
+
const res = await (0, run_1.runSimulatePolicy)(args);
|
|
44
|
+
return (0, result_ts_1.mcpResultFromCore)(res);
|
|
45
|
+
});
|
|
46
|
+
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.', schemas_ts_1.VerifyPolicyToolShape, async (args) => {
|
|
47
|
+
const res = await (0, run_1.runVerifyPolicy)(args);
|
|
48
|
+
return (0, result_ts_1.mcpResultFromCore)(res);
|
|
49
|
+
});
|
|
50
|
+
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.', schemas_ts_1.InstallPolicyToolShape, async (args) => {
|
|
51
|
+
const res = await (0, run_1.runInstallPolicy)(args);
|
|
52
|
+
return (0, result_ts_1.mcpResultFromCore)(res);
|
|
53
|
+
});
|
|
54
|
+
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.', schemas_ts_1.RevokePolicyToolShape, async (args) => {
|
|
55
|
+
const res = await (0, run_1.runRevokePolicy)(args);
|
|
56
|
+
return (0, result_ts_1.mcpResultFromCore)(res);
|
|
57
|
+
});
|
|
58
|
+
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.', schemas_ts_1.GetInterpreterInfoToolShape, async (args) => {
|
|
59
|
+
const res = await (0, run_1.runGetInterpreterInfo)(args);
|
|
60
|
+
return (0, result_ts_1.mcpResultFromCore)(res);
|
|
61
|
+
});
|
|
42
62
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crediolabs/policy-builder-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
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",
|
|
@@ -63,8 +63,9 @@
|
|
|
63
63
|
"prepack": "bun run build"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@crediolabs/policy-synth": "
|
|
66
|
+
"@crediolabs/policy-synth": "workspace:*",
|
|
67
67
|
"@modelcontextprotocol/sdk": "1.18.1",
|
|
68
|
+
"@stellar/stellar-sdk": "14.4.0",
|
|
68
69
|
"zod": "3.25.76"
|
|
69
70
|
},
|
|
70
71
|
"devDependencies": {
|
package/src/schemas.ts
CHANGED
|
@@ -23,14 +23,21 @@
|
|
|
23
23
|
|
|
24
24
|
import {
|
|
25
25
|
ComposeUserResponsesSchema,
|
|
26
|
+
GetInterpreterInfoInputSchema,
|
|
27
|
+
InstallPolicyInputSchema,
|
|
26
28
|
InterpreterOptionsSchema,
|
|
27
29
|
MandateSpecSchema,
|
|
28
30
|
NetworkSchema,
|
|
31
|
+
OraclePriceFixtureSchema,
|
|
29
32
|
OzAdapterConfigSchema,
|
|
33
|
+
PredicateNodeSchema,
|
|
30
34
|
RecordedTransactionSchema,
|
|
31
35
|
RecordTransactionInputSchema,
|
|
36
|
+
RevokePolicyInputSchema,
|
|
37
|
+
SimulatePolicyInputSchema,
|
|
32
38
|
SynthesizePolicyInputSchema,
|
|
33
39
|
ToolErrorSchema,
|
|
40
|
+
VerifyPolicyInputSchema,
|
|
34
41
|
} from '@crediolabs/policy-synth/run'
|
|
35
42
|
import { z } from 'zod'
|
|
36
43
|
|
|
@@ -41,14 +48,21 @@ import { z } from 'zod'
|
|
|
41
48
|
// package directly.
|
|
42
49
|
export {
|
|
43
50
|
ComposeUserResponsesSchema,
|
|
51
|
+
GetInterpreterInfoInputSchema,
|
|
52
|
+
InstallPolicyInputSchema,
|
|
44
53
|
InterpreterOptionsSchema,
|
|
45
54
|
MandateSpecSchema,
|
|
46
55
|
NetworkSchema,
|
|
56
|
+
OraclePriceFixtureSchema,
|
|
47
57
|
OzAdapterConfigSchema,
|
|
58
|
+
PredicateNodeSchema,
|
|
48
59
|
RecordedTransactionSchema,
|
|
49
60
|
RecordTransactionInputSchema,
|
|
61
|
+
RevokePolicyInputSchema,
|
|
62
|
+
SimulatePolicyInputSchema,
|
|
50
63
|
SynthesizePolicyInputSchema,
|
|
51
64
|
ToolErrorSchema,
|
|
65
|
+
VerifyPolicyInputSchema,
|
|
52
66
|
}
|
|
53
67
|
|
|
54
68
|
/** Flat ZodRawShape used for the MCP SDK tool registration. The body
|
|
@@ -73,4 +87,85 @@ export const SynthesizePolicyToolShape = {
|
|
|
73
87
|
confidenceOverride: z.object({ threshold: z.number().min(0).max(1) }).optional(),
|
|
74
88
|
interpreter: InterpreterOptionsSchema.optional(),
|
|
75
89
|
ozConfig: OzAdapterConfigSchema.optional(),
|
|
90
|
+
// Without this the tool chain has no join. A ProposedPolicy carries
|
|
91
|
+
// `policyDocuments[].encodedPredicate` (canonical ScVal bytes), while
|
|
92
|
+
// `simulate_policy` and `verify_policy` both want the PredicateNode TREE,
|
|
93
|
+
// and the tree is only returned under `explain`. Omitting it here left an
|
|
94
|
+
// MCP client able to synthesize a policy and then unable to prove anything
|
|
95
|
+
// about it - the two checks were reachable only with `predicate: null`,
|
|
96
|
+
// which skips the interpreter predicate entirely.
|
|
97
|
+
explain: z.boolean().optional(),
|
|
98
|
+
} as const
|
|
99
|
+
|
|
100
|
+
/** Flat ZodRawShape for `simulate_policy`. The `predicate` is typed as
|
|
101
|
+
* `z.unknown()` at the tool boundary because the recursive
|
|
102
|
+
* `PredicateNodeSchema` is a `z.lazy()` union (the SDK does not accept
|
|
103
|
+
* unions at the tool-registration boundary); the body re-validates
|
|
104
|
+
* against `SimulatePolicyInputSchema`, which fails closed on a
|
|
105
|
+
* malformed predicate. `predicate` is nullable here (vs required for
|
|
106
|
+
* verify_policy) so the SDK-emitted JSON Schema mirrors the engine's
|
|
107
|
+
* "OZ-only / no interpreter predicate" contract. */
|
|
108
|
+
export const SimulatePolicyToolShape = {
|
|
109
|
+
predicate: z.unknown().nullable().optional(),
|
|
110
|
+
permitTx: RecordedTransactionSchema,
|
|
111
|
+
validUntilLedger: z.number().int().positive().optional(),
|
|
112
|
+
oraclePricesByAsset: z.record(z.string(), OraclePriceFixtureSchema).optional(),
|
|
113
|
+
} as const
|
|
114
|
+
|
|
115
|
+
/** Flat ZodRawShape for `verify_policy`. Same `z.unknown()` boundary
|
|
116
|
+
* trick for `predicate` as `SimulatePolicyToolShape`; `predicate` is
|
|
117
|
+
* required at the strict-schema level (`VerifyPolicyInputSchema`) so
|
|
118
|
+
* the body fails closed on a missing predicate. */
|
|
119
|
+
export const VerifyPolicyToolShape = {
|
|
120
|
+
predicate: z.unknown(),
|
|
121
|
+
permitTx: RecordedTransactionSchema,
|
|
122
|
+
validUntilLedger: z.number().int().positive().optional(),
|
|
123
|
+
oraclePricesByAsset: z.record(z.string(), OraclePriceFixtureSchema).optional(),
|
|
124
|
+
} as const
|
|
125
|
+
|
|
126
|
+
// Re-export the strict input schemas so MCP consumers (and downstream
|
|
127
|
+
// tests) can import the canonical wire shapes from the same module
|
|
128
|
+
// that owns the tool-shape glue.
|
|
129
|
+
export type {
|
|
130
|
+
GetInterpreterInfoInput,
|
|
131
|
+
InstallPolicyInput,
|
|
132
|
+
RevokePolicyInput,
|
|
133
|
+
SimulatePolicyInput,
|
|
134
|
+
VerifyPolicyInput,
|
|
135
|
+
} from '@crediolabs/policy-synth/run'
|
|
136
|
+
|
|
137
|
+
/** Flat ZodRawShape for `install_policy`. `rule` is typed as `z.unknown()`
|
|
138
|
+
* at the tool boundary because the rule schema is a discriminated union
|
|
139
|
+
* the SDK does not accept at registration; the body re-validates
|
|
140
|
+
* against `InstallPolicyInputSchema`. `encodedPredicate` /
|
|
141
|
+
* `predicateHash` live INSIDE `rule.policies[].predicateBlobBase64`
|
|
142
|
+
* (the policy already carries the encoded predicate); the run-layer
|
|
143
|
+
* extracts them from there. */
|
|
144
|
+
export const InstallPolicyToolShape = {
|
|
145
|
+
smartAccount: z.string().min(1).optional(),
|
|
146
|
+
sourceAccount: z.string().min(1).optional(),
|
|
147
|
+
rule: z.unknown().optional(),
|
|
148
|
+
installNonce: z.number().int().positive().optional(),
|
|
149
|
+
interpreterAddress: z.string().optional(),
|
|
150
|
+
rpcUrl: z.string().url().optional(),
|
|
151
|
+
baseFee: z.number().int().positive().optional(),
|
|
152
|
+
} as const
|
|
153
|
+
|
|
154
|
+
/** Flat ZodRawShape for `revoke_policy`. */
|
|
155
|
+
export const RevokePolicyToolShape = {
|
|
156
|
+
smartAccount: z.string().min(1).optional(),
|
|
157
|
+
sourceAccount: z.string().min(1).optional(),
|
|
158
|
+
ruleId: z.number().int().nonnegative().optional(),
|
|
159
|
+
interpreterAddress: z.string().optional(),
|
|
160
|
+
rpcUrl: z.string().url().optional(),
|
|
161
|
+
baseFee: z.number().int().positive().optional(),
|
|
162
|
+
} as const
|
|
163
|
+
|
|
164
|
+
/** Flat ZodRawShape for `get_interpreter_info`. `verifyLive` triggers an
|
|
165
|
+
* optional RPC `grammar_version()` call so the caller can verify the
|
|
166
|
+
* deployed contract matches the pin. */
|
|
167
|
+
export const GetInterpreterInfoToolShape = {
|
|
168
|
+
network: z.enum(['mainnet', 'testnet']).optional(),
|
|
169
|
+
verifyLive: z.boolean().optional(),
|
|
170
|
+
rpcUrl: z.string().url().optional(),
|
|
76
171
|
} as const
|
package/src/server.ts
CHANGED
|
@@ -11,10 +11,26 @@
|
|
|
11
11
|
// shared mutable state across calls; nothing here caches, queues, or holds
|
|
12
12
|
// key material.
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
runGetInterpreterInfo,
|
|
16
|
+
runInstallPolicy,
|
|
17
|
+
runRecordTransaction,
|
|
18
|
+
runRevokePolicy,
|
|
19
|
+
runSimulatePolicy,
|
|
20
|
+
runSynthesizePolicy,
|
|
21
|
+
runVerifyPolicy,
|
|
22
|
+
} from '@crediolabs/policy-synth/run'
|
|
15
23
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
16
24
|
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'
|
|
17
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
GetInterpreterInfoToolShape,
|
|
27
|
+
InstallPolicyToolShape,
|
|
28
|
+
RecordTransactionToolShape,
|
|
29
|
+
RevokePolicyToolShape,
|
|
30
|
+
SimulatePolicyToolShape,
|
|
31
|
+
SynthesizePolicyToolShape,
|
|
32
|
+
VerifyPolicyToolShape,
|
|
33
|
+
} from './schemas.ts'
|
|
18
34
|
import { mcpResultFromCore } from './tools/result.ts'
|
|
19
35
|
|
|
20
36
|
/** Build a fresh, stateless MCP server. The caller owns the returned object
|
|
@@ -53,4 +69,54 @@ export function registerTools(server: McpServer): void {
|
|
|
53
69
|
return mcpResultFromCore(res) as unknown as CallToolResult
|
|
54
70
|
}
|
|
55
71
|
)
|
|
72
|
+
|
|
73
|
+
server.tool(
|
|
74
|
+
'simulate_policy',
|
|
75
|
+
'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.',
|
|
76
|
+
SimulatePolicyToolShape,
|
|
77
|
+
async (args) => {
|
|
78
|
+
const res = await runSimulatePolicy(args)
|
|
79
|
+
return mcpResultFromCore(res) as unknown as CallToolResult
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
server.tool(
|
|
84
|
+
'verify_policy',
|
|
85
|
+
'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.',
|
|
86
|
+
VerifyPolicyToolShape,
|
|
87
|
+
async (args) => {
|
|
88
|
+
const res = await runVerifyPolicy(args)
|
|
89
|
+
return mcpResultFromCore(res) as unknown as CallToolResult
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
server.tool(
|
|
94
|
+
'install_policy',
|
|
95
|
+
'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.',
|
|
96
|
+
InstallPolicyToolShape,
|
|
97
|
+
async (args) => {
|
|
98
|
+
const res = await runInstallPolicy(args)
|
|
99
|
+
return mcpResultFromCore(res) as unknown as CallToolResult
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
server.tool(
|
|
104
|
+
'revoke_policy',
|
|
105
|
+
'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.',
|
|
106
|
+
RevokePolicyToolShape,
|
|
107
|
+
async (args) => {
|
|
108
|
+
const res = await runRevokePolicy(args)
|
|
109
|
+
return mcpResultFromCore(res) as unknown as CallToolResult
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
server.tool(
|
|
114
|
+
'get_interpreter_info',
|
|
115
|
+
'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.',
|
|
116
|
+
GetInterpreterInfoToolShape,
|
|
117
|
+
async (args) => {
|
|
118
|
+
const res = await runGetInterpreterInfo(args)
|
|
119
|
+
return mcpResultFromCore(res) as unknown as CallToolResult
|
|
120
|
+
}
|
|
121
|
+
)
|
|
56
122
|
}
|