@scriptmasterlabs/mcp-x402 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/.well-known/agentcard.json +34 -34
  2. package/.well-known/ai.txt +32 -0
  3. package/CONTRIBUTING.md +76 -76
  4. package/LICENSE +21 -21
  5. package/README.md +304 -304
  6. package/agents.json +81 -67
  7. package/ai/faq.json +74 -0
  8. package/ai/summary.json +157 -0
  9. package/dist/lib/chains/base.d.ts.map +1 -1
  10. package/dist/lib/chains/base.js +2 -0
  11. package/dist/lib/chains/base.js.map +1 -1
  12. package/dist/lib/credit/bureau.d.ts +7 -1
  13. package/dist/lib/credit/bureau.d.ts.map +1 -1
  14. package/dist/lib/credit/bureau.js +40 -10
  15. package/dist/lib/credit/bureau.js.map +1 -1
  16. package/dist/server/index.js +128 -5
  17. package/dist/server/index.js.map +1 -1
  18. package/llms.txt +170 -70
  19. package/package.json +78 -78
  20. package/server.json +52 -48
  21. package/.env.example +0 -35
  22. package/.github/workflows/ci.yml +0 -59
  23. package/.github/workflows/keepalive.yml +0 -31
  24. package/Dockerfile +0 -19
  25. package/docker-compose.yml +0 -50
  26. package/mcp-publisher.exe +0 -0
  27. package/render.yaml +0 -39
  28. package/sdk/mcp-x402-sdk/package.json +0 -18
  29. package/sdk/mcp-x402-sdk/src/index.ts +0 -118
  30. package/sdk/mcp-x402-sdk/tsconfig.json +0 -14
  31. package/services/backtest_service.py +0 -176
  32. package/src/lib/chains/base.ts +0 -77
  33. package/src/lib/chains/solana.ts +0 -59
  34. package/src/lib/chains/xrpl.ts +0 -63
  35. package/src/lib/credit/bureau.ts +0 -65
  36. package/src/lib/sml-api/agentcard.ts +0 -40
  37. package/src/lib/sml-api/backtest.ts +0 -47
  38. package/src/lib/sml-api/brokers.ts +0 -160
  39. package/src/lib/sml-api/copytrader.ts +0 -33
  40. package/src/lib/sml-api/crawl.ts +0 -44
  41. package/src/lib/sml-api/echo.ts +0 -28
  42. package/src/lib/sml-api/forge.ts +0 -33
  43. package/src/lib/sml-api/ftd.ts +0 -53
  44. package/src/lib/sml-api/ghost.ts +0 -35
  45. package/src/lib/sml-api/launchpad.ts +0 -43
  46. package/src/lib/sml-api/leviathan.ts +0 -49
  47. package/src/lib/sml-api/nexus.ts +0 -50
  48. package/src/lib/sml-api/proof402.ts +0 -27
  49. package/src/lib/sml-api/rails.ts +0 -34
  50. package/src/lib/sml-api/shadow.ts +0 -35
  51. package/src/lib/sml-api/squeezeos.ts +0 -95
  52. package/src/lib/sml-api/xdeo.ts +0 -40
  53. package/src/lib/sml-api/xmit.ts +0 -40
  54. package/src/server/health.ts +0 -52
  55. package/src/server/index.ts +0 -213
  56. package/src/server/payments/ap2.ts +0 -101
  57. package/src/server/payments/receipt.ts +0 -85
  58. package/src/server/payments/router.ts +0 -110
  59. package/src/server/payments/wallet.ts +0 -123
  60. package/src/server/payments/x402.ts +0 -177
  61. package/src/server/registry/catalog.ts +0 -61
  62. package/src/server/registry/discovery.ts +0 -39
  63. package/src/server/registry/pricing.ts +0 -133
  64. package/src/server/security/acl.ts +0 -42
  65. package/src/server/security/audit.ts +0 -94
  66. package/src/server/security/rate-limit.ts +0 -84
  67. package/src/server/security/sandbox.ts +0 -40
  68. package/src/server/tools/agentcard.ts +0 -134
  69. package/src/server/tools/backtest.ts +0 -119
  70. package/src/server/tools/brokers.ts +0 -250
  71. package/src/server/tools/copytrader.ts +0 -104
  72. package/src/server/tools/crawl.ts +0 -70
  73. package/src/server/tools/discovery.ts +0 -202
  74. package/src/server/tools/echo.ts +0 -58
  75. package/src/server/tools/forge.ts +0 -87
  76. package/src/server/tools/ftd.ts +0 -88
  77. package/src/server/tools/ghost.ts +0 -93
  78. package/src/server/tools/index.ts +0 -42
  79. package/src/server/tools/launchpad.ts +0 -173
  80. package/src/server/tools/leviathan.ts +0 -81
  81. package/src/server/tools/nexus.ts +0 -76
  82. package/src/server/tools/proof402.ts +0 -87
  83. package/src/server/tools/rails.ts +0 -92
  84. package/src/server/tools/shadow.ts +0 -128
  85. package/src/server/tools/squeezeos.ts +0 -312
  86. package/src/server/tools/xdeo.ts +0 -67
  87. package/src/server/tools/xmit.ts +0 -68
  88. package/tests/integration/e2e.test.ts +0 -51
  89. package/tests/unit/payments.test.ts +0 -49
  90. package/tests/unit/security.test.ts +0 -92
  91. package/tests/unit/tools.test.ts +0 -42
  92. package/tsconfig.json +0 -21
  93. package/vitest.config.ts +0 -20
@@ -1,173 +0,0 @@
1
- import { z } from 'zod';
2
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { executeX402Payment } from '../payments/x402.js';
4
- import { RateLimiter } from '../security/rate-limit.js';
5
- import { Sandbox } from '../security/sandbox.js';
6
- import { AuditLogger } from '../security/audit.js';
7
- import { PriceRegistry } from '../registry/pricing.js';
8
- import { LaunchpadAPI } from '../../lib/sml-api/launchpad.js';
9
-
10
- const CreateSchema = z.object({
11
- name: z.string().min(1).max(64),
12
- symbol: z.string().min(1).max(10).toUpperCase(),
13
- description: z.string().max(512),
14
- creator_address: z.string().min(10),
15
- initial_supply: z.number().int().positive(),
16
- target_liquidity_xrp: z.number().positive(),
17
- wallet_address: z.string().optional(),
18
- });
19
-
20
- const BuySchema = z.object({
21
- token_address: z.string().min(10),
22
- buyer_address: z.string().min(10),
23
- xrp_amount: z.number().positive(),
24
- wallet_address: z.string().optional(),
25
- });
26
-
27
- export function registerLaunchpad(server: McpServer): void {
28
- const audit = AuditLogger.getInstance();
29
-
30
- // ── FREE: launchpad_status ─────────────────────────────────────────────────
31
- server.tool(
32
- 'launchpad_status',
33
- {},
34
- async () => {
35
- try {
36
- const data = await LaunchpadAPI.status();
37
- return { content: [{ type: 'text', text: JSON.stringify(data) }] };
38
- } catch (err) {
39
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
40
- }
41
- },
42
- );
43
-
44
- // ── FREE: launchpad_list ───────────────────────────────────────────────────
45
- server.tool(
46
- 'launchpad_list',
47
- {},
48
- async () => {
49
- if (!RateLimiter.getInstance().checkTool('launchpad_list')) {
50
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
51
- }
52
- try {
53
- const data = await LaunchpadAPI.list();
54
- audit.info('launchpad_list', {});
55
- return { content: [{ type: 'text', text: JSON.stringify(data) }] };
56
- } catch (err) {
57
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
58
- }
59
- },
60
- );
61
-
62
- // ── PAID: launchpad_create (0.10 USDC) ────────────────────────────────────
63
- server.tool(
64
- 'launchpad_create',
65
- {
66
- name: z.string().describe('Token name (e.g. "Moon Rocket").'),
67
- symbol: z.string().describe('Ticker symbol (e.g. MNRKT, max 10 chars).'),
68
- description: z.string().describe('Token description (max 512 chars).'),
69
- creator_address: z.string().describe('XRPL address of the token creator.'),
70
- initial_supply: z.number().describe('Total token supply (integer).'),
71
- target_liquidity_xrp: z.number().describe('XRP target to graduate from bonding curve to DEX.'),
72
- wallet_address: z.string().describe('Agent wallet for x402 payment.'),
73
- },
74
- async (rawArgs) => {
75
- const args = Sandbox.validate(CreateSchema, rawArgs);
76
-
77
- if (!RateLimiter.getInstance().checkTool('launchpad_create')) {
78
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
79
- }
80
-
81
- await PriceRegistry.getInstance().seedDefaults();
82
- const price = await PriceRegistry.getInstance().getPrice('launchpad_create');
83
- if (!price) {
84
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'price_unavailable' }) }], isError: true };
85
- }
86
-
87
- let payment;
88
- try {
89
- payment = await executeX402Payment({ price, currency: 'USDC', toolName: 'launchpad_create', walletAddress: args.wallet_address });
90
- } catch (err) {
91
- audit.warn('launchpad_create_payment_fail', { error: String(err) });
92
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: String(err) }) }], isError: true };
93
- }
94
-
95
- try {
96
- const data = await LaunchpadAPI.create({
97
- name: args.name,
98
- symbol: args.symbol,
99
- description: args.description,
100
- creatorAddress: args.creator_address,
101
- initialSupply: args.initial_supply,
102
- targetLiquidityXrp: args.target_liquidity_xrp,
103
- });
104
- audit.info('launchpad_create_success', { symbol: args.symbol, receiptId: payment.receiptId });
105
- return {
106
- content: [{
107
- type: 'text',
108
- text: JSON.stringify({
109
- data,
110
- _meta: { receipt_id: payment.receiptId, tx_hash: payment.txHash, chain: payment.chain, amount_paid: `${payment.amountPaid} ${payment.currency}`, timestamp: payment.timestamp },
111
- }),
112
- }],
113
- };
114
- } catch (err) {
115
- audit.error('launchpad_create_api_fail', { error: String(err) });
116
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
117
- }
118
- },
119
- );
120
-
121
- // ── PAID: launchpad_buy (0.01 USDC) ───────────────────────────────────────
122
- server.tool(
123
- 'launchpad_buy',
124
- {
125
- token_address: z.string().describe('Token contract/address on XRPL.'),
126
- buyer_address: z.string().describe('XRPL address of the buyer.'),
127
- xrp_amount: z.number().describe('Amount of XRP to spend on the bonding curve.'),
128
- wallet_address: z.string().describe('Agent wallet for x402 payment.'),
129
- },
130
- async (rawArgs) => {
131
- const args = Sandbox.validate(BuySchema, rawArgs);
132
-
133
- if (!RateLimiter.getInstance().checkTool('launchpad_buy')) {
134
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
135
- }
136
-
137
- await PriceRegistry.getInstance().seedDefaults();
138
- const price = await PriceRegistry.getInstance().getPrice('launchpad_buy');
139
- if (!price) {
140
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'price_unavailable' }) }], isError: true };
141
- }
142
-
143
- let payment;
144
- try {
145
- payment = await executeX402Payment({ price, currency: 'USDC', toolName: 'launchpad_buy', walletAddress: args.wallet_address });
146
- } catch (err) {
147
- audit.warn('launchpad_buy_payment_fail', { error: String(err) });
148
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: String(err) }) }], isError: true };
149
- }
150
-
151
- try {
152
- const data = await LaunchpadAPI.buy({
153
- tokenAddress: args.token_address,
154
- buyerAddress: args.buyer_address,
155
- xrpAmount: args.xrp_amount,
156
- });
157
- audit.info('launchpad_buy_success', { receiptId: payment.receiptId });
158
- return {
159
- content: [{
160
- type: 'text',
161
- text: JSON.stringify({
162
- data,
163
- _meta: { receipt_id: payment.receiptId, tx_hash: payment.txHash, chain: payment.chain, amount_paid: `${payment.amountPaid} ${payment.currency}`, timestamp: payment.timestamp },
164
- }),
165
- }],
166
- };
167
- } catch (err) {
168
- audit.error('launchpad_buy_api_fail', { error: String(err) });
169
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
170
- }
171
- },
172
- );
173
- }
@@ -1,81 +0,0 @@
1
- import { z } from 'zod';
2
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { executeX402Payment } from '../payments/x402.js';
4
- import { RateLimiter } from '../security/rate-limit.js';
5
- import { Sandbox } from '../security/sandbox.js';
6
- import { AuditLogger } from '../security/audit.js';
7
- import { LeviathanClient } from '../../lib/sml-api/leviathan.js';
8
- import { PriceRegistry } from '../registry/pricing.js';
9
-
10
- const InputSchema = z.object({
11
- ticker: z.string().regex(/^[A-Z]{1,5}$/).optional(),
12
- signal_type: z.enum(['squeeze', 'momentum', 'dark_pool', 'all']),
13
- min_confidence: z.number().min(0).max(100).default(60),
14
- wallet_address: z.string().optional(),
15
- });
16
-
17
- export function registerLeviathan(server: McpServer): void {
18
- server.tool(
19
- 'leviathan_signal',
20
- {
21
- ticker: z.string().describe('Ticker symbol (e.g. TSLA, MSTR). Optional — omit for top signals.'),
22
- signal_type: z.enum(['squeeze', 'momentum', 'dark_pool', 'all']).describe('Signal category.'),
23
- min_confidence: z.number().describe('Minimum confidence score 0-100. Default: 60.'),
24
- wallet_address: z.string().describe('Agent wallet address for payment. Auto-provisioned if omitted.'),
25
- },
26
- async (rawArgs) => {
27
- const args = Sandbox.validate(InputSchema, rawArgs);
28
- const audit = AuditLogger.getInstance();
29
-
30
- if (!RateLimiter.getInstance().checkTool('leviathan_signal')) {
31
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
32
- }
33
-
34
- await PriceRegistry.getInstance().seedDefaults();
35
- const price = await PriceRegistry.getInstance().getPrice('leviathan_signal');
36
- if (!price) {
37
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'price_unavailable', message: 'Cannot determine price. Try again shortly.' }) }], isError: true };
38
- }
39
-
40
- let payment;
41
- try {
42
- payment = await executeX402Payment({
43
- price,
44
- currency: 'USDC',
45
- toolName: 'leviathan_signal',
46
- walletAddress: args.wallet_address,
47
- });
48
- } catch (err) {
49
- audit.warn('leviathan_payment_fail', { error: String(err) });
50
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: String(err) }) }], isError: true };
51
- }
52
-
53
- const client = LeviathanClient.getInstance();
54
- const data = await client.getSignal({
55
- ticker: args.ticker,
56
- signalType: args.signal_type,
57
- minConfidence: args.min_confidence ?? 60,
58
- });
59
-
60
- audit.info('leviathan_success', { ticker: args.ticker ?? 'all', receiptId: payment.receiptId });
61
-
62
- return {
63
- content: [
64
- {
65
- type: 'text',
66
- text: JSON.stringify({
67
- data,
68
- _meta: {
69
- receipt_id: payment.receiptId,
70
- tx_hash: payment.txHash,
71
- chain: payment.chain,
72
- amount_paid: `${payment.amountPaid} ${payment.currency}`,
73
- timestamp: payment.timestamp,
74
- },
75
- }),
76
- },
77
- ],
78
- };
79
- },
80
- );
81
- }
@@ -1,76 +0,0 @@
1
- import { z } from 'zod';
2
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { executeX402Payment } from '../payments/x402.js';
4
- import { RateLimiter } from '../security/rate-limit.js';
5
- import { Sandbox } from '../security/sandbox.js';
6
- import { AuditLogger } from '../security/audit.js';
7
- import { NexusClient } from '../../lib/sml-api/nexus.js';
8
-
9
- const InputSchema = z.object({
10
- capability: z.string().min(1).max(200),
11
- max_budget: z.string().regex(/^\d+(\.\d+)?$/),
12
- chain_preference: z.enum(['base', 'xrpl', 'solana']).optional(),
13
- action: z.enum(['query', 'hire']).default('query'),
14
- agent_id: z.string().optional(),
15
- wallet_address: z.string().optional(),
16
- });
17
-
18
- const COMMISSION_RATE = 0.05;
19
-
20
- export function registerNexus(server: McpServer): void {
21
- server.tool(
22
- 'nexus_agent_hire',
23
- {
24
- capability: z.string().describe('Capability or skill to search for (e.g. "options flow analysis").'),
25
- max_budget: z.string().describe('Max budget in USDC for hire (e.g. "1.00").'),
26
- chain_preference: z.enum(['base', 'xrpl', 'solana']).describe('Preferred payment chain.'),
27
- action: z.enum(['query', 'hire']).describe('"query" is free. "hire" charges 5% commission on agent fee.'),
28
- agent_id: z.string().describe('Agent ID to hire (required for action=hire).'),
29
- wallet_address: z.string().describe('Agent wallet for payment.'),
30
- },
31
- async (rawArgs) => {
32
- const args = Sandbox.validate(InputSchema, rawArgs);
33
- const audit = AuditLogger.getInstance();
34
-
35
- if (!RateLimiter.getInstance().checkTool('nexus_agent_hire')) {
36
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded' }) }], isError: true };
37
- }
38
-
39
- const client = NexusClient.getInstance();
40
-
41
- // Free query tier
42
- if (args.action === 'query') {
43
- const results = await client.queryAgents({ capability: args.capability, maxBudget: args.max_budget });
44
- audit.info('nexus_query_success', { capability: args.capability });
45
- return { content: [{ type: 'text', text: JSON.stringify({ data: results, tier: 'free' }) }] };
46
- }
47
-
48
- // Hire — commission-based payment
49
- if (!args.agent_id) {
50
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'agent_id_required', message: 'Specify agent_id to hire.' }) }], isError: true };
51
- }
52
-
53
- const agentFee = parseFloat(args.max_budget);
54
- const commission = (agentFee * COMMISSION_RATE).toFixed(4);
55
-
56
- let payment;
57
- try {
58
- payment = await executeX402Payment({
59
- price: commission,
60
- currency: 'USDC',
61
- toolName: 'nexus_agent_hire',
62
- walletAddress: args.wallet_address,
63
- });
64
- } catch (err) {
65
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: String(err) }) }], isError: true };
66
- }
67
-
68
- const hireResult = await client.hireAgent({ agentId: args.agent_id, budget: args.max_budget, chainPreference: args.chain_preference });
69
-
70
- audit.info('nexus_hire_success', { agentId: args.agent_id, commission, receiptId: payment.receiptId });
71
- return {
72
- content: [{ type: 'text', text: JSON.stringify({ data: hireResult, commission: `${commission} USDC (5%)`, _meta: { receipt_id: payment.receiptId, tx_hash: payment.txHash, chain: payment.chain } }) }],
73
- };
74
- },
75
- );
76
- }
@@ -1,87 +0,0 @@
1
- import { z } from 'zod';
2
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { RateLimiter } from '../security/rate-limit.js';
4
- import { Sandbox } from '../security/sandbox.js';
5
- import { AuditLogger } from '../security/audit.js';
6
- import { Proof402API } from '../../lib/sml-api/proof402.js';
7
-
8
- const InvoiceSchema = z.object({
9
- endpoint_id: z.string().uuid(),
10
- });
11
-
12
- const VerifySchema = z.object({
13
- tx_hash: z.string().min(10),
14
- endpoint_id: z.string().uuid(),
15
- });
16
-
17
- const CreditSchema = z.object({
18
- wallet_address: z.string().min(10),
19
- });
20
-
21
- export function registerProof402(server: McpServer): void {
22
- const audit = AuditLogger.getInstance();
23
-
24
- // ── FREE: proof_invoice ────────────────────────────────────────────────────
25
- server.tool(
26
- 'proof_invoice',
27
- {
28
- endpoint_id: z.string().describe('UUID of the premium endpoint to get a payment invoice for.'),
29
- },
30
- async (rawArgs) => {
31
- const { endpoint_id } = Sandbox.validate(InvoiceSchema, rawArgs);
32
- if (!RateLimiter.getInstance().checkTool('proof_invoice')) {
33
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
34
- }
35
- try {
36
- const data = await Proof402API.invoice(endpoint_id);
37
- audit.info('proof_invoice', { endpoint_id });
38
- return { content: [{ type: 'text', text: JSON.stringify(data) }] };
39
- } catch (err) {
40
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
41
- }
42
- },
43
- );
44
-
45
- // ── FREE: proof_verify ─────────────────────────────────────────────────────
46
- server.tool(
47
- 'proof_verify',
48
- {
49
- tx_hash: z.string().describe('XRPL transaction hash to verify.'),
50
- endpoint_id: z.string().describe('UUID of the endpoint the payment was for.'),
51
- },
52
- async (rawArgs) => {
53
- const args = Sandbox.validate(VerifySchema, rawArgs);
54
- if (!RateLimiter.getInstance().checkTool('proof_verify')) {
55
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
56
- }
57
- try {
58
- const data = await Proof402API.verify(args.tx_hash, args.endpoint_id);
59
- audit.info('proof_verify', { tx_hash: args.tx_hash });
60
- return { content: [{ type: 'text', text: JSON.stringify(data) }] };
61
- } catch (err) {
62
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
63
- }
64
- },
65
- );
66
-
67
- // ── FREE: proof_credit_score ───────────────────────────────────────────────
68
- server.tool(
69
- 'proof_credit_score',
70
- {
71
- wallet_address: z.string().describe('Agent wallet address to look up credit score for (300-850 scale).'),
72
- },
73
- async (rawArgs) => {
74
- const { wallet_address } = Sandbox.validate(CreditSchema, rawArgs);
75
- if (!RateLimiter.getInstance().checkTool('proof_credit_score')) {
76
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
77
- }
78
- try {
79
- const data = await Proof402API.creditScore(wallet_address);
80
- audit.info('proof_credit_score', { wallet_address });
81
- return { content: [{ type: 'text', text: JSON.stringify(data) }] };
82
- } catch (err) {
83
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
84
- }
85
- },
86
- );
87
- }
@@ -1,92 +0,0 @@
1
- import { z } from 'zod';
2
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { executeX402Payment } from '../payments/x402.js';
4
- import { RateLimiter } from '../security/rate-limit.js';
5
- import { Sandbox } from '../security/sandbox.js';
6
- import { AuditLogger } from '../security/audit.js';
7
- import { PriceRegistry } from '../registry/pricing.js';
8
- import { RailsAPI } from '../../lib/sml-api/rails.js';
9
-
10
- const TransferSchema = z.object({
11
- from_address: z.string().min(10),
12
- to_address: z.string().min(10),
13
- amount: z.string().min(1),
14
- currency: z.enum(['RLUSD', 'XRP']),
15
- memo: z.string().max(256).optional(),
16
- wallet_address: z.string().optional(),
17
- });
18
-
19
- export function registerRails(server: McpServer): void {
20
- const audit = AuditLogger.getInstance();
21
-
22
- // ── FREE: rails_status ────────────────────────────────────────────────────
23
- server.tool(
24
- 'rails_status',
25
- {},
26
- async () => {
27
- try {
28
- const data = await RailsAPI.status();
29
- return { content: [{ type: 'text', text: JSON.stringify(data) }] };
30
- } catch (err) {
31
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
32
- }
33
- },
34
- );
35
-
36
- // ── PAID: rails_transfer (0.01 USDC) ──────────────────────────────────────
37
- server.tool(
38
- 'rails_transfer',
39
- {
40
- from_address: z.string().describe('Sender XRPL address.'),
41
- to_address: z.string().describe('Recipient XRPL or Xahau address.'),
42
- amount: z.string().describe('Amount to transfer (as string to preserve precision).'),
43
- currency: z.enum(['RLUSD', 'XRP']).describe('Token to transfer.'),
44
- memo: z.string().describe('Optional transfer memo (max 256 chars).'),
45
- wallet_address: z.string().describe('Agent wallet for x402 payment.'),
46
- },
47
- async (rawArgs) => {
48
- const args = Sandbox.validate(TransferSchema, rawArgs);
49
-
50
- if (!RateLimiter.getInstance().checkTool('rails_transfer')) {
51
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
52
- }
53
-
54
- await PriceRegistry.getInstance().seedDefaults();
55
- const price = await PriceRegistry.getInstance().getPrice('rails_transfer');
56
- if (!price) {
57
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'price_unavailable' }) }], isError: true };
58
- }
59
-
60
- let payment;
61
- try {
62
- payment = await executeX402Payment({ price, currency: 'USDC', toolName: 'rails_transfer', walletAddress: args.wallet_address });
63
- } catch (err) {
64
- audit.warn('rails_transfer_payment_fail', { error: String(err) });
65
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: String(err) }) }], isError: true };
66
- }
67
-
68
- try {
69
- const data = await RailsAPI.transfer({
70
- fromAddress: args.from_address,
71
- toAddress: args.to_address,
72
- amount: args.amount,
73
- currency: args.currency,
74
- memo: args.memo,
75
- });
76
- audit.info('rails_transfer_success', { receiptId: payment.receiptId });
77
- return {
78
- content: [{
79
- type: 'text',
80
- text: JSON.stringify({
81
- data,
82
- _meta: { receipt_id: payment.receiptId, tx_hash: payment.txHash, chain: payment.chain, amount_paid: `${payment.amountPaid} ${payment.currency}`, timestamp: payment.timestamp },
83
- }),
84
- }],
85
- };
86
- } catch (err) {
87
- audit.error('rails_transfer_api_fail', { error: String(err) });
88
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
89
- }
90
- },
91
- );
92
- }
@@ -1,128 +0,0 @@
1
- import { z } from 'zod';
2
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { executeX402Payment } from '../payments/x402.js';
4
- import { RateLimiter } from '../security/rate-limit.js';
5
- import { Sandbox } from '../security/sandbox.js';
6
- import { AuditLogger } from '../security/audit.js';
7
- import { PriceRegistry } from '../registry/pricing.js';
8
- import { ShadowDeskAPI } from '../../lib/sml-api/shadow.js';
9
-
10
- const QuerySchema = z.object({
11
- query: z.string().min(1).max(2048),
12
- context: z.string().max(1024).optional(),
13
- wallet_address: z.string().optional(),
14
- });
15
-
16
- const IngestSchema = z.object({
17
- source: z.string().min(1).max(256),
18
- payload: z.record(z.unknown()),
19
- wallet_address: z.string().optional(),
20
- });
21
-
22
- export function registerShadow(server: McpServer): void {
23
- const audit = AuditLogger.getInstance();
24
-
25
- // ── PAID: shadow_query (0.02 USDC) ────────────────────────────────────────
26
- server.tool(
27
- 'shadow_query',
28
- {
29
- query: z.string().describe('Natural language query for signal intelligence (max 2048 chars).'),
30
- context: z.string().describe('Optional context to refine the query (max 1024 chars).'),
31
- wallet_address: z.string().describe('Agent wallet for x402 payment.'),
32
- },
33
- async (rawArgs) => {
34
- const args = Sandbox.validate(QuerySchema, rawArgs);
35
-
36
- if (!RateLimiter.getInstance().checkTool('shadow_query')) {
37
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
38
- }
39
-
40
- await PriceRegistry.getInstance().seedDefaults();
41
- const price = await PriceRegistry.getInstance().getPrice('shadow_query');
42
- if (!price) {
43
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'price_unavailable' }) }], isError: true };
44
- }
45
-
46
- let payment;
47
- try {
48
- payment = await executeX402Payment({ price, currency: 'USDC', toolName: 'shadow_query', walletAddress: args.wallet_address });
49
- } catch (err) {
50
- audit.warn('shadow_query_payment_fail', { error: String(err) });
51
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: String(err) }) }], isError: true };
52
- }
53
-
54
- try {
55
- const data = await ShadowDeskAPI.query({
56
- query: args.query,
57
- context: args.context,
58
- walletAddress: args.wallet_address ?? payment.walletAddress ?? 'anonymous',
59
- });
60
- audit.info('shadow_query_success', { receiptId: payment.receiptId });
61
- return {
62
- content: [{
63
- type: 'text',
64
- text: JSON.stringify({
65
- data,
66
- _meta: { receipt_id: payment.receiptId, tx_hash: payment.txHash, chain: payment.chain, amount_paid: `${payment.amountPaid} ${payment.currency}`, timestamp: payment.timestamp },
67
- }),
68
- }],
69
- };
70
- } catch (err) {
71
- audit.error('shadow_query_api_fail', { error: String(err) });
72
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
73
- }
74
- },
75
- );
76
-
77
- // ── PAID: shadow_ingest (0.01 USDC) ───────────────────────────────────────
78
- server.tool(
79
- 'shadow_ingest',
80
- {
81
- source: z.string().describe('Source identifier for the data being ingested (e.g. "discord", "twitter", "on-chain").'),
82
- payload: z.record(z.unknown()).describe('Signal data payload as a JSON object.'),
83
- wallet_address: z.string().describe('Agent wallet for x402 payment.'),
84
- },
85
- async (rawArgs) => {
86
- const args = Sandbox.validate(IngestSchema, rawArgs);
87
-
88
- if (!RateLimiter.getInstance().checkTool('shadow_ingest')) {
89
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'rate_limit_exceeded', retry_after: 60 }) }], isError: true };
90
- }
91
-
92
- await PriceRegistry.getInstance().seedDefaults();
93
- const price = await PriceRegistry.getInstance().getPrice('shadow_ingest');
94
- if (!price) {
95
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'price_unavailable' }) }], isError: true };
96
- }
97
-
98
- let payment;
99
- try {
100
- payment = await executeX402Payment({ price, currency: 'USDC', toolName: 'shadow_ingest', walletAddress: args.wallet_address });
101
- } catch (err) {
102
- audit.warn('shadow_ingest_payment_fail', { error: String(err) });
103
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: String(err) }) }], isError: true };
104
- }
105
-
106
- try {
107
- const data = await ShadowDeskAPI.ingest({
108
- source: args.source,
109
- payload: args.payload,
110
- walletAddress: args.wallet_address ?? payment.walletAddress ?? 'anonymous',
111
- });
112
- audit.info('shadow_ingest_success', { source: args.source, receiptId: payment.receiptId });
113
- return {
114
- content: [{
115
- type: 'text',
116
- text: JSON.stringify({
117
- data,
118
- _meta: { receipt_id: payment.receiptId, tx_hash: payment.txHash, chain: payment.chain, amount_paid: `${payment.amountPaid} ${payment.currency}`, timestamp: payment.timestamp },
119
- }),
120
- }],
121
- };
122
- } catch (err) {
123
- audit.error('shadow_ingest_api_fail', { error: String(err) });
124
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'api_error', message: String(err) }) }], isError: true };
125
- }
126
- },
127
- );
128
- }