@oobe-protocol-labs/sap-mcp-server 0.9.1 → 0.9.3
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/.env.example +8 -7
- package/CHANGELOG.md +732 -1
- package/README.md +9 -3
- package/USER_DOCS/00_START_HERE.md +51 -4
- package/USER_DOCS/01_HOSTED_REMOTE_MCP.md +1 -1
- package/USER_DOCS/03_PAYMENTS_X402_PAYSH.md +32 -3
- package/USER_DOCS/04_CLIENT_CONFIGS.md +14 -7
- package/USER_DOCS/05_SKILLS_AND_TOOLS.md +68 -8
- package/USER_DOCS/06_DESKTOP_GUI_WIZARD.md +20 -14
- package/USER_DOCS/07_SMITHERY_AND_MARKETPLACES.md +7 -0
- package/config.example.json +5 -4
- package/config.schema.json +9 -4
- package/config.secure-example.json +5 -4
- package/dist/adapters/index.d.ts +7 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +7 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/mcp/errors.d.ts +13 -1
- package/dist/adapters/mcp/errors.d.ts.map +1 -1
- package/dist/adapters/mcp/errors.js +13 -1
- package/dist/adapters/mcp/errors.js.map +1 -1
- package/dist/adapters/mcp/index.d.ts +7 -1
- package/dist/adapters/mcp/index.d.ts.map +1 -1
- package/dist/adapters/mcp/index.js +7 -1
- package/dist/adapters/mcp/index.js.map +1 -1
- package/dist/adapters/mcp/prompt-response.d.ts +13 -1
- package/dist/adapters/mcp/prompt-response.d.ts.map +1 -1
- package/dist/adapters/mcp/prompt-response.js +13 -1
- package/dist/adapters/mcp/prompt-response.js.map +1 -1
- package/dist/adapters/mcp/resource-response.d.ts +14 -1
- package/dist/adapters/mcp/resource-response.d.ts.map +1 -1
- package/dist/adapters/mcp/resource-response.js +14 -1
- package/dist/adapters/mcp/resource-response.js.map +1 -1
- package/dist/adapters/mcp/sdk-compat.d.ts +11 -3
- package/dist/adapters/mcp/sdk-compat.d.ts.map +1 -1
- package/dist/adapters/mcp/sdk-compat.js +232 -25
- package/dist/adapters/mcp/sdk-compat.js.map +1 -1
- package/dist/adapters/mcp/tool-response.d.ts +51 -3
- package/dist/adapters/mcp/tool-response.d.ts.map +1 -1
- package/dist/adapters/mcp/tool-response.js +48 -3
- package/dist/adapters/mcp/tool-response.js.map +1 -1
- package/dist/adapters/solana/commitment.d.ts +14 -2
- package/dist/adapters/solana/commitment.d.ts.map +1 -1
- package/dist/adapters/solana/commitment.js +14 -2
- package/dist/adapters/solana/commitment.js.map +1 -1
- package/dist/adapters/solana/connection.d.ts +11 -2
- package/dist/adapters/solana/connection.d.ts.map +1 -1
- package/dist/adapters/solana/connection.js +11 -2
- package/dist/adapters/solana/connection.js.map +1 -1
- package/dist/adapters/solana/index.d.ts +7 -1
- package/dist/adapters/solana/index.d.ts.map +1 -1
- package/dist/adapters/solana/index.js +7 -1
- package/dist/adapters/solana/index.js.map +1 -1
- package/dist/adapters/solana/public-key.d.ts +11 -2
- package/dist/adapters/solana/public-key.d.ts.map +1 -1
- package/dist/adapters/solana/public-key.js +11 -2
- package/dist/adapters/solana/public-key.js.map +1 -1
- package/dist/config/defaults.d.ts +5 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +5 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/env.d.ts +4 -0
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +15 -10
- package/dist/config/env.js.map +1 -1
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/mcp-client-injection.d.ts.map +1 -1
- package/dist/config/mcp-client-injection.js +136 -33
- package/dist/config/mcp-client-injection.js.map +1 -1
- package/dist/config/paths.d.ts +14 -1
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +20 -1
- package/dist/config/paths.js.map +1 -1
- package/dist/config/profiles.d.ts +3 -10
- package/dist/config/profiles.d.ts.map +1 -1
- package/dist/config/profiles.js +5 -0
- package/dist/config/profiles.js.map +1 -1
- package/dist/config/schema.d.ts +5 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +5 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/config/secure-config.d.ts +5 -0
- package/dist/config/secure-config.d.ts.map +1 -1
- package/dist/config/secure-config.js +5 -0
- package/dist/config/secure-config.js.map +1 -1
- package/dist/config/setup.d.ts +5 -0
- package/dist/config/setup.d.ts.map +1 -1
- package/dist/config/setup.js +5 -0
- package/dist/config/setup.js.map +1 -1
- package/dist/config/wizard.d.ts +6 -0
- package/dist/config/wizard.d.ts.map +1 -1
- package/dist/config/wizard.js +102 -18
- package/dist/config/wizard.js.map +1 -1
- package/dist/config-cli.d.ts +3 -13
- package/dist/config-cli.d.ts.map +1 -1
- package/dist/config-cli.js +14 -1
- package/dist/config-cli.js.map +1 -1
- package/dist/core/constants.d.ts +38 -6
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +49 -6
- package/dist/core/constants.js.map +1 -1
- package/dist/core/errors.d.ts +5 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +5 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/guards.d.ts +5 -0
- package/dist/core/guards.d.ts.map +1 -1
- package/dist/core/guards.js +3 -1
- package/dist/core/guards.js.map +1 -1
- package/dist/core/index.d.ts +7 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +7 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/logger.js +1 -1
- package/dist/core/result.d.ts +77 -9
- package/dist/core/result.d.ts.map +1 -1
- package/dist/core/result.js +68 -9
- package/dist/core/result.js.map +1 -1
- package/dist/core/types.d.ts +5 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +3 -4
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/async-processor.d.ts +107 -0
- package/dist/memory/async-processor.d.ts.map +1 -0
- package/dist/memory/async-processor.js +204 -0
- package/dist/memory/async-processor.js.map +1 -0
- package/dist/memory/auto-record.d.ts +47 -0
- package/dist/memory/auto-record.d.ts.map +1 -0
- package/dist/memory/auto-record.js +133 -0
- package/dist/memory/auto-record.js.map +1 -0
- package/dist/memory/database.d.ts +103 -0
- package/dist/memory/database.d.ts.map +1 -0
- package/dist/memory/database.js +337 -0
- package/dist/memory/database.js.map +1 -0
- package/dist/memory/hermes-bridge.d.ts +70 -0
- package/dist/memory/hermes-bridge.d.ts.map +1 -0
- package/dist/memory/hermes-bridge.js +155 -0
- package/dist/memory/hermes-bridge.js.map +1 -0
- package/dist/memory/index.d.ts +23 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +22 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/memory-store.d.ts +76 -0
- package/dist/memory/memory-store.d.ts.map +1 -0
- package/dist/memory/memory-store.js +231 -0
- package/dist/memory/memory-store.js.map +1 -0
- package/dist/memory/stream-buffer-store.d.ts +69 -0
- package/dist/memory/stream-buffer-store.d.ts.map +1 -0
- package/dist/memory/stream-buffer-store.js +182 -0
- package/dist/memory/stream-buffer-store.js.map +1 -0
- package/dist/memory/tool-call-store.d.ts +68 -0
- package/dist/memory/tool-call-store.d.ts.map +1 -0
- package/dist/memory/tool-call-store.js +189 -0
- package/dist/memory/tool-call-store.js.map +1 -0
- package/dist/memory/types.d.ts +197 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +15 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/memory/utils.d.ts +30 -0
- package/dist/memory/utils.d.ts.map +1 -0
- package/dist/memory/utils.js +47 -0
- package/dist/memory/utils.js.map +1 -0
- package/dist/payments/facilitator-rpc-fallback.d.ts.map +1 -1
- package/dist/payments/facilitator-rpc-fallback.js +95 -0
- package/dist/payments/facilitator-rpc-fallback.js.map +1 -1
- package/dist/payments/hosted-tool-eligibility.d.ts +22 -0
- package/dist/payments/hosted-tool-eligibility.d.ts.map +1 -0
- package/dist/payments/hosted-tool-eligibility.js +173 -0
- package/dist/payments/hosted-tool-eligibility.js.map +1 -0
- package/dist/payments/index.d.ts +2 -2
- package/dist/payments/index.d.ts.map +1 -1
- package/dist/payments/index.js +1 -1
- package/dist/payments/index.js.map +1 -1
- package/dist/payments/mcp-session-cache.d.ts +35 -0
- package/dist/payments/mcp-session-cache.d.ts.map +1 -0
- package/dist/payments/mcp-session-cache.js +83 -0
- package/dist/payments/mcp-session-cache.js.map +1 -0
- package/dist/payments/monetization-gate.d.ts +33 -0
- package/dist/payments/monetization-gate.d.ts.map +1 -1
- package/dist/payments/monetization-gate.js +124 -12
- package/dist/payments/monetization-gate.js.map +1 -1
- package/dist/payments/pricing.d.ts +31 -0
- package/dist/payments/pricing.d.ts.map +1 -1
- package/dist/payments/pricing.js +317 -19
- package/dist/payments/pricing.js.map +1 -1
- package/dist/payments/usage-ledger.d.ts +36 -2
- package/dist/payments/usage-ledger.d.ts.map +1 -1
- package/dist/payments/usage-ledger.js +121 -4
- package/dist/payments/usage-ledger.js.map +1 -1
- package/dist/payments/x402-paid-call.d.ts +121 -0
- package/dist/payments/x402-paid-call.d.ts.map +1 -1
- package/dist/payments/x402-paid-call.js +428 -1
- package/dist/payments/x402-paid-call.js.map +1 -1
- package/dist/policy/default-policies.d.ts +18 -2
- package/dist/policy/default-policies.d.ts.map +1 -1
- package/dist/policy/default-policies.js +18 -2
- package/dist/policy/default-policies.js.map +1 -1
- package/dist/policy/index.d.ts +6 -3
- package/dist/policy/index.d.ts.map +1 -1
- package/dist/policy/index.js +6 -3
- package/dist/policy/index.js.map +1 -1
- package/dist/policy/local-policy-engine.d.ts +71 -13
- package/dist/policy/local-policy-engine.d.ts.map +1 -1
- package/dist/policy/local-policy-engine.js +33 -11
- package/dist/policy/local-policy-engine.js.map +1 -1
- package/dist/policy/permission-checks.d.ts +29 -3
- package/dist/policy/permission-checks.d.ts.map +1 -1
- package/dist/policy/permission-checks.js +29 -3
- package/dist/policy/permission-checks.js.map +1 -1
- package/dist/policy/policy-engine.d.ts +22 -2
- package/dist/policy/policy-engine.d.ts.map +1 -1
- package/dist/policy/policy-engine.js +22 -2
- package/dist/policy/policy-engine.js.map +1 -1
- package/dist/policy/policy-types.d.ts +55 -5
- package/dist/policy/policy-types.d.ts.map +1 -1
- package/dist/policy/policy-types.js +8 -1
- package/dist/policy/policy-types.js.map +1 -1
- package/dist/policy/risk-level.d.ts +32 -3
- package/dist/policy/risk-level.d.ts.map +1 -1
- package/dist/policy/risk-level.js +32 -3
- package/dist/policy/risk-level.js.map +1 -1
- package/dist/policy/spending-limits.d.ts +29 -3
- package/dist/policy/spending-limits.d.ts.map +1 -1
- package/dist/policy/spending-limits.js +29 -3
- package/dist/policy/spending-limits.js.map +1 -1
- package/dist/premium/activation-manager.d.ts +43 -0
- package/dist/premium/activation-manager.d.ts.map +1 -0
- package/dist/premium/activation-manager.js +131 -0
- package/dist/premium/activation-manager.js.map +1 -0
- package/dist/premium/builtin-plugins.d.ts +165 -0
- package/dist/premium/builtin-plugins.d.ts.map +1 -0
- package/dist/premium/builtin-plugins.js +422 -0
- package/dist/premium/builtin-plugins.js.map +1 -0
- package/dist/premium/event-store.d.ts +61 -0
- package/dist/premium/event-store.d.ts.map +1 -0
- package/dist/premium/event-store.js +130 -0
- package/dist/premium/event-store.js.map +1 -0
- package/dist/premium/index.d.ts +54 -0
- package/dist/premium/index.d.ts.map +1 -0
- package/dist/premium/index.js +54 -0
- package/dist/premium/index.js.map +1 -0
- package/dist/premium/manifest-builder.d.ts +65 -0
- package/dist/premium/manifest-builder.d.ts.map +1 -0
- package/dist/premium/manifest-builder.js +182 -0
- package/dist/premium/manifest-builder.js.map +1 -0
- package/dist/premium/meme-radar-capabilities.d.ts +38 -0
- package/dist/premium/meme-radar-capabilities.d.ts.map +1 -0
- package/dist/premium/meme-radar-capabilities.js +306 -0
- package/dist/premium/meme-radar-capabilities.js.map +1 -0
- package/dist/premium/metrics.d.ts +27 -0
- package/dist/premium/metrics.d.ts.map +1 -0
- package/dist/premium/metrics.js +65 -0
- package/dist/premium/metrics.js.map +1 -0
- package/dist/premium/plugin-validator.d.ts +39 -0
- package/dist/premium/plugin-validator.d.ts.map +1 -0
- package/dist/premium/plugin-validator.js +325 -0
- package/dist/premium/plugin-validator.js.map +1 -0
- package/dist/premium/private-manifest-loader.d.ts +111 -0
- package/dist/premium/private-manifest-loader.d.ts.map +1 -0
- package/dist/premium/private-manifest-loader.js +285 -0
- package/dist/premium/private-manifest-loader.js.map +1 -0
- package/dist/premium/provider-bridge.d.ts +133 -0
- package/dist/premium/provider-bridge.d.ts.map +1 -0
- package/dist/premium/provider-bridge.js +349 -0
- package/dist/premium/provider-bridge.js.map +1 -0
- package/dist/premium/session-manager.d.ts +125 -0
- package/dist/premium/session-manager.d.ts.map +1 -0
- package/dist/premium/session-manager.js +337 -0
- package/dist/premium/session-manager.js.map +1 -0
- package/dist/premium/stream-broker.d.ts +98 -0
- package/dist/premium/stream-broker.d.ts.map +1 -0
- package/dist/premium/stream-broker.js +199 -0
- package/dist/premium/stream-broker.js.map +1 -0
- package/dist/premium/tech-fundamentals-capabilities.d.ts +37 -0
- package/dist/premium/tech-fundamentals-capabilities.d.ts.map +1 -0
- package/dist/premium/tech-fundamentals-capabilities.js +283 -0
- package/dist/premium/tech-fundamentals-capabilities.js.map +1 -0
- package/dist/premium/trading-capabilities.d.ts +36 -0
- package/dist/premium/trading-capabilities.d.ts.map +1 -0
- package/dist/premium/trading-capabilities.js +205 -0
- package/dist/premium/trading-capabilities.js.map +1 -0
- package/dist/premium/types.d.ts +518 -0
- package/dist/premium/types.d.ts.map +1 -0
- package/dist/premium/types.js +23 -0
- package/dist/premium/types.js.map +1 -0
- package/dist/premium/webhook-engine.d.ts +138 -0
- package/dist/premium/webhook-engine.d.ts.map +1 -0
- package/dist/premium/webhook-engine.js +516 -0
- package/dist/premium/webhook-engine.js.map +1 -0
- package/dist/prompts/context/sap-agent-context.prompt.d.ts +5 -0
- package/dist/prompts/context/sap-agent-context.prompt.d.ts.map +1 -1
- package/dist/prompts/context/sap-agent-context.prompt.js +20 -16
- package/dist/prompts/context/sap-agent-context.prompt.js.map +1 -1
- package/dist/prompts/context/sap-agent-intent-router.prompt.d.ts +14 -0
- package/dist/prompts/context/sap-agent-intent-router.prompt.d.ts.map +1 -0
- package/dist/prompts/context/sap-agent-intent-router.prompt.js +155 -0
- package/dist/prompts/context/sap-agent-intent-router.prompt.js.map +1 -0
- package/dist/prompts/context/sap-agent-start.prompt.js +7 -0
- package/dist/prompts/context/sap-agent-start.prompt.js.map +1 -1
- package/dist/prompts/developer/debug-sap-error.prompt.d.ts +5 -0
- package/dist/prompts/developer/debug-sap-error.prompt.d.ts.map +1 -1
- package/dist/prompts/developer/debug-sap-error.prompt.js +3 -4
- package/dist/prompts/developer/debug-sap-error.prompt.js.map +1 -1
- package/dist/prompts/developer/generate-sap-integration.prompt.d.ts +5 -0
- package/dist/prompts/developer/generate-sap-integration.prompt.d.ts.map +1 -1
- package/dist/prompts/developer/generate-sap-integration.prompt.js +3 -4
- package/dist/prompts/developer/generate-sap-integration.prompt.js.map +1 -1
- package/dist/prompts/developer/index.d.ts +4 -1
- package/dist/prompts/developer/index.d.ts.map +1 -1
- package/dist/prompts/developer/index.js +4 -1
- package/dist/prompts/developer/index.js.map +1 -1
- package/dist/prompts/execution-proof/explain-proof-of-execution.prompt.d.ts +5 -0
- package/dist/prompts/execution-proof/explain-proof-of-execution.prompt.d.ts.map +1 -1
- package/dist/prompts/execution-proof/explain-proof-of-execution.prompt.js +3 -4
- package/dist/prompts/execution-proof/explain-proof-of-execution.prompt.js.map +1 -1
- package/dist/prompts/execution-proof/index.d.ts +4 -1
- package/dist/prompts/execution-proof/index.d.ts.map +1 -1
- package/dist/prompts/execution-proof/index.js +4 -1
- package/dist/prompts/execution-proof/index.js.map +1 -1
- package/dist/prompts/execution-proof/verify-execution-proof.prompt.d.ts +5 -0
- package/dist/prompts/execution-proof/verify-execution-proof.prompt.d.ts.map +1 -1
- package/dist/prompts/execution-proof/verify-execution-proof.prompt.js +3 -4
- package/dist/prompts/execution-proof/verify-execution-proof.prompt.js.map +1 -1
- package/dist/prompts/index.d.ts +4 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +4 -1
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/payments/create-paid-api.prompt.d.ts +5 -0
- package/dist/prompts/payments/create-paid-api.prompt.d.ts.map +1 -1
- package/dist/prompts/payments/create-paid-api.prompt.js +3 -4
- package/dist/prompts/payments/create-paid-api.prompt.js.map +1 -1
- package/dist/prompts/payments/explain-x402-settlement.prompt.d.ts +5 -0
- package/dist/prompts/payments/explain-x402-settlement.prompt.d.ts.map +1 -1
- package/dist/prompts/payments/explain-x402-settlement.prompt.js +16 -14
- package/dist/prompts/payments/explain-x402-settlement.prompt.js.map +1 -1
- package/dist/prompts/payments/index.d.ts +4 -1
- package/dist/prompts/payments/index.d.ts.map +1 -1
- package/dist/prompts/payments/index.js +4 -1
- package/dist/prompts/payments/index.js.map +1 -1
- package/dist/prompts/register-prompts.d.ts +18 -2
- package/dist/prompts/register-prompts.d.ts.map +1 -1
- package/dist/prompts/register-prompts.js +21 -3
- package/dist/prompts/register-prompts.js.map +1 -1
- package/dist/prompts/registry/analyze-sap-agent.prompt.d.ts +5 -0
- package/dist/prompts/registry/analyze-sap-agent.prompt.d.ts.map +1 -1
- package/dist/prompts/registry/analyze-sap-agent.prompt.js +3 -4
- package/dist/prompts/registry/analyze-sap-agent.prompt.js.map +1 -1
- package/dist/prompts/registry/index.d.ts +4 -1
- package/dist/prompts/registry/index.d.ts.map +1 -1
- package/dist/prompts/registry/index.js +4 -1
- package/dist/prompts/registry/index.js.map +1 -1
- package/dist/prompts/registry/register-sap-agent.prompt.d.ts +5 -0
- package/dist/prompts/registry/register-sap-agent.prompt.d.ts.map +1 -1
- package/dist/prompts/registry/register-sap-agent.prompt.js +22 -23
- package/dist/prompts/registry/register-sap-agent.prompt.js.map +1 -1
- package/dist/remote/premium-memory.d.ts +90 -0
- package/dist/remote/premium-memory.d.ts.map +1 -0
- package/dist/remote/premium-memory.js +161 -0
- package/dist/remote/premium-memory.js.map +1 -0
- package/dist/remote/premium-routes.d.ts +99 -0
- package/dist/remote/premium-routes.d.ts.map +1 -0
- package/dist/remote/premium-routes.js +347 -0
- package/dist/remote/premium-routes.js.map +1 -0
- package/dist/remote/public-home/sections.d.ts.map +1 -1
- package/dist/remote/public-home/sections.js +23 -4
- package/dist/remote/public-home/sections.js.map +1 -1
- package/dist/remote/public-home/types.d.ts +9 -0
- package/dist/remote/public-home/types.d.ts.map +1 -1
- package/dist/remote/server.d.ts +20 -0
- package/dist/remote/server.d.ts.map +1 -1
- package/dist/remote/server.js +370 -9
- package/dist/remote/server.js.map +1 -1
- package/dist/remote/tx-relay.d.ts +42 -0
- package/dist/remote/tx-relay.d.ts.map +1 -0
- package/dist/remote/tx-relay.js +118 -0
- package/dist/remote/tx-relay.js.map +1 -0
- package/dist/resources/current/sap-current-config.resource.d.ts +5 -0
- package/dist/resources/current/sap-current-config.resource.d.ts.map +1 -1
- package/dist/resources/current/sap-current-config.resource.js +2 -5
- package/dist/resources/current/sap-current-config.resource.js.map +1 -1
- package/dist/resources/execution-proof/index.d.ts +5 -0
- package/dist/resources/execution-proof/index.d.ts.map +1 -1
- package/dist/resources/execution-proof/index.js +5 -0
- package/dist/resources/execution-proof/index.js.map +1 -1
- package/dist/resources/execution-proof/sap-execution-record.resource.d.ts +5 -0
- package/dist/resources/execution-proof/sap-execution-record.resource.d.ts.map +1 -1
- package/dist/resources/execution-proof/sap-execution-record.resource.js +3 -4
- package/dist/resources/execution-proof/sap-execution-record.resource.js.map +1 -1
- package/dist/resources/index.d.ts +5 -0
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +5 -0
- package/dist/resources/index.js.map +1 -1
- package/dist/resources/memory/index.d.ts +5 -0
- package/dist/resources/memory/index.d.ts.map +1 -1
- package/dist/resources/memory/index.js +5 -0
- package/dist/resources/memory/index.js.map +1 -1
- package/dist/resources/memory/sap-memory.resource.d.ts +5 -0
- package/dist/resources/memory/sap-memory.resource.d.ts.map +1 -1
- package/dist/resources/memory/sap-memory.resource.js +3 -4
- package/dist/resources/memory/sap-memory.resource.js.map +1 -1
- package/dist/resources/profile/sap-active-profile.resource.d.ts +5 -0
- package/dist/resources/profile/sap-active-profile.resource.d.ts.map +1 -1
- package/dist/resources/profile/sap-active-profile.resource.js +2 -5
- package/dist/resources/profile/sap-active-profile.resource.js.map +1 -1
- package/dist/resources/register-resources.d.ts +5 -0
- package/dist/resources/register-resources.d.ts.map +1 -1
- package/dist/resources/register-resources.js +3 -1
- package/dist/resources/register-resources.js.map +1 -1
- package/dist/resources/registry/index.d.ts +5 -0
- package/dist/resources/registry/index.d.ts.map +1 -1
- package/dist/resources/registry/index.js +5 -0
- package/dist/resources/registry/index.js.map +1 -1
- package/dist/resources/registry/sap-agent.resource.d.ts +5 -0
- package/dist/resources/registry/sap-agent.resource.d.ts.map +1 -1
- package/dist/resources/registry/sap-agent.resource.js +3 -4
- package/dist/resources/registry/sap-agent.resource.js.map +1 -1
- package/dist/resources/registry/sap-global-registry.resource.d.ts +18 -4
- package/dist/resources/registry/sap-global-registry.resource.d.ts.map +1 -1
- package/dist/resources/registry/sap-global-registry.resource.js +18 -4
- package/dist/resources/registry/sap-global-registry.resource.js.map +1 -1
- package/dist/resources/reputation/index.d.ts +4 -1
- package/dist/resources/reputation/index.d.ts.map +1 -1
- package/dist/resources/reputation/index.js +4 -1
- package/dist/resources/reputation/index.js.map +1 -1
- package/dist/resources/reputation/sap-reputation.resource.d.ts +18 -4
- package/dist/resources/reputation/sap-reputation.resource.d.ts.map +1 -1
- package/dist/resources/reputation/sap-reputation.resource.js +18 -4
- package/dist/resources/reputation/sap-reputation.resource.js.map +1 -1
- package/dist/resources/tool-schema/index.d.ts +4 -1
- package/dist/resources/tool-schema/index.d.ts.map +1 -1
- package/dist/resources/tool-schema/index.js +4 -1
- package/dist/resources/tool-schema/index.js.map +1 -1
- package/dist/resources/tool-schema/sap-tool-schema.resource.d.ts +18 -4
- package/dist/resources/tool-schema/sap-tool-schema.resource.d.ts.map +1 -1
- package/dist/resources/tool-schema/sap-tool-schema.resource.js +18 -4
- package/dist/resources/tool-schema/sap-tool-schema.resource.js.map +1 -1
- package/dist/sap/index.d.ts +7 -1
- package/dist/sap/index.d.ts.map +1 -1
- package/dist/sap/index.js +7 -1
- package/dist/sap/index.js.map +1 -1
- package/dist/sap/sap-client-manager.d.ts +80 -13
- package/dist/sap/sap-client-manager.d.ts.map +1 -1
- package/dist/sap/sap-client-manager.js +80 -13
- package/dist/sap/sap-client-manager.js.map +1 -1
- package/dist/sap/sap-errors.d.ts +22 -3
- package/dist/sap/sap-errors.d.ts.map +1 -1
- package/dist/sap/sap-errors.js +22 -3
- package/dist/sap/sap-errors.js.map +1 -1
- package/dist/sap/sap-types.d.ts +75 -6
- package/dist/sap/sap-types.d.ts.map +1 -1
- package/dist/sap/sap-types.js +11 -1
- package/dist/sap/sap-types.js.map +1 -1
- package/dist/schemas/common.schema.d.ts +45 -8
- package/dist/schemas/common.schema.d.ts.map +1 -1
- package/dist/schemas/common.schema.js +45 -8
- package/dist/schemas/common.schema.js.map +1 -1
- package/dist/schemas/developer.schema.d.ts +22 -3
- package/dist/schemas/developer.schema.d.ts.map +1 -1
- package/dist/schemas/developer.schema.js +22 -3
- package/dist/schemas/developer.schema.js.map +1 -1
- package/dist/schemas/execution-proof.schema.d.ts +29 -4
- package/dist/schemas/execution-proof.schema.d.ts.map +1 -1
- package/dist/schemas/execution-proof.schema.js +29 -4
- package/dist/schemas/execution-proof.schema.js.map +1 -1
- package/dist/schemas/identity.schema.d.ts +23 -3
- package/dist/schemas/identity.schema.d.ts.map +1 -1
- package/dist/schemas/identity.schema.js +23 -3
- package/dist/schemas/identity.schema.js.map +1 -1
- package/dist/schemas/index.d.ts +11 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +11 -1
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/memory.schema.d.ts +23 -3
- package/dist/schemas/memory.schema.d.ts.map +1 -1
- package/dist/schemas/memory.schema.js +23 -3
- package/dist/schemas/memory.schema.js.map +1 -1
- package/dist/schemas/payments.schema.d.ts +24 -3
- package/dist/schemas/payments.schema.d.ts.map +1 -1
- package/dist/schemas/payments.schema.js +24 -3
- package/dist/schemas/payments.schema.js.map +1 -1
- package/dist/schemas/registry.schema.d.ts +38 -6
- package/dist/schemas/registry.schema.d.ts.map +1 -1
- package/dist/schemas/registry.schema.js +36 -4
- package/dist/schemas/registry.schema.js.map +1 -1
- package/dist/schemas/reputation.schema.d.ts +22 -3
- package/dist/schemas/reputation.schema.d.ts.map +1 -1
- package/dist/schemas/reputation.schema.js +22 -3
- package/dist/schemas/reputation.schema.js.map +1 -1
- package/dist/schemas/settlement.schema.d.ts +31 -4
- package/dist/schemas/settlement.schema.d.ts.map +1 -1
- package/dist/schemas/settlement.schema.js +31 -4
- package/dist/schemas/settlement.schema.js.map +1 -1
- package/dist/schemas/tool-schema.schema.d.ts +29 -3
- package/dist/schemas/tool-schema.schema.d.ts.map +1 -1
- package/dist/schemas/tool-schema.schema.js +29 -3
- package/dist/schemas/tool-schema.schema.js.map +1 -1
- package/dist/schemas/transaction.schema.d.ts +23 -3
- package/dist/schemas/transaction.schema.d.ts.map +1 -1
- package/dist/schemas/transaction.schema.js +23 -3
- package/dist/schemas/transaction.schema.js.map +1 -1
- package/dist/security/approval-required.d.ts +19 -2
- package/dist/security/approval-required.d.ts.map +1 -1
- package/dist/security/approval-required.js +19 -2
- package/dist/security/approval-required.js.map +1 -1
- package/dist/security/index.d.ts +7 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +7 -1
- package/dist/security/index.js.map +1 -1
- package/dist/security/private-key-guard.d.ts +18 -2
- package/dist/security/private-key-guard.d.ts.map +1 -1
- package/dist/security/private-key-guard.js +19 -2
- package/dist/security/private-key-guard.js.map +1 -1
- package/dist/security/prompt-injection-notes.d.ts +10 -1
- package/dist/security/prompt-injection-notes.d.ts.map +1 -1
- package/dist/security/prompt-injection-notes.js +10 -1
- package/dist/security/prompt-injection-notes.js.map +1 -1
- package/dist/security/tool-permissions.d.ts.map +1 -1
- package/dist/security/tool-permissions.js +12 -0
- package/dist/security/tool-permissions.js.map +1 -1
- package/dist/security/unsafe-action-guard.d.ts +36 -10
- package/dist/security/unsafe-action-guard.d.ts.map +1 -1
- package/dist/security/unsafe-action-guard.js +67 -15
- package/dist/security/unsafe-action-guard.js.map +1 -1
- package/dist/server/create-server.d.ts +18 -3
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +20 -4
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/index.d.ts +6 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +6 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/register-capabilities.d.ts +17 -2
- package/dist/server/register-capabilities.d.ts.map +1 -1
- package/dist/server/register-capabilities.js +17 -2
- package/dist/server/register-capabilities.js.map +1 -1
- package/dist/server/server-metadata.d.ts +35 -1
- package/dist/server/server-metadata.d.ts.map +1 -1
- package/dist/server/server-metadata.js +36 -2
- package/dist/server/server-metadata.js.map +1 -1
- package/dist/session/agent-session.d.ts +35 -4
- package/dist/session/agent-session.d.ts.map +1 -1
- package/dist/session/agent-session.js +35 -4
- package/dist/session/agent-session.js.map +1 -1
- package/dist/session/delegated-session.d.ts +31 -3
- package/dist/session/delegated-session.d.ts.map +1 -1
- package/dist/session/delegated-session.js +31 -3
- package/dist/session/delegated-session.js.map +1 -1
- package/dist/session/index.d.ts +7 -1
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +7 -1
- package/dist/session/index.js.map +1 -1
- package/dist/session/redis-session-store.d.ts +94 -21
- package/dist/session/redis-session-store.d.ts.map +1 -1
- package/dist/session/redis-session-store.js +87 -20
- package/dist/session/redis-session-store.js.map +1 -1
- package/dist/session/session-limits.d.ts +34 -4
- package/dist/session/session-limits.d.ts.map +1 -1
- package/dist/session/session-limits.js +34 -4
- package/dist/session/session-limits.js.map +1 -1
- package/dist/session/session-permissions.d.ts +57 -7
- package/dist/session/session-permissions.d.ts.map +1 -1
- package/dist/session/session-permissions.js +57 -7
- package/dist/session/session-permissions.js.map +1 -1
- package/dist/session/session-store.d.ts +9 -1
- package/dist/session/session-store.d.ts.map +1 -1
- package/dist/session/session-store.js +18 -3
- package/dist/session/session-store.js.map +1 -1
- package/dist/session/session-types.d.ts +33 -4
- package/dist/session/session-types.d.ts.map +1 -1
- package/dist/session/session-types.js +9 -1
- package/dist/session/session-types.js.map +1 -1
- package/dist/signer/index.d.ts +7 -1
- package/dist/signer/index.d.ts.map +1 -1
- package/dist/signer/index.js +7 -1
- package/dist/signer/index.js.map +1 -1
- package/dist/signer/load-keypair.d.ts +25 -4
- package/dist/signer/load-keypair.d.ts.map +1 -1
- package/dist/signer/load-keypair.js +25 -4
- package/dist/signer/load-keypair.js.map +1 -1
- package/dist/signer/local-keypair-signer.d.ts +19 -3
- package/dist/signer/local-keypair-signer.d.ts.map +1 -1
- package/dist/signer/local-keypair-signer.js +24 -4
- package/dist/signer/local-keypair-signer.js.map +1 -1
- package/dist/signer/signer-resolver.d.ts +19 -2
- package/dist/signer/signer-resolver.d.ts.map +1 -1
- package/dist/signer/signer-resolver.js +26 -3
- package/dist/signer/signer-resolver.js.map +1 -1
- package/dist/signer/signer-types.d.ts +47 -5
- package/dist/signer/signer-types.d.ts.map +1 -1
- package/dist/signer/signer-types.js +13 -1
- package/dist/signer/signer-types.js.map +1 -1
- package/dist/strategies/strategy-store.d.ts +82 -0
- package/dist/strategies/strategy-store.d.ts.map +1 -0
- package/dist/strategies/strategy-store.js +165 -0
- package/dist/strategies/strategy-store.js.map +1 -0
- package/dist/tools/agent-start-tool.d.ts.map +1 -1
- package/dist/tools/agent-start-tool.js +481 -5
- package/dist/tools/agent-start-tool.js.map +1 -1
- package/dist/tools/client-sdk-tools.d.ts.map +1 -1
- package/dist/tools/client-sdk-tools.js +32 -7
- package/dist/tools/client-sdk-tools.js.map +1 -1
- package/dist/tools/estimate-tool-cost.d.ts +13 -0
- package/dist/tools/estimate-tool-cost.d.ts.map +1 -0
- package/dist/tools/estimate-tool-cost.js +139 -0
- package/dist/tools/estimate-tool-cost.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/magicblock-tools.d.ts +31 -6
- package/dist/tools/magicblock-tools.d.ts.map +1 -1
- package/dist/tools/magicblock-tools.js +178 -53
- package/dist/tools/magicblock-tools.js.map +1 -1
- package/dist/tools/memory-tools.d.ts +26 -0
- package/dist/tools/memory-tools.d.ts.map +1 -0
- package/dist/tools/memory-tools.js +533 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/perp-tools.d.ts +39 -0
- package/dist/tools/perp-tools.d.ts.map +1 -0
- package/dist/tools/perp-tools.js +1110 -0
- package/dist/tools/perp-tools.js.map +1 -0
- package/dist/tools/premium-tools.d.ts +8 -0
- package/dist/tools/premium-tools.d.ts.map +1 -0
- package/dist/tools/premium-tools.js +1102 -0
- package/dist/tools/premium-tools.js.map +1 -0
- package/dist/tools/profile-tools.d.ts.map +1 -1
- package/dist/tools/profile-tools.js +18 -1
- package/dist/tools/profile-tools.js.map +1 -1
- package/dist/tools/quick-context-tool.d.ts +16 -0
- package/dist/tools/quick-context-tool.d.ts.map +1 -0
- package/dist/tools/quick-context-tool.js +304 -0
- package/dist/tools/quick-context-tool.js.map +1 -0
- package/dist/tools/register-tools.d.ts.map +1 -1
- package/dist/tools/register-tools.js +17 -0
- package/dist/tools/register-tools.js.map +1 -1
- package/dist/tools/sap-sdk-tools.d.ts +420 -1
- package/dist/tools/sap-sdk-tools.d.ts.map +1 -1
- package/dist/tools/sap-sdk-tools.js +1548 -127
- 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.d.ts.map +1 -1
- package/dist/tools/sap-sns-tools.js +12 -8
- package/dist/tools/sap-sns-tools.js.map +1 -1
- package/dist/tools/skills-tools.d.ts +16 -0
- package/dist/tools/skills-tools.d.ts.map +1 -1
- package/dist/tools/skills-tools.js +282 -5
- package/dist/tools/skills-tools.js.map +1 -1
- package/dist/tools/tool-aliases.d.ts.map +1 -1
- package/dist/tools/tool-aliases.js +7 -0
- package/dist/tools/tool-aliases.js.map +1 -1
- package/dist/tools/transaction-tools.d.ts +135 -0
- package/dist/tools/transaction-tools.d.ts.map +1 -1
- package/dist/tools/transaction-tools.js +515 -16
- package/dist/tools/transaction-tools.js.map +1 -1
- package/dist/tools/x402-paid-call-tool.d.ts.map +1 -1
- package/dist/tools/x402-paid-call-tool.js +756 -23
- package/dist/tools/x402-paid-call-tool.js.map +1 -1
- package/dist/transports/index.d.ts +6 -1
- package/dist/transports/index.d.ts.map +1 -1
- package/dist/transports/index.js +6 -1
- package/dist/transports/index.js.map +1 -1
- package/dist/transports/stdio.d.ts +17 -5
- package/dist/transports/stdio.d.ts.map +1 -1
- package/dist/transports/stdio.js +17 -5
- package/dist/transports/stdio.js.map +1 -1
- package/dist/tui/wizard-save.d.ts +88 -8
- package/dist/tui/wizard-save.d.ts.map +1 -1
- package/dist/tui/wizard-save.js +77 -8
- package/dist/tui/wizard-save.js.map +1 -1
- package/dist/wizard-core/desktop-flow.d.ts.map +1 -1
- package/dist/wizard-core/desktop-flow.js +4 -2
- package/dist/wizard-core/desktop-flow.js.map +1 -1
- package/docs/03_CONFIGURATION_AND_WIZARD.md +5 -3
- package/docs/06_PAYMENTS_X402_AND_PAYSH.md +82 -4
- package/docs/07_ENDPOINTS_AND_CLIENTS.md +7 -3
- package/docs/09_TOOLS_SKILLS_AND_AGENT_GUIDE.md +21 -3
- package/docs/14_DESKTOP_WIZARD_RELEASE.md +8 -6
- package/docs/16_SAP_AGENT_IDENTITY_PIPELINE.md +304 -0
- package/docs/18_PREMIUM_PLUGIN_RUNTIME.md +108 -0
- package/docs/BRANCH_AND_CI.md +67 -0
- package/docs/README.md +19 -2
- package/docs/magicblock-tools.md +70 -29
- package/package.json +10 -6
- package/server.json +3 -3
- package/skills/README.md +12 -2
- package/skills/sap-agent-registry/SKILL.md +99 -4
- package/skills/sap-defi/SKILL.md +8 -4
- package/skills/sap-discovery-indexing/SKILL.md +26 -4
- package/skills/sap-escrow-settlement/SKILL.md +22 -4
- package/skills/sap-mcp/SKILL.md +140 -22
- package/skills/sap-mcp/TOOL_REFERENCE.md +47 -7
- package/skills/sap-nft-metaplex/SKILL.md +22 -0
- package/skills/sap-operations/SKILL.md +32 -3
- package/skills/sap-payments-x402/SKILL.md +85 -8
- package/skills/sap-sns/SKILL.md +32 -10
- package/smithery.config.schema.json +7 -0
|
@@ -5,18 +5,233 @@
|
|
|
5
5
|
* `@oobe-protocol-labs/synapse-sap-sdk@1.0.x`. It does not create local
|
|
6
6
|
* facades for missing SDK namespaces and it does not fabricate network data.
|
|
7
7
|
*/
|
|
8
|
-
import { PublicKey } from '@solana/web3.js';
|
|
8
|
+
import { PublicKey, SystemProgram, Transaction } from '@solana/web3.js';
|
|
9
9
|
import BN from 'bn.js';
|
|
10
|
-
import { TOOL_CATEGORY_VALUES } from '@oobe-protocol-labs/synapse-sap-sdk';
|
|
10
|
+
import { Pda, TOOL_CATEGORY_VALUES, USDC_MINT_DEVNET, USDC_MINT_MAINNET } from '@oobe-protocol-labs/synapse-sap-sdk';
|
|
11
11
|
import { SettlementMode, TokenType, } from '@oobe-protocol-labs/synapse-sap-sdk/types';
|
|
12
12
|
import { createTextResponse } from '../adapters/mcp/tool-response.js';
|
|
13
13
|
import { registerTool } from '../adapters/mcp/sdk-compat.js';
|
|
14
14
|
import { getSapClient, isSapClientInitialized } from '../sap/sap-client-manager.js';
|
|
15
15
|
import { logger } from '../core/logger.js';
|
|
16
|
+
import { DEFAULT_SAP_PROGRAM_ID, SAP_PROTOCOL_TREASURY, SAP_REGISTRATION_FEE_LAMPORTS, } from '../core/constants.js';
|
|
17
|
+
import { classifyTool } from '../payments/pricing.js';
|
|
16
18
|
const ESCROW_AMOUNT_DESCRIPTION = 'Amount in the escrow token smallest unit: lamports for SOL, micro-USDC for USDC, or base units for the configured SPL token.';
|
|
17
19
|
const ESCROW_V2_COSIGNED_MODE = 1;
|
|
18
20
|
const ESCROW_V2_DISPUTE_WINDOW_MODE = 2;
|
|
19
21
|
const DEFAULT_ESCROW_V2_DISPUTE_WINDOW_SLOTS = new BN(2160);
|
|
22
|
+
const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
|
|
23
|
+
const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
|
|
24
|
+
export const SAP_AGENT_CAPABILITY_INPUT_SCHEMA = {
|
|
25
|
+
oneOf: [
|
|
26
|
+
{
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Capability id shorthand, for example jupiter:swap, pyth:price, metaplex:identity, sns:identity, or risk:management.',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {
|
|
33
|
+
id: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
description: 'Required stable capability id. Use protocol:action naming, for example jupiter:swap, pyth:price, metaplex:identity, sns:identity, x402:payments, or risk:management.',
|
|
36
|
+
},
|
|
37
|
+
description: {
|
|
38
|
+
type: 'string',
|
|
39
|
+
description: 'Optional human-readable capability description for agents and explorers.',
|
|
40
|
+
},
|
|
41
|
+
protocolId: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Optional protocol namespace backing this capability, for example sap, mcp, jupiter, pyth, metaplex, sns, x402, or custom.',
|
|
44
|
+
},
|
|
45
|
+
version: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'Optional capability version string. Use semver when the capability maps to an API contract.',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
required: ['id'],
|
|
51
|
+
additionalProperties: false,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
export const SAP_AGENT_PRICING_TIER_INPUT_SCHEMA = {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
tierId: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
description: 'Stable tier id, for example default, read, premium, value-action, or enterprise.',
|
|
61
|
+
},
|
|
62
|
+
pricePerCall: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: 'Price per call in the smallest unit of tokenType: lamports for sol, micro-USDC for usdc, or base units for spl.',
|
|
65
|
+
},
|
|
66
|
+
minPricePerCall: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: 'Optional floor price per call in the smallest unit of tokenType.',
|
|
69
|
+
},
|
|
70
|
+
maxPricePerCall: {
|
|
71
|
+
type: 'string',
|
|
72
|
+
description: 'Optional ceiling price per call in the smallest unit of tokenType.',
|
|
73
|
+
},
|
|
74
|
+
rateLimit: {
|
|
75
|
+
type: 'number',
|
|
76
|
+
description: 'Maximum calls per second allowed by this tier. Defaults to 60.',
|
|
77
|
+
},
|
|
78
|
+
maxCallsPerSession: {
|
|
79
|
+
type: 'number',
|
|
80
|
+
description: 'Maximum calls allowed per session for this tier. Defaults to 1000.',
|
|
81
|
+
},
|
|
82
|
+
burstLimit: {
|
|
83
|
+
type: 'number',
|
|
84
|
+
description: 'Optional short-window burst allowance for this tier.',
|
|
85
|
+
},
|
|
86
|
+
tokenType: {
|
|
87
|
+
type: 'string',
|
|
88
|
+
enum: ['sol', 'usdc', 'spl'],
|
|
89
|
+
description: 'Payment token type. Use usdc for x402/pay.sh agent commerce. Use spl only with tokenMint.',
|
|
90
|
+
},
|
|
91
|
+
tokenMint: {
|
|
92
|
+
type: 'string',
|
|
93
|
+
description: 'Optional SPL token mint public key. Required when tokenType is spl. For mainnet USDC use EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v.',
|
|
94
|
+
},
|
|
95
|
+
tokenDecimals: {
|
|
96
|
+
type: 'number',
|
|
97
|
+
description: 'Decimals for the payment token. Defaults to 6 for usdc and 9 for sol when omitted.',
|
|
98
|
+
},
|
|
99
|
+
settlementMode: {
|
|
100
|
+
type: 'string',
|
|
101
|
+
enum: ['instant', 'escrow', 'batched', 'x402'],
|
|
102
|
+
description: 'Settlement strategy. Use x402 for HTTP 402/pay.sh flows, escrow for prepaid SAP usage ledgers, instant for direct pay-per-call, and batched for periodic settlement.',
|
|
103
|
+
},
|
|
104
|
+
minEscrowDeposit: {
|
|
105
|
+
type: 'string',
|
|
106
|
+
description: 'Optional minimum escrow deposit in the smallest unit of tokenType.',
|
|
107
|
+
},
|
|
108
|
+
batchIntervalSec: {
|
|
109
|
+
type: 'number',
|
|
110
|
+
description: 'Optional settlement batch interval in seconds when settlementMode is batched.',
|
|
111
|
+
},
|
|
112
|
+
volumeCurve: {
|
|
113
|
+
type: 'array',
|
|
114
|
+
description: 'Optional volume discounts. Each item lowers pricePerCall after a call threshold.',
|
|
115
|
+
items: {
|
|
116
|
+
type: 'object',
|
|
117
|
+
properties: {
|
|
118
|
+
afterCalls: { type: 'number', description: 'Call count threshold where this price starts.' },
|
|
119
|
+
pricePerCall: { type: 'string', description: 'Discounted price per call in the smallest unit of tokenType.' },
|
|
120
|
+
},
|
|
121
|
+
required: ['afterCalls', 'pricePerCall'],
|
|
122
|
+
additionalProperties: false,
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
required: ['pricePerCall'],
|
|
127
|
+
additionalProperties: false,
|
|
128
|
+
};
|
|
129
|
+
export const SAP_AGENT_REGISTER_INPUT_SCHEMA = {
|
|
130
|
+
name: {
|
|
131
|
+
type: 'string',
|
|
132
|
+
description: 'Required public display name for the SAP agent. Keep it stable enough for explorers and humans.',
|
|
133
|
+
},
|
|
134
|
+
description: {
|
|
135
|
+
type: 'string',
|
|
136
|
+
description: 'Required public description of what the agent does, which protocols it can use, and its safety/trust boundaries.',
|
|
137
|
+
},
|
|
138
|
+
capabilities: {
|
|
139
|
+
type: 'array',
|
|
140
|
+
description: 'Required capability list. Prefer object form for production; strings are accepted as shorthand.',
|
|
141
|
+
items: SAP_AGENT_CAPABILITY_INPUT_SCHEMA,
|
|
142
|
+
},
|
|
143
|
+
pricing: {
|
|
144
|
+
type: 'array',
|
|
145
|
+
description: 'Optional pricing tiers advertised by the agent. Use tokenType usdc + settlementMode x402 for pay.sh/x402 agent commerce.',
|
|
146
|
+
items: SAP_AGENT_PRICING_TIER_INPUT_SCHEMA,
|
|
147
|
+
},
|
|
148
|
+
protocols: {
|
|
149
|
+
type: 'array',
|
|
150
|
+
items: { type: 'string' },
|
|
151
|
+
description: 'Required protocol tags the agent supports, for example sap, mcp, jupiter, pyth, metaplex, sns, x402, payments.',
|
|
152
|
+
},
|
|
153
|
+
agentId: {
|
|
154
|
+
type: 'string',
|
|
155
|
+
description: 'Optional stable lowercase agent id, for example solking. This is separate from the on-chain agent PDA.',
|
|
156
|
+
},
|
|
157
|
+
agentUri: {
|
|
158
|
+
type: 'string',
|
|
159
|
+
description: 'Optional public HTTPS/IPFS/Arweave/Kommodo URI for the agent profile metadata or profile page. Never use local desktop file paths.',
|
|
160
|
+
},
|
|
161
|
+
metadataUri: {
|
|
162
|
+
type: 'string',
|
|
163
|
+
description: 'Alias for agentUri. Prefer a public JSON metadata document containing name, description, image, external_url, attributes, sap, metaplex, sns, and x402 fields.',
|
|
164
|
+
},
|
|
165
|
+
x402Endpoint: {
|
|
166
|
+
type: 'string',
|
|
167
|
+
description: 'Optional public x402 discovery/payment endpoint, usually https://host/.well-known/x402 for external agent services.',
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
export const SAP_AGENT_UPDATE_INPUT_SCHEMA = {
|
|
171
|
+
name: {
|
|
172
|
+
type: 'string',
|
|
173
|
+
description: 'Optional replacement display name. Omit to keep the current name.',
|
|
174
|
+
},
|
|
175
|
+
description: {
|
|
176
|
+
type: 'string',
|
|
177
|
+
description: 'Optional replacement description. Omit to keep the current description.',
|
|
178
|
+
},
|
|
179
|
+
capabilities: {
|
|
180
|
+
type: 'array',
|
|
181
|
+
description: 'Optional full replacement capability list. Omit to keep current capabilities; do not send only the new item unless replacing the whole list is intended.',
|
|
182
|
+
items: SAP_AGENT_CAPABILITY_INPUT_SCHEMA,
|
|
183
|
+
},
|
|
184
|
+
pricing: {
|
|
185
|
+
type: 'array',
|
|
186
|
+
description: 'Optional full replacement pricing tier list. Omit to keep current pricing.',
|
|
187
|
+
items: SAP_AGENT_PRICING_TIER_INPUT_SCHEMA,
|
|
188
|
+
},
|
|
189
|
+
protocols: {
|
|
190
|
+
type: 'array',
|
|
191
|
+
items: { type: 'string' },
|
|
192
|
+
description: 'Optional full replacement protocol list. Omit to keep current protocols.',
|
|
193
|
+
},
|
|
194
|
+
agentId: {
|
|
195
|
+
type: 'string',
|
|
196
|
+
description: 'Optional replacement stable agent id. Omit to keep current agentId.',
|
|
197
|
+
},
|
|
198
|
+
agentUri: {
|
|
199
|
+
type: 'string',
|
|
200
|
+
description: 'Optional replacement public URI for agent metadata/profile. Use this to update pictures after uploading metadata to IPFS, Arweave, Kommodo, or HTTPS.',
|
|
201
|
+
},
|
|
202
|
+
metadataUri: {
|
|
203
|
+
type: 'string',
|
|
204
|
+
description: 'Alias for agentUri. Use a public metadata JSON URI; never use a desktop file path.',
|
|
205
|
+
},
|
|
206
|
+
x402Endpoint: {
|
|
207
|
+
type: 'string',
|
|
208
|
+
description: 'Optional replacement x402 discovery/payment endpoint. Omit to keep current endpoint.',
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
const SAP_AGENT_IDENTITY_PLAN_INPUT_SCHEMA = {
|
|
212
|
+
intendedAction: {
|
|
213
|
+
type: 'string',
|
|
214
|
+
enum: ['register', 'update', 'link-metaplex', 'link-sns', 'full-identity'],
|
|
215
|
+
description: 'Agent identity lifecycle step to plan. Use register for a new SAP agent, update for profile/image/capability changes, link-metaplex for NFT/MPL Core identity, link-sns for .sol identity, or full-identity for the recommended end-to-end flow.',
|
|
216
|
+
},
|
|
217
|
+
...SAP_AGENT_REGISTER_INPUT_SCHEMA,
|
|
218
|
+
snsDomain: {
|
|
219
|
+
type: 'string',
|
|
220
|
+
description: 'Optional .sol domain to link after ownership or registration is verified.',
|
|
221
|
+
},
|
|
222
|
+
imageUrl: {
|
|
223
|
+
type: 'string',
|
|
224
|
+
description: 'Optional public image URL. This must be HTTPS, IPFS, Arweave, or another public URI; desktop file paths are not valid.',
|
|
225
|
+
},
|
|
226
|
+
metaplexAsset: {
|
|
227
|
+
type: 'string',
|
|
228
|
+
description: 'Optional Metaplex NFT or MPL Core asset/collection address to reference from public agent metadata.',
|
|
229
|
+
},
|
|
230
|
+
ownerWallet: {
|
|
231
|
+
type: 'string',
|
|
232
|
+
description: 'Optional expected SAP owner wallet. Use this for verification planning only; signing still comes from the active local SAP profile.',
|
|
233
|
+
},
|
|
234
|
+
};
|
|
20
235
|
const escrowV2CreateInputSchema = {
|
|
21
236
|
agentWallet: {
|
|
22
237
|
type: 'string',
|
|
@@ -68,6 +283,122 @@ const escrowV2CreateInputSchema = {
|
|
|
68
283
|
description: 'Optional arbiter public key kept for IDL compatibility and dispute workflows.',
|
|
69
284
|
},
|
|
70
285
|
};
|
|
286
|
+
const escrowV2CreateBuilderInputSchema = {
|
|
287
|
+
depositorWallet: {
|
|
288
|
+
type: 'string',
|
|
289
|
+
description: 'Depositor wallet public key (base58). This wallet signs locally and funds the escrow; hosted SAP MCP never receives its private key.',
|
|
290
|
+
},
|
|
291
|
+
...escrowV2CreateInputSchema,
|
|
292
|
+
};
|
|
293
|
+
const escrowV2DepositBuilderInputSchema = {
|
|
294
|
+
depositorWallet: {
|
|
295
|
+
type: 'string',
|
|
296
|
+
description: 'Depositor wallet public key (base58). This wallet signs locally and provides the additional escrow funds.',
|
|
297
|
+
},
|
|
298
|
+
agentWallet: {
|
|
299
|
+
type: 'string',
|
|
300
|
+
description: 'Agent owner wallet public key (base58). The escrow PDA is derived from agentWallet, depositorWallet, and nonce.',
|
|
301
|
+
},
|
|
302
|
+
nonce: {
|
|
303
|
+
type: 'string',
|
|
304
|
+
description: 'Optional escrow nonce as a decimal string. Defaults to 0.',
|
|
305
|
+
},
|
|
306
|
+
amount: {
|
|
307
|
+
type: 'string',
|
|
308
|
+
description: `Deposit amount as a decimal string. ${ESCROW_AMOUNT_DESCRIPTION}`,
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
const escrowV2WithdrawBuilderInputSchema = {
|
|
312
|
+
depositorWallet: {
|
|
313
|
+
type: 'string',
|
|
314
|
+
description: 'Depositor wallet public key (base58). Only the depositor can locally sign a withdrawal from this escrow.',
|
|
315
|
+
},
|
|
316
|
+
agentWallet: {
|
|
317
|
+
type: 'string',
|
|
318
|
+
description: 'Agent owner wallet public key (base58). The escrow PDA is derived from agentWallet, depositorWallet, and nonce.',
|
|
319
|
+
},
|
|
320
|
+
nonce: {
|
|
321
|
+
type: 'string',
|
|
322
|
+
description: 'Optional escrow nonce as a decimal string. Defaults to 0.',
|
|
323
|
+
},
|
|
324
|
+
amount: {
|
|
325
|
+
type: 'string',
|
|
326
|
+
description: `Withdrawal amount as a decimal string. ${ESCROW_AMOUNT_DESCRIPTION}`,
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
const escrowV2SettleBuilderInputSchema = {
|
|
330
|
+
agentWallet: {
|
|
331
|
+
type: 'string',
|
|
332
|
+
description: 'Agent owner wallet public key (base58). This wallet signs locally because settlement releases funds to the serving agent.',
|
|
333
|
+
},
|
|
334
|
+
depositorWallet: {
|
|
335
|
+
type: 'string',
|
|
336
|
+
description: 'Depositor wallet public key (base58) for the escrow being settled.',
|
|
337
|
+
},
|
|
338
|
+
nonce: {
|
|
339
|
+
type: 'string',
|
|
340
|
+
description: 'Optional escrow nonce as a decimal string. Defaults to 0.',
|
|
341
|
+
},
|
|
342
|
+
callsToSettle: {
|
|
343
|
+
type: 'string',
|
|
344
|
+
description: 'Number of served calls to settle as a decimal string.',
|
|
345
|
+
},
|
|
346
|
+
serviceHash: {
|
|
347
|
+
oneOf: [
|
|
348
|
+
{
|
|
349
|
+
type: 'array',
|
|
350
|
+
items: { type: 'number' },
|
|
351
|
+
description: '32-byte service/audit hash as byte array.',
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
type: 'string',
|
|
355
|
+
description: '32-byte service/audit hash encoded as 64-char hex or base64 string.',
|
|
356
|
+
},
|
|
357
|
+
],
|
|
358
|
+
description: '32-byte service/audit hash. Use a stable hash of the fulfilled paid work.',
|
|
359
|
+
},
|
|
360
|
+
coSigner: {
|
|
361
|
+
type: 'string',
|
|
362
|
+
description: 'Optional co-signer public key for CoSigned escrows when the escrow account requires it.',
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
const escrowV2FinalizeBuilderInputSchema = {
|
|
366
|
+
payerWallet: {
|
|
367
|
+
type: 'string',
|
|
368
|
+
description: 'Wallet public key (base58) that signs and pays transaction fees to finalize the pending settlement.',
|
|
369
|
+
},
|
|
370
|
+
agentWallet: {
|
|
371
|
+
type: 'string',
|
|
372
|
+
description: 'Agent owner wallet public key (base58).',
|
|
373
|
+
},
|
|
374
|
+
depositorWallet: {
|
|
375
|
+
type: 'string',
|
|
376
|
+
description: 'Depositor wallet public key (base58).',
|
|
377
|
+
},
|
|
378
|
+
nonce: {
|
|
379
|
+
type: 'string',
|
|
380
|
+
description: 'Optional escrow nonce as a decimal string. Defaults to 0.',
|
|
381
|
+
},
|
|
382
|
+
settlementIndex: {
|
|
383
|
+
type: 'string',
|
|
384
|
+
description: 'Pending settlement index as a decimal string.',
|
|
385
|
+
},
|
|
386
|
+
};
|
|
387
|
+
const escrowV2CloseBuilderInputSchema = {
|
|
388
|
+
depositorWallet: {
|
|
389
|
+
type: 'string',
|
|
390
|
+
description: 'Depositor wallet public key (base58). The depositor signs locally to close the empty escrow.',
|
|
391
|
+
},
|
|
392
|
+
agentWallet: {
|
|
393
|
+
type: 'string',
|
|
394
|
+
description: 'Agent owner wallet public key (base58).',
|
|
395
|
+
},
|
|
396
|
+
nonce: {
|
|
397
|
+
type: 'string',
|
|
398
|
+
description: 'Optional escrow nonce as a decimal string. Defaults to 0.',
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
const directoryPageInflight = new Map();
|
|
71
402
|
/**
|
|
72
403
|
* @name jsonReplacer
|
|
73
404
|
* @description Serializes SDK values such as PublicKey, BN, bigint, Buffer, and Uint8Array into JSON-safe output.
|
|
@@ -90,9 +421,29 @@ function jsonReplacer(_key, value) {
|
|
|
90
421
|
/**
|
|
91
422
|
* @name ok
|
|
92
423
|
* @description Wraps a successful tool result in the MCP text response shape.
|
|
424
|
+
* Includes hostedPricing metadata so agents know the tier and estimated cost.
|
|
93
425
|
*/
|
|
94
|
-
function ok(payload) {
|
|
95
|
-
|
|
426
|
+
function ok(payload, toolName) {
|
|
427
|
+
const pricingMeta = toolName ? buildHostedPricingMeta(toolName) : undefined;
|
|
428
|
+
return createTextResponse(JSON.stringify({ success: true, ...(pricingMeta ? { hostedPricing: pricingMeta } : {}), ...asObjectPayload(payload) }, jsonReplacer, 2));
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* @name buildHostedPricingMeta
|
|
432
|
+
* @description Returns a human-readable pricing hint for a SAP SDK tool.
|
|
433
|
+
* Uses the same classifyTool function as the hosted monetization gate.
|
|
434
|
+
*/
|
|
435
|
+
function buildHostedPricingMeta(toolName) {
|
|
436
|
+
const tier = classifyTool(toolName);
|
|
437
|
+
if (tier === 'free')
|
|
438
|
+
return 'free — no x402 payment required';
|
|
439
|
+
const prices = {
|
|
440
|
+
'read-premium': '~$0.001',
|
|
441
|
+
'builder': '~$0.008',
|
|
442
|
+
'value-action': '~$0.09 standard / ~$0.05 heavy',
|
|
443
|
+
'batch': '~$0.09+',
|
|
444
|
+
};
|
|
445
|
+
const price = prices[tier] ?? '~$0.001';
|
|
446
|
+
return `${tier} tier — estimated ${price} USD per call. Use sap_estimate_tool_cost for exact pricing.`;
|
|
96
447
|
}
|
|
97
448
|
/**
|
|
98
449
|
* @name asObjectPayload
|
|
@@ -110,6 +461,22 @@ function asObjectPayload(payload) {
|
|
|
110
461
|
function getSapAnchorAccounts(client) {
|
|
111
462
|
return client.program.account;
|
|
112
463
|
}
|
|
464
|
+
function stableJson(value) {
|
|
465
|
+
if (value === undefined) {
|
|
466
|
+
return 'undefined';
|
|
467
|
+
}
|
|
468
|
+
if (value === null) {
|
|
469
|
+
return 'null';
|
|
470
|
+
}
|
|
471
|
+
if (typeof value !== 'object') {
|
|
472
|
+
return JSON.stringify(value) ?? String(value);
|
|
473
|
+
}
|
|
474
|
+
if (Array.isArray(value)) {
|
|
475
|
+
return `[${value.map(stableJson).join(',')}]`;
|
|
476
|
+
}
|
|
477
|
+
const record = value;
|
|
478
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(',')}}`;
|
|
479
|
+
}
|
|
113
480
|
/**
|
|
114
481
|
* @name bnString
|
|
115
482
|
* @description Converts BN-like SDK counters into stable decimal strings.
|
|
@@ -147,6 +514,40 @@ function summarizeProtocolIndexes(protocolIndexes) {
|
|
|
147
514
|
}))
|
|
148
515
|
.sort((left, right) => left.protocolId.localeCompare(right.protocolId));
|
|
149
516
|
}
|
|
517
|
+
function normalizeDirectoryToken(value) {
|
|
518
|
+
return value.trim().toLowerCase();
|
|
519
|
+
}
|
|
520
|
+
function matchesNormalizedValue(values, expected) {
|
|
521
|
+
const normalizedExpected = normalizeDirectoryToken(expected);
|
|
522
|
+
return values.some((value) => normalizeDirectoryToken(value) === normalizedExpected);
|
|
523
|
+
}
|
|
524
|
+
function matchesNormalizedSubstring(values, query) {
|
|
525
|
+
return values.some((value) => normalizeDirectoryToken(value).includes(query));
|
|
526
|
+
}
|
|
527
|
+
function encodeDirectoryCursor(offset) {
|
|
528
|
+
return encodeDirectoryCursorPayload(offset);
|
|
529
|
+
}
|
|
530
|
+
function decodeDirectoryCursor(cursor) {
|
|
531
|
+
if (!cursor) {
|
|
532
|
+
return undefined;
|
|
533
|
+
}
|
|
534
|
+
try {
|
|
535
|
+
const parsed = decodeDirectoryCursorPayload(cursor);
|
|
536
|
+
const offset = parsed.offset;
|
|
537
|
+
return typeof offset === 'number' && Number.isInteger(offset) && offset >= 0 ? offset : undefined;
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
throw new Error('cursor must be a nextCursor value returned by sap_list_all_agents or sap_discover_agents');
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
function encodeDirectoryCursorPayload(offset) {
|
|
544
|
+
const base64 = Buffer.from(JSON.stringify({ offset }), 'utf-8').toString('base64');
|
|
545
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/u, '');
|
|
546
|
+
}
|
|
547
|
+
function decodeDirectoryCursorPayload(cursor) {
|
|
548
|
+
const padded = cursor.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(cursor.length / 4) * 4, '=');
|
|
549
|
+
return JSON.parse(Buffer.from(padded, 'base64').toString('utf-8'));
|
|
550
|
+
}
|
|
150
551
|
/**
|
|
151
552
|
* @name buildAgentDirectoryEntry
|
|
152
553
|
* @description Converts an AgentAccount into a compact directory row with optional stats and protocol-index membership.
|
|
@@ -185,14 +586,355 @@ function matchesAgentDirectoryFilters(entry, filters) {
|
|
|
185
586
|
if (!filters.includeInactive && !entry.isActive) {
|
|
186
587
|
return false;
|
|
187
588
|
}
|
|
188
|
-
if (filters.
|
|
589
|
+
if (filters.wallet && normalizeDirectoryToken(entry.wallet) !== normalizeDirectoryToken(filters.wallet)) {
|
|
590
|
+
return false;
|
|
591
|
+
}
|
|
592
|
+
if (filters.agentPda && normalizeDirectoryToken(entry.agentPda) !== normalizeDirectoryToken(filters.agentPda)) {
|
|
189
593
|
return false;
|
|
190
594
|
}
|
|
191
|
-
if (filters.
|
|
595
|
+
if (filters.hasX402Endpoint !== undefined && Boolean(entry.x402Endpoint) !== filters.hasX402Endpoint) {
|
|
192
596
|
return false;
|
|
193
597
|
}
|
|
598
|
+
if (filters.protocol
|
|
599
|
+
&& !matchesNormalizedValue(entry.protocols, filters.protocol)
|
|
600
|
+
&& !matchesNormalizedValue(entry.indexedProtocols, filters.protocol)) {
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
const requiredCapabilities = [
|
|
604
|
+
...(filters.capability ? [filters.capability] : []),
|
|
605
|
+
...(filters.capabilities ?? []),
|
|
606
|
+
];
|
|
607
|
+
if (requiredCapabilities.length > 0) {
|
|
608
|
+
const mode = filters.capabilityMode ?? 'any';
|
|
609
|
+
const predicate = (capability) => matchesNormalizedValue(entry.capabilities, capability);
|
|
610
|
+
if (mode === 'all' ? !requiredCapabilities.every(predicate) : !requiredCapabilities.some(predicate)) {
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
const query = filters.query ? normalizeDirectoryToken(filters.query) : undefined;
|
|
615
|
+
if (query) {
|
|
616
|
+
const searchableValues = [
|
|
617
|
+
entry.agentPda,
|
|
618
|
+
entry.wallet,
|
|
619
|
+
entry.name,
|
|
620
|
+
entry.description,
|
|
621
|
+
entry.agentId,
|
|
622
|
+
entry.agentUri,
|
|
623
|
+
entry.x402Endpoint,
|
|
624
|
+
...entry.protocols,
|
|
625
|
+
...entry.indexedProtocols,
|
|
626
|
+
...entry.capabilities,
|
|
627
|
+
...entry.activePlugins,
|
|
628
|
+
].filter((value) => typeof value === 'string');
|
|
629
|
+
if (!matchesNormalizedSubstring(searchableValues, query)) {
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
194
633
|
return true;
|
|
195
634
|
}
|
|
635
|
+
function compactAgentDirectoryEntry(entry) {
|
|
636
|
+
return {
|
|
637
|
+
agentPda: entry.agentPda,
|
|
638
|
+
wallet: entry.wallet,
|
|
639
|
+
name: entry.name,
|
|
640
|
+
description: entry.description,
|
|
641
|
+
agentId: entry.agentId,
|
|
642
|
+
x402Endpoint: entry.x402Endpoint,
|
|
643
|
+
isActive: entry.isActive,
|
|
644
|
+
protocols: entry.protocols,
|
|
645
|
+
indexedProtocols: entry.indexedProtocols,
|
|
646
|
+
capabilities: entry.capabilities,
|
|
647
|
+
reputationScore: entry.reputationScore,
|
|
648
|
+
totalCallsServed: entry.totalCallsServed,
|
|
649
|
+
uptimePercent: entry.uptimePercent,
|
|
650
|
+
createdAt: entry.createdAt,
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
function directoryAgentGuidance(page) {
|
|
654
|
+
return {
|
|
655
|
+
paidHostedRead: true,
|
|
656
|
+
useThisWhen: [
|
|
657
|
+
'The user asks to find SAP agents, list the ecosystem, inspect available on-chain agents, or discover x402-enabled agents.',
|
|
658
|
+
'Use query/protocol/capability/capabilities filters first; avoid repeated broad scans.',
|
|
659
|
+
],
|
|
660
|
+
pagination: page.hasMore
|
|
661
|
+
? `Call the same tool with cursor="${page.nextCursor}" to fetch the next page.`
|
|
662
|
+
: 'No further page is available for the current filters.',
|
|
663
|
+
nextTools: [
|
|
664
|
+
'sap_get_agent_profile with wallet for one hydrated owner profile.',
|
|
665
|
+
'sap_fetch_protocol_index with protocolId when the user wants protocol membership.',
|
|
666
|
+
'sap_fetch_capability_index with capabilityId when the user wants a capability-specific index.',
|
|
667
|
+
'sap_x402_estimate_cost before calling a paid x402 endpoint exposed by a discovered agent.',
|
|
668
|
+
],
|
|
669
|
+
matchingNotes: {
|
|
670
|
+
query: 'Matches name, description, agentId, wallet, PDA, endpoint, protocols, capabilities, and active plugin labels.',
|
|
671
|
+
capability: 'Capability matching is case-insensitive and exact after trimming. For multiple capabilities set capabilityMode to any or all.',
|
|
672
|
+
x402: 'Set hasX402Endpoint=true to find agents that advertise paid HTTP/x402 resources.',
|
|
673
|
+
},
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
async function buildAgentDirectoryPage(client, options) {
|
|
677
|
+
const accounts = getSapAnchorAccounts(client);
|
|
678
|
+
const [agentAccounts, statsAccounts, protocolIndexes, overview] = await Promise.all([
|
|
679
|
+
accounts.agentAccount.all(),
|
|
680
|
+
accounts.agentStats.all(),
|
|
681
|
+
accounts.protocolIndex.all(),
|
|
682
|
+
client.discovery.getNetworkOverview(),
|
|
683
|
+
]);
|
|
684
|
+
const statsByAgent = new Map(statsAccounts.map(({ account }) => [account.agent.toBase58(), account]));
|
|
685
|
+
const indexedProtocolsByAgent = buildProtocolMembership(protocolIndexes);
|
|
686
|
+
const filteredAgents = agentAccounts
|
|
687
|
+
.map((account) => buildAgentDirectoryEntry(account, statsByAgent, indexedProtocolsByAgent))
|
|
688
|
+
.filter((entry) => matchesAgentDirectoryFilters(entry, options))
|
|
689
|
+
.sort((left, right) => Number(right.createdAt) - Number(left.createdAt));
|
|
690
|
+
const page = filteredAgents.slice(options.offset, options.offset + options.limit);
|
|
691
|
+
const hasMore = options.offset + page.length < filteredAgents.length;
|
|
692
|
+
const nextOffset = hasMore ? options.offset + page.length : null;
|
|
693
|
+
const nextCursor = nextOffset === null ? null : encodeDirectoryCursor(nextOffset);
|
|
694
|
+
const agents = options.view === 'compact' ? page.map(compactAgentDirectoryEntry) : page;
|
|
695
|
+
return {
|
|
696
|
+
source: 'program.account.agentAccount.all + program.account.protocolIndex.all',
|
|
697
|
+
freshness: {
|
|
698
|
+
status: 'fresh',
|
|
699
|
+
cache: 'disabled',
|
|
700
|
+
fetchedAt: new Date().toISOString(),
|
|
701
|
+
},
|
|
702
|
+
overview,
|
|
703
|
+
filters: {
|
|
704
|
+
includeInactive: options.includeInactive,
|
|
705
|
+
protocol: options.protocol ?? null,
|
|
706
|
+
capability: options.capability ?? null,
|
|
707
|
+
capabilities: options.capabilities ?? [],
|
|
708
|
+
capabilityMode: options.capabilityMode ?? 'any',
|
|
709
|
+
query: options.query ?? null,
|
|
710
|
+
wallet: options.wallet ?? null,
|
|
711
|
+
agentPda: options.agentPda ?? null,
|
|
712
|
+
hasX402Endpoint: options.hasX402Endpoint ?? null,
|
|
713
|
+
view: options.view,
|
|
714
|
+
},
|
|
715
|
+
count: page.length,
|
|
716
|
+
totalEnumerated: filteredAgents.length,
|
|
717
|
+
returned: page.length,
|
|
718
|
+
offset: options.offset,
|
|
719
|
+
limit: options.limit,
|
|
720
|
+
truncated: hasMore,
|
|
721
|
+
pagination: {
|
|
722
|
+
total: filteredAgents.length,
|
|
723
|
+
returned: page.length,
|
|
724
|
+
offset: options.offset,
|
|
725
|
+
limit: options.limit,
|
|
726
|
+
hasMore,
|
|
727
|
+
nextOffset,
|
|
728
|
+
nextCursor,
|
|
729
|
+
},
|
|
730
|
+
totalAgentAccounts: agentAccounts.length,
|
|
731
|
+
activeAgentAccounts: agentAccounts.filter(({ account }) => account.isActive).length,
|
|
732
|
+
protocolIndexes: options.includeProtocolIndexes ? summarizeProtocolIndexes(protocolIndexes) : undefined,
|
|
733
|
+
agents,
|
|
734
|
+
agentGuidance: directoryAgentGuidance({ hasMore, nextCursor, filters: options }),
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
async function getFreshAgentDirectoryPage(client, options) {
|
|
738
|
+
const cacheKey = stableJson(options);
|
|
739
|
+
const inflight = directoryPageInflight.get(cacheKey);
|
|
740
|
+
if (inflight) {
|
|
741
|
+
const page = await inflight;
|
|
742
|
+
return {
|
|
743
|
+
...page,
|
|
744
|
+
freshness: {
|
|
745
|
+
...page.freshness,
|
|
746
|
+
status: 'fresh_joined_inflight',
|
|
747
|
+
cache: 'disabled',
|
|
748
|
+
key: cacheKey.slice(0, 24),
|
|
749
|
+
},
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
const load = buildAgentDirectoryPage(client, options)
|
|
753
|
+
.finally(() => {
|
|
754
|
+
directoryPageInflight.delete(cacheKey);
|
|
755
|
+
});
|
|
756
|
+
directoryPageInflight.set(cacheKey, load);
|
|
757
|
+
const page = await load;
|
|
758
|
+
return {
|
|
759
|
+
...page,
|
|
760
|
+
freshness: {
|
|
761
|
+
...page.freshness,
|
|
762
|
+
status: 'fresh',
|
|
763
|
+
cache: 'disabled',
|
|
764
|
+
key: cacheKey.slice(0, 24),
|
|
765
|
+
},
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
async function buildSapAgentContext(input, client) {
|
|
769
|
+
const wallet = optionalString(input, 'wallet');
|
|
770
|
+
const agentPda = optionalString(input, 'agentPda');
|
|
771
|
+
const query = optionalString(input, 'query');
|
|
772
|
+
const limit = Math.max(1, Math.min(optionalNumber(input, 'limit') ?? 10, 20));
|
|
773
|
+
const exact = {};
|
|
774
|
+
if (wallet) {
|
|
775
|
+
const owner = new PublicKey(wallet);
|
|
776
|
+
const derivedAgentPda = client.agent.deriveAgent(owner)[0].toBase58();
|
|
777
|
+
const [agent, active, profile] = await Promise.all([
|
|
778
|
+
client.agent.fetchNullable(owner),
|
|
779
|
+
client.discovery.isAgentActive(owner).catch(() => false),
|
|
780
|
+
client.discovery.getAgentProfile(owner).catch((error) => ({
|
|
781
|
+
unavailable: true,
|
|
782
|
+
reason: error instanceof Error ? error.message : 'profile_fetch_failed',
|
|
783
|
+
})),
|
|
784
|
+
]);
|
|
785
|
+
exact.wallet = wallet;
|
|
786
|
+
exact.agentPda = derivedAgentPda;
|
|
787
|
+
exact.active = active;
|
|
788
|
+
exact.agent = agent;
|
|
789
|
+
exact.profile = profile;
|
|
790
|
+
}
|
|
791
|
+
const directory = wallet
|
|
792
|
+
? null
|
|
793
|
+
: await getFreshAgentDirectoryPage(client, {
|
|
794
|
+
includeInactive: false,
|
|
795
|
+
protocol: undefined,
|
|
796
|
+
capability: undefined,
|
|
797
|
+
capabilities: [],
|
|
798
|
+
capabilityMode: 'any',
|
|
799
|
+
query,
|
|
800
|
+
wallet: undefined,
|
|
801
|
+
agentPda,
|
|
802
|
+
hasX402Endpoint: undefined,
|
|
803
|
+
limit,
|
|
804
|
+
offset: 0,
|
|
805
|
+
view: 'compact',
|
|
806
|
+
includeProtocolIndexes: false,
|
|
807
|
+
});
|
|
808
|
+
return {
|
|
809
|
+
contextType: wallet ? 'exact-wallet' : agentPda ? 'exact-agent-pda' : query ? 'compact-query' : 'compact-orientation',
|
|
810
|
+
freeRead: true,
|
|
811
|
+
exact,
|
|
812
|
+
directory,
|
|
813
|
+
routing: {
|
|
814
|
+
firstReads: [
|
|
815
|
+
'Use sap_get_agent or sap_get_agent_profile when the owner wallet is known.',
|
|
816
|
+
'Use sap_list_agents with limit <= 20 and view: compact for free orientation.',
|
|
817
|
+
'Use sap_discover_agents or sap_list_all_agents only for paid search, enriched rows, large pages, or ecosystem-scale scans.',
|
|
818
|
+
],
|
|
819
|
+
paidHostedTools: 'Use sap_payments_call_paid_tool when a hosted tool returns x402 payment_required and the runtime cannot replay x402 natively.',
|
|
820
|
+
registryWrites: 'Use sap_payments_register_agent and sap_payments_update_agent for wallet-owned SAP registry writes. Do not retry hosted accountless writes after hosted_local_signer_required.',
|
|
821
|
+
unsignedTransactions: 'Use hosted builders when available, then sap_payments_finalize_transaction with submit:true after user confirmation.',
|
|
822
|
+
},
|
|
823
|
+
nextActions: [
|
|
824
|
+
wallet ? 'If the user wants details, use the exact profile already returned here before paid discovery.' : 'If the user selects an agent row, call sap_get_agent_profile with that row wallet.',
|
|
825
|
+
'For registration or image/profile updates, call sap_agent_identity_plan before any write.',
|
|
826
|
+
'For paid or write flows, call sap_payments_readiness first when the local bridge is visible.',
|
|
827
|
+
],
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
function parseCapabilityMode(input) {
|
|
831
|
+
const mode = optionalString(input, 'capabilityMode')?.trim().toLowerCase();
|
|
832
|
+
if (!mode) {
|
|
833
|
+
return 'any';
|
|
834
|
+
}
|
|
835
|
+
if (mode === 'any' || mode === 'all') {
|
|
836
|
+
return mode;
|
|
837
|
+
}
|
|
838
|
+
throw new Error('capabilityMode must be "any" or "all"');
|
|
839
|
+
}
|
|
840
|
+
function parseOptionalStringArray(input, field) {
|
|
841
|
+
const value = input[field];
|
|
842
|
+
if (value === undefined || value === null) {
|
|
843
|
+
return [];
|
|
844
|
+
}
|
|
845
|
+
if (!Array.isArray(value)) {
|
|
846
|
+
throw new Error(`${field} must be an array of strings`);
|
|
847
|
+
}
|
|
848
|
+
return value
|
|
849
|
+
.filter((item) => typeof item === 'string' && item.trim().length > 0)
|
|
850
|
+
.map((item) => item.trim());
|
|
851
|
+
}
|
|
852
|
+
function parseDirectoryOffset(input) {
|
|
853
|
+
return Math.max(0, decodeDirectoryCursor(optionalString(input, 'cursor')) ?? optionalNumber(input, 'offset') ?? 0);
|
|
854
|
+
}
|
|
855
|
+
function parseDirectoryView(input) {
|
|
856
|
+
const view = optionalString(input, 'view');
|
|
857
|
+
if (!view && input.hydrate === true) {
|
|
858
|
+
return 'full';
|
|
859
|
+
}
|
|
860
|
+
if (!view || view === 'compact') {
|
|
861
|
+
return 'compact';
|
|
862
|
+
}
|
|
863
|
+
if (view === 'full') {
|
|
864
|
+
return 'full';
|
|
865
|
+
}
|
|
866
|
+
throw new Error('view must be "compact" or "full"');
|
|
867
|
+
}
|
|
868
|
+
function parseHasX402Endpoint(input) {
|
|
869
|
+
return optionalBoolean(input, 'hasX402Endpoint');
|
|
870
|
+
}
|
|
871
|
+
function makeAgentDirectoryInputSchema(defaultLimit) {
|
|
872
|
+
return {
|
|
873
|
+
query: {
|
|
874
|
+
type: 'string',
|
|
875
|
+
description: 'Optional text search across name, description, agentId, wallet, PDA, x402 endpoint, protocols, capabilities, and active plugins. Example: "XONA" or "creative".',
|
|
876
|
+
},
|
|
877
|
+
wallet: {
|
|
878
|
+
type: 'string',
|
|
879
|
+
description: 'Optional exact owner wallet public key filter. Use this when a wallet is known; it is the most reliable lookup path.',
|
|
880
|
+
},
|
|
881
|
+
agentPda: {
|
|
882
|
+
type: 'string',
|
|
883
|
+
description: 'Optional exact SAP agent PDA filter.',
|
|
884
|
+
},
|
|
885
|
+
protocol: {
|
|
886
|
+
type: 'string',
|
|
887
|
+
description: 'Optional protocol filter matched case-insensitively against agent protocols and protocol-index membership. Example: "jupiter", "creative", "payments".',
|
|
888
|
+
},
|
|
889
|
+
capability: {
|
|
890
|
+
type: 'string',
|
|
891
|
+
description: 'Optional single capability ID filter matched case-insensitively. Example: "creative:imageGeneration" or "jupiter:swap".',
|
|
892
|
+
},
|
|
893
|
+
capabilities: {
|
|
894
|
+
type: 'array',
|
|
895
|
+
items: { type: 'string' },
|
|
896
|
+
description: 'Optional list of capability IDs. Use capabilityMode="all" when the agent must have every capability.',
|
|
897
|
+
},
|
|
898
|
+
capabilityMode: {
|
|
899
|
+
type: 'string',
|
|
900
|
+
enum: ['any', 'all'],
|
|
901
|
+
description: 'How to match the capability/capabilities filters. Defaults to "any".',
|
|
902
|
+
},
|
|
903
|
+
hasX402Endpoint: {
|
|
904
|
+
type: 'boolean',
|
|
905
|
+
description: 'Optional filter for agents that advertise a paid HTTP/x402 endpoint.',
|
|
906
|
+
},
|
|
907
|
+
includeInactive: {
|
|
908
|
+
type: 'boolean',
|
|
909
|
+
description: 'Include inactive agents. Defaults to false.',
|
|
910
|
+
},
|
|
911
|
+
limit: {
|
|
912
|
+
type: 'number',
|
|
913
|
+
description: `Maximum rows to return. Defaults to ${defaultLimit}; hard-capped at 500.`,
|
|
914
|
+
},
|
|
915
|
+
offset: {
|
|
916
|
+
type: 'number',
|
|
917
|
+
description: 'Zero-based pagination offset. Defaults to 0. Prefer cursor after the first page when nextCursor is returned.',
|
|
918
|
+
},
|
|
919
|
+
cursor: {
|
|
920
|
+
type: 'string',
|
|
921
|
+
description: 'Opaque pagination cursor returned as pagination.nextCursor by a previous sap_list_all_agents or sap_discover_agents call.',
|
|
922
|
+
},
|
|
923
|
+
view: {
|
|
924
|
+
type: 'string',
|
|
925
|
+
enum: ['compact', 'full'],
|
|
926
|
+
description: 'Result shape. Use compact for broad discovery and full for detailed rows. Defaults to compact.',
|
|
927
|
+
},
|
|
928
|
+
hydrate: {
|
|
929
|
+
type: 'boolean',
|
|
930
|
+
description: 'Deprecated compatibility alias. Use view="full" for full rows or view="compact" for directory rows.',
|
|
931
|
+
},
|
|
932
|
+
includeProtocolIndexes: {
|
|
933
|
+
type: 'boolean',
|
|
934
|
+
description: 'Include compact protocol index summaries. Defaults to false for sap_discover_agents and true for sap_list_all_agents.',
|
|
935
|
+
},
|
|
936
|
+
};
|
|
937
|
+
}
|
|
196
938
|
/**
|
|
197
939
|
* @name asRecord
|
|
198
940
|
* @description Normalizes MCP tool input into an object.
|
|
@@ -317,6 +1059,45 @@ function parseVolumeCurve(value) {
|
|
|
317
1059
|
};
|
|
318
1060
|
});
|
|
319
1061
|
}
|
|
1062
|
+
/**
|
|
1063
|
+
* @name optionalTokenType
|
|
1064
|
+
* @description Converts public tokenType strings into SDK Anchor enum variants.
|
|
1065
|
+
*/
|
|
1066
|
+
function optionalTokenType(input) {
|
|
1067
|
+
const raw = optionalString(input, 'tokenType') ?? 'sol';
|
|
1068
|
+
const normalized = raw.trim().toLowerCase();
|
|
1069
|
+
if (normalized === 'sol' || normalized === 'native' || normalized === 'lamports') {
|
|
1070
|
+
return { tokenType: TokenType.Sol, decimalsFallback: 9 };
|
|
1071
|
+
}
|
|
1072
|
+
if (normalized === 'usdc' || normalized === 'micro-usdc' || normalized === 'micro_usdc') {
|
|
1073
|
+
return { tokenType: TokenType.Usdc, decimalsFallback: 6 };
|
|
1074
|
+
}
|
|
1075
|
+
if (normalized === 'spl' || normalized === 'token') {
|
|
1076
|
+
return { tokenType: TokenType.Spl, decimalsFallback: 0 };
|
|
1077
|
+
}
|
|
1078
|
+
throw new Error('tokenType must be one of sol, usdc, or spl');
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* @name optionalSettlementMode
|
|
1082
|
+
* @description Converts public settlementMode strings into SDK Anchor enum variants.
|
|
1083
|
+
*/
|
|
1084
|
+
function optionalSettlementMode(input) {
|
|
1085
|
+
const raw = optionalString(input, 'settlementMode') ?? 'escrow';
|
|
1086
|
+
const normalized = raw.trim().toLowerCase();
|
|
1087
|
+
if (normalized === 'instant') {
|
|
1088
|
+
return SettlementMode.Instant;
|
|
1089
|
+
}
|
|
1090
|
+
if (normalized === 'escrow') {
|
|
1091
|
+
return SettlementMode.Escrow;
|
|
1092
|
+
}
|
|
1093
|
+
if (normalized === 'batched' || normalized === 'batch') {
|
|
1094
|
+
return SettlementMode.Batched;
|
|
1095
|
+
}
|
|
1096
|
+
if (normalized === 'x402' || normalized === 'pay.sh' || normalized === 'paysh') {
|
|
1097
|
+
return SettlementMode.X402;
|
|
1098
|
+
}
|
|
1099
|
+
throw new Error('settlementMode must be one of instant, escrow, batched, or x402');
|
|
1100
|
+
}
|
|
320
1101
|
/**
|
|
321
1102
|
* @name requiredBytes
|
|
322
1103
|
* @description Reads byte-array fields used for hashes, nonces, and encrypted payloads.
|
|
@@ -423,6 +1204,12 @@ function parsePricingTiers(value) {
|
|
|
423
1204
|
return value.map((item) => {
|
|
424
1205
|
const record = asRecord(item);
|
|
425
1206
|
const pricePerCall = optionalBn(record, 'pricePerCall', new BN(0));
|
|
1207
|
+
const { tokenType, decimalsFallback } = optionalTokenType(record);
|
|
1208
|
+
const tokenMint = optionalPublicKey(record, 'tokenMint') ?? null;
|
|
1209
|
+
if (tokenType === TokenType.Spl && tokenMint === null) {
|
|
1210
|
+
throw new Error('pricing.tokenMint is required when tokenType is spl');
|
|
1211
|
+
}
|
|
1212
|
+
const volumeCurve = parseVolumeCurve(record.volumeCurve);
|
|
426
1213
|
return {
|
|
427
1214
|
tierId: optionalString(record, 'tierId') ?? 'default',
|
|
428
1215
|
pricePerCall,
|
|
@@ -431,13 +1218,13 @@ function parsePricingTiers(value) {
|
|
|
431
1218
|
rateLimit: optionalNumber(record, 'rateLimit') ?? 60,
|
|
432
1219
|
maxCallsPerSession: optionalNumber(record, 'maxCallsPerSession') ?? 1_000,
|
|
433
1220
|
burstLimit: optionalNumber(record, 'burstLimit') ?? null,
|
|
434
|
-
tokenType
|
|
435
|
-
tokenMint
|
|
436
|
-
tokenDecimals: optionalNumber(record, 'tokenDecimals') ??
|
|
437
|
-
settlementMode:
|
|
1221
|
+
tokenType,
|
|
1222
|
+
tokenMint,
|
|
1223
|
+
tokenDecimals: optionalNumber(record, 'tokenDecimals') ?? decimalsFallback,
|
|
1224
|
+
settlementMode: optionalSettlementMode(record),
|
|
438
1225
|
minEscrowDeposit: record.minEscrowDeposit === undefined ? null : requiredBn(record, 'minEscrowDeposit'),
|
|
439
1226
|
batchIntervalSec: optionalNumber(record, 'batchIntervalSec') ?? null,
|
|
440
|
-
volumeCurve: null,
|
|
1227
|
+
volumeCurve: volumeCurve.length > 0 ? volumeCurve : null,
|
|
441
1228
|
};
|
|
442
1229
|
});
|
|
443
1230
|
}
|
|
@@ -463,7 +1250,7 @@ function parseProtocols(value) {
|
|
|
463
1250
|
* @name parseRegisterAgentArgs
|
|
464
1251
|
* @description Builds strongly typed `RegisterAgentArgs` from MCP JSON input.
|
|
465
1252
|
*/
|
|
466
|
-
function parseRegisterAgentArgs(input) {
|
|
1253
|
+
export function parseRegisterAgentArgs(input) {
|
|
467
1254
|
return {
|
|
468
1255
|
name: requiredString(input, 'name'),
|
|
469
1256
|
description: requiredString(input, 'description'),
|
|
@@ -479,7 +1266,7 @@ function parseRegisterAgentArgs(input) {
|
|
|
479
1266
|
* @name parseUpdateAgentArgs
|
|
480
1267
|
* @description Builds strongly typed `UpdateAgentArgs` from MCP JSON input.
|
|
481
1268
|
*/
|
|
482
|
-
function parseUpdateAgentArgs(input) {
|
|
1269
|
+
export function parseUpdateAgentArgs(input) {
|
|
483
1270
|
return {
|
|
484
1271
|
name: optionalString(input, 'name') ?? null,
|
|
485
1272
|
description: optionalString(input, 'description') ?? null,
|
|
@@ -491,6 +1278,168 @@ function parseUpdateAgentArgs(input) {
|
|
|
491
1278
|
x402Endpoint: optionalString(input, 'x402Endpoint') ?? null,
|
|
492
1279
|
};
|
|
493
1280
|
}
|
|
1281
|
+
function parseIdentityPlanAction(input) {
|
|
1282
|
+
const value = optionalString(input, 'intendedAction') ?? 'full-identity';
|
|
1283
|
+
if (['register', 'update', 'link-metaplex', 'link-sns', 'full-identity'].includes(value)) {
|
|
1284
|
+
return value;
|
|
1285
|
+
}
|
|
1286
|
+
throw new Error('intendedAction must be one of register, update, link-metaplex, link-sns, full-identity');
|
|
1287
|
+
}
|
|
1288
|
+
function optionalPublicMetadataUri(input) {
|
|
1289
|
+
return optionalString(input, 'metadataUri') ?? optionalString(input, 'agentUri') ?? null;
|
|
1290
|
+
}
|
|
1291
|
+
function buildSapAgentIdentityPlan(input) {
|
|
1292
|
+
const intendedAction = parseIdentityPlanAction(input);
|
|
1293
|
+
const metadataUri = optionalPublicMetadataUri(input);
|
|
1294
|
+
const imageUrl = optionalString(input, 'imageUrl') ?? null;
|
|
1295
|
+
const metaplexAsset = optionalString(input, 'metaplexAsset') ?? null;
|
|
1296
|
+
const snsDomain = optionalString(input, 'snsDomain') ?? null;
|
|
1297
|
+
const ownerWallet = optionalString(input, 'ownerWallet') ?? null;
|
|
1298
|
+
const missingRegisterFields = ['name', 'description', 'capabilities', 'protocols']
|
|
1299
|
+
.filter((field) => input[field] === undefined || input[field] === null);
|
|
1300
|
+
const hasCompleteRegisterFields = missingRegisterFields.length === 0;
|
|
1301
|
+
const registerArgs = hasCompleteRegisterFields
|
|
1302
|
+
? parseRegisterAgentArgs({
|
|
1303
|
+
...input,
|
|
1304
|
+
capabilities: input.capabilities ?? [],
|
|
1305
|
+
pricing: input.pricing ?? [],
|
|
1306
|
+
protocols: input.protocols ?? [],
|
|
1307
|
+
})
|
|
1308
|
+
: null;
|
|
1309
|
+
const updateArgs = parseUpdateAgentArgs(input);
|
|
1310
|
+
return {
|
|
1311
|
+
intendedAction,
|
|
1312
|
+
trustBoundary: {
|
|
1313
|
+
hostedSap: 'Use hosted sap for reads, paid hosted tools, and unsigned builders.',
|
|
1314
|
+
localSapPayments: 'Use local sap_payments for x402 payment signing, SAP registry writes, and transaction finalization.',
|
|
1315
|
+
keypairMaterial: 'Never read or export keypair JSON. Only local SAP MCP signer tools may sign.',
|
|
1316
|
+
},
|
|
1317
|
+
nextTools: {
|
|
1318
|
+
readiness: 'sap_payments_readiness',
|
|
1319
|
+
register: intendedAction === 'register' || intendedAction === 'full-identity' ? 'sap_payments_register_agent' : null,
|
|
1320
|
+
update: intendedAction !== 'register' ? 'sap_payments_update_agent' : null,
|
|
1321
|
+
metaplex: metaplexAsset ? 'metaplex-nft_* or DAS verification tools before SAP metadata update' : null,
|
|
1322
|
+
sns: snsDomain ? ['sap_sns_check_domain', 'sap_sns_check_ownership', 'sap_sns_build_manage_record_transaction when managing records'] : null,
|
|
1323
|
+
profileVerification: 'sap_get_agent_profile',
|
|
1324
|
+
},
|
|
1325
|
+
missingRegisterFields,
|
|
1326
|
+
normalizedRegistration: registerArgs
|
|
1327
|
+
? {
|
|
1328
|
+
name: registerArgs.name,
|
|
1329
|
+
description: registerArgs.description,
|
|
1330
|
+
agentId: registerArgs.agentId,
|
|
1331
|
+
agentUri: registerArgs.agentUri,
|
|
1332
|
+
x402Endpoint: registerArgs.x402Endpoint,
|
|
1333
|
+
protocols: registerArgs.protocols,
|
|
1334
|
+
capabilities: registerArgs.capabilities,
|
|
1335
|
+
pricing: registerArgs.pricing,
|
|
1336
|
+
confirm: true,
|
|
1337
|
+
}
|
|
1338
|
+
: null,
|
|
1339
|
+
normalizedUpdate: {
|
|
1340
|
+
name: updateArgs.name,
|
|
1341
|
+
description: updateArgs.description,
|
|
1342
|
+
agentId: updateArgs.agentId,
|
|
1343
|
+
agentUri: updateArgs.agentUri,
|
|
1344
|
+
x402Endpoint: updateArgs.x402Endpoint,
|
|
1345
|
+
protocols: updateArgs.protocols,
|
|
1346
|
+
capabilities: updateArgs.capabilities,
|
|
1347
|
+
pricing: updateArgs.pricing,
|
|
1348
|
+
confirm: true,
|
|
1349
|
+
},
|
|
1350
|
+
publicMetadataContract: {
|
|
1351
|
+
requiredForImages: true,
|
|
1352
|
+
metadataUri,
|
|
1353
|
+
imageUrl,
|
|
1354
|
+
metaplexAsset,
|
|
1355
|
+
snsDomain,
|
|
1356
|
+
recommendedShape: {
|
|
1357
|
+
name: input.name ?? '<agent name>',
|
|
1358
|
+
description: input.description ?? '<agent description>',
|
|
1359
|
+
image: imageUrl ?? '<public image URL>',
|
|
1360
|
+
external_url: ownerWallet ? `https://explorer.oobeprotocol.ai/agents/${ownerWallet}` : '<public agent page>',
|
|
1361
|
+
attributes: [
|
|
1362
|
+
{ trait_type: 'Protocol', value: 'SAP' },
|
|
1363
|
+
{ trait_type: 'Identity', value: [metaplexAsset ? 'Metaplex' : null, snsDomain ? 'SNS' : null].filter(Boolean).join(' + ') || 'SAP' },
|
|
1364
|
+
],
|
|
1365
|
+
sap: {
|
|
1366
|
+
ownerWallet: ownerWallet ?? '<owner wallet>',
|
|
1367
|
+
agentId: optionalString(input, 'agentId') ?? '<stable id>',
|
|
1368
|
+
capabilities: Array.isArray(input.capabilities) ? input.capabilities : [],
|
|
1369
|
+
},
|
|
1370
|
+
metaplex: metaplexAsset ? { asset: metaplexAsset } : null,
|
|
1371
|
+
sns: snsDomain ? { domain: snsDomain } : null,
|
|
1372
|
+
x402: optionalString(input, 'x402Endpoint') ? { endpoint: optionalString(input, 'x402Endpoint') } : null,
|
|
1373
|
+
},
|
|
1374
|
+
},
|
|
1375
|
+
verificationChecklist: [
|
|
1376
|
+
'Call sap_payments_readiness before paid/write actions.',
|
|
1377
|
+
'For registration, call sap_payments_register_agent with confirm:true; do not call hosted sap_register_agent after hosted_local_signer_required.',
|
|
1378
|
+
'Verify sap_payments_register_agent success, confirmationStatus, agentPda, and protocolFee.status.',
|
|
1379
|
+
'Fetch sap_get_agent_profile by owner wallet after registration or update.',
|
|
1380
|
+
'For update, verify every intended replacement field because arrays are full replacements.',
|
|
1381
|
+
'For Metaplex identity, verify the asset/collection metadata URI and update authority before linking it from SAP metadata.',
|
|
1382
|
+
'For SNS identity, verify domain ownership and records before claiming the .sol identity is linked.',
|
|
1383
|
+
],
|
|
1384
|
+
forbiddenActions: [
|
|
1385
|
+
'Do not create temporary signing scripts.',
|
|
1386
|
+
'Do not read keypair JSON.',
|
|
1387
|
+
'Do not reuse stale x402 payment signatures.',
|
|
1388
|
+
'Do not pay hosted x402 fees for hosted_local_signer_required registry writes.',
|
|
1389
|
+
'Do not announce lifecycle complete if protocolFee.status is missing_or_underpaid.',
|
|
1390
|
+
],
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
function buildSapProtocolInvariants() {
|
|
1394
|
+
return {
|
|
1395
|
+
protocol: {
|
|
1396
|
+
name: 'Synapse Agent Protocol',
|
|
1397
|
+
programId: DEFAULT_SAP_PROGRAM_ID,
|
|
1398
|
+
network: 'mainnet-beta',
|
|
1399
|
+
custodyModel: 'non-custodial',
|
|
1400
|
+
},
|
|
1401
|
+
registrationFee: {
|
|
1402
|
+
sourceExpected: true,
|
|
1403
|
+
treasury: SAP_PROTOCOL_TREASURY,
|
|
1404
|
+
lamports: SAP_REGISTRATION_FEE_LAMPORTS.toString(10),
|
|
1405
|
+
sol: Number(SAP_REGISTRATION_FEE_LAMPORTS) / 1_000_000_000,
|
|
1406
|
+
verification: 'sap_payments_register_agent verifies the landed transaction pre/post balance delta for the treasury account because deployed program behavior can drift from the source-level invariant.',
|
|
1407
|
+
failureStatus: 'missing_or_underpaid',
|
|
1408
|
+
failureRule: 'If protocolFee.status is missing_or_underpaid, the agent account can still exist, but sap_payments_register_agent must return success:false, agentRegistered:true, and protocolComplete:false. Do not retry registration automatically; inspect the signature, deployed SAP program, and treasury delta first.',
|
|
1409
|
+
},
|
|
1410
|
+
hostedWritePolicy: {
|
|
1411
|
+
register: 'Hosted sap_register_agent is accountless and returns hosted_local_signer_required before x402 payment.',
|
|
1412
|
+
update: 'Hosted sap_update_agent is accountless and returns hosted_local_signer_required before x402 payment.',
|
|
1413
|
+
sns: 'Hosted direct SNS writes require a local signer or unsigned builder. If no builder exists, stop and route through local SAP MCP.',
|
|
1414
|
+
noChargeRule: 'hosted_local_signer_required is a routing guard, not a paid failure; no hosted x402 fee should be charged for that blocked write.',
|
|
1415
|
+
},
|
|
1416
|
+
localSignerRoutes: {
|
|
1417
|
+
readiness: 'sap_payments_readiness',
|
|
1418
|
+
registerAgent: 'sap_payments_register_agent',
|
|
1419
|
+
updateAgent: 'sap_payments_update_agent',
|
|
1420
|
+
finalizeUnsignedTransaction: 'sap_payments_finalize_transaction',
|
|
1421
|
+
paidHostedTool: 'sap_payments_call_paid_tool',
|
|
1422
|
+
externalX402Http: 'sap_payments_call_external_x402',
|
|
1423
|
+
},
|
|
1424
|
+
identityPipeline: [
|
|
1425
|
+
'Call sap_agent_identity_plan for register, update, Metaplex, SNS, or full-identity intent.',
|
|
1426
|
+
'Upload image and metadata to a public URL before writing agentUri or metadataUri.',
|
|
1427
|
+
'Use sap_payments_register_agent for local non-custodial registration.',
|
|
1428
|
+
'Verify success, agentRegistered, confirmationStatus, agentPda, protocolComplete, and protocolFee.status.',
|
|
1429
|
+
'Use Metaplex/MPL Core tools only after metadata authority and URI are clear.',
|
|
1430
|
+
'Use SNS tools only after domain availability/ownership and user confirmation are clear.',
|
|
1431
|
+
'Use sap_payments_update_agent for profile image, metadata, capabilities, pricing, protocols, or x402 endpoint updates.',
|
|
1432
|
+
'Fetch sap_get_agent_profile after every registry write and compare intended fields.',
|
|
1433
|
+
],
|
|
1434
|
+
forbiddenActions: [
|
|
1435
|
+
'Do not create temporary signing scripts.',
|
|
1436
|
+
'Do not read keypair JSON.',
|
|
1437
|
+
'Do not call hosted sap_sign_transaction for user-owned signatures.',
|
|
1438
|
+
'Do not call hosted sap_register_agent or sap_update_agent again after hosted_local_signer_required.',
|
|
1439
|
+
'Do not call an agent lifecycle complete when protocolFee.status is missing_or_underpaid, unavailable, or anything other than verified.',
|
|
1440
|
+
],
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
494
1443
|
/**
|
|
495
1444
|
* @name parseX402PreparePaymentOptions
|
|
496
1445
|
* @description Builds typed x402 payment preparation options from MCP JSON input.
|
|
@@ -608,6 +1557,433 @@ function parseEscrowV2Args(input) {
|
|
|
608
1557
|
arbiter: optionalPublicKey(input, 'arbiter') ?? null,
|
|
609
1558
|
};
|
|
610
1559
|
}
|
|
1560
|
+
function publicKeyOrNull(value) {
|
|
1561
|
+
return value instanceof PublicKey ? value : null;
|
|
1562
|
+
}
|
|
1563
|
+
function bnToBigInt(value) {
|
|
1564
|
+
if (typeof value === 'bigint') {
|
|
1565
|
+
return value;
|
|
1566
|
+
}
|
|
1567
|
+
if (typeof value === 'number') {
|
|
1568
|
+
return BigInt(value);
|
|
1569
|
+
}
|
|
1570
|
+
return BigInt(value.toString());
|
|
1571
|
+
}
|
|
1572
|
+
function bnToPdaSeed(value, field) {
|
|
1573
|
+
const asBigInt = BigInt(value.toString(10));
|
|
1574
|
+
if (asBigInt < 0n) {
|
|
1575
|
+
throw new Error(`${field} must be >= 0`);
|
|
1576
|
+
}
|
|
1577
|
+
return asBigInt;
|
|
1578
|
+
}
|
|
1579
|
+
function serializeAccountMetas(accounts) {
|
|
1580
|
+
return accounts.map((account) => ({
|
|
1581
|
+
pubkey: account.pubkey.toBase58(),
|
|
1582
|
+
isSigner: account.isSigner,
|
|
1583
|
+
isWritable: account.isWritable,
|
|
1584
|
+
}));
|
|
1585
|
+
}
|
|
1586
|
+
function validateEscrowPaymentMint(tokenMint) {
|
|
1587
|
+
if (!tokenMint) {
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
if (!tokenMint.equals(USDC_MINT_MAINNET) && !tokenMint.equals(USDC_MINT_DEVNET)) {
|
|
1591
|
+
throw new Error('Escrow V2 hosted builders only accept native SOL or USDC mints supported by the current SAP program.');
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
function deriveAssociatedTokenAddress(tokenMint, owner) {
|
|
1595
|
+
const [address] = PublicKey.findProgramAddressSync([owner.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), tokenMint.toBuffer()], ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
1596
|
+
return address;
|
|
1597
|
+
}
|
|
1598
|
+
function getEscrowPdas(client, agentWallet, depositorWallet, nonce) {
|
|
1599
|
+
const [agentPda] = Pda.deriveAgent(agentWallet, client.programId);
|
|
1600
|
+
const [escrowPda] = Pda.deriveEscrowV2(agentPda, depositorWallet, bnToPdaSeed(nonce, 'nonce'), client.programId);
|
|
1601
|
+
const [agentStake] = Pda.deriveStake(agentPda, client.programId);
|
|
1602
|
+
const [agentStats] = Pda.deriveAgentStats(agentPda, client.programId);
|
|
1603
|
+
const [pricingMenu] = Pda.derivePricingMenu(agentPda, client.programId);
|
|
1604
|
+
return { agentPda, escrowPda, agentStake, agentStats, pricingMenu };
|
|
1605
|
+
}
|
|
1606
|
+
function buildSplRemainingAccounts(tokenMint, sourceOwner, destinationOwner) {
|
|
1607
|
+
if (!tokenMint) {
|
|
1608
|
+
return [];
|
|
1609
|
+
}
|
|
1610
|
+
return [
|
|
1611
|
+
{
|
|
1612
|
+
pubkey: deriveAssociatedTokenAddress(tokenMint, sourceOwner),
|
|
1613
|
+
isSigner: false,
|
|
1614
|
+
isWritable: true,
|
|
1615
|
+
},
|
|
1616
|
+
{
|
|
1617
|
+
pubkey: deriveAssociatedTokenAddress(tokenMint, destinationOwner),
|
|
1618
|
+
isSigner: false,
|
|
1619
|
+
isWritable: true,
|
|
1620
|
+
},
|
|
1621
|
+
{ pubkey: tokenMint, isSigner: false, isWritable: false },
|
|
1622
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
1623
|
+
];
|
|
1624
|
+
}
|
|
1625
|
+
function buildEscrowSettlementRemainingAccounts(params) {
|
|
1626
|
+
const accounts = params.tokenMint
|
|
1627
|
+
? [
|
|
1628
|
+
...buildSplRemainingAccounts(params.tokenMint, params.escrowPda, params.agentWallet),
|
|
1629
|
+
{
|
|
1630
|
+
pubkey: deriveAssociatedTokenAddress(params.tokenMint, new PublicKey(SAP_PROTOCOL_TREASURY)),
|
|
1631
|
+
isSigner: false,
|
|
1632
|
+
isWritable: true,
|
|
1633
|
+
},
|
|
1634
|
+
]
|
|
1635
|
+
: [
|
|
1636
|
+
{
|
|
1637
|
+
pubkey: new PublicKey(SAP_PROTOCOL_TREASURY),
|
|
1638
|
+
isSigner: false,
|
|
1639
|
+
isWritable: true,
|
|
1640
|
+
},
|
|
1641
|
+
];
|
|
1642
|
+
if (params.pendingSettlementPda) {
|
|
1643
|
+
accounts.push({ pubkey: params.pendingSettlementPda, isSigner: false, isWritable: true });
|
|
1644
|
+
}
|
|
1645
|
+
if (params.coSigner) {
|
|
1646
|
+
accounts.push({ pubkey: params.coSigner, isSigner: true, isWritable: false });
|
|
1647
|
+
}
|
|
1648
|
+
return accounts;
|
|
1649
|
+
}
|
|
1650
|
+
async function serializeUnsignedTransaction(client, feePayer, instructions) {
|
|
1651
|
+
const latestBlockhash = await client.connection.getLatestBlockhash('confirmed');
|
|
1652
|
+
const tx = new Transaction();
|
|
1653
|
+
tx.feePayer = feePayer;
|
|
1654
|
+
tx.recentBlockhash = latestBlockhash.blockhash;
|
|
1655
|
+
for (const instruction of instructions) {
|
|
1656
|
+
tx.add(instruction);
|
|
1657
|
+
}
|
|
1658
|
+
return {
|
|
1659
|
+
transactionBase64: Buffer.from(tx.serialize({ requireAllSignatures: false })).toString('base64'),
|
|
1660
|
+
blockhash: latestBlockhash.blockhash,
|
|
1661
|
+
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
async function fetchEscrowV2Nullable(client, escrowPda) {
|
|
1665
|
+
const accounts = getSapAnchorAccounts(client);
|
|
1666
|
+
return accounts.escrowAccountV2.fetchNullable(escrowPda);
|
|
1667
|
+
}
|
|
1668
|
+
async function fetchPendingSettlementNullable(client, pendingPda) {
|
|
1669
|
+
const accounts = getSapAnchorAccounts(client);
|
|
1670
|
+
return accounts.pendingSettlement.fetchNullable(pendingPda);
|
|
1671
|
+
}
|
|
1672
|
+
function isDisputeWindowEscrow(escrow) {
|
|
1673
|
+
const security = escrow.settlementSecurity;
|
|
1674
|
+
return typeof security === 'object' && security !== null && 'disputeWindow' in security;
|
|
1675
|
+
}
|
|
1676
|
+
function isCoSignedEscrow(escrow) {
|
|
1677
|
+
const security = escrow.settlementSecurity;
|
|
1678
|
+
return typeof security === 'object' && security !== null && 'coSigned' in security;
|
|
1679
|
+
}
|
|
1680
|
+
function escrowBuilderResponse(params) {
|
|
1681
|
+
return {
|
|
1682
|
+
action: params.action,
|
|
1683
|
+
transactionBase64: params.transactionBase64,
|
|
1684
|
+
encoding: 'base64',
|
|
1685
|
+
requiredSigner: params.requiredSigner.toBase58(),
|
|
1686
|
+
requiredSignerRole: params.requiredSignerRole,
|
|
1687
|
+
submitWith: 'sap_payments_finalize_transaction',
|
|
1688
|
+
nextStep: 'Call sap_payments_finalize_transaction with transactionBase64, submit:true, confirm:true, and the same user-approved intent. Do not create temporary signing scripts and do not read keypair JSON.',
|
|
1689
|
+
accounts: {
|
|
1690
|
+
...params.accounts,
|
|
1691
|
+
blockhash: params.blockhash,
|
|
1692
|
+
lastValidBlockHeight: params.lastValidBlockHeight,
|
|
1693
|
+
},
|
|
1694
|
+
tokenMode: params.tokenMint ? 'SPL' : 'SOL',
|
|
1695
|
+
...(params.security ? { security: params.security } : {}),
|
|
1696
|
+
...(params.warnings && params.warnings.length > 0 ? { warnings: params.warnings } : {}),
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
async function buildEscrowCreateTransaction(input, client) {
|
|
1700
|
+
const depositorWallet = requiredPublicKey(input, 'depositorWallet');
|
|
1701
|
+
const agentWallet = requiredPublicKey(input, 'agentWallet');
|
|
1702
|
+
const args = parseEscrowV2Args(input);
|
|
1703
|
+
validateEscrowPaymentMint(args.tokenMint);
|
|
1704
|
+
const pdas = getEscrowPdas(client, agentWallet, depositorWallet, args.escrowNonce);
|
|
1705
|
+
const remainingAccounts = buildSplRemainingAccounts(args.tokenMint, depositorWallet, pdas.escrowPda);
|
|
1706
|
+
const methods = client.program.methods;
|
|
1707
|
+
const instruction = await methods.createEscrowV2(args.escrowNonce, args.pricePerCall, args.maxCalls, args.initialDeposit, args.expiresAt, args.volumeCurve, args.tokenMint, args.tokenDecimals, args.settlementSecurity, args.disputeWindowSlots, args.coSigner, args.arbiter)
|
|
1708
|
+
.accounts({
|
|
1709
|
+
depositor: depositorWallet,
|
|
1710
|
+
agent: pdas.agentPda,
|
|
1711
|
+
agentStake: pdas.agentStake,
|
|
1712
|
+
agentStats: pdas.agentStats,
|
|
1713
|
+
pricingMenu: pdas.pricingMenu,
|
|
1714
|
+
escrow: pdas.escrowPda,
|
|
1715
|
+
systemProgram: SystemProgram.programId,
|
|
1716
|
+
})
|
|
1717
|
+
.remainingAccounts(remainingAccounts)
|
|
1718
|
+
.instruction();
|
|
1719
|
+
const tx = await serializeUnsignedTransaction(client, depositorWallet, [instruction]);
|
|
1720
|
+
return escrowBuilderResponse({
|
|
1721
|
+
action: 'create_escrow_v2',
|
|
1722
|
+
transactionBase64: tx.transactionBase64,
|
|
1723
|
+
requiredSigner: depositorWallet,
|
|
1724
|
+
requiredSignerRole: 'depositor',
|
|
1725
|
+
tokenMint: args.tokenMint,
|
|
1726
|
+
blockhash: tx.blockhash,
|
|
1727
|
+
lastValidBlockHeight: tx.lastValidBlockHeight,
|
|
1728
|
+
accounts: {
|
|
1729
|
+
agentWallet,
|
|
1730
|
+
depositorWallet,
|
|
1731
|
+
agentPda: pdas.agentPda,
|
|
1732
|
+
escrowPda: pdas.escrowPda,
|
|
1733
|
+
agentStake: pdas.agentStake,
|
|
1734
|
+
agentStats: pdas.agentStats,
|
|
1735
|
+
pricingMenu: pdas.pricingMenu,
|
|
1736
|
+
remainingAccounts: serializeAccountMetas(remainingAccounts),
|
|
1737
|
+
},
|
|
1738
|
+
security: {
|
|
1739
|
+
settlementSecurity: args.settlementSecurity,
|
|
1740
|
+
disputeWindowSlots: args.disputeWindowSlots,
|
|
1741
|
+
coSigner: args.coSigner,
|
|
1742
|
+
arbiter: args.arbiter,
|
|
1743
|
+
},
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
async function buildEscrowDepositTransaction(input, client) {
|
|
1747
|
+
const depositorWallet = requiredPublicKey(input, 'depositorWallet');
|
|
1748
|
+
const agentWallet = requiredPublicKey(input, 'agentWallet');
|
|
1749
|
+
const nonce = optionalBn(input, 'nonce', new BN(0));
|
|
1750
|
+
const amount = requiredBn(input, 'amount');
|
|
1751
|
+
const pdas = getEscrowPdas(client, agentWallet, depositorWallet, nonce);
|
|
1752
|
+
const escrow = await fetchEscrowV2Nullable(client, pdas.escrowPda);
|
|
1753
|
+
if (!escrow) {
|
|
1754
|
+
throw new Error(`Escrow V2 PDA ${pdas.escrowPda.toBase58()} does not exist. Build and finalize sap_escrow_build_create_transaction first.`);
|
|
1755
|
+
}
|
|
1756
|
+
const tokenMint = publicKeyOrNull(escrow.tokenMint);
|
|
1757
|
+
const remainingAccounts = buildSplRemainingAccounts(tokenMint, depositorWallet, pdas.escrowPda);
|
|
1758
|
+
const methods = client.program.methods;
|
|
1759
|
+
const instruction = await methods.depositEscrowV2(nonce, amount)
|
|
1760
|
+
.accounts({
|
|
1761
|
+
depositor: depositorWallet,
|
|
1762
|
+
escrow: pdas.escrowPda,
|
|
1763
|
+
systemProgram: SystemProgram.programId,
|
|
1764
|
+
})
|
|
1765
|
+
.remainingAccounts(remainingAccounts)
|
|
1766
|
+
.instruction();
|
|
1767
|
+
const tx = await serializeUnsignedTransaction(client, depositorWallet, [instruction]);
|
|
1768
|
+
return escrowBuilderResponse({
|
|
1769
|
+
action: 'deposit_escrow_v2',
|
|
1770
|
+
transactionBase64: tx.transactionBase64,
|
|
1771
|
+
requiredSigner: depositorWallet,
|
|
1772
|
+
requiredSignerRole: 'depositor',
|
|
1773
|
+
tokenMint,
|
|
1774
|
+
blockhash: tx.blockhash,
|
|
1775
|
+
lastValidBlockHeight: tx.lastValidBlockHeight,
|
|
1776
|
+
accounts: {
|
|
1777
|
+
agentWallet,
|
|
1778
|
+
depositorWallet,
|
|
1779
|
+
escrowPda: pdas.escrowPda,
|
|
1780
|
+
amount,
|
|
1781
|
+
remainingAccounts: serializeAccountMetas(remainingAccounts),
|
|
1782
|
+
},
|
|
1783
|
+
});
|
|
1784
|
+
}
|
|
1785
|
+
async function buildEscrowWithdrawTransaction(input, client) {
|
|
1786
|
+
const depositorWallet = requiredPublicKey(input, 'depositorWallet');
|
|
1787
|
+
const agentWallet = requiredPublicKey(input, 'agentWallet');
|
|
1788
|
+
const nonce = optionalBn(input, 'nonce', new BN(0));
|
|
1789
|
+
const amount = requiredBn(input, 'amount');
|
|
1790
|
+
const pdas = getEscrowPdas(client, agentWallet, depositorWallet, nonce);
|
|
1791
|
+
const escrow = await fetchEscrowV2Nullable(client, pdas.escrowPda);
|
|
1792
|
+
if (!escrow) {
|
|
1793
|
+
throw new Error(`Escrow V2 PDA ${pdas.escrowPda.toBase58()} does not exist.`);
|
|
1794
|
+
}
|
|
1795
|
+
const balance = bnToBigInt(escrow.balance);
|
|
1796
|
+
const pendingAmount = bnToBigInt(escrow.pendingAmount);
|
|
1797
|
+
const withdrawable = balance > pendingAmount ? balance - pendingAmount : 0n;
|
|
1798
|
+
if (BigInt(amount.toString(10)) > withdrawable) {
|
|
1799
|
+
throw new Error(`Withdraw amount exceeds withdrawable escrow balance. requested=${amount.toString(10)}, withdrawable=${withdrawable.toString()}.`);
|
|
1800
|
+
}
|
|
1801
|
+
const tokenMint = publicKeyOrNull(escrow.tokenMint);
|
|
1802
|
+
const remainingAccounts = buildSplRemainingAccounts(tokenMint, pdas.escrowPda, depositorWallet);
|
|
1803
|
+
const methods = client.program.methods;
|
|
1804
|
+
const instruction = await methods.withdrawEscrowV2(amount)
|
|
1805
|
+
.accounts({
|
|
1806
|
+
depositor: depositorWallet,
|
|
1807
|
+
escrow: pdas.escrowPda,
|
|
1808
|
+
})
|
|
1809
|
+
.remainingAccounts(remainingAccounts)
|
|
1810
|
+
.instruction();
|
|
1811
|
+
const tx = await serializeUnsignedTransaction(client, depositorWallet, [instruction]);
|
|
1812
|
+
return escrowBuilderResponse({
|
|
1813
|
+
action: 'withdraw_escrow_v2',
|
|
1814
|
+
transactionBase64: tx.transactionBase64,
|
|
1815
|
+
requiredSigner: depositorWallet,
|
|
1816
|
+
requiredSignerRole: 'depositor',
|
|
1817
|
+
tokenMint,
|
|
1818
|
+
blockhash: tx.blockhash,
|
|
1819
|
+
lastValidBlockHeight: tx.lastValidBlockHeight,
|
|
1820
|
+
accounts: {
|
|
1821
|
+
agentWallet,
|
|
1822
|
+
depositorWallet,
|
|
1823
|
+
escrowPda: pdas.escrowPda,
|
|
1824
|
+
amount,
|
|
1825
|
+
withdrawable: withdrawable.toString(),
|
|
1826
|
+
remainingAccounts: serializeAccountMetas(remainingAccounts),
|
|
1827
|
+
},
|
|
1828
|
+
});
|
|
1829
|
+
}
|
|
1830
|
+
async function buildEscrowSettleTransaction(input, client) {
|
|
1831
|
+
const agentWallet = requiredPublicKey(input, 'agentWallet');
|
|
1832
|
+
const depositorWallet = requiredPublicKey(input, 'depositorWallet');
|
|
1833
|
+
const nonce = optionalBn(input, 'nonce', new BN(0));
|
|
1834
|
+
const callsToSettle = requiredBn(input, 'callsToSettle');
|
|
1835
|
+
const serviceHash = requiredBytes(input, 'serviceHash', 32);
|
|
1836
|
+
const pdas = getEscrowPdas(client, agentWallet, depositorWallet, nonce);
|
|
1837
|
+
const escrow = await fetchEscrowV2Nullable(client, pdas.escrowPda);
|
|
1838
|
+
if (!escrow) {
|
|
1839
|
+
throw new Error(`Escrow V2 PDA ${pdas.escrowPda.toBase58()} does not exist.`);
|
|
1840
|
+
}
|
|
1841
|
+
const tokenMint = publicKeyOrNull(escrow.tokenMint);
|
|
1842
|
+
const pendingSettlementIndex = bnToBigInt(escrow.settlementIndex);
|
|
1843
|
+
let pendingSettlementPda;
|
|
1844
|
+
if (isDisputeWindowEscrow(escrow)) {
|
|
1845
|
+
[pendingSettlementPda] = Pda.derivePendingSettlement(pdas.escrowPda, pendingSettlementIndex, client.programId);
|
|
1846
|
+
const existing = await fetchPendingSettlementNullable(client, pendingSettlementPda);
|
|
1847
|
+
if (existing) {
|
|
1848
|
+
throw new Error(`Pending settlement ${pendingSettlementPda.toBase58()} already exists for settlementIndex=${pendingSettlementIndex.toString()}. Finalize or quarantine it before building another DisputeWindow settlement.`);
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
const coSigner = isCoSignedEscrow(escrow) ? publicKeyOrNull(escrow.coSigner) : optionalPublicKey(input, 'coSigner') ?? null;
|
|
1852
|
+
if (isCoSignedEscrow(escrow) && !coSigner) {
|
|
1853
|
+
throw new Error('CoSigned escrow requires coSigner in the escrow account.');
|
|
1854
|
+
}
|
|
1855
|
+
const remainingAccounts = buildEscrowSettlementRemainingAccounts({
|
|
1856
|
+
tokenMint,
|
|
1857
|
+
escrowPda: pdas.escrowPda,
|
|
1858
|
+
agentWallet,
|
|
1859
|
+
pendingSettlementPda,
|
|
1860
|
+
coSigner,
|
|
1861
|
+
});
|
|
1862
|
+
const methods = client.program.methods;
|
|
1863
|
+
const instruction = await methods.settleCallsV2(nonce, callsToSettle, serviceHash)
|
|
1864
|
+
.accountsPartial({
|
|
1865
|
+
wallet: agentWallet,
|
|
1866
|
+
agent: pdas.agentPda,
|
|
1867
|
+
agentStats: pdas.agentStats,
|
|
1868
|
+
escrow: pdas.escrowPda,
|
|
1869
|
+
systemProgram: SystemProgram.programId,
|
|
1870
|
+
})
|
|
1871
|
+
.remainingAccounts(remainingAccounts)
|
|
1872
|
+
.instruction();
|
|
1873
|
+
const tx = await serializeUnsignedTransaction(client, agentWallet, [instruction]);
|
|
1874
|
+
return escrowBuilderResponse({
|
|
1875
|
+
action: 'settle_calls_v2',
|
|
1876
|
+
transactionBase64: tx.transactionBase64,
|
|
1877
|
+
requiredSigner: agentWallet,
|
|
1878
|
+
requiredSignerRole: 'agentWallet',
|
|
1879
|
+
tokenMint,
|
|
1880
|
+
blockhash: tx.blockhash,
|
|
1881
|
+
lastValidBlockHeight: tx.lastValidBlockHeight,
|
|
1882
|
+
accounts: {
|
|
1883
|
+
agentWallet,
|
|
1884
|
+
depositorWallet,
|
|
1885
|
+
agentPda: pdas.agentPda,
|
|
1886
|
+
agentStats: pdas.agentStats,
|
|
1887
|
+
escrowPda: pdas.escrowPda,
|
|
1888
|
+
pendingSettlementPda: pendingSettlementPda ?? null,
|
|
1889
|
+
pendingSettlementIndex: pendingSettlementIndex.toString(),
|
|
1890
|
+
callsToSettle,
|
|
1891
|
+
serviceHash,
|
|
1892
|
+
remainingAccounts: serializeAccountMetas(remainingAccounts),
|
|
1893
|
+
},
|
|
1894
|
+
security: {
|
|
1895
|
+
settlementSecurity: isDisputeWindowEscrow(escrow) ? ESCROW_V2_DISPUTE_WINDOW_MODE : ESCROW_V2_COSIGNED_MODE,
|
|
1896
|
+
coSigner,
|
|
1897
|
+
},
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
async function buildEscrowFinalizeTransaction(input, client) {
|
|
1901
|
+
const payerWallet = requiredPublicKey(input, 'payerWallet');
|
|
1902
|
+
const agentWallet = requiredPublicKey(input, 'agentWallet');
|
|
1903
|
+
const depositorWallet = requiredPublicKey(input, 'depositorWallet');
|
|
1904
|
+
const nonce = optionalBn(input, 'nonce', new BN(0));
|
|
1905
|
+
const settlementIndex = requiredBn(input, 'settlementIndex');
|
|
1906
|
+
const pdas = getEscrowPdas(client, agentWallet, depositorWallet, nonce);
|
|
1907
|
+
const [pendingSettlementPda] = Pda.derivePendingSettlement(pdas.escrowPda, bnToPdaSeed(settlementIndex, 'settlementIndex'), client.programId);
|
|
1908
|
+
const escrow = await fetchEscrowV2Nullable(client, pdas.escrowPda);
|
|
1909
|
+
if (!escrow) {
|
|
1910
|
+
throw new Error(`Escrow V2 PDA ${pdas.escrowPda.toBase58()} does not exist.`);
|
|
1911
|
+
}
|
|
1912
|
+
const pending = await fetchPendingSettlementNullable(client, pendingSettlementPda);
|
|
1913
|
+
if (!pending) {
|
|
1914
|
+
throw new Error(`Pending settlement ${pendingSettlementPda.toBase58()} does not exist.`);
|
|
1915
|
+
}
|
|
1916
|
+
const tokenMint = publicKeyOrNull(escrow.tokenMint);
|
|
1917
|
+
const remainingAccounts = buildSplRemainingAccounts(tokenMint, pdas.escrowPda, agentWallet);
|
|
1918
|
+
const methods = client.program.methods;
|
|
1919
|
+
const instruction = await methods.finalizeSettlement()
|
|
1920
|
+
.accounts({
|
|
1921
|
+
payer: payerWallet,
|
|
1922
|
+
agentWallet,
|
|
1923
|
+
escrow: pdas.escrowPda,
|
|
1924
|
+
pendingSettlement: pendingSettlementPda,
|
|
1925
|
+
agentStats: pdas.agentStats,
|
|
1926
|
+
})
|
|
1927
|
+
.remainingAccounts(remainingAccounts)
|
|
1928
|
+
.instruction();
|
|
1929
|
+
const tx = await serializeUnsignedTransaction(client, payerWallet, [instruction]);
|
|
1930
|
+
return escrowBuilderResponse({
|
|
1931
|
+
action: 'finalize_settlement',
|
|
1932
|
+
transactionBase64: tx.transactionBase64,
|
|
1933
|
+
requiredSigner: payerWallet,
|
|
1934
|
+
requiredSignerRole: 'payer',
|
|
1935
|
+
tokenMint,
|
|
1936
|
+
blockhash: tx.blockhash,
|
|
1937
|
+
lastValidBlockHeight: tx.lastValidBlockHeight,
|
|
1938
|
+
accounts: {
|
|
1939
|
+
payerWallet,
|
|
1940
|
+
agentWallet,
|
|
1941
|
+
depositorWallet,
|
|
1942
|
+
escrowPda: pdas.escrowPda,
|
|
1943
|
+
pendingSettlementPda,
|
|
1944
|
+
settlementIndex,
|
|
1945
|
+
releaseSlot: pending.releaseSlot,
|
|
1946
|
+
remainingAccounts: serializeAccountMetas(remainingAccounts),
|
|
1947
|
+
},
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
async function buildEscrowCloseTransaction(input, client) {
|
|
1951
|
+
const depositorWallet = requiredPublicKey(input, 'depositorWallet');
|
|
1952
|
+
const agentWallet = requiredPublicKey(input, 'agentWallet');
|
|
1953
|
+
const nonce = optionalBn(input, 'nonce', new BN(0));
|
|
1954
|
+
const pdas = getEscrowPdas(client, agentWallet, depositorWallet, nonce);
|
|
1955
|
+
const escrow = await fetchEscrowV2Nullable(client, pdas.escrowPda);
|
|
1956
|
+
if (!escrow) {
|
|
1957
|
+
throw new Error(`Escrow V2 PDA ${pdas.escrowPda.toBase58()} does not exist.`);
|
|
1958
|
+
}
|
|
1959
|
+
if (bnToBigInt(escrow.balance) !== 0n || bnToBigInt(escrow.pendingAmount) !== 0n) {
|
|
1960
|
+
throw new Error('Escrow cannot close until balance and pendingAmount are both zero.');
|
|
1961
|
+
}
|
|
1962
|
+
const methods = client.program.methods;
|
|
1963
|
+
const instruction = await methods.closeEscrowV2()
|
|
1964
|
+
.accounts({
|
|
1965
|
+
depositor: depositorWallet,
|
|
1966
|
+
escrow: pdas.escrowPda,
|
|
1967
|
+
agentStats: pdas.agentStats,
|
|
1968
|
+
})
|
|
1969
|
+
.instruction();
|
|
1970
|
+
const tx = await serializeUnsignedTransaction(client, depositorWallet, [instruction]);
|
|
1971
|
+
return escrowBuilderResponse({
|
|
1972
|
+
action: 'close_escrow_v2',
|
|
1973
|
+
transactionBase64: tx.transactionBase64,
|
|
1974
|
+
requiredSigner: depositorWallet,
|
|
1975
|
+
requiredSignerRole: 'depositor',
|
|
1976
|
+
tokenMint: publicKeyOrNull(escrow.tokenMint),
|
|
1977
|
+
blockhash: tx.blockhash,
|
|
1978
|
+
lastValidBlockHeight: tx.lastValidBlockHeight,
|
|
1979
|
+
accounts: {
|
|
1980
|
+
agentWallet,
|
|
1981
|
+
depositorWallet,
|
|
1982
|
+
escrowPda: pdas.escrowPda,
|
|
1983
|
+
agentStats: pdas.agentStats,
|
|
1984
|
+
},
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
611
1987
|
/**
|
|
612
1988
|
* @name parseFeedbackArgs
|
|
613
1989
|
* @description Builds typed feedback args from MCP JSON input.
|
|
@@ -707,7 +2083,7 @@ function registerSapTool(server, client, definition) {
|
|
|
707
2083
|
inputSchema: definition.inputSchema,
|
|
708
2084
|
}, async (rawInput) => {
|
|
709
2085
|
try {
|
|
710
|
-
return ok(await definition.handler(asRecord(rawInput), client));
|
|
2086
|
+
return ok(await definition.handler(asRecord(rawInput), client), definition.name);
|
|
711
2087
|
}
|
|
712
2088
|
catch (error) {
|
|
713
2089
|
logger.error(`SAP SDK tool failed: ${definition.name}`, { error });
|
|
@@ -723,7 +2099,7 @@ function buildSapSdkToolDescription(definition) {
|
|
|
723
2099
|
}
|
|
724
2100
|
function getSapSdkToolContext(name) {
|
|
725
2101
|
if (name === 'sap_register_agent') {
|
|
726
|
-
return 'SAP MCP context:
|
|
2102
|
+
return 'SAP MCP context: Do not use this raw SDK wrapper for production registration. The canonical registration path is sap_payments_register_agent, because it confirms the account, audits the protocol treasury fee, and fails closed when protocolComplete is false. Hosted accountless SAP MCP rejects direct registration before x402 payment because OOBE never custodies user wallet keys. Use sap_agent_identity_plan first, then sap_payments_register_agent with confirm:true.';
|
|
727
2103
|
}
|
|
728
2104
|
if (name === 'sap_update_agent') {
|
|
729
2105
|
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.';
|
|
@@ -731,6 +2107,9 @@ function getSapSdkToolContext(name) {
|
|
|
731
2107
|
if (name.startsWith('sap_publish_tool') || name.startsWith('sap_update_tool')) {
|
|
732
2108
|
return 'SAP MCP context: Use tool registry writes to advertise concrete capabilities that this MCP can serve, including AgentKit bridge tools such as bridging_bridgeWormhole and Metaplex tools such as metaplex-nft_mintNFT. Publish only schemas and descriptions that match the actual MCP tool surface.';
|
|
733
2109
|
}
|
|
2110
|
+
if (name.startsWith('sap_escrow_build_')) {
|
|
2111
|
+
return 'SAP MCP context: Hosted-safe unsigned Escrow V2 builder. The output is not submitted and is not signed by hosted SAP MCP. Preview it, then call local sap_payments_finalize_transaction with submit:true and confirm:true. Never create temporary signing scripts or read keypair JSON.';
|
|
2112
|
+
}
|
|
734
2113
|
if (name.startsWith('sap_discover') || name.startsWith('sap_list') || name.startsWith('sap_find') || name.startsWith('sap_fetch') || name.startsWith('sap_get') || name.startsWith('sap_is')) {
|
|
735
2114
|
return 'SAP MCP context: Read-only SAP SDK wrapper against the configured Solana RPC and SAP program. Use these reads to inspect current chain state before mutating registry, payment, reputation, memory, or tool accounts.';
|
|
736
2115
|
}
|
|
@@ -749,28 +2128,34 @@ function getSapSdkToolContext(name) {
|
|
|
749
2128
|
return 'SAP MCP context: Direct synapse-sap-sdk wrapper served by this MCP. Read tools return on-chain state; write tools require signer policy, configured RPC, and the active SAP profile.';
|
|
750
2129
|
}
|
|
751
2130
|
const agentTools = [
|
|
2131
|
+
{
|
|
2132
|
+
name: 'sap_protocol_invariants',
|
|
2133
|
+
title: 'Get SAP Protocol Invariants',
|
|
2134
|
+
description: 'Free read-only protocol invariant card for agents. Returns the current SAP program id, protocol treasury, source-level expected 0.1 SOL registration fee invariant, hosted write routing rules, local sap_payments routes, identity pipeline, and forbidden actions. Use this before SAP registry writes and whenever fee/treasury behavior is unclear.',
|
|
2135
|
+
inputSchema: {},
|
|
2136
|
+
handler: async () => buildSapProtocolInvariants(),
|
|
2137
|
+
},
|
|
2138
|
+
{
|
|
2139
|
+
name: 'sap_agent_identity_plan',
|
|
2140
|
+
title: 'Plan SAP Agent Identity',
|
|
2141
|
+
description: 'Free read-only planner for SAP agent registration, profile/image updates, Metaplex/MPL Core identity linking, SNS linking, x402 pricing metadata, and post-write verification. Use this before sap_payments_register_agent or sap_payments_update_agent so agents know the exact local-signer route, metadata contract, forbidden actions, and protocol fee verification checklist. It does not touch chain and never signs.',
|
|
2142
|
+
inputSchema: SAP_AGENT_IDENTITY_PLAN_INPUT_SCHEMA,
|
|
2143
|
+
handler: async (input) => buildSapAgentIdentityPlan(input),
|
|
2144
|
+
},
|
|
752
2145
|
{
|
|
753
2146
|
name: 'sap_register_agent',
|
|
754
|
-
title: 'Register SAP Agent',
|
|
755
|
-
description: '
|
|
756
|
-
inputSchema:
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
capabilities: { type: 'array', description: 'Array of capability objects or strings identifying what the agent can do (e.g. "jupiter:swap")' },
|
|
760
|
-
pricing: { type: 'array', description: 'Array of pricing tier objects defining per-call costs, rate limits, and settlement terms' },
|
|
761
|
-
protocols: { type: 'array', items: { type: 'string' }, description: 'Array of protocol identifiers the agent supports (e.g. "jupiter", "drift")' },
|
|
762
|
-
agentId: { type: 'string', description: 'Optional unique agent identifier string' },
|
|
763
|
-
agentUri: { type: 'string', description: 'Optional URI to the agent\'s off-chain metadata or service endpoint' },
|
|
764
|
-
metadataUri: { type: 'string', description: 'Alias for agentUri — URI to off-chain agent metadata JSON' },
|
|
765
|
-
x402Endpoint: { type: 'string', description: 'Optional x402 payment endpoint URL for HTTP-based agent payments' },
|
|
2147
|
+
title: 'Register SAP Agent (Raw SDK Deprecated)',
|
|
2148
|
+
description: 'Deprecated raw SDK wrapper. Production registration must use sap_payments_register_agent so the local signer path confirms the account, verifies the 0.1 SOL protocol treasury fee invariant, and returns protocolComplete. Hosted accountless SAP MCP rejects this direct write before x402 payment.',
|
|
2149
|
+
inputSchema: SAP_AGENT_REGISTER_INPUT_SCHEMA,
|
|
2150
|
+
handler: async () => {
|
|
2151
|
+
throw new Error('sap_register_agent raw SDK path is disabled for production safety. Call sap_agent_identity_plan, then sap_payments_register_agent with the same registration fields and confirm: true. success is true only when the agent account exists and protocolFee.status is verified.');
|
|
766
2152
|
},
|
|
767
|
-
handler: async (input, client) => ({ signature: await client.agent.register(parseRegisterAgentArgs(input)) }),
|
|
768
2153
|
},
|
|
769
2154
|
{
|
|
770
2155
|
name: 'sap_update_agent',
|
|
771
2156
|
title: 'Update SAP Agent',
|
|
772
|
-
description: '
|
|
773
|
-
inputSchema:
|
|
2157
|
+
description: 'Local-signer-only: update the connected wallet SAP agent using SDK AgentModule.update. Hosted accountless SAP MCP rejects this direct write before x402 payment; hosted users should call sap_payments_update_agent from the local sap_payments bridge.',
|
|
2158
|
+
inputSchema: SAP_AGENT_UPDATE_INPUT_SCHEMA,
|
|
774
2159
|
handler: async (input, client) => ({ signature: await client.agent.update(parseUpdateAgentArgs(input)) }),
|
|
775
2160
|
},
|
|
776
2161
|
{
|
|
@@ -813,7 +2198,7 @@ const agentTools = [
|
|
|
813
2198
|
{
|
|
814
2199
|
name: 'sap_get_agent',
|
|
815
2200
|
title: 'Get SAP Agent',
|
|
816
|
-
description: '
|
|
2201
|
+
description: 'Free exact SAP agent identity read by owner wallet. If omitted, fetches the connected wallet agent. Use this before paid discovery when the wallet is known.',
|
|
817
2202
|
inputSchema: { wallet: { type: 'string', description: 'Solana public key of the agent owner wallet (base58). If omitted, uses the connected wallet.' } },
|
|
818
2203
|
handler: async (input, client) => {
|
|
819
2204
|
const wallet = optionalPublicKey(input, 'wallet');
|
|
@@ -825,7 +2210,7 @@ const agentTools = [
|
|
|
825
2210
|
{
|
|
826
2211
|
name: 'sap_get_agent_stats',
|
|
827
2212
|
title: 'Get SAP Agent Stats',
|
|
828
|
-
description: '
|
|
2213
|
+
description: 'Free exact SAP agent stats read by agent PDA. Use after sap_get_agent or sap_get_agent_profile when stats are needed.',
|
|
829
2214
|
inputSchema: { agentPda: { type: 'string', description: 'Agent PDA (base58) to fetch stats for' } },
|
|
830
2215
|
handler: async (input, client) => ({
|
|
831
2216
|
stats: await client.agent.fetchStatsNullable(requiredPublicKey(input, 'agentPda')),
|
|
@@ -834,7 +2219,7 @@ const agentTools = [
|
|
|
834
2219
|
{
|
|
835
2220
|
name: 'sap_get_global_state',
|
|
836
2221
|
title: 'Get SAP Global State',
|
|
837
|
-
description: '
|
|
2222
|
+
description: 'Free compact global SAP registry state read. Use for initial orientation before paid network analytics.',
|
|
838
2223
|
inputSchema: {},
|
|
839
2224
|
handler: async (_input, client) => ({ state: await client.agent.fetchGlobalRegistry() }),
|
|
840
2225
|
},
|
|
@@ -847,124 +2232,118 @@ const discoveryTools = [
|
|
|
847
2232
|
inputSchema: {},
|
|
848
2233
|
handler: async (_input, client) => ({ overview: await client.discovery.getNetworkOverview() }),
|
|
849
2234
|
},
|
|
2235
|
+
{
|
|
2236
|
+
name: 'sap_agent_context',
|
|
2237
|
+
title: 'Get SAP Agent Context',
|
|
2238
|
+
description: 'Free one-shot SAP orientation context for agents. Use this when the user asks whether SAP MCP is connected, wants to understand an agent/wallet, or needs the next safe paid/write route. It combines exact reads or a compact directory page with routing guidance without triggering x402.',
|
|
2239
|
+
inputSchema: {
|
|
2240
|
+
wallet: {
|
|
2241
|
+
type: 'string',
|
|
2242
|
+
description: 'Optional exact owner wallet public key (base58). When supplied, returns the matching agent identity, PDA, active state, and hydrated profile when available.',
|
|
2243
|
+
},
|
|
2244
|
+
agentPda: {
|
|
2245
|
+
type: 'string',
|
|
2246
|
+
description: 'Optional exact SAP agent PDA (base58) for compact context lookup when the owner wallet is not known.',
|
|
2247
|
+
},
|
|
2248
|
+
query: {
|
|
2249
|
+
type: 'string',
|
|
2250
|
+
description: 'Optional text query for a free compact orientation search. Keep this narrow, for example "XONA" or "Solking".',
|
|
2251
|
+
},
|
|
2252
|
+
limit: {
|
|
2253
|
+
type: 'number',
|
|
2254
|
+
description: 'Maximum compact orientation rows to include when wallet is not supplied. Defaults to 10 and is capped at 20 to keep this tool free.',
|
|
2255
|
+
},
|
|
2256
|
+
},
|
|
2257
|
+
handler: async (input, client) => buildSapAgentContext(input, client),
|
|
2258
|
+
},
|
|
850
2259
|
{
|
|
851
2260
|
name: 'sap_get_agent_profile',
|
|
852
2261
|
title: 'Get SAP Agent Profile',
|
|
853
|
-
description: '
|
|
2262
|
+
description: 'Free exact SAP agent profile read by owner wallet. Use this for a known agent before paid discovery or enrichment.',
|
|
854
2263
|
inputSchema: { wallet: { type: 'string', description: 'Solana public key of the agent owner wallet (base58)' } },
|
|
855
2264
|
handler: async (input, client) => ({ profile: await client.discovery.getAgentProfile(requiredPublicKey(input, 'wallet')) }),
|
|
856
2265
|
},
|
|
857
2266
|
{
|
|
858
2267
|
name: 'sap_is_agent_active',
|
|
859
2268
|
title: 'Check SAP Agent Active',
|
|
860
|
-
description: '
|
|
2269
|
+
description: 'Free exact activity check for an owner wallet. Use this before paid discovery when the wallet is known.',
|
|
861
2270
|
inputSchema: { wallet: { type: 'string', description: 'Solana public key of the wallet to check for an active SAP agent (base58)' } },
|
|
862
2271
|
handler: async (input, client) => ({ active: await client.discovery.isAgentActive(requiredPublicKey(input, 'wallet')) }),
|
|
863
2272
|
},
|
|
864
2273
|
{
|
|
865
2274
|
name: 'sap_discover_agents',
|
|
866
2275
|
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
|
-
},
|
|
2276
|
+
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.',
|
|
2277
|
+
inputSchema: makeAgentDirectoryInputSchema(50),
|
|
875
2278
|
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');
|
|
2279
|
+
const limit = Math.max(1, Math.min(optionalNumber(input, 'limit') ?? 50, 500));
|
|
882
2280
|
const capability = optionalString(input, 'capability');
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
note: 'SDK v0.20 exposes filtered discovery, not unfiltered global agent enumeration. Provide protocol or capability.',
|
|
900
|
-
};
|
|
2281
|
+
const capabilities = parseOptionalStringArray(input, 'capabilities');
|
|
2282
|
+
return getFreshAgentDirectoryPage(client, {
|
|
2283
|
+
includeInactive: input.includeInactive === true,
|
|
2284
|
+
protocol: optionalString(input, 'protocol'),
|
|
2285
|
+
capability,
|
|
2286
|
+
capabilities,
|
|
2287
|
+
capabilityMode: parseCapabilityMode(input),
|
|
2288
|
+
query: optionalString(input, 'query'),
|
|
2289
|
+
wallet: optionalString(input, 'wallet'),
|
|
2290
|
+
agentPda: optionalString(input, 'agentPda'),
|
|
2291
|
+
hasX402Endpoint: parseHasX402Endpoint(input),
|
|
2292
|
+
limit,
|
|
2293
|
+
offset: parseDirectoryOffset(input),
|
|
2294
|
+
view: parseDirectoryView(input),
|
|
2295
|
+
includeProtocolIndexes: input.includeProtocolIndexes === true,
|
|
2296
|
+
});
|
|
901
2297
|
},
|
|
902
2298
|
},
|
|
903
2299
|
{
|
|
904
2300
|
name: 'sap_list_agents',
|
|
905
2301
|
title: 'List SAP Agents',
|
|
906
|
-
description: '
|
|
907
|
-
inputSchema:
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
2302
|
+
description: 'Compact SAP agent orientation list. Free only when limit <= 20, view is compact, hydrate is false, and includeProtocolIndexes is false; larger or enriched pages are paid read-premium.',
|
|
2303
|
+
inputSchema: makeAgentDirectoryInputSchema(20),
|
|
2304
|
+
handler: async (input, client) => {
|
|
2305
|
+
const limit = Math.max(1, Math.min(optionalNumber(input, 'limit') ?? 20, 500));
|
|
2306
|
+
const capability = optionalString(input, 'capability');
|
|
2307
|
+
return getFreshAgentDirectoryPage(client, {
|
|
2308
|
+
includeInactive: input.includeInactive === true,
|
|
2309
|
+
protocol: optionalString(input, 'protocol'),
|
|
2310
|
+
capability,
|
|
2311
|
+
capabilities: parseOptionalStringArray(input, 'capabilities'),
|
|
2312
|
+
capabilityMode: parseCapabilityMode(input),
|
|
2313
|
+
query: optionalString(input, 'query'),
|
|
2314
|
+
wallet: optionalString(input, 'wallet'),
|
|
2315
|
+
agentPda: optionalString(input, 'agentPda'),
|
|
2316
|
+
hasX402Endpoint: parseHasX402Endpoint(input),
|
|
2317
|
+
limit,
|
|
2318
|
+
offset: parseDirectoryOffset(input),
|
|
2319
|
+
view: parseDirectoryView(input),
|
|
2320
|
+
includeProtocolIndexes: input.includeProtocolIndexes === true,
|
|
2321
|
+
});
|
|
913
2322
|
},
|
|
914
|
-
handler: async (input, client) => discoveryTools[3].handler(input, client),
|
|
915
2323
|
},
|
|
916
2324
|
{
|
|
917
2325
|
name: 'sap_list_all_agents',
|
|
918
2326
|
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
|
-
},
|
|
2327
|
+
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.',
|
|
2328
|
+
inputSchema: makeAgentDirectoryInputSchema(100),
|
|
928
2329
|
handler: async (input, client) => {
|
|
929
2330
|
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
2331
|
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,
|
|
2332
|
+
return getFreshAgentDirectoryPage(client, {
|
|
2333
|
+
includeInactive: input.includeInactive === true,
|
|
2334
|
+
protocol: optionalString(input, 'protocol'),
|
|
2335
|
+
capability,
|
|
2336
|
+
capabilities: parseOptionalStringArray(input, 'capabilities'),
|
|
2337
|
+
capabilityMode: parseCapabilityMode(input),
|
|
2338
|
+
query: optionalString(input, 'query'),
|
|
2339
|
+
wallet: optionalString(input, 'wallet'),
|
|
2340
|
+
agentPda: optionalString(input, 'agentPda'),
|
|
2341
|
+
hasX402Endpoint: parseHasX402Endpoint(input),
|
|
962
2342
|
limit,
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
};
|
|
2343
|
+
offset: parseDirectoryOffset(input),
|
|
2344
|
+
view: parseDirectoryView(input),
|
|
2345
|
+
includeProtocolIndexes: input.includeProtocolIndexes !== false,
|
|
2346
|
+
});
|
|
968
2347
|
},
|
|
969
2348
|
},
|
|
970
2349
|
{
|
|
@@ -1228,24 +2607,66 @@ const paymentAndEscrowTools = [
|
|
|
1228
2607
|
},
|
|
1229
2608
|
];
|
|
1230
2609
|
const escrowV2Tools = [
|
|
2610
|
+
{
|
|
2611
|
+
name: 'sap_escrow_build_create_transaction',
|
|
2612
|
+
title: 'Build SAP Escrow V2 Create Transaction',
|
|
2613
|
+
description: 'Hosted-safe unsigned builder for create_escrow_v2. Use this from hosted SAP MCP, preview the result, then call local sap_payments_finalize_transaction with submit:true. The depositorWallet signs locally; keypair bytes never leave the user machine. Defaults to DisputeWindow settlementSecurity=2 and rejects SelfReport/0.',
|
|
2614
|
+
inputSchema: escrowV2CreateBuilderInputSchema,
|
|
2615
|
+
handler: buildEscrowCreateTransaction,
|
|
2616
|
+
},
|
|
2617
|
+
{
|
|
2618
|
+
name: 'sap_escrow_build_deposit_transaction',
|
|
2619
|
+
title: 'Build SAP Escrow V2 Deposit Transaction',
|
|
2620
|
+
description: 'Hosted-safe unsigned builder for deposit_escrow_v2. Use this when a hosted workflow needs to add funds to an existing V2 escrow, then finalize locally with sap_payments_finalize_transaction.',
|
|
2621
|
+
inputSchema: escrowV2DepositBuilderInputSchema,
|
|
2622
|
+
handler: buildEscrowDepositTransaction,
|
|
2623
|
+
},
|
|
2624
|
+
{
|
|
2625
|
+
name: 'sap_escrow_build_settle_transaction',
|
|
2626
|
+
title: 'Build SAP Escrow V2 Settlement Transaction',
|
|
2627
|
+
description: 'Hosted-safe unsigned builder for settle_calls_v2. The agent owner wallet signs locally. DisputeWindow escrows create a pending settlement PDA; CoSigned escrows require the coSigner account when configured.',
|
|
2628
|
+
inputSchema: escrowV2SettleBuilderInputSchema,
|
|
2629
|
+
handler: buildEscrowSettleTransaction,
|
|
2630
|
+
},
|
|
2631
|
+
{
|
|
2632
|
+
name: 'sap_escrow_build_finalize_transaction',
|
|
2633
|
+
title: 'Build SAP Escrow V2 Finalize Transaction',
|
|
2634
|
+
description: 'Hosted-safe unsigned builder for finalize_settlement. Use after the dispute window has elapsed and a pending settlement exists; any payerWallet can locally sign to crank finalization.',
|
|
2635
|
+
inputSchema: escrowV2FinalizeBuilderInputSchema,
|
|
2636
|
+
handler: buildEscrowFinalizeTransaction,
|
|
2637
|
+
},
|
|
2638
|
+
{
|
|
2639
|
+
name: 'sap_escrow_build_withdraw_transaction',
|
|
2640
|
+
title: 'Build SAP Escrow V2 Withdraw Transaction',
|
|
2641
|
+
description: 'Hosted-safe unsigned builder for withdraw_escrow_v2. The depositor signs locally and can only withdraw unlocked balance after pending amounts are excluded.',
|
|
2642
|
+
inputSchema: escrowV2WithdrawBuilderInputSchema,
|
|
2643
|
+
handler: buildEscrowWithdrawTransaction,
|
|
2644
|
+
},
|
|
2645
|
+
{
|
|
2646
|
+
name: 'sap_escrow_build_close_transaction',
|
|
2647
|
+
title: 'Build SAP Escrow V2 Close Transaction',
|
|
2648
|
+
description: 'Hosted-safe unsigned builder for close_escrow_v2. The depositor signs locally; the builder refuses to close until balance and pendingAmount are both zero.',
|
|
2649
|
+
inputSchema: escrowV2CloseBuilderInputSchema,
|
|
2650
|
+
handler: buildEscrowCloseTransaction,
|
|
2651
|
+
},
|
|
1231
2652
|
{
|
|
1232
2653
|
name: 'sap_create_escrow_v2',
|
|
1233
2654
|
title: 'Create SAP Escrow V2',
|
|
1234
|
-
description: '
|
|
2655
|
+
description: 'Local-signer-only direct V2 escrow creation using SDK EscrowV2Module.create. Defaults to DisputeWindow settlementSecurity=2; SelfReport/0 is rejected. Hosted accountless SAP MCP rejects this before x402 payment; hosted users should call sap_escrow_build_create_transaction and finalize locally.',
|
|
1235
2656
|
inputSchema: escrowV2CreateInputSchema,
|
|
1236
2657
|
handler: async (input, client) => ({ signature: await client.escrowV2.create(requiredPublicKey(input, 'agentWallet'), parseEscrowV2Args(input)) }),
|
|
1237
2658
|
},
|
|
1238
2659
|
{
|
|
1239
2660
|
name: 'sap_deposit_escrow_v2',
|
|
1240
2661
|
title: 'Deposit SAP Escrow V2',
|
|
1241
|
-
description: '
|
|
2662
|
+
description: 'Local-signer-only direct deposit into a V2 escrow. Hosted users should call sap_escrow_build_deposit_transaction and finalize locally.',
|
|
1242
2663
|
inputSchema: { agentWallet: { type: 'string', description: 'Agent wallet public key (base58)' }, nonce: { type: 'string', description: 'Escrow nonce (as a decimal string, default: 0)' }, amount: { type: 'string', description: `Deposit amount as a decimal string. ${ESCROW_AMOUNT_DESCRIPTION}` } },
|
|
1243
2664
|
handler: async (input, client) => ({ signature: await client.escrowV2.deposit(requiredPublicKey(input, 'agentWallet'), optionalBn(input, 'nonce', new BN(0)), requiredBn(input, 'amount')) }),
|
|
1244
2665
|
},
|
|
1245
2666
|
{
|
|
1246
2667
|
name: 'sap_settle_escrow_v2',
|
|
1247
2668
|
title: 'Settle SAP Escrow V2',
|
|
1248
|
-
description: '
|
|
2669
|
+
description: 'Local-signer-only direct settlement against a V2 escrow. Hosted users should call sap_escrow_build_settle_transaction and finalize locally.',
|
|
1249
2670
|
inputSchema: { depositorWallet: { type: 'string', description: 'Depositor wallet public key (base58)' }, nonce: { type: 'string', description: 'Escrow nonce (as a decimal string, default: 0)' }, callsToSettle: { type: 'string', description: 'Number of calls to settle (as a decimal string)' }, serviceHash: { type: 'array', description: '32-byte service hash as a byte array, hex string, or base64 string' } },
|
|
1250
2671
|
handler: async (input, client) => ({
|
|
1251
2672
|
signature: await client.escrowV2.settle(requiredPublicKey(input, 'depositorWallet'), optionalBn(input, 'nonce', new BN(0)), requiredBn(input, 'callsToSettle'), requiredBytes(input, 'serviceHash', 32)),
|
|
@@ -1263,7 +2684,7 @@ const escrowV2Tools = [
|
|
|
1263
2684
|
{
|
|
1264
2685
|
name: 'sap_finalize_settlement_v2',
|
|
1265
2686
|
title: 'Finalize SAP Escrow V2 Settlement',
|
|
1266
|
-
description: '
|
|
2687
|
+
description: 'Local-signer-only direct finalization of a V2 pending settlement. Hosted users should call sap_escrow_build_finalize_transaction and finalize locally.',
|
|
1267
2688
|
inputSchema: { agentWallet: { type: 'string', description: 'Agent wallet public key (base58)' }, depositorWallet: { type: 'string', description: 'Depositor wallet public key (base58)' }, nonce: { type: 'string', description: 'Escrow nonce (as a decimal string, default: 0)' }, settlementIndex: { type: 'string', description: 'Settlement index to finalize (as a decimal string)' } },
|
|
1268
2689
|
handler: async (input, client) => ({
|
|
1269
2690
|
signature: await client.escrowV2.finalizeSettlement(requiredPublicKey(input, 'agentWallet'), requiredPublicKey(input, 'depositorWallet'), optionalBn(input, 'nonce', new BN(0)), requiredBn(input, 'settlementIndex')),
|
|
@@ -1281,14 +2702,14 @@ const escrowV2Tools = [
|
|
|
1281
2702
|
{
|
|
1282
2703
|
name: 'sap_withdraw_escrow_v2',
|
|
1283
2704
|
title: 'Withdraw SAP Escrow V2',
|
|
1284
|
-
description: '
|
|
2705
|
+
description: 'Local-signer-only direct withdrawal from a V2 escrow. Hosted users should call sap_escrow_build_withdraw_transaction and finalize locally.',
|
|
1285
2706
|
inputSchema: { agentWallet: { type: 'string', description: 'Agent wallet public key (base58)' }, nonce: { type: 'string', description: 'Escrow nonce (as a decimal string, default: 0)' }, amount: { type: 'string', description: `Withdrawal amount as a decimal string. ${ESCROW_AMOUNT_DESCRIPTION}` } },
|
|
1286
2707
|
handler: async (input, client) => ({ signature: await client.escrowV2.withdraw(requiredPublicKey(input, 'agentWallet'), optionalBn(input, 'nonce', new BN(0)), requiredBn(input, 'amount')) }),
|
|
1287
2708
|
},
|
|
1288
2709
|
{
|
|
1289
2710
|
name: 'sap_close_escrow_v2',
|
|
1290
2711
|
title: 'Close SAP Escrow V2',
|
|
1291
|
-
description: '
|
|
2712
|
+
description: 'Local-signer-only direct close for an empty V2 escrow. Hosted users should call sap_escrow_build_close_transaction and finalize locally.',
|
|
1292
2713
|
inputSchema: { agentWallet: { type: 'string', description: 'Agent wallet public key (base58)' }, nonce: { type: 'string', description: 'Escrow nonce (as a decimal string, default: 0)' } },
|
|
1293
2714
|
handler: async (input, client) => ({ signature: await client.escrowV2.close(requiredPublicKey(input, 'agentWallet'), optionalBn(input, 'nonce', new BN(0))) }),
|
|
1294
2715
|
},
|
|
@@ -1530,7 +2951,7 @@ const sapToolGroups = [
|
|
|
1530
2951
|
];
|
|
1531
2952
|
/**
|
|
1532
2953
|
* @name registerSapSdkTools
|
|
1533
|
-
* @description Registers production SAP SDK-backed tools using the public SDK
|
|
2954
|
+
* @description Registers production SAP SDK-backed tools using the current public SDK v1.0.x client surface.
|
|
1534
2955
|
*/
|
|
1535
2956
|
export function registerSapSdkTools(server, _context) {
|
|
1536
2957
|
logger.debug('Registering SAP SDK tools');
|