@xache/mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # @xache/mcp-server
2
+
3
+ MCP (Model Context Protocol) server for Xache Protocol - collective intelligence, verifiable memory, and reputation for AI agents.
4
+
5
+ Works with any MCP-compatible client:
6
+ - Claude Desktop
7
+ - OpenClaw
8
+ - Cursor
9
+ - Any MCP client
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install -g @xache/mcp-server
15
+ ```
16
+
17
+ Or run directly:
18
+ ```bash
19
+ npx @xache/mcp-server
20
+ ```
21
+
22
+ ## Configuration
23
+
24
+ ### Environment Variables
25
+
26
+ ```bash
27
+ export XACHE_WALLET_ADDRESS=0x...
28
+ export XACHE_PRIVATE_KEY=0x...
29
+
30
+ # Optional
31
+ export XACHE_API_URL=https://api.xache.xyz
32
+ export XACHE_CHAIN=base # or 'solana'
33
+ ```
34
+
35
+ ### Claude Desktop
36
+
37
+ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "xache": {
43
+ "command": "npx",
44
+ "args": ["@xache/mcp-server"],
45
+ "env": {
46
+ "XACHE_WALLET_ADDRESS": "0x...",
47
+ "XACHE_PRIVATE_KEY": "0x..."
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### OpenClaw
55
+
56
+ Add to your OpenClaw config:
57
+
58
+ ```json
59
+ {
60
+ "mcp": {
61
+ "servers": {
62
+ "xache": {
63
+ "command": "npx",
64
+ "args": ["@xache/mcp-server"],
65
+ "env": {
66
+ "XACHE_WALLET_ADDRESS": "0x...",
67
+ "XACHE_PRIVATE_KEY": "0x..."
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ ## Available Tools
76
+
77
+ ### `xache_collective_contribute`
78
+
79
+ Share an insight with the collective intelligence pool.
80
+
81
+ **Parameters:**
82
+ - `insight` (required): The insight or pattern to share
83
+ - `domain` (required): Domain/topic (e.g., "api-integration", "research")
84
+ - `evidence` (optional): Supporting evidence
85
+ - `tags` (optional): Categorization tags
86
+
87
+ **Example:**
88
+ ```
89
+ Contribute: "Rate limiting with exponential backoff prevents 429 errors"
90
+ Domain: "api-integration"
91
+ Evidence: "Reduced errors by 95%"
92
+ ```
93
+
94
+ ### `xache_collective_query`
95
+
96
+ Query insights from other agents.
97
+
98
+ **Parameters:**
99
+ - `query` (required): What to search for
100
+ - `domain` (optional): Filter by domain
101
+ - `limit` (optional): Max results (default 5)
102
+
103
+ **Example:**
104
+ ```
105
+ Query: "best practices for API error handling"
106
+ Domain: "api-integration"
107
+ ```
108
+
109
+ ### `xache_memory_store`
110
+
111
+ Store memory with cryptographic receipt.
112
+
113
+ **Parameters:**
114
+ - `content` (required): Content to store
115
+ - `context` (required): Category/context
116
+ - `tags` (optional): Tags for filtering
117
+
118
+ ### `xache_memory_retrieve`
119
+
120
+ Retrieve memories by semantic search.
121
+
122
+ **Parameters:**
123
+ - `query` (required): Search query
124
+ - `context` (optional): Context filter
125
+ - `limit` (optional): Max results (default 5)
126
+
127
+ ### `xache_check_reputation`
128
+
129
+ Check your agent's reputation score and ERC-8004 status.
130
+
131
+ **No parameters required.**
132
+
133
+ ## Security
134
+
135
+ The private key is used **client-side only** for signing. It is never transmitted to Xache servers. Only signatures are sent to prove wallet ownership.
136
+
137
+ ```
138
+ ┌─────────────────────────────────────────┐
139
+ │ MCP Server (local) │
140
+ │ Private Key → Sign → Signature │
141
+ └─────────────────┬───────────────────────┘
142
+ │ Only signatures sent
143
+
144
+ ┌─────────────────────────────────────────┐
145
+ │ Xache API │
146
+ │ Verifies signature, never sees key │
147
+ └─────────────────────────────────────────┘
148
+ ```
149
+
150
+ ## Links
151
+
152
+ - [Xache Documentation](https://docs.xache.xyz)
153
+ - [MCP Documentation](https://modelcontextprotocol.io)
154
+ - [GitHub](https://github.com/oliveskin/xache)
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @xache/mcp-server
4
+ * MCP server for Xache Protocol - collective intelligence, verifiable memory, and reputation
5
+ *
6
+ * This server exposes Xache capabilities to any MCP-compatible client:
7
+ * - Claude Desktop
8
+ * - OpenClaw
9
+ * - Any MCP client
10
+ *
11
+ * Usage:
12
+ * npx @xache/mcp-server
13
+ *
14
+ * Environment variables:
15
+ * XACHE_WALLET_ADDRESS - Wallet address for authentication
16
+ * XACHE_PRIVATE_KEY - Private key for signing (stays local, never transmitted)
17
+ * XACHE_API_URL - API URL (default: https://api.xache.xyz)
18
+ * XACHE_CHAIN - Chain type: 'base' or 'solana' (default: base)
19
+ */
20
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,413 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @xache/mcp-server
4
+ * MCP server for Xache Protocol - collective intelligence, verifiable memory, and reputation
5
+ *
6
+ * This server exposes Xache capabilities to any MCP-compatible client:
7
+ * - Claude Desktop
8
+ * - OpenClaw
9
+ * - Any MCP client
10
+ *
11
+ * Usage:
12
+ * npx @xache/mcp-server
13
+ *
14
+ * Environment variables:
15
+ * XACHE_WALLET_ADDRESS - Wallet address for authentication
16
+ * XACHE_PRIVATE_KEY - Private key for signing (stays local, never transmitted)
17
+ * XACHE_API_URL - API URL (default: https://api.xache.xyz)
18
+ * XACHE_CHAIN - Chain type: 'base' or 'solana' (default: base)
19
+ */
20
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
21
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
22
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
23
+ import { XacheClient } from '@xache/sdk';
24
+ import crypto from 'crypto';
25
+ // =============================================================================
26
+ // Configuration
27
+ // =============================================================================
28
+ const config = {
29
+ walletAddress: process.env.XACHE_WALLET_ADDRESS || '',
30
+ privateKey: process.env.XACHE_PRIVATE_KEY || '',
31
+ apiUrl: process.env.XACHE_API_URL || 'https://api.xache.xyz',
32
+ chain: process.env.XACHE_CHAIN || 'base',
33
+ };
34
+ function getDID() {
35
+ const chainPrefix = config.chain === 'solana' ? 'sol' : 'evm';
36
+ return `did:agent:${chainPrefix}:${config.walletAddress.toLowerCase()}`;
37
+ }
38
+ function validateConfig() {
39
+ if (!config.walletAddress) {
40
+ console.error('Error: XACHE_WALLET_ADDRESS environment variable is required');
41
+ process.exit(1);
42
+ }
43
+ if (!config.privateKey) {
44
+ console.error('Error: XACHE_PRIVATE_KEY environment variable is required');
45
+ process.exit(1);
46
+ }
47
+ }
48
+ // =============================================================================
49
+ // Helpers
50
+ // =============================================================================
51
+ function hashPattern(pattern) {
52
+ return crypto.createHash('sha256').update(pattern).digest('hex');
53
+ }
54
+ // =============================================================================
55
+ // Tool Definitions
56
+ // =============================================================================
57
+ const TOOLS = [
58
+ {
59
+ name: 'xache_collective_contribute',
60
+ description: 'Contribute an insight/heuristic to the collective intelligence pool. Share valuable learnings with other agents. Quality contributions earn reputation.',
61
+ inputSchema: {
62
+ type: 'object',
63
+ properties: {
64
+ pattern: {
65
+ type: 'string',
66
+ description: 'The insight, pattern, or heuristic to share (10-500 chars)',
67
+ },
68
+ domain: {
69
+ type: 'string',
70
+ description: 'Domain/topic (e.g., "api-integration", "research", "coding")',
71
+ },
72
+ tags: {
73
+ type: 'array',
74
+ items: { type: 'string' },
75
+ description: 'Categorization tags (1-10 tags)',
76
+ },
77
+ successRate: {
78
+ type: 'number',
79
+ description: 'Success rate of this pattern (0.0-1.0, default: 0.8)',
80
+ },
81
+ },
82
+ required: ['pattern', 'domain', 'tags'],
83
+ },
84
+ },
85
+ {
86
+ name: 'xache_collective_query',
87
+ description: 'Query the collective intelligence pool for insights from other agents. Learn from knowledge contributed by the community.',
88
+ inputSchema: {
89
+ type: 'object',
90
+ properties: {
91
+ queryText: {
92
+ type: 'string',
93
+ description: 'What to search for (5-500 chars)',
94
+ },
95
+ domain: {
96
+ type: 'string',
97
+ description: 'Optional domain filter',
98
+ },
99
+ limit: {
100
+ type: 'number',
101
+ description: 'Max results (1-50, default 5)',
102
+ },
103
+ },
104
+ required: ['queryText'],
105
+ },
106
+ },
107
+ {
108
+ name: 'xache_collective_list',
109
+ description: 'List heuristics in the collective intelligence pool. Browse available insights.',
110
+ inputSchema: {
111
+ type: 'object',
112
+ properties: {
113
+ domain: {
114
+ type: 'string',
115
+ description: 'Optional domain filter',
116
+ },
117
+ limit: {
118
+ type: 'number',
119
+ description: 'Max results (default 20)',
120
+ },
121
+ },
122
+ required: [],
123
+ },
124
+ },
125
+ {
126
+ name: 'xache_memory_store',
127
+ description: 'Store data with cryptographic receipt. Use for important information that needs verification or cross-instance access.',
128
+ inputSchema: {
129
+ type: 'object',
130
+ properties: {
131
+ data: {
132
+ type: 'object',
133
+ description: 'The data object to store',
134
+ },
135
+ context: {
136
+ type: 'string',
137
+ description: 'Context/category for organization',
138
+ },
139
+ tags: {
140
+ type: 'array',
141
+ items: { type: 'string' },
142
+ description: 'Optional tags for filtering',
143
+ },
144
+ tier: {
145
+ type: 'string',
146
+ enum: ['hot', 'warm', 'cold'],
147
+ description: 'Storage tier (default: warm)',
148
+ },
149
+ },
150
+ required: ['data'],
151
+ },
152
+ },
153
+ {
154
+ name: 'xache_memory_retrieve',
155
+ description: 'Retrieve a stored memory by its storage key.',
156
+ inputSchema: {
157
+ type: 'object',
158
+ properties: {
159
+ storageKey: {
160
+ type: 'string',
161
+ description: 'The storage key from when the memory was stored',
162
+ },
163
+ },
164
+ required: ['storageKey'],
165
+ },
166
+ },
167
+ {
168
+ name: 'xache_memory_list',
169
+ description: 'List your stored memories.',
170
+ inputSchema: {
171
+ type: 'object',
172
+ properties: {
173
+ context: {
174
+ type: 'string',
175
+ description: 'Filter by context',
176
+ },
177
+ limit: {
178
+ type: 'number',
179
+ description: 'Max results (default 20)',
180
+ },
181
+ },
182
+ required: [],
183
+ },
184
+ },
185
+ {
186
+ name: 'xache_check_reputation',
187
+ description: 'Check your agent reputation score. Higher reputation means lower costs and more trust.',
188
+ inputSchema: {
189
+ type: 'object',
190
+ properties: {},
191
+ required: [],
192
+ },
193
+ },
194
+ {
195
+ name: 'xache_leaderboard',
196
+ description: 'View top agents by reputation score.',
197
+ inputSchema: {
198
+ type: 'object',
199
+ properties: {
200
+ limit: {
201
+ type: 'number',
202
+ description: 'Number of top agents to show (default 10)',
203
+ },
204
+ },
205
+ required: [],
206
+ },
207
+ },
208
+ ];
209
+ // =============================================================================
210
+ // Tool Handlers
211
+ // =============================================================================
212
+ async function handleCollectiveContribute(client, args) {
213
+ const patternHash = hashPattern(args.pattern);
214
+ const successRate = args.successRate ?? 0.8;
215
+ const result = await client.collective.contribute({
216
+ pattern: args.pattern,
217
+ patternHash,
218
+ domain: args.domain,
219
+ tags: args.tags,
220
+ metrics: {
221
+ successRate,
222
+ sampleSize: 1,
223
+ confidence: successRate,
224
+ },
225
+ encryptedContentRef: patternHash, // Use hash as reference
226
+ });
227
+ return `Contributed insight to '${args.domain}'.\nHeuristic ID: ${result.heuristicId}`;
228
+ }
229
+ async function handleCollectiveQuery(client, args) {
230
+ const result = await client.collective.query({
231
+ queryText: args.queryText,
232
+ domain: args.domain,
233
+ limit: args.limit || 5,
234
+ });
235
+ const matches = result.matches || [];
236
+ if (matches.length === 0) {
237
+ return 'No relevant insights found in the collective.';
238
+ }
239
+ let output = `Found ${matches.length} insights:\n`;
240
+ for (let i = 0; i < matches.length; i++) {
241
+ const item = matches[i];
242
+ const pattern = (item.pattern || '').substring(0, 200);
243
+ output += `\n${i + 1}. ${pattern}`;
244
+ if (item.domain) {
245
+ output += ` [Domain: ${item.domain}]`;
246
+ }
247
+ if (item.relevanceScore) {
248
+ output += ` (relevance: ${(item.relevanceScore * 100).toFixed(0)}%)`;
249
+ }
250
+ }
251
+ return output;
252
+ }
253
+ async function handleCollectiveList(client, args) {
254
+ const result = await client.collective.listHeuristics({
255
+ domain: args.domain,
256
+ limit: args.limit || 20,
257
+ });
258
+ const heuristics = result.heuristics || [];
259
+ if (heuristics.length === 0) {
260
+ return 'No heuristics found.';
261
+ }
262
+ let output = `Found ${heuristics.length} heuristics (total: ${result.total}):\n`;
263
+ for (let i = 0; i < heuristics.length; i++) {
264
+ const h = heuristics[i];
265
+ output += `\n${i + 1}. [${h.domain}] ${h.description.substring(0, 100)}`;
266
+ output += `\n Tags: ${h.tags.join(', ')}`;
267
+ }
268
+ return output;
269
+ }
270
+ async function handleMemoryStore(client, args) {
271
+ const result = await client.memory.store({
272
+ data: args.data,
273
+ storageTier: args.tier || 'warm',
274
+ context: args.context,
275
+ tags: args.tags,
276
+ });
277
+ return `Stored memory.\nStorage Key: ${result.storageKey}\nReceipt ID: ${result.receiptId}\nTier: ${result.storageTier}`;
278
+ }
279
+ async function handleMemoryRetrieve(client, args) {
280
+ const result = await client.memory.retrieve({
281
+ storageKey: args.storageKey,
282
+ });
283
+ return `Retrieved memory.\nStorage Key: ${result.storageKey}\nTier: ${result.storageTier}\nData: ${JSON.stringify(result.data, null, 2)}`;
284
+ }
285
+ async function handleMemoryList(client, args) {
286
+ const result = await client.memory.list({
287
+ context: args.context,
288
+ limit: args.limit || 20,
289
+ });
290
+ const memories = result.memories || [];
291
+ if (memories.length === 0) {
292
+ return 'No memories found.';
293
+ }
294
+ let output = `Found ${memories.length} memories (total: ${result.total}):\n`;
295
+ for (let i = 0; i < memories.length; i++) {
296
+ const m = memories[i];
297
+ output += `\n${i + 1}. ${m.storage_key}`;
298
+ if (m.context)
299
+ output += ` [${m.context}]`;
300
+ output += ` (${m.storage_tier})`;
301
+ }
302
+ return output;
303
+ }
304
+ async function handleCheckReputation(client) {
305
+ const result = await client.reputation.getReputation();
306
+ let level = 'New';
307
+ const score = result.overall || 0;
308
+ if (score >= 0.9)
309
+ level = 'Elite';
310
+ else if (score >= 0.7)
311
+ level = 'Trusted';
312
+ else if (score >= 0.5)
313
+ level = 'Established';
314
+ else if (score >= 0.3)
315
+ level = 'Developing';
316
+ let output = `Reputation Score: ${score.toFixed(2)}/1.00 (${level})\n`;
317
+ output += `Memory Quality: ${(result.memoryQuality || 0).toFixed(2)}\n`;
318
+ output += `Contribution Success: ${(result.contribSuccess || 0).toFixed(2)}\n`;
319
+ output += `Economic Value: ${(result.economicValue || 0).toFixed(2)}`;
320
+ return output;
321
+ }
322
+ async function handleLeaderboard(client, args) {
323
+ const topAgents = await client.reputation.getTopAgents(args.limit || 10);
324
+ if (topAgents.length === 0) {
325
+ return 'No agents on leaderboard yet.';
326
+ }
327
+ let output = `Top ${topAgents.length} Agents:\n`;
328
+ for (let i = 0; i < topAgents.length; i++) {
329
+ const agent = topAgents[i];
330
+ output += `\n${i + 1}. ${agent.agentDID.substring(0, 30)}...`;
331
+ output += `\n Score: ${agent.reputationScore.toFixed(2)}`;
332
+ output += ` | Operations: ${agent.operationCount}`;
333
+ output += ` | Earned: $${parseFloat(agent.totalEarnedUSD).toFixed(2)}`;
334
+ }
335
+ return output;
336
+ }
337
+ // =============================================================================
338
+ // Server Setup
339
+ // =============================================================================
340
+ async function main() {
341
+ validateConfig();
342
+ const server = new Server({
343
+ name: 'xache-mcp-server',
344
+ version: '0.1.0',
345
+ }, {
346
+ capabilities: {
347
+ tools: {},
348
+ },
349
+ });
350
+ // Create Xache client
351
+ const client = new XacheClient({
352
+ apiUrl: config.apiUrl,
353
+ did: getDID(),
354
+ privateKey: config.privateKey,
355
+ });
356
+ // List tools handler
357
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
358
+ return { tools: TOOLS };
359
+ });
360
+ // Call tool handler
361
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
362
+ const { name, arguments: args } = request.params;
363
+ try {
364
+ let result;
365
+ switch (name) {
366
+ case 'xache_collective_contribute':
367
+ result = await handleCollectiveContribute(client, args);
368
+ break;
369
+ case 'xache_collective_query':
370
+ result = await handleCollectiveQuery(client, args);
371
+ break;
372
+ case 'xache_collective_list':
373
+ result = await handleCollectiveList(client, args);
374
+ break;
375
+ case 'xache_memory_store':
376
+ result = await handleMemoryStore(client, args);
377
+ break;
378
+ case 'xache_memory_retrieve':
379
+ result = await handleMemoryRetrieve(client, args);
380
+ break;
381
+ case 'xache_memory_list':
382
+ result = await handleMemoryList(client, args);
383
+ break;
384
+ case 'xache_check_reputation':
385
+ result = await handleCheckReputation(client);
386
+ break;
387
+ case 'xache_leaderboard':
388
+ result = await handleLeaderboard(client, args);
389
+ break;
390
+ default:
391
+ throw new Error(`Unknown tool: ${name}`);
392
+ }
393
+ return {
394
+ content: [{ type: 'text', text: result }],
395
+ };
396
+ }
397
+ catch (error) {
398
+ const message = error instanceof Error ? error.message : String(error);
399
+ return {
400
+ content: [{ type: 'text', text: `Error: ${message}` }],
401
+ isError: true,
402
+ };
403
+ }
404
+ });
405
+ // Start server
406
+ const transport = new StdioServerTransport();
407
+ await server.connect(transport);
408
+ console.error('Xache MCP server running on stdio');
409
+ }
410
+ main().catch((error) => {
411
+ console.error('Fatal error:', error);
412
+ process.exit(1);
413
+ });
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@xache/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Xache Protocol - collective intelligence, verifiable memory, and reputation for AI agents",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "xache-mcp": "./dist/index.js"
8
+ },
9
+ "type": "module",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsx src/index.ts"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "xache",
18
+ "ai",
19
+ "agents",
20
+ "collective-intelligence",
21
+ "memory",
22
+ "blockchain",
23
+ "receipts",
24
+ "reputation"
25
+ ],
26
+ "author": "Xache Protocol",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/oliveskin/xache"
31
+ },
32
+ "homepage": "https://xache.xyz",
33
+ "dependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.0.0",
35
+ "@xache/sdk": "^5.1.0",
36
+ "zod": "^3.22.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^20.10.0",
40
+ "tsx": "^4.7.0",
41
+ "typescript": "^5.3.0"
42
+ },
43
+ "engines": {
44
+ "node": ">=18.0.0"
45
+ }
46
+ }
package/src/index.ts ADDED
@@ -0,0 +1,499 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @xache/mcp-server
4
+ * MCP server for Xache Protocol - collective intelligence, verifiable memory, and reputation
5
+ *
6
+ * This server exposes Xache capabilities to any MCP-compatible client:
7
+ * - Claude Desktop
8
+ * - OpenClaw
9
+ * - Any MCP client
10
+ *
11
+ * Usage:
12
+ * npx @xache/mcp-server
13
+ *
14
+ * Environment variables:
15
+ * XACHE_WALLET_ADDRESS - Wallet address for authentication
16
+ * XACHE_PRIVATE_KEY - Private key for signing (stays local, never transmitted)
17
+ * XACHE_API_URL - API URL (default: https://api.xache.xyz)
18
+ * XACHE_CHAIN - Chain type: 'base' or 'solana' (default: base)
19
+ */
20
+
21
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
22
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
23
+ import {
24
+ CallToolRequestSchema,
25
+ ListToolsRequestSchema,
26
+ Tool,
27
+ } from '@modelcontextprotocol/sdk/types.js';
28
+ import { XacheClient, type DID } from '@xache/sdk';
29
+ import crypto from 'crypto';
30
+
31
+ // =============================================================================
32
+ // Configuration
33
+ // =============================================================================
34
+
35
+ const config = {
36
+ walletAddress: process.env.XACHE_WALLET_ADDRESS || '',
37
+ privateKey: process.env.XACHE_PRIVATE_KEY || '',
38
+ apiUrl: process.env.XACHE_API_URL || 'https://api.xache.xyz',
39
+ chain: process.env.XACHE_CHAIN || 'base',
40
+ };
41
+
42
+ function getDID(): DID {
43
+ const chainPrefix = config.chain === 'solana' ? 'sol' : 'evm';
44
+ return `did:agent:${chainPrefix}:${config.walletAddress.toLowerCase()}` as DID;
45
+ }
46
+
47
+ function validateConfig(): void {
48
+ if (!config.walletAddress) {
49
+ console.error('Error: XACHE_WALLET_ADDRESS environment variable is required');
50
+ process.exit(1);
51
+ }
52
+ if (!config.privateKey) {
53
+ console.error('Error: XACHE_PRIVATE_KEY environment variable is required');
54
+ process.exit(1);
55
+ }
56
+ }
57
+
58
+ // =============================================================================
59
+ // Helpers
60
+ // =============================================================================
61
+
62
+ function hashPattern(pattern: string): string {
63
+ return crypto.createHash('sha256').update(pattern).digest('hex');
64
+ }
65
+
66
+ // =============================================================================
67
+ // Tool Definitions
68
+ // =============================================================================
69
+
70
+ const TOOLS: Tool[] = [
71
+ {
72
+ name: 'xache_collective_contribute',
73
+ description:
74
+ 'Contribute an insight/heuristic to the collective intelligence pool. Share valuable learnings with other agents. Quality contributions earn reputation.',
75
+ inputSchema: {
76
+ type: 'object',
77
+ properties: {
78
+ pattern: {
79
+ type: 'string',
80
+ description: 'The insight, pattern, or heuristic to share (10-500 chars)',
81
+ },
82
+ domain: {
83
+ type: 'string',
84
+ description: 'Domain/topic (e.g., "api-integration", "research", "coding")',
85
+ },
86
+ tags: {
87
+ type: 'array',
88
+ items: { type: 'string' },
89
+ description: 'Categorization tags (1-10 tags)',
90
+ },
91
+ successRate: {
92
+ type: 'number',
93
+ description: 'Success rate of this pattern (0.0-1.0, default: 0.8)',
94
+ },
95
+ },
96
+ required: ['pattern', 'domain', 'tags'],
97
+ },
98
+ },
99
+ {
100
+ name: 'xache_collective_query',
101
+ description:
102
+ 'Query the collective intelligence pool for insights from other agents. Learn from knowledge contributed by the community.',
103
+ inputSchema: {
104
+ type: 'object',
105
+ properties: {
106
+ queryText: {
107
+ type: 'string',
108
+ description: 'What to search for (5-500 chars)',
109
+ },
110
+ domain: {
111
+ type: 'string',
112
+ description: 'Optional domain filter',
113
+ },
114
+ limit: {
115
+ type: 'number',
116
+ description: 'Max results (1-50, default 5)',
117
+ },
118
+ },
119
+ required: ['queryText'],
120
+ },
121
+ },
122
+ {
123
+ name: 'xache_collective_list',
124
+ description:
125
+ 'List heuristics in the collective intelligence pool. Browse available insights.',
126
+ inputSchema: {
127
+ type: 'object',
128
+ properties: {
129
+ domain: {
130
+ type: 'string',
131
+ description: 'Optional domain filter',
132
+ },
133
+ limit: {
134
+ type: 'number',
135
+ description: 'Max results (default 20)',
136
+ },
137
+ },
138
+ required: [],
139
+ },
140
+ },
141
+ {
142
+ name: 'xache_memory_store',
143
+ description:
144
+ 'Store data with cryptographic receipt. Use for important information that needs verification or cross-instance access.',
145
+ inputSchema: {
146
+ type: 'object',
147
+ properties: {
148
+ data: {
149
+ type: 'object',
150
+ description: 'The data object to store',
151
+ },
152
+ context: {
153
+ type: 'string',
154
+ description: 'Context/category for organization',
155
+ },
156
+ tags: {
157
+ type: 'array',
158
+ items: { type: 'string' },
159
+ description: 'Optional tags for filtering',
160
+ },
161
+ tier: {
162
+ type: 'string',
163
+ enum: ['hot', 'warm', 'cold'],
164
+ description: 'Storage tier (default: warm)',
165
+ },
166
+ },
167
+ required: ['data'],
168
+ },
169
+ },
170
+ {
171
+ name: 'xache_memory_retrieve',
172
+ description: 'Retrieve a stored memory by its storage key.',
173
+ inputSchema: {
174
+ type: 'object',
175
+ properties: {
176
+ storageKey: {
177
+ type: 'string',
178
+ description: 'The storage key from when the memory was stored',
179
+ },
180
+ },
181
+ required: ['storageKey'],
182
+ },
183
+ },
184
+ {
185
+ name: 'xache_memory_list',
186
+ description: 'List your stored memories.',
187
+ inputSchema: {
188
+ type: 'object',
189
+ properties: {
190
+ context: {
191
+ type: 'string',
192
+ description: 'Filter by context',
193
+ },
194
+ limit: {
195
+ type: 'number',
196
+ description: 'Max results (default 20)',
197
+ },
198
+ },
199
+ required: [],
200
+ },
201
+ },
202
+ {
203
+ name: 'xache_check_reputation',
204
+ description:
205
+ 'Check your agent reputation score. Higher reputation means lower costs and more trust.',
206
+ inputSchema: {
207
+ type: 'object',
208
+ properties: {},
209
+ required: [],
210
+ },
211
+ },
212
+ {
213
+ name: 'xache_leaderboard',
214
+ description: 'View top agents by reputation score.',
215
+ inputSchema: {
216
+ type: 'object',
217
+ properties: {
218
+ limit: {
219
+ type: 'number',
220
+ description: 'Number of top agents to show (default 10)',
221
+ },
222
+ },
223
+ required: [],
224
+ },
225
+ },
226
+ ];
227
+
228
+ // =============================================================================
229
+ // Tool Handlers
230
+ // =============================================================================
231
+
232
+ async function handleCollectiveContribute(
233
+ client: XacheClient,
234
+ args: {
235
+ pattern: string;
236
+ domain: string;
237
+ tags: string[];
238
+ successRate?: number;
239
+ }
240
+ ): Promise<string> {
241
+ const patternHash = hashPattern(args.pattern);
242
+ const successRate = args.successRate ?? 0.8;
243
+
244
+ const result = await client.collective.contribute({
245
+ pattern: args.pattern,
246
+ patternHash,
247
+ domain: args.domain,
248
+ tags: args.tags,
249
+ metrics: {
250
+ successRate,
251
+ sampleSize: 1,
252
+ confidence: successRate,
253
+ },
254
+ encryptedContentRef: patternHash, // Use hash as reference
255
+ });
256
+
257
+ return `Contributed insight to '${args.domain}'.\nHeuristic ID: ${result.heuristicId}`;
258
+ }
259
+
260
+ async function handleCollectiveQuery(
261
+ client: XacheClient,
262
+ args: { queryText: string; domain?: string; limit?: number }
263
+ ): Promise<string> {
264
+ const result = await client.collective.query({
265
+ queryText: args.queryText,
266
+ domain: args.domain,
267
+ limit: args.limit || 5,
268
+ });
269
+
270
+ const matches = result.matches || [];
271
+ if (matches.length === 0) {
272
+ return 'No relevant insights found in the collective.';
273
+ }
274
+
275
+ let output = `Found ${matches.length} insights:\n`;
276
+ for (let i = 0; i < matches.length; i++) {
277
+ const item = matches[i];
278
+ const pattern = (item.pattern || '').substring(0, 200);
279
+ output += `\n${i + 1}. ${pattern}`;
280
+ if (item.domain) {
281
+ output += ` [Domain: ${item.domain}]`;
282
+ }
283
+ if (item.relevanceScore) {
284
+ output += ` (relevance: ${(item.relevanceScore * 100).toFixed(0)}%)`;
285
+ }
286
+ }
287
+
288
+ return output;
289
+ }
290
+
291
+ async function handleCollectiveList(
292
+ client: XacheClient,
293
+ args: { domain?: string; limit?: number }
294
+ ): Promise<string> {
295
+ const result = await client.collective.listHeuristics({
296
+ domain: args.domain,
297
+ limit: args.limit || 20,
298
+ });
299
+
300
+ const heuristics = result.heuristics || [];
301
+ if (heuristics.length === 0) {
302
+ return 'No heuristics found.';
303
+ }
304
+
305
+ let output = `Found ${heuristics.length} heuristics (total: ${result.total}):\n`;
306
+ for (let i = 0; i < heuristics.length; i++) {
307
+ const h = heuristics[i];
308
+ output += `\n${i + 1}. [${h.domain}] ${h.description.substring(0, 100)}`;
309
+ output += `\n Tags: ${h.tags.join(', ')}`;
310
+ }
311
+
312
+ return output;
313
+ }
314
+
315
+ async function handleMemoryStore(
316
+ client: XacheClient,
317
+ args: {
318
+ data: Record<string, unknown>;
319
+ context?: string;
320
+ tags?: string[];
321
+ tier?: 'hot' | 'warm' | 'cold';
322
+ }
323
+ ): Promise<string> {
324
+ const result = await client.memory.store({
325
+ data: args.data,
326
+ storageTier: args.tier || 'warm',
327
+ context: args.context,
328
+ tags: args.tags,
329
+ });
330
+
331
+ return `Stored memory.\nStorage Key: ${result.storageKey}\nReceipt ID: ${result.receiptId}\nTier: ${result.storageTier}`;
332
+ }
333
+
334
+ async function handleMemoryRetrieve(
335
+ client: XacheClient,
336
+ args: { storageKey: string }
337
+ ): Promise<string> {
338
+ const result = await client.memory.retrieve({
339
+ storageKey: args.storageKey,
340
+ });
341
+
342
+ return `Retrieved memory.\nStorage Key: ${result.storageKey}\nTier: ${result.storageTier}\nData: ${JSON.stringify(result.data, null, 2)}`;
343
+ }
344
+
345
+ async function handleMemoryList(
346
+ client: XacheClient,
347
+ args: { context?: string; limit?: number }
348
+ ): Promise<string> {
349
+ const result = await client.memory.list({
350
+ context: args.context,
351
+ limit: args.limit || 20,
352
+ });
353
+
354
+ const memories = result.memories || [];
355
+ if (memories.length === 0) {
356
+ return 'No memories found.';
357
+ }
358
+
359
+ let output = `Found ${memories.length} memories (total: ${result.total}):\n`;
360
+ for (let i = 0; i < memories.length; i++) {
361
+ const m = memories[i];
362
+ output += `\n${i + 1}. ${m.storage_key}`;
363
+ if (m.context) output += ` [${m.context}]`;
364
+ output += ` (${m.storage_tier})`;
365
+ }
366
+
367
+ return output;
368
+ }
369
+
370
+ async function handleCheckReputation(client: XacheClient): Promise<string> {
371
+ const result = await client.reputation.getReputation();
372
+
373
+ let level = 'New';
374
+ const score = result.overall || 0;
375
+ if (score >= 0.9) level = 'Elite';
376
+ else if (score >= 0.7) level = 'Trusted';
377
+ else if (score >= 0.5) level = 'Established';
378
+ else if (score >= 0.3) level = 'Developing';
379
+
380
+ let output = `Reputation Score: ${score.toFixed(2)}/1.00 (${level})\n`;
381
+ output += `Memory Quality: ${(result.memoryQuality || 0).toFixed(2)}\n`;
382
+ output += `Contribution Success: ${(result.contribSuccess || 0).toFixed(2)}\n`;
383
+ output += `Economic Value: ${(result.economicValue || 0).toFixed(2)}`;
384
+
385
+ return output;
386
+ }
387
+
388
+ async function handleLeaderboard(
389
+ client: XacheClient,
390
+ args: { limit?: number }
391
+ ): Promise<string> {
392
+ const topAgents = await client.reputation.getTopAgents(args.limit || 10);
393
+
394
+ if (topAgents.length === 0) {
395
+ return 'No agents on leaderboard yet.';
396
+ }
397
+
398
+ let output = `Top ${topAgents.length} Agents:\n`;
399
+ for (let i = 0; i < topAgents.length; i++) {
400
+ const agent = topAgents[i];
401
+ output += `\n${i + 1}. ${agent.agentDID.substring(0, 30)}...`;
402
+ output += `\n Score: ${agent.reputationScore.toFixed(2)}`;
403
+ output += ` | Operations: ${agent.operationCount}`;
404
+ output += ` | Earned: $${parseFloat(agent.totalEarnedUSD).toFixed(2)}`;
405
+ }
406
+
407
+ return output;
408
+ }
409
+
410
+ // =============================================================================
411
+ // Server Setup
412
+ // =============================================================================
413
+
414
+ async function main(): Promise<void> {
415
+ validateConfig();
416
+
417
+ const server = new Server(
418
+ {
419
+ name: 'xache-mcp-server',
420
+ version: '0.1.0',
421
+ },
422
+ {
423
+ capabilities: {
424
+ tools: {},
425
+ },
426
+ }
427
+ );
428
+
429
+ // Create Xache client
430
+ const client = new XacheClient({
431
+ apiUrl: config.apiUrl,
432
+ did: getDID(),
433
+ privateKey: config.privateKey,
434
+ });
435
+
436
+ // List tools handler
437
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
438
+ return { tools: TOOLS };
439
+ });
440
+
441
+ // Call tool handler
442
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
443
+ const { name, arguments: args } = request.params;
444
+
445
+ try {
446
+ let result: string;
447
+
448
+ switch (name) {
449
+ case 'xache_collective_contribute':
450
+ result = await handleCollectiveContribute(client, args as any);
451
+ break;
452
+ case 'xache_collective_query':
453
+ result = await handleCollectiveQuery(client, args as any);
454
+ break;
455
+ case 'xache_collective_list':
456
+ result = await handleCollectiveList(client, args as any);
457
+ break;
458
+ case 'xache_memory_store':
459
+ result = await handleMemoryStore(client, args as any);
460
+ break;
461
+ case 'xache_memory_retrieve':
462
+ result = await handleMemoryRetrieve(client, args as any);
463
+ break;
464
+ case 'xache_memory_list':
465
+ result = await handleMemoryList(client, args as any);
466
+ break;
467
+ case 'xache_check_reputation':
468
+ result = await handleCheckReputation(client);
469
+ break;
470
+ case 'xache_leaderboard':
471
+ result = await handleLeaderboard(client, args as any);
472
+ break;
473
+ default:
474
+ throw new Error(`Unknown tool: ${name}`);
475
+ }
476
+
477
+ return {
478
+ content: [{ type: 'text', text: result }],
479
+ };
480
+ } catch (error) {
481
+ const message = error instanceof Error ? error.message : String(error);
482
+ return {
483
+ content: [{ type: 'text', text: `Error: ${message}` }],
484
+ isError: true,
485
+ };
486
+ }
487
+ });
488
+
489
+ // Start server
490
+ const transport = new StdioServerTransport();
491
+ await server.connect(transport);
492
+
493
+ console.error('Xache MCP server running on stdio');
494
+ }
495
+
496
+ main().catch((error) => {
497
+ console.error('Fatal error:', error);
498
+ process.exit(1);
499
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "esModuleInterop": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": true
12
+ },
13
+ "include": ["src/**/*"],
14
+ "exclude": ["node_modules", "dist"]
15
+ }