@varnir/agent-server 0.1.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/LICENSE +20 -0
- package/README.md +282 -0
- package/dist/bearer.d.ts +5 -0
- package/dist/bearer.d.ts.map +1 -0
- package/dist/bearer.js +12 -0
- package/dist/bearer.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +151 -0
- package/dist/config.js.map +1 -0
- package/dist/guard.d.ts +28 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +56 -0
- package/dist/guard.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/key-match.d.ts +2 -0
- package/dist/key-match.d.ts.map +1 -0
- package/dist/key-match.js +33 -0
- package/dist/key-match.js.map +1 -0
- package/dist/log.d.ts +8 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +30 -0
- package/dist/log.js.map +1 -0
- package/dist/mcp-http.d.ts +58 -0
- package/dist/mcp-http.d.ts.map +1 -0
- package/dist/mcp-http.js +121 -0
- package/dist/mcp-http.js.map +1 -0
- package/dist/mcp-stdio.d.ts +11 -0
- package/dist/mcp-stdio.d.ts.map +1 -0
- package/dist/mcp-stdio.js +14 -0
- package/dist/mcp-stdio.js.map +1 -0
- package/dist/mcp.d.ts +10 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +18 -0
- package/dist/mcp.js.map +1 -0
- package/dist/rest-methods.d.ts +31 -0
- package/dist/rest-methods.d.ts.map +1 -0
- package/dist/rest-methods.js +66 -0
- package/dist/rest-methods.js.map +1 -0
- package/dist/rest.d.ts +17 -0
- package/dist/rest.d.ts.map +1 -0
- package/dist/rest.js +84 -0
- package/dist/rest.js.map +1 -0
- package/dist/tool-error.d.ts +31 -0
- package/dist/tool-error.d.ts.map +1 -0
- package/dist/tool-error.js +66 -0
- package/dist/tool-error.js.map +1 -0
- package/dist/tools.d.ts +31 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +223 -0
- package/dist/tools.js.map +1 -0
- package/package.json +47 -0
package/dist/rest.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { tokenMatches } from './bearer.js';
|
|
3
|
+
import { toToolFailure, httpStatusFor, classifyBodyError } from './tool-error.js';
|
|
4
|
+
import { REST_METHODS } from './rest-methods.js';
|
|
5
|
+
import { log } from './log.js';
|
|
6
|
+
/**
|
|
7
|
+
* The SecureAPI: the TypeScript SDK's methods mapped to HTTP, for integrating
|
|
8
|
+
* software that can only call HTTP endpoints. This is the surface that can move
|
|
9
|
+
* money, so its gates are all here and all tested: off unless enabled, a
|
|
10
|
+
* mandatory bearer token, and writes behind their own flag on top of the
|
|
11
|
+
* boot-time key guard.
|
|
12
|
+
*/
|
|
13
|
+
export function createRestApp(deps) {
|
|
14
|
+
const { client, config, mode } = deps;
|
|
15
|
+
if (!config.restApi.enabled)
|
|
16
|
+
throw new Error('createRestApp called while the REST API is disabled.');
|
|
17
|
+
const { token, writes } = config.restApi;
|
|
18
|
+
const methods = new Map(REST_METHODS.map(m => [m.name, m]));
|
|
19
|
+
const app = express();
|
|
20
|
+
// Unauthenticated liveness. Deliberately carries no identity and no key data.
|
|
21
|
+
app.get('/v1/health', (_req, res) => {
|
|
22
|
+
res.json({ ok: true, readOnly: mode !== 'writes', writesEnabled: writes });
|
|
23
|
+
});
|
|
24
|
+
const authorise = (req, res, next) => {
|
|
25
|
+
const header = req.header('authorization') ?? '';
|
|
26
|
+
const presented = header.startsWith('Bearer ') ? header.slice(7) : '';
|
|
27
|
+
if (!presented || !tokenMatches(presented, token)) {
|
|
28
|
+
res.status(401).json({ error: { code: 'UNAUTHORIZED', message: 'A valid bearer token is required.' } });
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
next();
|
|
32
|
+
};
|
|
33
|
+
// I5: auth runs BEFORE the body parser on every route that takes one, so an
|
|
34
|
+
// unauthenticated caller can never reach express.json() at all - a bad body
|
|
35
|
+
// from an authenticated caller still only ever gets the structured error
|
|
36
|
+
// handler below, never express's default handler (which echoes err.stack
|
|
37
|
+
// whenever NODE_ENV isn't 'production' - nothing here sets it).
|
|
38
|
+
const jsonBody = express.json({ limit: '1mb' });
|
|
39
|
+
app.get('/v1/methods', authorise, (_req, res) => {
|
|
40
|
+
res.json({ methods: REST_METHODS.map(m => ({ name: m.name, write: m.write })) });
|
|
41
|
+
});
|
|
42
|
+
app.post('/v1/:method', authorise, jsonBody, async (req, res) => {
|
|
43
|
+
const methodName = req.params.method ?? '';
|
|
44
|
+
const method = methods.get(methodName);
|
|
45
|
+
if (!method) {
|
|
46
|
+
res.status(404).json({ error: { code: 'NOT_FOUND', message: `No such method: ${methodName}. GET /v1/methods lists what is callable.` } });
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (method.write && !writes) {
|
|
50
|
+
res.status(403).json({ error: { code: 'WRITES_DISABLED', message: 'Write methods are disabled. Set VARNIR_HTTP_API_WRITES=on to enable them.' } });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (method.write && mode !== 'writes') {
|
|
54
|
+
res.status(403).json({ error: { code: 'READ_ONLY', message: 'This server is running read-only because of its key; see the server logs. Nothing was attempted.' } });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
res.json({ result: await method.call(client, (req.body ?? {})) });
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
const failure = toToolFailure(e);
|
|
62
|
+
log.warn(`REST ${method.name} failed: ${failure.code}`);
|
|
63
|
+
res.status(httpStatusFor(failure.code)).json({ error: failure });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Structured JSON errors, never express's default handler - a malformed
|
|
67
|
+
// body throws inside express.json() and would otherwise reach the default
|
|
68
|
+
// final handler, which echoes err.stack (absolute paths, the operator's
|
|
69
|
+
// username, express internals) whenever NODE_ENV isn't 'production'. Must
|
|
70
|
+
// be declared after the routes/middleware it protects.
|
|
71
|
+
app.use((err, _req, res, next) => {
|
|
72
|
+
// Once a response has started, express's contract is to delegate to the
|
|
73
|
+
// default handler rather than write again - calling res.status() after
|
|
74
|
+
// headers are sent throws and drops the socket opaquely.
|
|
75
|
+
if (res.headersSent) {
|
|
76
|
+
next(err);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const { status, code, message } = classifyBodyError(err);
|
|
80
|
+
res.status(status).json({ error: { code, message } });
|
|
81
|
+
});
|
|
82
|
+
return app;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=rest.js.map
|
package/dist/rest.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../src/rest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A failure shaped so an assistant can EXPLAIN it rather than blindly retry.
|
|
3
|
+
* `policy: true` means the ledger refused on the key's spending policy - the
|
|
4
|
+
* feature working as designed, and something the user should hear in those
|
|
5
|
+
* terms ("your agent key's per-transaction limit blocked this"), not as an
|
|
6
|
+
* error.
|
|
7
|
+
*/
|
|
8
|
+
export interface ToolFailure {
|
|
9
|
+
code: string;
|
|
10
|
+
message: string;
|
|
11
|
+
retryable: boolean;
|
|
12
|
+
policy: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function toToolFailure(e: unknown): ToolFailure;
|
|
15
|
+
/**
|
|
16
|
+
* Classifies a body-parsing error (from `express.json({limit})`) into a
|
|
17
|
+
* status/message pair that's safe to send over the wire. `express.json`
|
|
18
|
+
* raises more than plain JSON syntax errors: `entity.too.large` (413) when
|
|
19
|
+
* the body exceeds `limit`, and `charset.unsupported`/`encoding.unsupported`
|
|
20
|
+
* (415) for a Content-Type/Content-Encoding it won't parse. Collapsing all
|
|
21
|
+
* of those to a flat 400 hides the real problem from an otherwise
|
|
22
|
+
* well-behaved caller. The message is always static - it must never echo
|
|
23
|
+
* `err.message`, which can carry request bytes.
|
|
24
|
+
*/
|
|
25
|
+
export declare function classifyBodyError(err: unknown): {
|
|
26
|
+
status: number;
|
|
27
|
+
code: string;
|
|
28
|
+
message: string;
|
|
29
|
+
};
|
|
30
|
+
export declare function httpStatusFor(code: string): number;
|
|
31
|
+
//# sourceMappingURL=tool-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-error.d.ts","sourceRoot":"","sources":["../src/tool-error.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAeD,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,WAAW,CAQrD;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAe/F;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAclD"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { VarnirError } from '@varnir/chain-client';
|
|
2
|
+
import { redact } from './log.js';
|
|
3
|
+
const POLICY_CODES = new Set([
|
|
4
|
+
'POLICY_PER_TX_EXCEEDED',
|
|
5
|
+
'POLICY_ASSET_DENIED',
|
|
6
|
+
'POLICY_RECIPIENT_DENIED',
|
|
7
|
+
'POLICY_PERIOD_CAP_EXCEEDED',
|
|
8
|
+
'POLICY_COSIGN_REQUIRED',
|
|
9
|
+
'SCOPE_DENIED',
|
|
10
|
+
]);
|
|
11
|
+
// I5: route every message through redact() here, at the single point every
|
|
12
|
+
// HTTP body and MCP tool result flows through, so the redaction contract
|
|
13
|
+
// holds by construction rather than by the current accident that no SDK
|
|
14
|
+
// error happens to interpolate the signing key.
|
|
15
|
+
export function toToolFailure(e) {
|
|
16
|
+
if (e instanceof VarnirError) {
|
|
17
|
+
return { code: e.code, message: redact(e.message), retryable: e.retryable, policy: POLICY_CODES.has(e.code) };
|
|
18
|
+
}
|
|
19
|
+
if (e instanceof Error) {
|
|
20
|
+
return { code: 'UNKNOWN', message: redact(e.message), retryable: false, policy: false };
|
|
21
|
+
}
|
|
22
|
+
return { code: 'UNKNOWN', message: redact(String(e)), retryable: false, policy: false };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Classifies a body-parsing error (from `express.json({limit})`) into a
|
|
26
|
+
* status/message pair that's safe to send over the wire. `express.json`
|
|
27
|
+
* raises more than plain JSON syntax errors: `entity.too.large` (413) when
|
|
28
|
+
* the body exceeds `limit`, and `charset.unsupported`/`encoding.unsupported`
|
|
29
|
+
* (415) for a Content-Type/Content-Encoding it won't parse. Collapsing all
|
|
30
|
+
* of those to a flat 400 hides the real problem from an otherwise
|
|
31
|
+
* well-behaved caller. The message is always static - it must never echo
|
|
32
|
+
* `err.message`, which can carry request bytes.
|
|
33
|
+
*/
|
|
34
|
+
export function classifyBodyError(err) {
|
|
35
|
+
const e = err;
|
|
36
|
+
if (e?.type === 'entity.too.large') {
|
|
37
|
+
return { status: 413, code: 'PAYLOAD_TOO_LARGE', message: 'Request body exceeds the 1MB limit.' };
|
|
38
|
+
}
|
|
39
|
+
if (e?.type === 'charset.unsupported' || e?.type === 'encoding.unsupported') {
|
|
40
|
+
return { status: 415, code: 'UNSUPPORTED_MEDIA_TYPE', message: 'Unsupported request charset or content-encoding.' };
|
|
41
|
+
}
|
|
42
|
+
// Anything else from the body parser (bad JSON syntax, etc.) - preserve a
|
|
43
|
+
// genuine 4xx status if the error carries one, clamped so an unrelated
|
|
44
|
+
// thrown value can never turn into an unexpected 5xx here. The message
|
|
45
|
+
// stays static either way.
|
|
46
|
+
const rawStatus = typeof e?.status === 'number' ? e.status : typeof e?.statusCode === 'number' ? e.statusCode : 400;
|
|
47
|
+
const status = rawStatus >= 400 && rawStatus < 500 ? rawStatus : 400;
|
|
48
|
+
return { status, code: 'VALIDATION', message: 'Malformed JSON body.' };
|
|
49
|
+
}
|
|
50
|
+
export function httpStatusFor(code) {
|
|
51
|
+
if (POLICY_CODES.has(code))
|
|
52
|
+
return 403;
|
|
53
|
+
switch (code) {
|
|
54
|
+
case 'VALIDATION': return 400;
|
|
55
|
+
case 'NOT_FOUND': return 404;
|
|
56
|
+
case 'NOT_OWNER': return 403;
|
|
57
|
+
case 'INSUFFICIENT_BALANCE': return 409;
|
|
58
|
+
case 'ALREADY_SETTLED': return 409;
|
|
59
|
+
case 'EXPIRED': return 409;
|
|
60
|
+
case 'TREASURY_GATED': return 409;
|
|
61
|
+
case 'CONTRACT_REJECTED': return 422;
|
|
62
|
+
case 'NODE_UNREACHABLE': return 503;
|
|
63
|
+
default: return 500;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=tool-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-error.js","sourceRoot":"","sources":["../src/tool-error.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { VarnirClient } from '@varnir/chain-client';
|
|
3
|
+
import type { GuardMode } from './guard.js';
|
|
4
|
+
export interface ToolContext {
|
|
5
|
+
client: VarnirClient;
|
|
6
|
+
identity: string;
|
|
7
|
+
/** The UNTAGGED on-wire public key — see key-match.ts and Task 3's preamble. */
|
|
8
|
+
publicKeyHex: string;
|
|
9
|
+
mode: GuardMode;
|
|
10
|
+
/**
|
|
11
|
+
* `KeyClassification.reason` from guard.ts's `classifyKey` - the ACTUAL
|
|
12
|
+
* cause this key ended up in `mode` (owner key, a read-only/offledger role,
|
|
13
|
+
* no spend policy, or not attached at all). A write-denial message that
|
|
14
|
+
* guesses among those causes instead of reporting this is liable to name
|
|
15
|
+
* the wrong one - see WRITE_DENIED_MESSAGE's history.
|
|
16
|
+
*/
|
|
17
|
+
reason: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ToolDef {
|
|
20
|
+
name: string;
|
|
21
|
+
title: string;
|
|
22
|
+
description: string;
|
|
23
|
+
/** True for anything that signs. Withheld when the guard degraded to read-only. */
|
|
24
|
+
write: boolean;
|
|
25
|
+
inputSchema: z.ZodRawShape;
|
|
26
|
+
handler(args: Record<string, unknown>): Promise<unknown>;
|
|
27
|
+
}
|
|
28
|
+
export declare const WRITE_DENIED_MESSAGE = "This server is running read-only, so it will not sign anything. Nothing was attempted.";
|
|
29
|
+
export declare const REFUSE_DENIED_MESSAGE = "This server refused to start signing anything: its own key is not attached to the configured identity on the ledger at all, so no write could ever succeed. Nothing was attempted.";
|
|
30
|
+
export declare function buildTools(ctx: ToolContext): ToolDef[];
|
|
31
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,EAAC,YAAY,EAAc,MAAM,sBAAsB,CAAC;AAIpE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,SAAS,CAAC;IAChB;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC;IAC3B,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D;AASD,eAAO,MAAM,oBAAoB,2FACyD,CAAC;AAE3F,eAAO,MAAM,qBAAqB,uLACoJ,CAAC;AAmDvL,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,EAAE,CA8MtD"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { chainConfig, fromRawAmount } from '@varnir/chain-client';
|
|
3
|
+
import { toToolFailure } from './tool-error.js';
|
|
4
|
+
import { samePublicKey } from './key-match.js';
|
|
5
|
+
// Generic fallbacks only - guarded() below appends the REAL reason
|
|
6
|
+
// (ctx.reason, straight from guard.ts's classifyKey) rather than guessing
|
|
7
|
+
// among the several causes that can put a key into read-only or refuse.
|
|
8
|
+
// classifyKey has FOUR distinct read-only causes (owner key, a read-only-role
|
|
9
|
+
// key, an offledger-role key, or a policy-less key) and a wrong guess here
|
|
10
|
+
// once told an assistant its key was "the owner key or has no spend policy"
|
|
11
|
+
// when it was actually a role the contracts refuse regardless of policy.
|
|
12
|
+
export const WRITE_DENIED_MESSAGE = 'This server is running read-only, so it will not sign anything. Nothing was attempted.';
|
|
13
|
+
export const REFUSE_DENIED_MESSAGE = 'This server refused to start signing anything: its own key is not attached to the configured identity on the ledger at all, so no write could ever succeed. Nothing was attempted.';
|
|
14
|
+
// Amounts are STRING-ONLY on purpose. A JS number serializes very small
|
|
15
|
+
// amounts as exponential notation ('1e-7') and very large ones the same way
|
|
16
|
+
// ('1e+21'), and both fail toRawAmount's plain-decimal check; a large token
|
|
17
|
+
// amount also loses float precision before it ever gets there. A string
|
|
18
|
+
// carries the exact decimal digits the ledger will scale.
|
|
19
|
+
const leg = z.object({
|
|
20
|
+
chain: z.string().describe("Chain alias ('niles', 'sep', 'tbnb') or ledger code ('TRX-NILE')."),
|
|
21
|
+
token: z.string().optional().describe("The token's L1 contract address; omit for the chain's native asset."),
|
|
22
|
+
amount: z.string().describe("Human decimal amount, as a STRING, e.g. '12.5' - not a JS number."),
|
|
23
|
+
});
|
|
24
|
+
/** Wrap a handler so a throw becomes a structured failure the assistant can explain. */
|
|
25
|
+
function guarded(write, mode, reason, schema, fn) {
|
|
26
|
+
const shape = z.object(schema);
|
|
27
|
+
return async (args) => {
|
|
28
|
+
if (write && mode === 'refuse') {
|
|
29
|
+
// Unreachable in this server's own index.ts today (it exits the process
|
|
30
|
+
// on 'refuse' before buildTools ever runs) - kept as defence-in-depth
|
|
31
|
+
// for any other embedder of buildTools that doesn't do the same.
|
|
32
|
+
return { status: 'error', error: { code: 'REFUSED', message: `${REFUSE_DENIED_MESSAGE} ${reason}`, retryable: false, policy: false } };
|
|
33
|
+
}
|
|
34
|
+
if (write && mode === 'read-only') {
|
|
35
|
+
return { status: 'error', error: { code: 'READ_ONLY', message: `${WRITE_DENIED_MESSAGE} ${reason}`, retryable: false, policy: false } };
|
|
36
|
+
}
|
|
37
|
+
const parsed = shape.safeParse(args);
|
|
38
|
+
if (!parsed.success) {
|
|
39
|
+
const detail = parsed.error.issues.map(i => `${i.path.join('.') || '(root)'}: ${i.message}`).join('; ');
|
|
40
|
+
return { status: 'error', error: { code: 'VALIDATION', message: `Invalid arguments: ${detail}`, retryable: false, policy: false } };
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
return await fn(parsed.data);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
return { status: 'error', error: toToolFailure(e) };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Best-effort decimals for a chain/token pair, for converting a raw on-ledger integer to a human string. Null when it can't be resolved. */
|
|
51
|
+
async function resolveDecimals(client, chain, token) {
|
|
52
|
+
try {
|
|
53
|
+
const { ledgerCode, nativeDecimals } = chainConfig(chain);
|
|
54
|
+
if (!token)
|
|
55
|
+
return nativeDecimals;
|
|
56
|
+
const described = await client.getToken(ledgerCode, token);
|
|
57
|
+
return described?.decimals ?? null;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function buildTools(ctx) {
|
|
64
|
+
const { client, mode, reason } = ctx;
|
|
65
|
+
const def = (name, title, description, write, inputSchema, fn) => ({ name, title, description, write, inputSchema, handler: guarded(write, mode, reason, inputSchema, fn) });
|
|
66
|
+
return [
|
|
67
|
+
// ---------- reads ----------
|
|
68
|
+
def('get_identity', 'Get identity', 'Read this Varnir identity and its on-ledger stream. Use it to confirm which account you are acting for before doing anything else.', false, {}, async () => client.getIdentityStream()),
|
|
69
|
+
def('get_balances', 'Get balances', "List this identity's Layer-2 balances by network and token. Each entry's `raw` figure is the running total, not what a new trade or transfer could freely use: this identity's own open resting orders may reserve part of it, reflected in that entry's `reserved`/`available` fields. Check `available`, not just the raw total, before proposing a trade or a transfer.", false, {}, async () => client.getBalances()),
|
|
70
|
+
def('list_tokens', 'List tokens', 'List the tokens the Varnir ledger knows about, with their networks, contract addresses and decimals. Use it to resolve a symbol a user mentions into the contract address the other tools expect.', false, {}, async () => client.listTokens()),
|
|
71
|
+
def('get_order_book', 'Get order book', 'Read the open exchange order book: every live order with what it gives, what it wants, and its order hash. Use the order hash with fill_order.', false, {}, async () => client.getOrderBook()),
|
|
72
|
+
def('list_transactions', 'List transactions', 'List recent transactions for this identity. The SDK does not guarantee any ordering. On a network whose transaction index is not available yet (e.g. freshly reset), this reports `indexed: false` with an empty list instead of an array - check `indexed` before treating the result as history.', false, { from: z.number().optional().describe('Index to start from.'), limit: z.number().optional().describe('How many to return.') }, async (a) => {
|
|
73
|
+
const result = await client.listTransactions({ from: a.from, limit: a.limit });
|
|
74
|
+
if (!Array.isArray(result)) {
|
|
75
|
+
return {
|
|
76
|
+
indexed: false, transactions: [],
|
|
77
|
+
note: "The ledger's transaction index is not available yet on this network. This is not an error and does not mean there is no history - it means it cannot be listed yet.",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return { indexed: true, transactions: result };
|
|
81
|
+
}),
|
|
82
|
+
def('get_transfer', 'Get transfer', "Read one transfer's L1 settlement receipt by the `umid` that `send` or `transfer_on_ledger` returned. The SDK's `getTransfer` returns `null` both when the umid is unknown AND while a submitted transfer is still working its way through the gateway's presign queue - a real transfer's receipt took about two minutes to appear after submission when this was last verified live, so a null result seconds after sending is normal and does NOT mean anything failed. This call does not wait or poll for that - it reports the truth as of right now, so check back again shortly rather than assuming a failure. When a receipt exists, `confirmed.success === false` is also a real, non-error terminal state - Varnir.ConfirmWithdraw writes that for a withdrawal that failed on L1 and was refunded back onto Layer 2, not only for one that went through. LIMITATION: given only a umid, this cannot tell 'still settling' apart from 'held for a treasury co-sign and will never settle without a second key confirming it' - that distinction is only visible in `send`'s/`transfer_on_ledger`'s own return at submission time (its `awaiting_cosign` status and `proposal`), not by looking the umid up afterwards. If the assistant already knows from that earlier response that the transfer was held, trust that over a 'not settled yet' result here.", false, { umid: z.string().describe('The umid returned by `send` or `transfer_on_ledger`.') }, async (a) => {
|
|
83
|
+
const receipt = await client.getTransfer(a.umid);
|
|
84
|
+
if (!receipt) {
|
|
85
|
+
return {
|
|
86
|
+
status: 'not_settled',
|
|
87
|
+
note: "No receipt yet. Real settlement on this network has taken about two minutes end to end, so this alone is not evidence of a problem - check again shortly. It also does not rule out that this transfer is being held for a treasury co-sign, which will never resolve on its own - if send/transfer_on_ledger reported `awaiting_cosign` for this umid, trust that over this result.",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (receipt.success === false) {
|
|
91
|
+
return {
|
|
92
|
+
status: 'failed',
|
|
93
|
+
confirmed: receipt.confirmed ?? null,
|
|
94
|
+
note: 'This transfer failed on L1 and was refunded back onto Layer 2 - see `confirmed` for the terminal detail. This is not a "not settled yet" case; it will not resolve differently on a retry.',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Receipt.receipt is typed `unknown` (minigate-transport.ts) - it's
|
|
98
|
+
// the gateway's raw broadcast receipt. Verified live shape carries
|
|
99
|
+
// `txid`; narrow it defensively rather than assume the field exists.
|
|
100
|
+
const raw = receipt.receipt;
|
|
101
|
+
return {
|
|
102
|
+
status: 'settled',
|
|
103
|
+
txid: typeof raw?.txid === 'string' ? raw.txid : null,
|
|
104
|
+
gasFee: receipt.confirmed?.gasFee ?? null,
|
|
105
|
+
confirmed: receipt.confirmed ?? null,
|
|
106
|
+
};
|
|
107
|
+
}),
|
|
108
|
+
def('get_spend_policy', 'Get spend policy', "Read the on-ledger spending policy that bounds THIS key: per-transaction ceilings, rolling-period caps, the recipient allowlist and the co-sign threshold. Explain these limits to the user when a write is refused. If `keyFound` is false, this key's policy could not be read at all - that is NOT the same as having no limits, and writes should be treated as unverified. Note this reports the LIMITS, not how much remains - remaining allowance is not readable yet.", false, {}, async () => {
|
|
109
|
+
const keys = await client.listLedgerKeys();
|
|
110
|
+
const mine = keys.find(k => samePublicKey(k.publicKey, ctx.publicKeyHex));
|
|
111
|
+
if (!mine) {
|
|
112
|
+
return {
|
|
113
|
+
identity: ctx.identity,
|
|
114
|
+
mode: ctx.mode,
|
|
115
|
+
keyFound: false,
|
|
116
|
+
role: null,
|
|
117
|
+
scopes: [],
|
|
118
|
+
policy: null,
|
|
119
|
+
note: "This server's own key was not found among this identity's ledger authorities, so its policy is UNKNOWN - this does not mean it has no spending limits.",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
identity: ctx.identity,
|
|
124
|
+
mode: ctx.mode,
|
|
125
|
+
keyFound: true,
|
|
126
|
+
role: mine.role,
|
|
127
|
+
scopes: mine.scopes,
|
|
128
|
+
policy: mine.policy,
|
|
129
|
+
note: 'These are the configured limits. Remaining allowance against a rolling-period cap is not readable through the SDK yet.',
|
|
130
|
+
};
|
|
131
|
+
}),
|
|
132
|
+
// ---------- writes ----------
|
|
133
|
+
def('create_order', 'Create order', 'Create and post a signed exchange order: you give one asset and want another, at the rate implied by the two amounts. Returns the order hash. This only signs the order and posts it to the off-ledger order book - nothing moves and no spending-policy check runs yet. The give-leg policy check happens only when a taker fills it, so an order over this key\'s spending policy will rest on the book and simply never settle rather than being refused up front.', true, { give: leg, want: leg, expireMs: z.number().optional().describe('Absolute ms-since-epoch expiry. Defaults to one hour out.') }, async (a) => {
|
|
134
|
+
const signed = await client.createOrder({
|
|
135
|
+
give: a.give, want: a.want,
|
|
136
|
+
expireMs: a.expireMs ?? Date.now() + 3_600_000,
|
|
137
|
+
});
|
|
138
|
+
await client.postOrder(signed);
|
|
139
|
+
return { status: 'ok', orderHash: signed.orderHash, order: signed.order };
|
|
140
|
+
}),
|
|
141
|
+
def('fill_order', 'Fill order', 'Fill an existing order from the book by its order hash, in whole or in part. Refused if your side of the swap exceeds this key\'s spending policy.', true, { orderHash: z.string().describe('The order hash from get_order_book.'),
|
|
142
|
+
fillAmount: z.string().optional().describe('Partial fill amount; omit to fill entirely.'),
|
|
143
|
+
minReceive: z.string().optional().describe('Minimum you will accept, as slippage protection.') }, async (a) => {
|
|
144
|
+
const book = await client.getOrderBook();
|
|
145
|
+
const entry = book.find(e => e.orderHash === a.orderHash);
|
|
146
|
+
if (!entry || !entry.sig) {
|
|
147
|
+
return { status: 'error', error: { code: 'NOT_FOUND', message: `No open order with hash ${String(a.orderHash)} is in the book. Re-read get_order_book; it may have been filled or cancelled.`, retryable: false, policy: false } };
|
|
148
|
+
}
|
|
149
|
+
const signed = { order: entry.order, sig: entry.sig, orderHash: entry.orderHash };
|
|
150
|
+
const r = await client.fillOrder(signed, {
|
|
151
|
+
fillAmount: a.fillAmount,
|
|
152
|
+
minReceive: a.minReceive,
|
|
153
|
+
});
|
|
154
|
+
return { status: 'ok', umid: r.umid };
|
|
155
|
+
}),
|
|
156
|
+
def('market_order', 'Market order', "Spend a given asset to buy another at whatever the book currently offers, within a slippage bound. Use when the user wants to trade now rather than post a price. Filling only PART of the amount is a normal v1 outcome, not an error - always read `status` and `unfilledGive` rather than assuming a full fill. When NOTHING can be filled at all, this returns an error explaining why (no crossing liquidity, the book raced you, etc.) - read the error, do not treat it as a completed no-op. Amounts are reported as human decimal strings where this identity's token registry can resolve the asset's decimals; when it cannot, only the raw smallest-unit integer is available and `decimals` is null.", true, { give: leg, wantAsset: z.object({ network: z.string(), token: z.string().optional() }),
|
|
157
|
+
maxSlippageBps: z.number().optional().describe('Max slippage in basis points; 100 = 1%.') }, async (a) => {
|
|
158
|
+
const give = a.give;
|
|
159
|
+
const wantAsset = a.wantAsset;
|
|
160
|
+
const r = await client.marketOrder({
|
|
161
|
+
give: give, wantAsset: wantAsset,
|
|
162
|
+
maxSlippageBps: a.maxSlippageBps,
|
|
163
|
+
});
|
|
164
|
+
const giveDecimals = await resolveDecimals(client, give.chain, give.token);
|
|
165
|
+
const wantDecimals = await resolveDecimals(client, wantAsset.network, wantAsset.token);
|
|
166
|
+
const view = (raw, decimals) => ({
|
|
167
|
+
raw, decimals, amount: decimals === null ? null : fromRawAmount(raw, decimals),
|
|
168
|
+
});
|
|
169
|
+
// marketOrder() has no return path that produces an empty `fills` today
|
|
170
|
+
// - every zero-fill case throws instead (no crossing liquidity, raced
|
|
171
|
+
// out, unsigned, or dust-indivisible; see orders.test.ts), so 'error'
|
|
172
|
+
// is what an assistant actually sees for a true zero fill. This branch
|
|
173
|
+
// is defence-in-depth only, for MarketOrderResult's own documented "0
|
|
174
|
+
// or 1 entries" contract should a future SDK version return one.
|
|
175
|
+
const status = r.fills.length === 0 ? 'unfilled' : r.unfilledGive !== '0' ? 'partial' : 'ok';
|
|
176
|
+
return {
|
|
177
|
+
status,
|
|
178
|
+
fills: r.fills,
|
|
179
|
+
give: view(r.spentGive, giveDecimals),
|
|
180
|
+
want: view(r.receivedWant, wantDecimals),
|
|
181
|
+
unfilledGive: view(r.unfilledGive, giveDecimals),
|
|
182
|
+
};
|
|
183
|
+
}),
|
|
184
|
+
def('cancel_order', 'Cancel order', 'Cancel one of this identity\'s own open orders by its order hash.', true, { orderHash: z.string().describe('The order hash to cancel.') }, async (a) => ({ status: 'ok', umid: (await client.cancelOrder(a.orderHash)).umid })),
|
|
185
|
+
def('send', 'Send / withdraw', "Send funds out to a Layer-1 address - a withdrawal. IMPORTANT: this can succeed WITHOUT moving money if the amount is over this key's co-sign threshold or a treasury limit; read the returned `status` before telling the user anything. Refused outright if it breaks a per-transaction or period cap.", true, { chain: z.string().describe("Chain alias ('niles', 'sep', 'tbnb')."),
|
|
186
|
+
to: z.string().describe('The Layer-1 recipient address.'),
|
|
187
|
+
amount: z.string().describe("Human decimal amount, as a STRING, e.g. '0.01' - not a JS number."),
|
|
188
|
+
token: z.string().optional().describe("The token's L1 contract address; omit for the native asset.") }, async (a) => {
|
|
189
|
+
const wallet = await client.getWallet(a.chain);
|
|
190
|
+
const t = await client.send({
|
|
191
|
+
wallet, to: a.to, amount: a.amount, token: a.token,
|
|
192
|
+
});
|
|
193
|
+
// send() does NOT throw POLICY_COSIGN_REQUIRED. A held transfer is a
|
|
194
|
+
// SUCCESS carrying a proposal. Reporting it as sent would be a lie.
|
|
195
|
+
if (t.proposal) {
|
|
196
|
+
return {
|
|
197
|
+
status: 'awaiting_cosign', umid: t.umid, proposal: t.proposal,
|
|
198
|
+
message: 'The transaction was recorded but NO MONEY HAS MOVED. It is over this key\'s co-sign threshold or a treasury limit, so it is held as a proposal until a co-signing key confirms it. Tell the user their funds have NOT been sent and that approval is needed.',
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
return { status: 'sent', umid: t.umid };
|
|
202
|
+
}),
|
|
203
|
+
def('transfer_on_ledger', 'Transfer on Varnir', "Transfer funds to another Varnir identity on Layer 2 - instant and gas-free, staying inside Varnir. Use this instead of `send` when the recipient is a Varnir identity rather than a Layer-1 address. IMPORTANT: like `send`, this can succeed WITHOUT moving money if the amount is over this key's co-sign threshold or a treasury limit; read the returned `status` before telling the user anything.", true, { to: z.string().describe('The recipient Varnir IDENTITY (not an L1 address).'),
|
|
204
|
+
chain: z.string().describe("Which chain's pooled balance to move."),
|
|
205
|
+
amount: z.string().describe("Human decimal amount, as a STRING, e.g. '12.5' - not a JS number."),
|
|
206
|
+
token: z.string().optional().describe("The token's L1 contract address; omit for the native asset.") }, async (a) => {
|
|
207
|
+
const t = await client.transferOnLedger({
|
|
208
|
+
to: a.to, chain: a.chain,
|
|
209
|
+
amount: a.amount, token: a.token,
|
|
210
|
+
});
|
|
211
|
+
// Mirrors send(): a treasury-gated transfer succeeds without moving
|
|
212
|
+
// anything and comes back carrying a proposal instead of throwing.
|
|
213
|
+
if (t.proposal) {
|
|
214
|
+
return {
|
|
215
|
+
status: 'awaiting_cosign', umid: t.umid, proposal: t.proposal,
|
|
216
|
+
message: 'The transfer was recorded but NO MONEY HAS MOVED. It is over this key\'s co-sign threshold or a treasury limit, so it is held as a proposal until a co-signing key confirms it. Tell the user their funds have NOT moved and that approval is needed.',
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
return { status: 'ok', umid: t.umid };
|
|
220
|
+
}),
|
|
221
|
+
];
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@varnir/agent-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Self-hosted Varnir agent server: MCP tools and an off-by-default REST API over a policy-scoped agent key.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Varnir/varnir.git",
|
|
9
|
+
"directory": "apps/agent-server"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"bin": {
|
|
14
|
+
"varnir-agent-server": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
24
|
+
"express": "^4.21.2",
|
|
25
|
+
"zod": "^3.24.1",
|
|
26
|
+
"@varnir/chain-client": "0.2.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/express": "^4.17.21",
|
|
30
|
+
"@types/node": "^22.0.0",
|
|
31
|
+
"tsx": "^4.19.2",
|
|
32
|
+
"typescript": "^5.7.2",
|
|
33
|
+
"@varnir/tsconfig": "0.1.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=20.19.4"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc -p tsconfig.json",
|
|
40
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
41
|
+
"lint": "echo \"no lint configured yet\"",
|
|
42
|
+
"clean": "rm -rf dist",
|
|
43
|
+
"start": "node dist/index.js",
|
|
44
|
+
"test": "tsx test/config.test.ts && tsx test/key-match.test.ts && tsx test/guard.test.ts && tsx test/tool-error.test.ts && tsx test/tools-read.test.ts && tsx test/tools-write.test.ts && tsx test/rest.test.ts && tsx test/rest-methods.test.ts && tsx test/mcp-http.test.ts",
|
|
45
|
+
"test:e2e": "tsx test/e2e.ts"
|
|
46
|
+
}
|
|
47
|
+
}
|