@hol-org/hashnet-mcp 1.0.17 → 1.0.19
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/README.md +3 -4
- package/dist/index.js +160 -115
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -93,7 +93,7 @@ Use `"type": "sse"` if your build expects it.
|
|
|
93
93
|
Categories are exposed as MCP tools (`hol.*`) plus workflows (`workflow.*`):
|
|
94
94
|
- **Discovery**: `hol.search`, `hol.vectorSearch`, `hol.registrySearchByNamespace`, `hol.resolveUaid`
|
|
95
95
|
- **Registration**: `hol.getRegistrationQuote`, `hol.registerAgent`, `hol.waitForRegistrationCompletion`, `hol.updateAgent`
|
|
96
|
-
- **Chat**: `hol.chat.createSession` (uaid
|
|
96
|
+
- **Chat**: `hol.chat.createSession` (uaid), `hol.chat.sendMessage` (sessionId or uaid; auto-creates session), `hol.chat.history`, `hol.chat.compact`, `hol.chat.end`, `hol.closeUaidConnection`
|
|
97
97
|
- **Protocols/Ops**: `hol.listProtocols`, `hol.detectProtocol`, `hol.stats`, `hol.metricsSummary`, `hol.dashboardStats`, `hol.websocketStats`
|
|
98
98
|
- **Credits**: `hol.credits.balance`, `hol.purchaseCredits.hbar`, `hol.x402.minimums`, `hol.x402.buyCredits`
|
|
99
99
|
- **Ledger**: `hol.ledger.challenge`, `hol.ledger.authenticate`
|
|
@@ -122,8 +122,8 @@ Categories are exposed as MCP tools (`hol.*`) plus workflows (`workflow.*`):
|
|
|
122
122
|
- `hol.additionalRegistries` — catalog of additional registries/networks.
|
|
123
123
|
|
|
124
124
|
**Chat**
|
|
125
|
-
- `hol.chat.createSession` — open a session by `uaid
|
|
126
|
-
- `hol.chat.sendMessage` — send to an existing sessionId or auto-create via `uaid
|
|
125
|
+
- `hol.chat.createSession` — open a session by `uaid`.
|
|
126
|
+
- `hol.chat.sendMessage` — send to an existing sessionId or auto-create via `uaid`.
|
|
127
127
|
- `hol.chat.history` / `hol.chat.compact` / `hol.chat.end` — manage chat lifecycle.
|
|
128
128
|
|
|
129
129
|
**Protocols / Ops**
|
|
@@ -163,4 +163,3 @@ Set in `.env` or your process:
|
|
|
163
163
|
## Logging & observability
|
|
164
164
|
- `pino` structured logs; set `LOG_LEVEL=fatal|error|warn|info|debug|trace`.
|
|
165
165
|
- Each tool call logs requestId + duration. SSE/HTTP transport logs requests. Credits/registration calls surface broker status/body on failure.
|
|
166
|
-
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,7 @@ import { PassThrough } from "stream";
|
|
|
5
5
|
|
|
6
6
|
// src/mcp.ts
|
|
7
7
|
import { randomUUID } from "crypto";
|
|
8
|
-
import {
|
|
9
|
-
RegistryBrokerError as RegistryBrokerError3
|
|
10
|
-
} from "@hashgraphonline/standards-sdk";
|
|
8
|
+
import { RegistryBrokerError as RegistryBrokerError3 } from "@hashgraphonline/standards-sdk";
|
|
11
9
|
import { FastMCP } from "fastmcp";
|
|
12
10
|
import { z as z3 } from "zod";
|
|
13
11
|
|
|
@@ -126,26 +124,15 @@ var broker = new RegistryBrokerClient({
|
|
|
126
124
|
var brokerLimiter = createLimiter();
|
|
127
125
|
function createLimiter() {
|
|
128
126
|
if (!config.rateLimit) return void 0;
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
if (config.rateLimit.reservoirRefreshAmount !== void 0) {
|
|
140
|
-
limiterOptions.reservoirRefreshAmount = config.rateLimit.reservoirRefreshAmount;
|
|
141
|
-
}
|
|
142
|
-
if (config.rateLimit.reservoirRefreshIntervalMs !== void 0) {
|
|
143
|
-
limiterOptions.reservoirRefreshInterval = config.rateLimit.reservoirRefreshIntervalMs;
|
|
144
|
-
}
|
|
145
|
-
if (config.rateLimit.redis?.url) {
|
|
146
|
-
limiterOptions.datastore = "ioredis";
|
|
147
|
-
limiterOptions.connection = new IORedis(config.rateLimit.redis.url);
|
|
148
|
-
}
|
|
127
|
+
const redisClient = config.rateLimit.redis?.url ? new IORedis(config.rateLimit.redis.url) : void 0;
|
|
128
|
+
const limiterOptions = {
|
|
129
|
+
...config.rateLimit.maxConcurrent !== void 0 ? { maxConcurrent: config.rateLimit.maxConcurrent } : {},
|
|
130
|
+
...config.rateLimit.minTimeMs !== void 0 ? { minTime: config.rateLimit.minTimeMs } : {},
|
|
131
|
+
...config.rateLimit.reservoir !== void 0 ? { reservoir: config.rateLimit.reservoir } : {},
|
|
132
|
+
...config.rateLimit.reservoirRefreshAmount !== void 0 ? { reservoirRefreshAmount: config.rateLimit.reservoirRefreshAmount } : {},
|
|
133
|
+
...config.rateLimit.reservoirRefreshIntervalMs !== void 0 ? { reservoirRefreshInterval: config.rateLimit.reservoirRefreshIntervalMs } : {},
|
|
134
|
+
...redisClient ? { datastore: "ioredis", connection: redisClient } : {}
|
|
135
|
+
};
|
|
149
136
|
if (!limiterOptions.maxConcurrent && !limiterOptions.minTime && !limiterOptions.reservoir && !limiterOptions.datastore) {
|
|
150
137
|
return void 0;
|
|
151
138
|
}
|
|
@@ -153,8 +140,7 @@ function createLimiter() {
|
|
|
153
140
|
}
|
|
154
141
|
async function withBroker(task, label) {
|
|
155
142
|
const run = async () => {
|
|
156
|
-
|
|
157
|
-
if (!config.registryBrokerApiKey && !isLocal) {
|
|
143
|
+
if (!config.registryBrokerApiKey) {
|
|
158
144
|
throw new Error("REGISTRY_BROKER_API_KEY is required to call the registry broker. Set it in your environment or .env file.");
|
|
159
145
|
}
|
|
160
146
|
try {
|
|
@@ -434,7 +420,7 @@ var InsufficientCreditsError = class extends Error {
|
|
|
434
420
|
super(message);
|
|
435
421
|
this.name = "InsufficientCreditsError";
|
|
436
422
|
this.summary = {
|
|
437
|
-
requiredCredits: quote.requiredCredits,
|
|
423
|
+
requiredCredits: quote.requiredCredits ?? 0,
|
|
438
424
|
availableCredits: quote.availableCredits ?? 0,
|
|
439
425
|
shortfallCredits: shortfall,
|
|
440
426
|
estimatedHbar: quote.estimatedHbar,
|
|
@@ -503,7 +489,7 @@ var registrationDefinition = {
|
|
|
503
489
|
run: async ({ context }) => {
|
|
504
490
|
const response = await runCreditAwareRegistration({
|
|
505
491
|
payload: context.payload,
|
|
506
|
-
onShortfall:
|
|
492
|
+
onShortfall: (err) => {
|
|
507
493
|
context.quote = err.summary;
|
|
508
494
|
return "abort";
|
|
509
495
|
}
|
|
@@ -527,8 +513,12 @@ var registrationDefinition = {
|
|
|
527
513
|
timeoutMs: 5 * 6e4
|
|
528
514
|
})
|
|
529
515
|
);
|
|
530
|
-
if (result
|
|
531
|
-
|
|
516
|
+
if (result && typeof result === "object" && "result" in result) {
|
|
517
|
+
const progress = result;
|
|
518
|
+
const maybeUaid = progress.result?.uaid;
|
|
519
|
+
if (typeof maybeUaid === "string") {
|
|
520
|
+
context.uaid = maybeUaid;
|
|
521
|
+
}
|
|
532
522
|
}
|
|
533
523
|
return result;
|
|
534
524
|
}
|
|
@@ -739,12 +729,6 @@ var openRouterChatDefinition = {
|
|
|
739
729
|
throw new Error(`Model ${input.modelId} not found in registry ${input.registry ?? "openrouter"}`);
|
|
740
730
|
}
|
|
741
731
|
context.uaid = result.hits[0].uaid;
|
|
742
|
-
const endpoints = result.hits[0].endpoints;
|
|
743
|
-
if (Array.isArray(endpoints)) {
|
|
744
|
-
context.agentUrl = endpoints.find((endpoint) => typeof endpoint === "string" && endpoint.length > 0);
|
|
745
|
-
} else if (endpoints && typeof endpoints === "object") {
|
|
746
|
-
context.agentUrl = Object.values(endpoints).find((value) => typeof value === "string" && value.length > 0);
|
|
747
|
-
}
|
|
748
732
|
return result.hits[0];
|
|
749
733
|
}
|
|
750
734
|
},
|
|
@@ -756,7 +740,6 @@ var openRouterChatDefinition = {
|
|
|
756
740
|
const response = await withBroker(
|
|
757
741
|
(client) => client.chat.createSession({
|
|
758
742
|
uaid: context.uaid,
|
|
759
|
-
agentUrl: context.agentUrl,
|
|
760
743
|
historyTtlSeconds: input.historyTtlSeconds ?? 900,
|
|
761
744
|
auth
|
|
762
745
|
})
|
|
@@ -771,7 +754,7 @@ var openRouterChatDefinition = {
|
|
|
771
754
|
if (!context.sessionId) throw new Error("Missing chat session");
|
|
772
755
|
const auth = input.authToken ? { type: "bearer", token: input.authToken } : void 0;
|
|
773
756
|
return withBroker(
|
|
774
|
-
(client) => client.chat.sendMessage({ sessionId: context.sessionId, auth, message: input.message
|
|
757
|
+
(client) => client.chat.sendMessage({ sessionId: context.sessionId, auth, message: input.message })
|
|
775
758
|
);
|
|
776
759
|
}
|
|
777
760
|
},
|
|
@@ -883,7 +866,9 @@ var registryShowcaseDefinition = {
|
|
|
883
866
|
name: "hol.getRegistrationQuote",
|
|
884
867
|
skip: ({ input }) => !input.performCreditCheck,
|
|
885
868
|
run: async ({ context }) => {
|
|
886
|
-
const
|
|
869
|
+
const discoveryRecord = context.discovery && typeof context.discovery === "object" ? context.discovery : null;
|
|
870
|
+
const payload = discoveryRecord?.context?.registrationPayload ?? context.discovery;
|
|
871
|
+
const response = await withBroker((client) => client.getRegistrationQuote(payload));
|
|
887
872
|
context.creditQuote = response;
|
|
888
873
|
return response;
|
|
889
874
|
}
|
|
@@ -998,14 +983,18 @@ var registerAgentAdvancedDefinition = {
|
|
|
998
983
|
name: "hol.getAdditionalRegistries",
|
|
999
984
|
allowDuringDryRun: true,
|
|
1000
985
|
skip: ({ input }) => !input.additionalRegistrySelections?.length && !input.updateAdditionalRegistries?.length,
|
|
1001
|
-
run: async (
|
|
986
|
+
run: async ({ context }) => {
|
|
987
|
+
const catalog = await withBroker((client) => client.getAdditionalRegistries());
|
|
988
|
+
context.catalog = catalog;
|
|
989
|
+
return catalog;
|
|
990
|
+
}
|
|
1002
991
|
},
|
|
1003
992
|
{
|
|
1004
993
|
name: "workflow.resolveAdditionalRegistries",
|
|
1005
994
|
allowDuringDryRun: true,
|
|
1006
|
-
run: async ({ input, context }
|
|
1007
|
-
|
|
1008
|
-
|
|
995
|
+
run: async ({ input, context }) => {
|
|
996
|
+
const catalog = context.catalog;
|
|
997
|
+
if (!catalog) return null;
|
|
1009
998
|
const selections = input.additionalRegistrySelections ?? [];
|
|
1010
999
|
const { resolved, missing } = resolveAdditionalSelections(selections, catalog);
|
|
1011
1000
|
context.resolvedRegistries = resolved;
|
|
@@ -1029,12 +1018,12 @@ var registerAgentAdvancedDefinition = {
|
|
|
1029
1018
|
run: async ({ input, context }) => {
|
|
1030
1019
|
const response = await runCreditAwareRegistration({
|
|
1031
1020
|
payload: context.payload,
|
|
1032
|
-
onShortfall: async (
|
|
1033
|
-
context.lastQuote = summary;
|
|
1021
|
+
onShortfall: async (err) => {
|
|
1022
|
+
context.lastQuote = err.summary;
|
|
1034
1023
|
if (!input.creditTopUp) {
|
|
1035
1024
|
return "abort";
|
|
1036
1025
|
}
|
|
1037
|
-
await purchaseCreditsWithHbar(input.creditTopUp, summary);
|
|
1026
|
+
await purchaseCreditsWithHbar(input.creditTopUp, err.summary);
|
|
1038
1027
|
return "retry";
|
|
1039
1028
|
}
|
|
1040
1029
|
});
|
|
@@ -1054,8 +1043,12 @@ var registerAgentAdvancedDefinition = {
|
|
|
1054
1043
|
if (!context.attemptId) throw new Error("Registration attemptId missing.");
|
|
1055
1044
|
const result = await waitForRegistrationCompletion(context.attemptId);
|
|
1056
1045
|
context.progress = result;
|
|
1057
|
-
if (result
|
|
1058
|
-
|
|
1046
|
+
if (result && typeof result === "object" && "result" in result) {
|
|
1047
|
+
const progress = result;
|
|
1048
|
+
const maybeUaid = progress.result?.uaid;
|
|
1049
|
+
if (typeof maybeUaid === "string") {
|
|
1050
|
+
context.uaid = maybeUaid;
|
|
1051
|
+
}
|
|
1059
1052
|
}
|
|
1060
1053
|
return result;
|
|
1061
1054
|
}
|
|
@@ -1079,6 +1072,9 @@ var registerAgentAdvancedDefinition = {
|
|
|
1079
1072
|
};
|
|
1080
1073
|
var registerAgentAdvancedPipeline = scaffoldWorkflow(registerAgentAdvancedDefinition);
|
|
1081
1074
|
function resolveAdditionalSelections(selections, catalog) {
|
|
1075
|
+
if (!catalog.registries || catalog.registries.length === 0) {
|
|
1076
|
+
return { resolved: [], missing: selections };
|
|
1077
|
+
}
|
|
1082
1078
|
const resolved = /* @__PURE__ */ new Set();
|
|
1083
1079
|
const missing = [];
|
|
1084
1080
|
for (const selection of selections) {
|
|
@@ -1095,13 +1091,20 @@ function collectMatches(selection, catalog) {
|
|
|
1095
1091
|
const target = selection.trim().toLowerCase();
|
|
1096
1092
|
if (!target) return [];
|
|
1097
1093
|
const matches = [];
|
|
1098
|
-
for (const registry of catalog.registries) {
|
|
1099
|
-
const registryId = registry.id
|
|
1094
|
+
for (const registry of catalog.registries ?? []) {
|
|
1095
|
+
const registryId = registry.id?.toLowerCase();
|
|
1096
|
+
const networks = registry.networks ?? [];
|
|
1097
|
+
if (!registryId || networks.length === 0) continue;
|
|
1100
1098
|
if (registryId === target) {
|
|
1101
|
-
|
|
1099
|
+
networks.forEach((network) => {
|
|
1100
|
+
if (network?.key) {
|
|
1101
|
+
matches.push(network.key);
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1102
1104
|
continue;
|
|
1103
1105
|
}
|
|
1104
|
-
for (const network of
|
|
1106
|
+
for (const network of networks) {
|
|
1107
|
+
if (!network?.key) continue;
|
|
1105
1108
|
const keyLower = network.key.toLowerCase();
|
|
1106
1109
|
const networkIdLower = network.networkId?.toLowerCase();
|
|
1107
1110
|
const labelLower = network.label?.toLowerCase();
|
|
@@ -1140,13 +1143,22 @@ var registerAgentErc8004Definition = {
|
|
|
1140
1143
|
{
|
|
1141
1144
|
name: "hol.getAdditionalRegistries",
|
|
1142
1145
|
allowDuringDryRun: true,
|
|
1143
|
-
run: async (
|
|
1146
|
+
run: async ({ context }) => {
|
|
1147
|
+
const catalog = await withBroker((client) => client.getAdditionalRegistries());
|
|
1148
|
+
context.catalog = catalog;
|
|
1149
|
+
return catalog;
|
|
1150
|
+
}
|
|
1144
1151
|
},
|
|
1145
1152
|
{
|
|
1146
1153
|
name: "workflow.erc8004.resolveNetworks",
|
|
1147
1154
|
allowDuringDryRun: true,
|
|
1148
|
-
run: async ({ input, context }
|
|
1149
|
-
const response = catalog;
|
|
1155
|
+
run: async ({ input, context }) => {
|
|
1156
|
+
const response = context.catalog;
|
|
1157
|
+
if (!response) {
|
|
1158
|
+
context.resolvedNetworks = [];
|
|
1159
|
+
context.missingNetworks = [];
|
|
1160
|
+
return { resolved: [], missing: [] };
|
|
1161
|
+
}
|
|
1150
1162
|
const selections = input.erc8004Networks?.length ? input.erc8004Networks : defaultErc8004Selections(response);
|
|
1151
1163
|
const { resolved, missing } = resolveErc8004Selections(selections, response);
|
|
1152
1164
|
context.resolvedNetworks = resolved;
|
|
@@ -1178,18 +1190,26 @@ var registerAgentErc8004Definition = {
|
|
|
1178
1190
|
};
|
|
1179
1191
|
var registerAgentErc8004Pipeline = scaffoldWorkflow(registerAgentErc8004Definition);
|
|
1180
1192
|
function resolveErc8004Selections(selections, catalog) {
|
|
1193
|
+
if (!catalog.registries || catalog.registries.length === 0) {
|
|
1194
|
+
return { resolved: [], missing: selections };
|
|
1195
|
+
}
|
|
1181
1196
|
const resolved = /* @__PURE__ */ new Set();
|
|
1182
1197
|
const missing = [];
|
|
1183
1198
|
selections.forEach((entry) => {
|
|
1184
1199
|
const normalized2 = entry.trim().toLowerCase();
|
|
1185
1200
|
if (!normalized2) return;
|
|
1186
1201
|
let matched = false;
|
|
1187
|
-
for (const descriptor of catalog.registries) {
|
|
1188
|
-
|
|
1189
|
-
|
|
1202
|
+
for (const descriptor of catalog.registries ?? []) {
|
|
1203
|
+
const descriptorId = descriptor.id?.toLowerCase();
|
|
1204
|
+
const networks = descriptor.networks ?? [];
|
|
1205
|
+
if (!descriptorId || !descriptorId.startsWith("erc-8004")) continue;
|
|
1206
|
+
for (const network of networks) {
|
|
1207
|
+
if (!network) continue;
|
|
1190
1208
|
const candidates = [network.key, network.networkId, network.label, network.name].map((value) => value?.toLowerCase().trim()).filter(Boolean);
|
|
1191
|
-
if (candidates.includes(normalized2) || `${
|
|
1192
|
-
|
|
1209
|
+
if (candidates.includes(normalized2) || `${descriptorId}:${network.networkId?.toLowerCase()}` === normalized2) {
|
|
1210
|
+
if (network.key) {
|
|
1211
|
+
resolved.add(network.key);
|
|
1212
|
+
}
|
|
1193
1213
|
matched = true;
|
|
1194
1214
|
}
|
|
1195
1215
|
}
|
|
@@ -1201,9 +1221,9 @@ function resolveErc8004Selections(selections, catalog) {
|
|
|
1201
1221
|
return { resolved: Array.from(resolved), missing };
|
|
1202
1222
|
}
|
|
1203
1223
|
function defaultErc8004Selections(catalog) {
|
|
1204
|
-
const defaults = catalog.registries
|
|
1205
|
-
if (!defaults) return [];
|
|
1206
|
-
return defaults.networks.map((network) => network.key);
|
|
1224
|
+
const defaults = catalog.registries?.find((entry) => entry.id?.toLowerCase() === "erc-8004");
|
|
1225
|
+
if (!defaults || !defaults.networks) return [];
|
|
1226
|
+
return defaults.networks.map((network) => network?.key).filter((key) => Boolean(key));
|
|
1207
1227
|
}
|
|
1208
1228
|
function withAdditionalRegistries(payload, networks) {
|
|
1209
1229
|
if (networks.length === 0) return payload;
|
|
@@ -1346,7 +1366,7 @@ var connectionInstructions = [
|
|
|
1346
1366
|
"You expose the Hashgraph Online Registry Broker via hol.* primitives and workflow.* pipelines. Prefer workflow.* when possible\u2014they bundle common steps and return a pipeline summary plus full results.",
|
|
1347
1367
|
"Discovery: use workflow.discovery (or hol.search / hol.vectorSearch) to find UAIDs/agents/MCP servers; pass q/query and optional filters like capabilities, metadata, or type=ai-agents|mcp-servers.",
|
|
1348
1368
|
"Registration: workflow.registerMcp (quote \u2192 register \u2192 wait) is the default; workflow.fullRegistration adds discovery/chat/ops. hol.registerAgent + hol.waitForRegistrationCompletion are the lower-level primitives.",
|
|
1349
|
-
"Chat: call hol.resolveUaid if the UAID is unverified, then hol.chat.createSession (uaid
|
|
1369
|
+
"Chat: call hol.resolveUaid if the UAID is unverified, then hol.chat.createSession (uaid + optional auth) followed by hol.chat.sendMessage (sessionId or uaid). Use hol.chat.history/compact/end to manage the session.",
|
|
1350
1370
|
"Operations: workflow.opsCheck or hol.stats/hol.metricsSummary/hol.dashboardStats show registry health; hol.listProtocols + hol.detectProtocol help route third-party requests.",
|
|
1351
1371
|
"Credits: check hol.credits.balance before purchases. Use hol.purchaseCredits.hbar or hol.x402.buyCredits only with explicit user approval (X402 requires an EVM key); hol.x402.minimums provides thresholds.",
|
|
1352
1372
|
"Always include UAIDs/sessionIds exactly as given and echo any auth headers/tokens the user supplies. If required fields are missing (UAID, payload, accountId), ask for them before calling tools.",
|
|
@@ -1362,25 +1382,21 @@ var agentAuthSchema = z3.object({
|
|
|
1362
1382
|
headers: z3.record(z3.string(), z3.string()).optional()
|
|
1363
1383
|
}).partial();
|
|
1364
1384
|
var chatSessionSchema = z3.object({
|
|
1365
|
-
uaid: z3.string().min(1)
|
|
1366
|
-
agentUrl: z3.string().url().optional(),
|
|
1385
|
+
uaid: z3.string().min(1),
|
|
1367
1386
|
historyTtlSeconds: z3.number().int().positive().optional(),
|
|
1368
|
-
auth: agentAuthSchema.optional()
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
ctx.addIssue({ code: z3.ZodIssueCode.custom, message: "uaid or agentUrl is required" });
|
|
1372
|
-
}
|
|
1387
|
+
auth: agentAuthSchema.optional(),
|
|
1388
|
+
senderUaid: z3.string().min(1).optional(),
|
|
1389
|
+
encryptionRequested: z3.boolean().optional()
|
|
1373
1390
|
});
|
|
1374
1391
|
var chatMessageSchema = z3.object({
|
|
1375
1392
|
sessionId: z3.string().min(1).optional(),
|
|
1376
1393
|
uaid: z3.string().min(1).optional(),
|
|
1377
|
-
agentUrl: z3.string().url().optional(),
|
|
1378
1394
|
message: z3.string().min(1),
|
|
1379
1395
|
streaming: z3.boolean().optional(),
|
|
1380
1396
|
auth: agentAuthSchema.optional()
|
|
1381
1397
|
}).superRefine((value, ctx) => {
|
|
1382
|
-
if (!value.sessionId && !value.uaid
|
|
1383
|
-
ctx.addIssue({ code: z3.ZodIssueCode.custom, message: "Provide sessionId for existing chats or uaid
|
|
1398
|
+
if (!value.sessionId && !value.uaid) {
|
|
1399
|
+
ctx.addIssue({ code: z3.ZodIssueCode.custom, message: "Provide sessionId for existing chats or uaid to start a new one." });
|
|
1384
1400
|
}
|
|
1385
1401
|
});
|
|
1386
1402
|
var chatCompactSchema = z3.object({
|
|
@@ -1426,6 +1442,49 @@ var workflowFullInput = z3.object({
|
|
|
1426
1442
|
discoveryQuery: z3.string().optional(),
|
|
1427
1443
|
chatMessage: z3.string().optional()
|
|
1428
1444
|
});
|
|
1445
|
+
var openRouterChatToolSchema = z3.object({
|
|
1446
|
+
modelId: z3.string().min(1),
|
|
1447
|
+
registry: z3.string().optional(),
|
|
1448
|
+
message: z3.string(),
|
|
1449
|
+
authToken: z3.string().optional()
|
|
1450
|
+
});
|
|
1451
|
+
var registryShowcaseToolSchema = z3.object({
|
|
1452
|
+
query: z3.string().optional(),
|
|
1453
|
+
uaid: z3.string().optional(),
|
|
1454
|
+
message: z3.string().optional(),
|
|
1455
|
+
performCreditCheck: z3.boolean().optional()
|
|
1456
|
+
});
|
|
1457
|
+
var erc8004DiscoveryToolSchema = z3.object({ query: z3.string().optional(), limit: z3.number().int().positive().optional() });
|
|
1458
|
+
var bridgePayloadSchema = z3.object({
|
|
1459
|
+
uaid: z3.string().min(1),
|
|
1460
|
+
agentverseUaid: z3.string().min(1),
|
|
1461
|
+
localMessage: z3.string().min(1),
|
|
1462
|
+
agentverseMessage: z3.string().min(1),
|
|
1463
|
+
iterations: z3.number().int().positive().optional()
|
|
1464
|
+
});
|
|
1465
|
+
var erc8004X402ToolSchema = z3.object({
|
|
1466
|
+
payload: agentRegistrationSchema,
|
|
1467
|
+
erc8004Networks: z3.array(z3.string()).optional(),
|
|
1468
|
+
chatMessage: z3.string().optional()
|
|
1469
|
+
});
|
|
1470
|
+
var x402RegistrationToolSchema = z3.object({
|
|
1471
|
+
payload: agentRegistrationSchema,
|
|
1472
|
+
x402: z3.object({
|
|
1473
|
+
accountId: z3.string().min(1),
|
|
1474
|
+
credits: z3.number().positive(),
|
|
1475
|
+
evmPrivateKey: z3.string().min(1),
|
|
1476
|
+
ledgerVerification: z3.object({
|
|
1477
|
+
challengeId: z3.string().min(1),
|
|
1478
|
+
accountId: z3.string().min(1),
|
|
1479
|
+
network: z3.enum(["mainnet", "testnet"]),
|
|
1480
|
+
signature: z3.string().min(1),
|
|
1481
|
+
signatureKind: z3.enum(["raw", "map"]).optional(),
|
|
1482
|
+
publicKey: z3.string().optional(),
|
|
1483
|
+
expiresInMinutes: z3.number().int().positive().optional()
|
|
1484
|
+
}).optional()
|
|
1485
|
+
}),
|
|
1486
|
+
chatMessage: z3.string().optional()
|
|
1487
|
+
});
|
|
1429
1488
|
var waitForRegistrationInput = z3.object({
|
|
1430
1489
|
attemptId: z3.string(),
|
|
1431
1490
|
intervalMs: z3.number().int().positive().default(2e3),
|
|
@@ -1483,7 +1542,6 @@ var buyX402Input = z3.object({
|
|
|
1483
1542
|
var mcp = new FastMCP({
|
|
1484
1543
|
name: "hashgraph-standards",
|
|
1485
1544
|
version: "1.0.0",
|
|
1486
|
-
description: "MCP tools exposing Hashgraph Online Registry Broker via standards-sdk",
|
|
1487
1545
|
instructions: connectionInstructions,
|
|
1488
1546
|
// Route FastMCP logging to our pino logger (stderr) to keep stdio transport clean.
|
|
1489
1547
|
logger: {
|
|
@@ -1494,7 +1552,7 @@ var mcp = new FastMCP({
|
|
|
1494
1552
|
log: (...args) => logger.info(args)
|
|
1495
1553
|
}
|
|
1496
1554
|
});
|
|
1497
|
-
var
|
|
1555
|
+
var rawToolDefinitions = [
|
|
1498
1556
|
{
|
|
1499
1557
|
name: "hol.search",
|
|
1500
1558
|
description: "Keyword search for agents or MCP servers with filtering controls.",
|
|
@@ -1579,29 +1637,26 @@ var toolDefinitions = [
|
|
|
1579
1637
|
description: "Send a message to an active chat session.",
|
|
1580
1638
|
schema: chatMessageSchema,
|
|
1581
1639
|
handler: (input) => withBroker(async (client) => {
|
|
1582
|
-
|
|
1583
|
-
|
|
1640
|
+
const { sessionId, uaid, message, auth, streaming } = input;
|
|
1641
|
+
if (sessionId) {
|
|
1642
|
+
const payload2 = { sessionId, message, auth, streaming };
|
|
1643
|
+
return client.chat.sendMessage(payload2);
|
|
1584
1644
|
}
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
if (!uaid && !agentUrl) {
|
|
1588
|
-
throw new Error("sessionId missing; provide uaid or agentUrl so a session can be created before sending.");
|
|
1645
|
+
if (!uaid) {
|
|
1646
|
+
throw new Error("sessionId missing; provide uaid so a session can be created before sending.");
|
|
1589
1647
|
}
|
|
1590
|
-
const session = await client.chat.createSession({
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
auth: input.auth
|
|
1594
|
-
});
|
|
1595
|
-
const sessionId = session.sessionId ?? session.id;
|
|
1596
|
-
if (!sessionId) {
|
|
1648
|
+
const session = await client.chat.createSession({ uaid, auth });
|
|
1649
|
+
const derivedSessionId = session.sessionId;
|
|
1650
|
+
if (!derivedSessionId) {
|
|
1597
1651
|
throw new Error("Unable to determine sessionId from broker response when auto-creating chat session.");
|
|
1598
1652
|
}
|
|
1599
|
-
|
|
1600
|
-
sessionId,
|
|
1601
|
-
message
|
|
1602
|
-
auth
|
|
1603
|
-
streaming
|
|
1604
|
-
}
|
|
1653
|
+
const payload = {
|
|
1654
|
+
sessionId: derivedSessionId,
|
|
1655
|
+
message,
|
|
1656
|
+
auth,
|
|
1657
|
+
streaming
|
|
1658
|
+
};
|
|
1659
|
+
return client.chat.sendMessage(payload);
|
|
1605
1660
|
}, "hol.chat.sendMessage")
|
|
1606
1661
|
},
|
|
1607
1662
|
{
|
|
@@ -1733,50 +1788,37 @@ var toolDefinitions = [
|
|
|
1733
1788
|
{
|
|
1734
1789
|
name: "workflow.openrouterChat",
|
|
1735
1790
|
description: "Pipeline: discover OpenRouter model and run a chat message",
|
|
1736
|
-
schema:
|
|
1791
|
+
schema: openRouterChatToolSchema,
|
|
1737
1792
|
handler: async (input) => formatPipelineResult(await openRouterChatWorkflow.run(input))
|
|
1738
1793
|
},
|
|
1739
1794
|
{
|
|
1740
1795
|
name: "workflow.registryBrokerShowcase",
|
|
1741
1796
|
description: "Pipeline: discovery, analytics, UAID validation, chat",
|
|
1742
|
-
schema:
|
|
1797
|
+
schema: registryShowcaseToolSchema,
|
|
1743
1798
|
handler: async (input) => formatPipelineResult(await registryBrokerShowcaseWorkflow.run(input))
|
|
1744
1799
|
},
|
|
1745
1800
|
{
|
|
1746
1801
|
name: "workflow.agentverseBridge",
|
|
1747
1802
|
description: "Pipeline: relay chat between local UAID and Agentverse UAID",
|
|
1748
|
-
schema:
|
|
1749
|
-
uaid: z3.string().min(1),
|
|
1750
|
-
agentverseUaid: z3.string().min(1),
|
|
1751
|
-
localMessage: z3.string().min(1),
|
|
1752
|
-
agentverseMessage: z3.string().min(1),
|
|
1753
|
-
iterations: z3.number().int().positive().optional()
|
|
1754
|
-
}),
|
|
1803
|
+
schema: bridgePayloadSchema,
|
|
1755
1804
|
handler: async (input) => formatPipelineResult(await agentverseBridgeWorkflow.run(input))
|
|
1756
1805
|
},
|
|
1757
1806
|
{
|
|
1758
1807
|
name: "workflow.erc8004Discovery",
|
|
1759
1808
|
description: "Pipeline: search ERC-8004 registries",
|
|
1760
|
-
schema:
|
|
1809
|
+
schema: erc8004DiscoveryToolSchema,
|
|
1761
1810
|
handler: async (input) => formatPipelineResult(await erc8004DiscoveryWorkflow.run(input))
|
|
1762
1811
|
},
|
|
1763
1812
|
{
|
|
1764
1813
|
name: "workflow.erc8004X402",
|
|
1765
1814
|
description: "Pipeline: ERC-8004 registration funded via X402 credits",
|
|
1766
|
-
schema:
|
|
1767
|
-
payload: agentRegistrationSchema,
|
|
1768
|
-
erc8004Networks: z3.array(z3.string()).optional(),
|
|
1769
|
-
chatMessage: z3.string().optional()
|
|
1770
|
-
}),
|
|
1815
|
+
schema: erc8004X402ToolSchema,
|
|
1771
1816
|
handler: async (input) => formatPipelineResult(await erc8004X402Workflow.run(input))
|
|
1772
1817
|
},
|
|
1773
1818
|
{
|
|
1774
1819
|
name: "workflow.x402Registration",
|
|
1775
1820
|
description: "Pipeline: register agent using X402 payments + chat smoke test",
|
|
1776
|
-
schema:
|
|
1777
|
-
payload: agentRegistrationSchema,
|
|
1778
|
-
chatMessage: z3.string().optional()
|
|
1779
|
-
}),
|
|
1821
|
+
schema: x402RegistrationToolSchema,
|
|
1780
1822
|
handler: async (input) => formatPipelineResult(await x402RegistrationWorkflow.run(input))
|
|
1781
1823
|
},
|
|
1782
1824
|
{
|
|
@@ -1786,11 +1828,14 @@ var toolDefinitions = [
|
|
|
1786
1828
|
handler: async (input) => formatPipelineResult(await fullWorkflowPipeline.run(input))
|
|
1787
1829
|
}
|
|
1788
1830
|
];
|
|
1831
|
+
var toolDefinitions = rawToolDefinitions;
|
|
1789
1832
|
function formatPipelineResult(result) {
|
|
1833
|
+
const contextRecord = result.context && typeof result.context === "object" ? result.context : {};
|
|
1834
|
+
const contextUaid = typeof contextRecord.uaid === "string" ? contextRecord.uaid : void 0;
|
|
1790
1835
|
const summaryLines = [
|
|
1791
1836
|
`Workflow: ${result.pipeline}`,
|
|
1792
1837
|
result.dryRun ? "(dry-run)" : void 0,
|
|
1793
|
-
|
|
1838
|
+
contextUaid ? `UAID: ${contextUaid}` : void 0,
|
|
1794
1839
|
`Steps executed: ${result.steps.length}`
|
|
1795
1840
|
].filter(Boolean);
|
|
1796
1841
|
return {
|
|
@@ -1941,7 +1986,7 @@ mcp.addResource({
|
|
|
1941
1986
|
"Prefer workflow.* pipelines when available\u2014they run multiple broker calls and return both a text summary and structured results:",
|
|
1942
1987
|
"- Discovery: workflow.discovery { query?, limit? } (or hol.search / hol.vectorSearch).",
|
|
1943
1988
|
"- Registration: workflow.registerMcp { payload } (quote \u2192 register \u2192 wait) or workflow.fullRegistration to add discovery/chat/ops.",
|
|
1944
|
-
"- Chat: hol.chat.createSession { uaid
|
|
1989
|
+
"- Chat: hol.chat.createSession { uaid, auth?, historyTtlSeconds? } \u2192 hol.chat.sendMessage { sessionId OR uaid, message, auth?, streaming? } \u2192 hol.chat.history/compact/end.",
|
|
1945
1990
|
"- UAID validation/resets: hol.resolveUaid { uaid }, hol.closeUaidConnection { uaid }.",
|
|
1946
1991
|
"- Ops/metrics: workflow.opsCheck or hol.stats / hol.metricsSummary / hol.dashboardStats.",
|
|
1947
1992
|
"- Credits: hol.credits.balance first, then hol.purchaseCredits.hbar or hol.x402.buyCredits (X402 requires evmPrivateKey; call hol.x402.minimums to inspect limits).",
|