@oobe-protocol-labs/sap-mcp-server 0.9.7 → 0.9.9
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/CHANGELOG.md +40 -0
- package/USER_DOCS/03_PAYMENTS_X402_PAYSH.md +6 -0
- package/USER_DOCS/04_CLIENT_CONFIGS.md +3 -3
- package/USER_DOCS/05_SKILLS_AND_TOOLS.md +17 -4
- package/USER_DOCS/06_DESKTOP_GUI_WIZARD.md +5 -5
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/payments/hosted-tool-eligibility.d.ts +21 -0
- package/dist/payments/hosted-tool-eligibility.d.ts.map +1 -0
- package/dist/payments/hosted-tool-eligibility.js +167 -0
- package/dist/payments/hosted-tool-eligibility.js.map +1 -0
- package/dist/payments/monetization-gate.d.ts.map +1 -1
- package/dist/payments/monetization-gate.js +6 -0
- package/dist/payments/monetization-gate.js.map +1 -1
- package/dist/payments/pricing.d.ts.map +1 -1
- package/dist/payments/pricing.js +2 -1
- package/dist/payments/pricing.js.map +1 -1
- package/dist/prompts/context/sap-agent-context.prompt.js +13 -8
- package/dist/prompts/context/sap-agent-context.prompt.js.map +1 -1
- package/dist/prompts/context/sap-agent-start.prompt.js +1 -0
- package/dist/prompts/context/sap-agent-start.prompt.js.map +1 -1
- package/dist/prompts/registry/register-sap-agent.prompt.js +2 -2
- package/dist/prompts/registry/register-sap-agent.prompt.js.map +1 -1
- package/dist/schemas/registry.schema.d.ts +2 -2
- package/dist/tools/agent-start-tool.js +3 -1
- package/dist/tools/agent-start-tool.js.map +1 -1
- package/dist/tools/client-sdk-tools.js +2 -2
- package/dist/tools/client-sdk-tools.js.map +1 -1
- package/dist/tools/sap-sdk-tools.d.ts.map +1 -1
- package/dist/tools/sap-sdk-tools.js +318 -89
- package/dist/tools/sap-sdk-tools.js.map +1 -1
- package/dist/tools/sap-sns-tools.d.ts +2 -2
- package/dist/tools/sap-sns-tools.js +6 -6
- package/dist/tools/sap-sns-tools.js.map +1 -1
- package/docs/06_PAYMENTS_X402_AND_PAYSH.md +7 -0
- package/docs/07_ENDPOINTS_AND_CLIENTS.md +1 -1
- package/docs/09_TOOLS_SKILLS_AND_AGENT_GUIDE.md +7 -0
- package/docs/14_DESKTOP_WIZARD_RELEASE.md +1 -1
- package/package.json +1 -1
- package/server.json +3 -3
- package/skills/README.md +4 -2
- package/skills/sap-agent-registry/SKILL.md +15 -2
- package/skills/sap-defi/SKILL.md +8 -4
- package/skills/sap-discovery-indexing/SKILL.md +15 -4
- package/skills/sap-mcp/SKILL.md +15 -3
- package/skills/sap-mcp/TOOL_REFERENCE.md +11 -5
- package/skills/sap-operations/SKILL.md +4 -3
- package/skills/sap-sns/SKILL.md +16 -11
|
@@ -147,6 +147,40 @@ function summarizeProtocolIndexes(protocolIndexes) {
|
|
|
147
147
|
}))
|
|
148
148
|
.sort((left, right) => left.protocolId.localeCompare(right.protocolId));
|
|
149
149
|
}
|
|
150
|
+
function normalizeDirectoryToken(value) {
|
|
151
|
+
return value.trim().toLowerCase();
|
|
152
|
+
}
|
|
153
|
+
function matchesNormalizedValue(values, expected) {
|
|
154
|
+
const normalizedExpected = normalizeDirectoryToken(expected);
|
|
155
|
+
return values.some((value) => normalizeDirectoryToken(value) === normalizedExpected);
|
|
156
|
+
}
|
|
157
|
+
function matchesNormalizedSubstring(values, query) {
|
|
158
|
+
return values.some((value) => normalizeDirectoryToken(value).includes(query));
|
|
159
|
+
}
|
|
160
|
+
function encodeDirectoryCursor(offset) {
|
|
161
|
+
return encodeDirectoryCursorPayload(offset);
|
|
162
|
+
}
|
|
163
|
+
function decodeDirectoryCursor(cursor) {
|
|
164
|
+
if (!cursor) {
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const parsed = decodeDirectoryCursorPayload(cursor);
|
|
169
|
+
const offset = parsed.offset;
|
|
170
|
+
return typeof offset === 'number' && Number.isInteger(offset) && offset >= 0 ? offset : undefined;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
throw new Error('cursor must be a nextCursor value returned by sap_list_all_agents or sap_discover_agents');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function encodeDirectoryCursorPayload(offset) {
|
|
177
|
+
const base64 = Buffer.from(JSON.stringify({ offset }), 'utf-8').toString('base64');
|
|
178
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/u, '');
|
|
179
|
+
}
|
|
180
|
+
function decodeDirectoryCursorPayload(cursor) {
|
|
181
|
+
const padded = cursor.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(cursor.length / 4) * 4, '=');
|
|
182
|
+
return JSON.parse(Buffer.from(padded, 'base64').toString('utf-8'));
|
|
183
|
+
}
|
|
150
184
|
/**
|
|
151
185
|
* @name buildAgentDirectoryEntry
|
|
152
186
|
* @description Converts an AgentAccount into a compact directory row with optional stats and protocol-index membership.
|
|
@@ -185,14 +219,257 @@ function matchesAgentDirectoryFilters(entry, filters) {
|
|
|
185
219
|
if (!filters.includeInactive && !entry.isActive) {
|
|
186
220
|
return false;
|
|
187
221
|
}
|
|
188
|
-
if (filters.
|
|
222
|
+
if (filters.wallet && normalizeDirectoryToken(entry.wallet) !== normalizeDirectoryToken(filters.wallet)) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
if (filters.agentPda && normalizeDirectoryToken(entry.agentPda) !== normalizeDirectoryToken(filters.agentPda)) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
if (filters.hasX402Endpoint !== undefined && Boolean(entry.x402Endpoint) !== filters.hasX402Endpoint) {
|
|
189
229
|
return false;
|
|
190
230
|
}
|
|
191
|
-
if (filters.
|
|
231
|
+
if (filters.protocol
|
|
232
|
+
&& !matchesNormalizedValue(entry.protocols, filters.protocol)
|
|
233
|
+
&& !matchesNormalizedValue(entry.indexedProtocols, filters.protocol)) {
|
|
192
234
|
return false;
|
|
193
235
|
}
|
|
236
|
+
const requiredCapabilities = [
|
|
237
|
+
...(filters.capability ? [filters.capability] : []),
|
|
238
|
+
...(filters.capabilities ?? []),
|
|
239
|
+
];
|
|
240
|
+
if (requiredCapabilities.length > 0) {
|
|
241
|
+
const mode = filters.capabilityMode ?? 'any';
|
|
242
|
+
const predicate = (capability) => matchesNormalizedValue(entry.capabilities, capability);
|
|
243
|
+
if (mode === 'all' ? !requiredCapabilities.every(predicate) : !requiredCapabilities.some(predicate)) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const query = filters.query ? normalizeDirectoryToken(filters.query) : undefined;
|
|
248
|
+
if (query) {
|
|
249
|
+
const searchableValues = [
|
|
250
|
+
entry.agentPda,
|
|
251
|
+
entry.wallet,
|
|
252
|
+
entry.name,
|
|
253
|
+
entry.description,
|
|
254
|
+
entry.agentId,
|
|
255
|
+
entry.agentUri,
|
|
256
|
+
entry.x402Endpoint,
|
|
257
|
+
...entry.protocols,
|
|
258
|
+
...entry.indexedProtocols,
|
|
259
|
+
...entry.capabilities,
|
|
260
|
+
...entry.activePlugins,
|
|
261
|
+
].filter((value) => typeof value === 'string');
|
|
262
|
+
if (!matchesNormalizedSubstring(searchableValues, query)) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
194
266
|
return true;
|
|
195
267
|
}
|
|
268
|
+
function compactAgentDirectoryEntry(entry) {
|
|
269
|
+
return {
|
|
270
|
+
agentPda: entry.agentPda,
|
|
271
|
+
wallet: entry.wallet,
|
|
272
|
+
name: entry.name,
|
|
273
|
+
description: entry.description,
|
|
274
|
+
agentId: entry.agentId,
|
|
275
|
+
x402Endpoint: entry.x402Endpoint,
|
|
276
|
+
isActive: entry.isActive,
|
|
277
|
+
protocols: entry.protocols,
|
|
278
|
+
indexedProtocols: entry.indexedProtocols,
|
|
279
|
+
capabilities: entry.capabilities,
|
|
280
|
+
reputationScore: entry.reputationScore,
|
|
281
|
+
totalCallsServed: entry.totalCallsServed,
|
|
282
|
+
uptimePercent: entry.uptimePercent,
|
|
283
|
+
createdAt: entry.createdAt,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function directoryAgentGuidance(page) {
|
|
287
|
+
return {
|
|
288
|
+
paidHostedRead: true,
|
|
289
|
+
useThisWhen: [
|
|
290
|
+
'The user asks to find SAP agents, list the ecosystem, inspect available on-chain agents, or discover x402-enabled agents.',
|
|
291
|
+
'Use query/protocol/capability/capabilities filters first; avoid repeated broad scans.',
|
|
292
|
+
],
|
|
293
|
+
pagination: page.hasMore
|
|
294
|
+
? `Call the same tool with cursor="${page.nextCursor}" to fetch the next page.`
|
|
295
|
+
: 'No further page is available for the current filters.',
|
|
296
|
+
nextTools: [
|
|
297
|
+
'sap_get_agent_profile with wallet for one hydrated owner profile.',
|
|
298
|
+
'sap_fetch_protocol_index with protocolId when the user wants protocol membership.',
|
|
299
|
+
'sap_fetch_capability_index with capabilityId when the user wants a capability-specific index.',
|
|
300
|
+
'sap_x402_estimate_cost before calling a paid x402 endpoint exposed by a discovered agent.',
|
|
301
|
+
],
|
|
302
|
+
matchingNotes: {
|
|
303
|
+
query: 'Matches name, description, agentId, wallet, PDA, endpoint, protocols, capabilities, and active plugin labels.',
|
|
304
|
+
capability: 'Capability matching is case-insensitive and exact after trimming. For multiple capabilities set capabilityMode to any or all.',
|
|
305
|
+
x402: 'Set hasX402Endpoint=true to find agents that advertise paid HTTP/x402 resources.',
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
async function buildAgentDirectoryPage(client, options) {
|
|
310
|
+
const accounts = getSapAnchorAccounts(client);
|
|
311
|
+
const [agentAccounts, statsAccounts, protocolIndexes, overview] = await Promise.all([
|
|
312
|
+
accounts.agentAccount.all(),
|
|
313
|
+
accounts.agentStats.all(),
|
|
314
|
+
accounts.protocolIndex.all(),
|
|
315
|
+
client.discovery.getNetworkOverview(),
|
|
316
|
+
]);
|
|
317
|
+
const statsByAgent = new Map(statsAccounts.map(({ account }) => [account.agent.toBase58(), account]));
|
|
318
|
+
const indexedProtocolsByAgent = buildProtocolMembership(protocolIndexes);
|
|
319
|
+
const filteredAgents = agentAccounts
|
|
320
|
+
.map((account) => buildAgentDirectoryEntry(account, statsByAgent, indexedProtocolsByAgent))
|
|
321
|
+
.filter((entry) => matchesAgentDirectoryFilters(entry, options))
|
|
322
|
+
.sort((left, right) => Number(right.createdAt) - Number(left.createdAt));
|
|
323
|
+
const page = filteredAgents.slice(options.offset, options.offset + options.limit);
|
|
324
|
+
const hasMore = options.offset + page.length < filteredAgents.length;
|
|
325
|
+
const nextOffset = hasMore ? options.offset + page.length : null;
|
|
326
|
+
const nextCursor = nextOffset === null ? null : encodeDirectoryCursor(nextOffset);
|
|
327
|
+
const agents = options.view === 'compact' ? page.map(compactAgentDirectoryEntry) : page;
|
|
328
|
+
return {
|
|
329
|
+
source: 'program.account.agentAccount.all + program.account.protocolIndex.all',
|
|
330
|
+
overview,
|
|
331
|
+
filters: {
|
|
332
|
+
includeInactive: options.includeInactive,
|
|
333
|
+
protocol: options.protocol ?? null,
|
|
334
|
+
capability: options.capability ?? null,
|
|
335
|
+
capabilities: options.capabilities ?? [],
|
|
336
|
+
capabilityMode: options.capabilityMode ?? 'any',
|
|
337
|
+
query: options.query ?? null,
|
|
338
|
+
wallet: options.wallet ?? null,
|
|
339
|
+
agentPda: options.agentPda ?? null,
|
|
340
|
+
hasX402Endpoint: options.hasX402Endpoint ?? null,
|
|
341
|
+
view: options.view,
|
|
342
|
+
},
|
|
343
|
+
count: page.length,
|
|
344
|
+
totalEnumerated: filteredAgents.length,
|
|
345
|
+
returned: page.length,
|
|
346
|
+
offset: options.offset,
|
|
347
|
+
limit: options.limit,
|
|
348
|
+
truncated: hasMore,
|
|
349
|
+
pagination: {
|
|
350
|
+
total: filteredAgents.length,
|
|
351
|
+
returned: page.length,
|
|
352
|
+
offset: options.offset,
|
|
353
|
+
limit: options.limit,
|
|
354
|
+
hasMore,
|
|
355
|
+
nextOffset,
|
|
356
|
+
nextCursor,
|
|
357
|
+
},
|
|
358
|
+
totalAgentAccounts: agentAccounts.length,
|
|
359
|
+
activeAgentAccounts: agentAccounts.filter(({ account }) => account.isActive).length,
|
|
360
|
+
protocolIndexes: options.includeProtocolIndexes ? summarizeProtocolIndexes(protocolIndexes) : undefined,
|
|
361
|
+
agents,
|
|
362
|
+
agentGuidance: directoryAgentGuidance({ hasMore, nextCursor, filters: options }),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
function parseCapabilityMode(input) {
|
|
366
|
+
const mode = optionalString(input, 'capabilityMode')?.trim().toLowerCase();
|
|
367
|
+
if (!mode) {
|
|
368
|
+
return 'any';
|
|
369
|
+
}
|
|
370
|
+
if (mode === 'any' || mode === 'all') {
|
|
371
|
+
return mode;
|
|
372
|
+
}
|
|
373
|
+
throw new Error('capabilityMode must be "any" or "all"');
|
|
374
|
+
}
|
|
375
|
+
function parseOptionalStringArray(input, field) {
|
|
376
|
+
const value = input[field];
|
|
377
|
+
if (value === undefined || value === null) {
|
|
378
|
+
return [];
|
|
379
|
+
}
|
|
380
|
+
if (!Array.isArray(value)) {
|
|
381
|
+
throw new Error(`${field} must be an array of strings`);
|
|
382
|
+
}
|
|
383
|
+
return value
|
|
384
|
+
.filter((item) => typeof item === 'string' && item.trim().length > 0)
|
|
385
|
+
.map((item) => item.trim());
|
|
386
|
+
}
|
|
387
|
+
function parseDirectoryOffset(input) {
|
|
388
|
+
return Math.max(0, decodeDirectoryCursor(optionalString(input, 'cursor')) ?? optionalNumber(input, 'offset') ?? 0);
|
|
389
|
+
}
|
|
390
|
+
function parseDirectoryView(input) {
|
|
391
|
+
const view = optionalString(input, 'view');
|
|
392
|
+
if (!view && input.hydrate === true) {
|
|
393
|
+
return 'full';
|
|
394
|
+
}
|
|
395
|
+
if (!view || view === 'compact') {
|
|
396
|
+
return 'compact';
|
|
397
|
+
}
|
|
398
|
+
if (view === 'full') {
|
|
399
|
+
return 'full';
|
|
400
|
+
}
|
|
401
|
+
throw new Error('view must be "compact" or "full"');
|
|
402
|
+
}
|
|
403
|
+
function parseHasX402Endpoint(input) {
|
|
404
|
+
return optionalBoolean(input, 'hasX402Endpoint');
|
|
405
|
+
}
|
|
406
|
+
function makeAgentDirectoryInputSchema(defaultLimit) {
|
|
407
|
+
return {
|
|
408
|
+
query: {
|
|
409
|
+
type: 'string',
|
|
410
|
+
description: 'Optional text search across name, description, agentId, wallet, PDA, x402 endpoint, protocols, capabilities, and active plugins. Example: "XONA" or "creative".',
|
|
411
|
+
},
|
|
412
|
+
wallet: {
|
|
413
|
+
type: 'string',
|
|
414
|
+
description: 'Optional exact owner wallet public key filter. Use this when a wallet is known; it is the most reliable lookup path.',
|
|
415
|
+
},
|
|
416
|
+
agentPda: {
|
|
417
|
+
type: 'string',
|
|
418
|
+
description: 'Optional exact SAP agent PDA filter.',
|
|
419
|
+
},
|
|
420
|
+
protocol: {
|
|
421
|
+
type: 'string',
|
|
422
|
+
description: 'Optional protocol filter matched case-insensitively against agent protocols and protocol-index membership. Example: "jupiter", "creative", "payments".',
|
|
423
|
+
},
|
|
424
|
+
capability: {
|
|
425
|
+
type: 'string',
|
|
426
|
+
description: 'Optional single capability ID filter matched case-insensitively. Example: "creative:imageGeneration" or "jupiter:swap".',
|
|
427
|
+
},
|
|
428
|
+
capabilities: {
|
|
429
|
+
type: 'array',
|
|
430
|
+
items: { type: 'string' },
|
|
431
|
+
description: 'Optional list of capability IDs. Use capabilityMode="all" when the agent must have every capability.',
|
|
432
|
+
},
|
|
433
|
+
capabilityMode: {
|
|
434
|
+
type: 'string',
|
|
435
|
+
enum: ['any', 'all'],
|
|
436
|
+
description: 'How to match the capability/capabilities filters. Defaults to "any".',
|
|
437
|
+
},
|
|
438
|
+
hasX402Endpoint: {
|
|
439
|
+
type: 'boolean',
|
|
440
|
+
description: 'Optional filter for agents that advertise a paid HTTP/x402 endpoint.',
|
|
441
|
+
},
|
|
442
|
+
includeInactive: {
|
|
443
|
+
type: 'boolean',
|
|
444
|
+
description: 'Include inactive agents. Defaults to false.',
|
|
445
|
+
},
|
|
446
|
+
limit: {
|
|
447
|
+
type: 'number',
|
|
448
|
+
description: `Maximum rows to return. Defaults to ${defaultLimit}; hard-capped at 500.`,
|
|
449
|
+
},
|
|
450
|
+
offset: {
|
|
451
|
+
type: 'number',
|
|
452
|
+
description: 'Zero-based pagination offset. Defaults to 0. Prefer cursor after the first page when nextCursor is returned.',
|
|
453
|
+
},
|
|
454
|
+
cursor: {
|
|
455
|
+
type: 'string',
|
|
456
|
+
description: 'Opaque pagination cursor returned as pagination.nextCursor by a previous sap_list_all_agents or sap_discover_agents call.',
|
|
457
|
+
},
|
|
458
|
+
view: {
|
|
459
|
+
type: 'string',
|
|
460
|
+
enum: ['compact', 'full'],
|
|
461
|
+
description: 'Result shape. Use compact for broad discovery and full for detailed rows. Defaults to compact.',
|
|
462
|
+
},
|
|
463
|
+
hydrate: {
|
|
464
|
+
type: 'boolean',
|
|
465
|
+
description: 'Deprecated compatibility alias. Use view="full" for full rows or view="compact" for directory rows.',
|
|
466
|
+
},
|
|
467
|
+
includeProtocolIndexes: {
|
|
468
|
+
type: 'boolean',
|
|
469
|
+
description: 'Include compact protocol index summaries. Defaults to false for sap_discover_agents and true for sap_list_all_agents.',
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
}
|
|
196
473
|
/**
|
|
197
474
|
* @name asRecord
|
|
198
475
|
* @description Normalizes MCP tool input into an object.
|
|
@@ -723,7 +1000,7 @@ function buildSapSdkToolDescription(definition) {
|
|
|
723
1000
|
}
|
|
724
1001
|
function getSapSdkToolContext(name) {
|
|
725
1002
|
if (name === 'sap_register_agent') {
|
|
726
|
-
return 'SAP MCP context: This is the primary on-chain SAP agent registration tool for
|
|
1003
|
+
return 'SAP MCP context: This is the primary on-chain SAP agent registration tool for a local profile signer or external signer. Hosted accountless SAP MCP rejects direct registration before x402 payment because OOBE never custodies user wallet keys. Use agentUri or metadataUri for off-chain metadata, including a Metaplex or DAS-backed identity document when the agent also has NFT/collection metadata. After registration, use sap_publish_tool_by_name for advertised MCP capabilities and AgentKit metaplex-nft_* tools for NFT collection, badge, or metadata workflows.';
|
|
727
1004
|
}
|
|
728
1005
|
if (name === 'sap_update_agent') {
|
|
729
1006
|
return 'SAP MCP context: Use this after sap_register_agent to refresh name, description, capabilities, pricing, supported protocols, x402 endpoint, or metadataUri. For NFT-backed identity changes, update the Metaplex asset first when needed, then point the SAP agent metadataUri at the current metadata document.';
|
|
@@ -752,7 +1029,7 @@ const agentTools = [
|
|
|
752
1029
|
{
|
|
753
1030
|
name: 'sap_register_agent',
|
|
754
1031
|
title: 'Register SAP Agent',
|
|
755
|
-
description: '
|
|
1032
|
+
description: 'Local-signer-only: register the connected wallet as a SAP agent using SDK AgentModule.register. Hosted accountless SAP MCP rejects this direct write before x402 payment; run it through a local SAP MCP profile or external signer.',
|
|
756
1033
|
inputSchema: {
|
|
757
1034
|
name: { type: 'string', description: 'Human-readable name for the SAP agent' },
|
|
758
1035
|
description: { type: 'string', description: 'Detailed description of the agent\'s purpose and capabilities' },
|
|
@@ -864,107 +1141,59 @@ const discoveryTools = [
|
|
|
864
1141
|
{
|
|
865
1142
|
name: 'sap_discover_agents',
|
|
866
1143
|
title: 'Discover SAP Agents',
|
|
867
|
-
description: '
|
|
868
|
-
inputSchema:
|
|
869
|
-
protocol: { type: 'string', description: 'Protocol identifier to filter agents by (e.g. "jupiter", "drift")' },
|
|
870
|
-
capability: { type: 'string', description: 'Single capability ID to filter agents by (e.g. "jupiter:swap")' },
|
|
871
|
-
capabilities: { type: 'array', items: { type: 'string' }, description: 'Array of capability IDs to filter agents by (requires at least one)' },
|
|
872
|
-
hydrate: { type: 'boolean', description: 'Whether to include full hydrated agent profiles in results (default: true)' },
|
|
873
|
-
limit: { type: 'number', description: 'Maximum number of agents to return (default: 50)' },
|
|
874
|
-
},
|
|
1144
|
+
description: 'Paid hosted discovery for SAP agents. Search and filter the current on-chain AgentAccount directory by query, wallet, protocol, capability, x402 endpoint presence, and cursor pagination. Use this for targeted agent discovery before calling per-agent fetch tools.',
|
|
1145
|
+
inputSchema: makeAgentDirectoryInputSchema(50),
|
|
875
1146
|
handler: async (input, client) => {
|
|
876
|
-
const
|
|
877
|
-
const limit = optionalNumber(input, 'limit') ?? 50;
|
|
878
|
-
const capabilities = Array.isArray(input.capabilities)
|
|
879
|
-
? input.capabilities.filter((item) => typeof item === 'string' && item.length > 0)
|
|
880
|
-
: [];
|
|
881
|
-
const protocol = optionalString(input, 'protocol');
|
|
1147
|
+
const limit = Math.max(1, Math.min(optionalNumber(input, 'limit') ?? 50, 500));
|
|
882
1148
|
const capability = optionalString(input, 'capability');
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
note: 'SDK filtered discovery requires a protocol or capability. For global on-chain directory snapshots, call sap_list_all_agents.',
|
|
900
|
-
};
|
|
1149
|
+
const capabilities = parseOptionalStringArray(input, 'capabilities');
|
|
1150
|
+
return buildAgentDirectoryPage(client, {
|
|
1151
|
+
includeInactive: input.includeInactive === true,
|
|
1152
|
+
protocol: optionalString(input, 'protocol'),
|
|
1153
|
+
capability,
|
|
1154
|
+
capabilities,
|
|
1155
|
+
capabilityMode: parseCapabilityMode(input),
|
|
1156
|
+
query: optionalString(input, 'query'),
|
|
1157
|
+
wallet: optionalString(input, 'wallet'),
|
|
1158
|
+
agentPda: optionalString(input, 'agentPda'),
|
|
1159
|
+
hasX402Endpoint: parseHasX402Endpoint(input),
|
|
1160
|
+
limit,
|
|
1161
|
+
offset: parseDirectoryOffset(input),
|
|
1162
|
+
view: parseDirectoryView(input),
|
|
1163
|
+
includeProtocolIndexes: input.includeProtocolIndexes === true,
|
|
1164
|
+
});
|
|
901
1165
|
},
|
|
902
1166
|
},
|
|
903
1167
|
{
|
|
904
1168
|
name: 'sap_list_agents',
|
|
905
1169
|
title: 'List SAP Agents',
|
|
906
|
-
description: 'Compatibility alias for
|
|
907
|
-
inputSchema:
|
|
908
|
-
protocol: { type: 'string', description: 'Protocol identifier to filter agents by (e.g. "jupiter", "drift")' },
|
|
909
|
-
capability: { type: 'string', description: 'Single capability ID to filter agents by (e.g. "jupiter:swap")' },
|
|
910
|
-
capabilities: { type: 'array', items: { type: 'string' }, description: 'Array of capability IDs to filter agents by (requires at least one)' },
|
|
911
|
-
hydrate: { type: 'boolean', description: 'Whether to include full hydrated agent profiles in results (default: true)' },
|
|
912
|
-
limit: { type: 'number', description: 'Maximum number of agents to return (default: 50)' },
|
|
913
|
-
},
|
|
1170
|
+
description: 'Compatibility alias for sap_discover_agents. Supports query, wallet, protocol, capability, x402 endpoint filtering, and cursor pagination.',
|
|
1171
|
+
inputSchema: makeAgentDirectoryInputSchema(50),
|
|
914
1172
|
handler: async (input, client) => discoveryTools[3].handler(input, client),
|
|
915
1173
|
},
|
|
916
1174
|
{
|
|
917
1175
|
name: 'sap_list_all_agents',
|
|
918
1176
|
title: 'List All SAP Agents',
|
|
919
|
-
description: '
|
|
920
|
-
inputSchema:
|
|
921
|
-
limit: { type: 'number', description: 'Maximum rows to return. Defaults to 100; hard-capped at 500.' },
|
|
922
|
-
offset: { type: 'number', description: 'Zero-based pagination offset. Defaults to 0.' },
|
|
923
|
-
includeInactive: { type: 'boolean', description: 'Include inactive agents. Defaults to false.' },
|
|
924
|
-
protocol: { type: 'string', description: 'Optional protocol filter matched against agent profile protocols and protocol-index membership.' },
|
|
925
|
-
capability: { type: 'string', description: 'Optional capability ID filter such as jupiter:swap.' },
|
|
926
|
-
includeProtocolIndexes: { type: 'boolean', description: 'Include compact protocol index summaries. Defaults to true.' },
|
|
927
|
-
},
|
|
1177
|
+
description: 'Paid hosted global SAP agent directory read. Enumerates current on-chain AgentAccount PDAs and supports query, wallet, protocol, capability, x402 endpoint filtering, compact/full views, and cursor pagination.',
|
|
1178
|
+
inputSchema: makeAgentDirectoryInputSchema(100),
|
|
928
1179
|
handler: async (input, client) => {
|
|
929
1180
|
const limit = Math.max(1, Math.min(optionalNumber(input, 'limit') ?? 100, 500));
|
|
930
|
-
const offset = Math.max(0, optionalNumber(input, 'offset') ?? 0);
|
|
931
|
-
const includeInactive = input.includeInactive === true;
|
|
932
|
-
const includeProtocolIndexes = input.includeProtocolIndexes !== false;
|
|
933
|
-
const protocol = optionalString(input, 'protocol');
|
|
934
1181
|
const capability = optionalString(input, 'capability');
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
.map((account) => buildAgentDirectoryEntry(account, statsByAgent, indexedProtocolsByAgent))
|
|
946
|
-
.filter((entry) => matchesAgentDirectoryFilters(entry, { includeInactive, protocol, capability }))
|
|
947
|
-
.sort((left, right) => Number(right.createdAt) - Number(left.createdAt));
|
|
948
|
-
const page = filteredAgents.slice(offset, offset + limit);
|
|
949
|
-
return {
|
|
950
|
-
source: 'program.account.agentAccount.all + program.account.protocolIndex.all',
|
|
951
|
-
overview,
|
|
952
|
-
filters: {
|
|
953
|
-
includeInactive,
|
|
954
|
-
protocol: protocol ?? null,
|
|
955
|
-
capability: capability ?? null,
|
|
956
|
-
},
|
|
957
|
-
totalEnumerated: filteredAgents.length,
|
|
958
|
-
totalAgentAccounts: agentAccounts.length,
|
|
959
|
-
activeAgentAccounts: agentAccounts.filter(({ account }) => account.isActive).length,
|
|
960
|
-
returned: page.length,
|
|
961
|
-
offset,
|
|
1182
|
+
return buildAgentDirectoryPage(client, {
|
|
1183
|
+
includeInactive: input.includeInactive === true,
|
|
1184
|
+
protocol: optionalString(input, 'protocol'),
|
|
1185
|
+
capability,
|
|
1186
|
+
capabilities: parseOptionalStringArray(input, 'capabilities'),
|
|
1187
|
+
capabilityMode: parseCapabilityMode(input),
|
|
1188
|
+
query: optionalString(input, 'query'),
|
|
1189
|
+
wallet: optionalString(input, 'wallet'),
|
|
1190
|
+
agentPda: optionalString(input, 'agentPda'),
|
|
1191
|
+
hasX402Endpoint: parseHasX402Endpoint(input),
|
|
962
1192
|
limit,
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
};
|
|
1193
|
+
offset: parseDirectoryOffset(input),
|
|
1194
|
+
view: parseDirectoryView(input),
|
|
1195
|
+
includeProtocolIndexes: input.includeProtocolIndexes !== false,
|
|
1196
|
+
});
|
|
968
1197
|
},
|
|
969
1198
|
},
|
|
970
1199
|
{
|