clawdentials-mcp 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 +108 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +55 -0
- package/dist/schemas/index.d.ts +40 -0
- package/dist/schemas/index.js +15 -0
- package/dist/services/firestore.d.ts +13 -0
- package/dist/services/firestore.js +99 -0
- package/dist/tools/escrow.d.ts +100 -0
- package/dist/tools/escrow.js +97 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +1 -0
- package/dist/types/index.d.ts +43 -0
- package/dist/types/index.js +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Clawdentials MCP Server
|
|
2
|
+
|
|
3
|
+
Escrow and reputation infrastructure for AI agent commerce.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install clawdentials-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or clone and build locally:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cd mcp-server
|
|
15
|
+
npm install
|
|
16
|
+
npm run build
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Configuration
|
|
20
|
+
|
|
21
|
+
### Claude Desktop
|
|
22
|
+
|
|
23
|
+
Add to your `claude_desktop_config.json`:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"clawdentials": {
|
|
29
|
+
"command": "node",
|
|
30
|
+
"args": ["/path/to/clawdentials/mcp-server/dist/index.js"],
|
|
31
|
+
"env": {
|
|
32
|
+
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/service-account.json"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Environment Variables
|
|
40
|
+
|
|
41
|
+
- `GOOGLE_APPLICATION_CREDENTIALS` - Path to Firebase service account JSON
|
|
42
|
+
|
|
43
|
+
## Tools
|
|
44
|
+
|
|
45
|
+
### escrow_create
|
|
46
|
+
|
|
47
|
+
Lock funds for a task.
|
|
48
|
+
|
|
49
|
+
**Input:**
|
|
50
|
+
- `taskDescription` (string) - What needs to be done
|
|
51
|
+
- `amount` (number) - Amount to escrow
|
|
52
|
+
- `currency` (string) - USD, USDC, or BTC
|
|
53
|
+
- `providerAgentId` (string) - Agent who will do the work
|
|
54
|
+
- `clientAgentId` (string) - Agent creating the escrow
|
|
55
|
+
|
|
56
|
+
**Output:**
|
|
57
|
+
- `escrowId` - Unique identifier for the escrow
|
|
58
|
+
- `status` - Current status (pending)
|
|
59
|
+
|
|
60
|
+
### escrow_complete
|
|
61
|
+
|
|
62
|
+
Release funds after task completion.
|
|
63
|
+
|
|
64
|
+
**Input:**
|
|
65
|
+
- `escrowId` (string) - The escrow to complete
|
|
66
|
+
- `proofOfWork` (string) - Evidence the task was done
|
|
67
|
+
|
|
68
|
+
**Output:**
|
|
69
|
+
- `success` - Whether funds were released
|
|
70
|
+
- `escrow` - Updated escrow details
|
|
71
|
+
|
|
72
|
+
### escrow_status
|
|
73
|
+
|
|
74
|
+
Check the state of an escrow.
|
|
75
|
+
|
|
76
|
+
**Input:**
|
|
77
|
+
- `escrowId` (string) - The escrow to check
|
|
78
|
+
|
|
79
|
+
**Output:**
|
|
80
|
+
- `escrow` - Full escrow details including status
|
|
81
|
+
|
|
82
|
+
## Development
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Install dependencies
|
|
86
|
+
npm install
|
|
87
|
+
|
|
88
|
+
# Build
|
|
89
|
+
npm run build
|
|
90
|
+
|
|
91
|
+
# Watch mode
|
|
92
|
+
npm run dev
|
|
93
|
+
|
|
94
|
+
# Type check
|
|
95
|
+
npm run typecheck
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Firestore Collections
|
|
99
|
+
|
|
100
|
+
The server uses these Firestore collections:
|
|
101
|
+
|
|
102
|
+
- `escrows/` - Escrow records
|
|
103
|
+
- `agents/` - Agent profiles and stats
|
|
104
|
+
- `tasks/` - Task history
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { escrowTools } from './tools/index.js';
|
|
6
|
+
import { initFirestore } from './services/firestore.js';
|
|
7
|
+
// Initialize Firestore
|
|
8
|
+
initFirestore();
|
|
9
|
+
// Create MCP server
|
|
10
|
+
const server = new McpServer({
|
|
11
|
+
name: 'clawdentials',
|
|
12
|
+
version: '0.1.0',
|
|
13
|
+
});
|
|
14
|
+
// Register escrow_create tool
|
|
15
|
+
server.tool('escrow_create', escrowTools.escrow_create.description, {
|
|
16
|
+
taskDescription: z.string().describe('Description of the task to be completed'),
|
|
17
|
+
amount: z.number().positive().describe('Amount to escrow in the specified currency'),
|
|
18
|
+
currency: z.enum(['USD', 'USDC', 'BTC']).default('USD').describe('Currency for the escrow'),
|
|
19
|
+
providerAgentId: z.string().describe('ID of the agent who will complete the task'),
|
|
20
|
+
clientAgentId: z.string().describe('ID of the agent creating the escrow'),
|
|
21
|
+
}, async (args) => {
|
|
22
|
+
const result = await escrowTools.escrow_create.handler(args);
|
|
23
|
+
return {
|
|
24
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
// Register escrow_complete tool
|
|
28
|
+
server.tool('escrow_complete', escrowTools.escrow_complete.description, {
|
|
29
|
+
escrowId: z.string().describe('ID of the escrow to complete'),
|
|
30
|
+
proofOfWork: z.string().describe('Proof that the task was completed'),
|
|
31
|
+
}, async (args) => {
|
|
32
|
+
const result = await escrowTools.escrow_complete.handler(args);
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
// Register escrow_status tool
|
|
38
|
+
server.tool('escrow_status', escrowTools.escrow_status.description, {
|
|
39
|
+
escrowId: z.string().describe('ID of the escrow to check'),
|
|
40
|
+
}, async (args) => {
|
|
41
|
+
const result = await escrowTools.escrow_status.handler(args);
|
|
42
|
+
return {
|
|
43
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
// Start server
|
|
47
|
+
async function main() {
|
|
48
|
+
const transport = new StdioServerTransport();
|
|
49
|
+
await server.connect(transport);
|
|
50
|
+
console.error('Clawdentials MCP server running on stdio');
|
|
51
|
+
}
|
|
52
|
+
main().catch((error) => {
|
|
53
|
+
console.error('Fatal error:', error);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const escrowCreateSchema: z.ZodObject<{
|
|
3
|
+
taskDescription: z.ZodString;
|
|
4
|
+
amount: z.ZodNumber;
|
|
5
|
+
currency: z.ZodDefault<z.ZodEnum<["USD", "USDC", "BTC"]>>;
|
|
6
|
+
providerAgentId: z.ZodString;
|
|
7
|
+
clientAgentId: z.ZodString;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
taskDescription: string;
|
|
10
|
+
amount: number;
|
|
11
|
+
currency: "USD" | "USDC" | "BTC";
|
|
12
|
+
providerAgentId: string;
|
|
13
|
+
clientAgentId: string;
|
|
14
|
+
}, {
|
|
15
|
+
taskDescription: string;
|
|
16
|
+
amount: number;
|
|
17
|
+
providerAgentId: string;
|
|
18
|
+
clientAgentId: string;
|
|
19
|
+
currency?: "USD" | "USDC" | "BTC" | undefined;
|
|
20
|
+
}>;
|
|
21
|
+
export declare const escrowCompleteSchema: z.ZodObject<{
|
|
22
|
+
escrowId: z.ZodString;
|
|
23
|
+
proofOfWork: z.ZodString;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
escrowId: string;
|
|
26
|
+
proofOfWork: string;
|
|
27
|
+
}, {
|
|
28
|
+
escrowId: string;
|
|
29
|
+
proofOfWork: string;
|
|
30
|
+
}>;
|
|
31
|
+
export declare const escrowStatusSchema: z.ZodObject<{
|
|
32
|
+
escrowId: z.ZodString;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
escrowId: string;
|
|
35
|
+
}, {
|
|
36
|
+
escrowId: string;
|
|
37
|
+
}>;
|
|
38
|
+
export type EscrowCreateInput = z.infer<typeof escrowCreateSchema>;
|
|
39
|
+
export type EscrowCompleteInput = z.infer<typeof escrowCompleteSchema>;
|
|
40
|
+
export type EscrowStatusInput = z.infer<typeof escrowStatusSchema>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const escrowCreateSchema = z.object({
|
|
3
|
+
taskDescription: z.string().min(1).describe('Description of the task to be completed'),
|
|
4
|
+
amount: z.number().positive().describe('Amount to escrow in the specified currency'),
|
|
5
|
+
currency: z.enum(['USD', 'USDC', 'BTC']).default('USD').describe('Currency for the escrow'),
|
|
6
|
+
providerAgentId: z.string().min(1).describe('ID of the agent who will complete the task'),
|
|
7
|
+
clientAgentId: z.string().min(1).describe('ID of the agent creating the escrow'),
|
|
8
|
+
});
|
|
9
|
+
export const escrowCompleteSchema = z.object({
|
|
10
|
+
escrowId: z.string().min(1).describe('ID of the escrow to complete'),
|
|
11
|
+
proofOfWork: z.string().min(1).describe('Proof that the task was completed (e.g., result summary, link, hash)'),
|
|
12
|
+
});
|
|
13
|
+
export const escrowStatusSchema = z.object({
|
|
14
|
+
escrowId: z.string().min(1).describe('ID of the escrow to check'),
|
|
15
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Firestore } from 'firebase-admin/firestore';
|
|
2
|
+
import type { Escrow } from '../types/index.js';
|
|
3
|
+
export declare function initFirestore(): Firestore;
|
|
4
|
+
export declare function getDb(): Firestore;
|
|
5
|
+
export declare const collections: {
|
|
6
|
+
escrows: () => FirebaseFirestore.CollectionReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
|
|
7
|
+
agents: () => FirebaseFirestore.CollectionReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
|
|
8
|
+
tasks: () => FirebaseFirestore.CollectionReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
|
|
9
|
+
subscriptions: () => FirebaseFirestore.CollectionReference<FirebaseFirestore.DocumentData, FirebaseFirestore.DocumentData>;
|
|
10
|
+
};
|
|
11
|
+
export declare function createEscrow(data: Omit<Escrow, 'id' | 'createdAt' | 'completedAt' | 'proofOfWork'>): Promise<Escrow>;
|
|
12
|
+
export declare function getEscrow(escrowId: string): Promise<Escrow | null>;
|
|
13
|
+
export declare function completeEscrow(escrowId: string, proofOfWork: string): Promise<Escrow | null>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { initializeApp, getApps, applicationDefault } from 'firebase-admin/app';
|
|
2
|
+
import { getFirestore, Timestamp } from 'firebase-admin/firestore';
|
|
3
|
+
let app;
|
|
4
|
+
let db;
|
|
5
|
+
export function initFirestore() {
|
|
6
|
+
if (getApps().length === 0) {
|
|
7
|
+
// Use Application Default Credentials (gcloud auth)
|
|
8
|
+
// This works with: gcloud auth application-default login
|
|
9
|
+
// Or with GOOGLE_APPLICATION_CREDENTIALS pointing to a service account key
|
|
10
|
+
app = initializeApp({
|
|
11
|
+
credential: applicationDefault(),
|
|
12
|
+
projectId: 'clawdentials',
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
app = getApps()[0];
|
|
17
|
+
}
|
|
18
|
+
db = getFirestore(app);
|
|
19
|
+
return db;
|
|
20
|
+
}
|
|
21
|
+
export function getDb() {
|
|
22
|
+
if (!db) {
|
|
23
|
+
return initFirestore();
|
|
24
|
+
}
|
|
25
|
+
return db;
|
|
26
|
+
}
|
|
27
|
+
// Collection references
|
|
28
|
+
export const collections = {
|
|
29
|
+
escrows: () => getDb().collection('escrows'),
|
|
30
|
+
agents: () => getDb().collection('agents'),
|
|
31
|
+
tasks: () => getDb().collection('tasks'),
|
|
32
|
+
subscriptions: () => getDb().collection('subscriptions'),
|
|
33
|
+
};
|
|
34
|
+
// Escrow operations
|
|
35
|
+
export async function createEscrow(data) {
|
|
36
|
+
const docRef = collections.escrows().doc();
|
|
37
|
+
const escrow = {
|
|
38
|
+
...data,
|
|
39
|
+
status: 'pending',
|
|
40
|
+
createdAt: new Date(),
|
|
41
|
+
completedAt: null,
|
|
42
|
+
proofOfWork: null,
|
|
43
|
+
};
|
|
44
|
+
await docRef.set({
|
|
45
|
+
...escrow,
|
|
46
|
+
createdAt: Timestamp.fromDate(escrow.createdAt),
|
|
47
|
+
});
|
|
48
|
+
return { id: docRef.id, ...escrow };
|
|
49
|
+
}
|
|
50
|
+
export async function getEscrow(escrowId) {
|
|
51
|
+
const doc = await collections.escrows().doc(escrowId).get();
|
|
52
|
+
if (!doc.exists) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const data = doc.data();
|
|
56
|
+
return {
|
|
57
|
+
id: doc.id,
|
|
58
|
+
clientAgentId: data.clientAgentId,
|
|
59
|
+
providerAgentId: data.providerAgentId,
|
|
60
|
+
taskDescription: data.taskDescription,
|
|
61
|
+
amount: data.amount,
|
|
62
|
+
currency: data.currency,
|
|
63
|
+
status: data.status,
|
|
64
|
+
createdAt: data.createdAt.toDate(),
|
|
65
|
+
completedAt: data.completedAt?.toDate() ?? null,
|
|
66
|
+
proofOfWork: data.proofOfWork ?? null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export async function completeEscrow(escrowId, proofOfWork) {
|
|
70
|
+
const escrowRef = collections.escrows().doc(escrowId);
|
|
71
|
+
const doc = await escrowRef.get();
|
|
72
|
+
if (!doc.exists) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const completedAt = new Date();
|
|
76
|
+
await escrowRef.update({
|
|
77
|
+
status: 'completed',
|
|
78
|
+
completedAt: Timestamp.fromDate(completedAt),
|
|
79
|
+
proofOfWork,
|
|
80
|
+
});
|
|
81
|
+
const escrow = await getEscrow(escrowId);
|
|
82
|
+
// Update agent stats
|
|
83
|
+
if (escrow) {
|
|
84
|
+
await updateAgentStats(escrow.providerAgentId, escrow.amount);
|
|
85
|
+
}
|
|
86
|
+
return escrow;
|
|
87
|
+
}
|
|
88
|
+
async function updateAgentStats(agentId, amount) {
|
|
89
|
+
const agentRef = collections.agents().doc(agentId);
|
|
90
|
+
const doc = await agentRef.get();
|
|
91
|
+
if (doc.exists) {
|
|
92
|
+
const data = doc.data();
|
|
93
|
+
const currentStats = data.stats || { tasksCompleted: 0, totalEarned: 0, successRate: 100, avgCompletionTime: 0 };
|
|
94
|
+
await agentRef.update({
|
|
95
|
+
'stats.tasksCompleted': currentStats.tasksCompleted + 1,
|
|
96
|
+
'stats.totalEarned': currentStats.totalEarned + amount,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type EscrowCreateInput, type EscrowCompleteInput, type EscrowStatusInput } from '../schemas/index.js';
|
|
3
|
+
export declare const escrowTools: {
|
|
4
|
+
escrow_create: {
|
|
5
|
+
description: string;
|
|
6
|
+
inputSchema: z.ZodObject<{
|
|
7
|
+
taskDescription: z.ZodString;
|
|
8
|
+
amount: z.ZodNumber;
|
|
9
|
+
currency: z.ZodDefault<z.ZodEnum<["USD", "USDC", "BTC"]>>;
|
|
10
|
+
providerAgentId: z.ZodString;
|
|
11
|
+
clientAgentId: z.ZodString;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
taskDescription: string;
|
|
14
|
+
amount: number;
|
|
15
|
+
currency: "USD" | "USDC" | "BTC";
|
|
16
|
+
providerAgentId: string;
|
|
17
|
+
clientAgentId: string;
|
|
18
|
+
}, {
|
|
19
|
+
taskDescription: string;
|
|
20
|
+
amount: number;
|
|
21
|
+
providerAgentId: string;
|
|
22
|
+
clientAgentId: string;
|
|
23
|
+
currency?: "USD" | "USDC" | "BTC" | undefined;
|
|
24
|
+
}>;
|
|
25
|
+
handler: (input: EscrowCreateInput) => Promise<{
|
|
26
|
+
success: boolean;
|
|
27
|
+
escrowId: string;
|
|
28
|
+
message: string;
|
|
29
|
+
escrow: {
|
|
30
|
+
id: string;
|
|
31
|
+
amount: number;
|
|
32
|
+
currency: import("../types/index.js").Currency;
|
|
33
|
+
status: import("../types/index.js").EscrowStatus;
|
|
34
|
+
providerAgentId: string;
|
|
35
|
+
createdAt: string;
|
|
36
|
+
};
|
|
37
|
+
}>;
|
|
38
|
+
};
|
|
39
|
+
escrow_complete: {
|
|
40
|
+
description: string;
|
|
41
|
+
inputSchema: z.ZodObject<{
|
|
42
|
+
escrowId: z.ZodString;
|
|
43
|
+
proofOfWork: z.ZodString;
|
|
44
|
+
}, "strip", z.ZodTypeAny, {
|
|
45
|
+
escrowId: string;
|
|
46
|
+
proofOfWork: string;
|
|
47
|
+
}, {
|
|
48
|
+
escrowId: string;
|
|
49
|
+
proofOfWork: string;
|
|
50
|
+
}>;
|
|
51
|
+
handler: (input: EscrowCompleteInput) => Promise<{
|
|
52
|
+
success: boolean;
|
|
53
|
+
error: string;
|
|
54
|
+
message?: undefined;
|
|
55
|
+
escrow?: undefined;
|
|
56
|
+
} | {
|
|
57
|
+
success: boolean;
|
|
58
|
+
message: string;
|
|
59
|
+
escrow: {
|
|
60
|
+
id: string;
|
|
61
|
+
amount: number;
|
|
62
|
+
currency: import("../types/index.js").Currency;
|
|
63
|
+
status: import("../types/index.js").EscrowStatus;
|
|
64
|
+
completedAt: string | undefined;
|
|
65
|
+
proofOfWork: string | null;
|
|
66
|
+
};
|
|
67
|
+
error?: undefined;
|
|
68
|
+
}>;
|
|
69
|
+
};
|
|
70
|
+
escrow_status: {
|
|
71
|
+
description: string;
|
|
72
|
+
inputSchema: z.ZodObject<{
|
|
73
|
+
escrowId: z.ZodString;
|
|
74
|
+
}, "strip", z.ZodTypeAny, {
|
|
75
|
+
escrowId: string;
|
|
76
|
+
}, {
|
|
77
|
+
escrowId: string;
|
|
78
|
+
}>;
|
|
79
|
+
handler: (input: EscrowStatusInput) => Promise<{
|
|
80
|
+
success: boolean;
|
|
81
|
+
error: string;
|
|
82
|
+
escrow?: undefined;
|
|
83
|
+
} | {
|
|
84
|
+
success: boolean;
|
|
85
|
+
escrow: {
|
|
86
|
+
id: string;
|
|
87
|
+
clientAgentId: string;
|
|
88
|
+
providerAgentId: string;
|
|
89
|
+
taskDescription: string;
|
|
90
|
+
amount: number;
|
|
91
|
+
currency: import("../types/index.js").Currency;
|
|
92
|
+
status: import("../types/index.js").EscrowStatus;
|
|
93
|
+
createdAt: string;
|
|
94
|
+
completedAt: string | null;
|
|
95
|
+
proofOfWork: string | null;
|
|
96
|
+
};
|
|
97
|
+
error?: undefined;
|
|
98
|
+
}>;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { escrowCreateSchema, escrowCompleteSchema, escrowStatusSchema, } from '../schemas/index.js';
|
|
2
|
+
import { createEscrow, getEscrow, completeEscrow } from '../services/firestore.js';
|
|
3
|
+
export const escrowTools = {
|
|
4
|
+
escrow_create: {
|
|
5
|
+
description: 'Create a new escrow to lock funds for a task. The funds will be held until the task is completed.',
|
|
6
|
+
inputSchema: escrowCreateSchema,
|
|
7
|
+
handler: async (input) => {
|
|
8
|
+
const escrow = await createEscrow({
|
|
9
|
+
clientAgentId: input.clientAgentId,
|
|
10
|
+
providerAgentId: input.providerAgentId,
|
|
11
|
+
taskDescription: input.taskDescription,
|
|
12
|
+
amount: input.amount,
|
|
13
|
+
currency: input.currency,
|
|
14
|
+
status: 'pending',
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
success: true,
|
|
18
|
+
escrowId: escrow.id,
|
|
19
|
+
message: `Escrow created successfully. ${input.amount} ${input.currency} locked for task: "${input.taskDescription}"`,
|
|
20
|
+
escrow: {
|
|
21
|
+
id: escrow.id,
|
|
22
|
+
amount: escrow.amount,
|
|
23
|
+
currency: escrow.currency,
|
|
24
|
+
status: escrow.status,
|
|
25
|
+
providerAgentId: escrow.providerAgentId,
|
|
26
|
+
createdAt: escrow.createdAt.toISOString(),
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
escrow_complete: {
|
|
32
|
+
description: 'Mark an escrow as complete and release the funds to the provider agent. Requires proof of work.',
|
|
33
|
+
inputSchema: escrowCompleteSchema,
|
|
34
|
+
handler: async (input) => {
|
|
35
|
+
const existingEscrow = await getEscrow(input.escrowId);
|
|
36
|
+
if (!existingEscrow) {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
error: `Escrow not found: ${input.escrowId}`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (existingEscrow.status === 'completed') {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: 'Escrow is already completed',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (existingEscrow.status === 'cancelled') {
|
|
49
|
+
return {
|
|
50
|
+
success: false,
|
|
51
|
+
error: 'Escrow was cancelled',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const escrow = await completeEscrow(input.escrowId, input.proofOfWork);
|
|
55
|
+
return {
|
|
56
|
+
success: true,
|
|
57
|
+
message: `Escrow completed. ${escrow.amount} ${escrow.currency} released to ${escrow.providerAgentId}`,
|
|
58
|
+
escrow: {
|
|
59
|
+
id: escrow.id,
|
|
60
|
+
amount: escrow.amount,
|
|
61
|
+
currency: escrow.currency,
|
|
62
|
+
status: escrow.status,
|
|
63
|
+
completedAt: escrow.completedAt?.toISOString(),
|
|
64
|
+
proofOfWork: escrow.proofOfWork,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
escrow_status: {
|
|
70
|
+
description: 'Check the current status of an escrow.',
|
|
71
|
+
inputSchema: escrowStatusSchema,
|
|
72
|
+
handler: async (input) => {
|
|
73
|
+
const escrow = await getEscrow(input.escrowId);
|
|
74
|
+
if (!escrow) {
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
error: `Escrow not found: ${input.escrowId}`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
success: true,
|
|
82
|
+
escrow: {
|
|
83
|
+
id: escrow.id,
|
|
84
|
+
clientAgentId: escrow.clientAgentId,
|
|
85
|
+
providerAgentId: escrow.providerAgentId,
|
|
86
|
+
taskDescription: escrow.taskDescription,
|
|
87
|
+
amount: escrow.amount,
|
|
88
|
+
currency: escrow.currency,
|
|
89
|
+
status: escrow.status,
|
|
90
|
+
createdAt: escrow.createdAt.toISOString(),
|
|
91
|
+
completedAt: escrow.completedAt?.toISOString() ?? null,
|
|
92
|
+
proofOfWork: escrow.proofOfWork,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { escrowTools } from './escrow.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { escrowTools } from './escrow.js';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type EscrowStatus = 'pending' | 'in_progress' | 'completed' | 'disputed' | 'cancelled';
|
|
2
|
+
export type Currency = 'USD' | 'USDC' | 'BTC';
|
|
3
|
+
export type SubscriptionTier = 'free' | 'verified' | 'pro';
|
|
4
|
+
export interface Escrow {
|
|
5
|
+
id: string;
|
|
6
|
+
clientAgentId: string;
|
|
7
|
+
providerAgentId: string;
|
|
8
|
+
taskDescription: string;
|
|
9
|
+
amount: number;
|
|
10
|
+
currency: Currency;
|
|
11
|
+
status: EscrowStatus;
|
|
12
|
+
createdAt: Date;
|
|
13
|
+
completedAt: Date | null;
|
|
14
|
+
proofOfWork: string | null;
|
|
15
|
+
}
|
|
16
|
+
export interface Agent {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
skills: string[];
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
verified: boolean;
|
|
23
|
+
subscriptionTier: SubscriptionTier;
|
|
24
|
+
stats: AgentStats;
|
|
25
|
+
}
|
|
26
|
+
export interface AgentStats {
|
|
27
|
+
tasksCompleted: number;
|
|
28
|
+
totalEarned: number;
|
|
29
|
+
successRate: number;
|
|
30
|
+
avgCompletionTime: number;
|
|
31
|
+
}
|
|
32
|
+
export interface Task {
|
|
33
|
+
id: string;
|
|
34
|
+
escrowId: string;
|
|
35
|
+
description: string;
|
|
36
|
+
clientAgentId: string;
|
|
37
|
+
providerAgentId: string;
|
|
38
|
+
status: 'pending' | 'claimed' | 'in_progress' | 'completed' | 'failed';
|
|
39
|
+
createdAt: Date;
|
|
40
|
+
claimedAt: Date | null;
|
|
41
|
+
completedAt: Date | null;
|
|
42
|
+
result: string | null;
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "clawdentials-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Clawdentials - escrow and reputation for AI agent commerce",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"clawdentials-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"test": "tsx scripts/test-tools.ts",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"modelcontextprotocol",
|
|
25
|
+
"ai-agents",
|
|
26
|
+
"escrow",
|
|
27
|
+
"reputation",
|
|
28
|
+
"claude",
|
|
29
|
+
"anthropic"
|
|
30
|
+
],
|
|
31
|
+
"author": "Fernando Nikolic",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/fernikolic/clawdentials.git",
|
|
36
|
+
"directory": "mcp-server"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://clawdentials.com",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/fernikolic/clawdentials/issues"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@google-cloud/firestore": "8.2.0",
|
|
44
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
45
|
+
"firebase-admin": "^12.0.0",
|
|
46
|
+
"zod": "^3.23.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^20.0.0",
|
|
50
|
+
"tsx": "4.21.0",
|
|
51
|
+
"typescript": "^5.4.0"
|
|
52
|
+
}
|
|
53
|
+
}
|