@kya-os/mcp-i 0.1.0-alpha.1.0 → 0.1.0-alpha.2.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 +158 -62
- package/dist/__tests__/challenge-response.test.d.ts +5 -0
- package/dist/__tests__/challenge-response.test.d.ts.map +1 -0
- package/dist/__tests__/challenge-response.test.js +217 -0
- package/dist/__tests__/challenge-response.test.js.map +1 -0
- package/dist/__tests__/crypto.test.d.ts +5 -0
- package/dist/__tests__/crypto.test.d.ts.map +1 -0
- package/dist/__tests__/crypto.test.js +153 -0
- package/dist/__tests__/crypto.test.js.map +1 -0
- package/dist/crypto.d.ts +32 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +117 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +35 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +139 -21
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,72 +1,153 @@
|
|
|
1
1
|
# @kya-os/mcp-i
|
|
2
2
|
|
|
3
|
-
Ultra-light MCP Identity auto-registration
|
|
3
|
+
Ultra-light MCP Identity auto-registration with cryptographic challenge-response authentication.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Enable any MCP server to get a verifiable identity with just 2 lines of code!
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🚀 **2-line integration** - Zero configuration required
|
|
10
|
+
- 🔐 **Ed25519 cryptographic signing** - Secure challenge-response authentication
|
|
11
|
+
- 🌐 **Auto-registration** - Automatic DID creation via knowthat.ai
|
|
12
|
+
- 🔏 **MCP-I Handshake support** - Full challenge-response protocol implementation
|
|
13
|
+
- 🛡️ **Replay protection** - Nonce tracking and timestamp validation
|
|
14
|
+
- 📦 **Ultra-lightweight** - Minimal dependencies
|
|
15
|
+
- ⚡ **Level 2 MCP-I conformance** - Production-ready security
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
6
18
|
|
|
7
19
|
```bash
|
|
8
20
|
npm install @kya-os/mcp-i
|
|
9
21
|
```
|
|
10
22
|
|
|
11
|
-
##
|
|
23
|
+
## Quick Start
|
|
12
24
|
|
|
13
25
|
```typescript
|
|
14
26
|
import { MCPIdentity } from "@kya-os/mcp-i";
|
|
15
27
|
|
|
16
|
-
// That's it! Your MCP server now has identity
|
|
28
|
+
// That's it! Your MCP server now has a verifiable identity
|
|
17
29
|
const identity = await MCPIdentity.init();
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Challenge-Response Authentication
|
|
33
|
+
|
|
34
|
+
The package now includes full MCP-I Handshake support with cryptographic challenge-response:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// Respond to authentication challenges
|
|
38
|
+
const challenge = {
|
|
39
|
+
nonce: "a1b2c3d4e5f6...",
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
verifier_did: "did:web:verifier.example.com"
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const response = await identity.respondToChallenge(challenge);
|
|
45
|
+
// Returns signed response with agent's DID and signature
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Core Features
|
|
49
|
+
|
|
50
|
+
### Auto-Registration
|
|
51
|
+
|
|
52
|
+
On first run, the SDK automatically:
|
|
53
|
+
1. Registers your agent with knowthat.ai
|
|
54
|
+
2. Generates cryptographic keys (Ed25519)
|
|
55
|
+
3. Saves identity for future use
|
|
56
|
+
4. Returns a DID like `did:web:knowthat.ai:agents:your-agent-name`
|
|
57
|
+
|
|
58
|
+
### Cryptographic Signing
|
|
59
|
+
|
|
60
|
+
All signatures use Ed25519 for security:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Sign any message
|
|
64
|
+
const signature = await identity.sign("Hello, World!");
|
|
18
65
|
|
|
19
|
-
|
|
20
|
-
|
|
66
|
+
// Verify signatures
|
|
67
|
+
const isValid = await identity.verify(message, signature, publicKey);
|
|
21
68
|
```
|
|
22
69
|
|
|
23
|
-
|
|
70
|
+
### MCP Response Signing
|
|
71
|
+
|
|
72
|
+
Automatically sign MCP responses with identity metadata:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const response = {
|
|
76
|
+
content: [{ type: 'text', text: 'Task completed!' }]
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const signedResponse = await identity.signResponse(response);
|
|
80
|
+
// Includes _mcp_identity with DID, signature, and timestamp
|
|
81
|
+
```
|
|
24
82
|
|
|
25
|
-
|
|
26
|
-
2. **Gets DID**: Receives a decentralized identifier for your agent
|
|
27
|
-
3. **Saves Identity**: Stores credentials in `.env.local` and `.mcp-identity.json`
|
|
28
|
-
4. **Future Runs**: Loads existing identity (no re-registration)
|
|
83
|
+
### Capability Advertisement
|
|
29
84
|
|
|
30
|
-
|
|
85
|
+
Advertise your MCP-I capabilities:
|
|
31
86
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
87
|
+
```typescript
|
|
88
|
+
const capabilities = identity.getCapabilities();
|
|
89
|
+
// {
|
|
90
|
+
// version: '1.0',
|
|
91
|
+
// did: 'did:web:knowthat.ai:agents:...',
|
|
92
|
+
// conformanceLevel: 2,
|
|
93
|
+
// handshakeSupported: true,
|
|
94
|
+
// handshakeEndpoint: '/_mcp-i/handshake'
|
|
95
|
+
// }
|
|
96
|
+
```
|
|
37
97
|
|
|
38
|
-
##
|
|
98
|
+
## Advanced Options
|
|
39
99
|
|
|
40
100
|
```typescript
|
|
41
101
|
const identity = await MCPIdentity.init({
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
102
|
+
// Custom agent metadata
|
|
103
|
+
name: 'My Amazing Agent',
|
|
104
|
+
description: 'Does amazing things',
|
|
105
|
+
repository: 'https://github.com/user/agent',
|
|
106
|
+
|
|
107
|
+
// Security options
|
|
108
|
+
timestampTolerance: 30000, // 30 seconds (default: 60)
|
|
109
|
+
enableNonceTracking: true, // Prevent replay attacks (default: true)
|
|
110
|
+
|
|
111
|
+
// Storage options
|
|
112
|
+
persistencePath: './config/identity.json'
|
|
46
113
|
});
|
|
47
114
|
```
|
|
48
115
|
|
|
49
|
-
##
|
|
116
|
+
## Security Features
|
|
50
117
|
|
|
51
|
-
|
|
118
|
+
- **Ed25519 signatures** - Cryptographically secure signing
|
|
119
|
+
- **Replay protection** - Tracks used nonces to prevent replay attacks
|
|
120
|
+
- **Timestamp validation** - Rejects expired challenges
|
|
121
|
+
- **Constant-time comparison** - Prevents timing attacks
|
|
122
|
+
- **Secure key storage** - Private keys never exposed in logs
|
|
52
123
|
|
|
53
|
-
|
|
124
|
+
## Identity Persistence
|
|
54
125
|
|
|
55
|
-
|
|
56
|
-
- `AGENT_PUBLIC_KEY`
|
|
57
|
-
- `AGENT_PRIVATE_KEY`
|
|
126
|
+
Identity is saved in multiple locations for maximum compatibility:
|
|
58
127
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
128
|
+
### Files Created:
|
|
129
|
+
1. **`.env`** - Standard environment file for Node.js
|
|
130
|
+
2. **`.env.local`** - For framework compatibility (Next.js, Vite, etc.)
|
|
131
|
+
3. **`.mcp-identity.json`** - JSON format for programmatic access
|
|
62
132
|
|
|
63
|
-
|
|
133
|
+
### Loading Priority:
|
|
134
|
+
1. Environment variables (if already loaded)
|
|
135
|
+
2. `.mcp-identity.json` file (most reliable)
|
|
64
136
|
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
137
|
+
### Environment Loading:
|
|
138
|
+
- **Plain Node.js**: Add `require('dotenv').config()` to load `.env`
|
|
139
|
+
- **Next.js/Vite**: Automatically loads `.env.local`
|
|
140
|
+
- **MCP Servers**: Typically need to configure environment loading
|
|
68
141
|
|
|
69
|
-
|
|
142
|
+
### Security Note:
|
|
143
|
+
Add these to your `.gitignore`:
|
|
144
|
+
```
|
|
145
|
+
.env
|
|
146
|
+
.env.local
|
|
147
|
+
.mcp-identity.json
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Example: Full MCP Server
|
|
70
151
|
|
|
71
152
|
```typescript
|
|
72
153
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -74,48 +155,63 @@ import { MCPIdentity } from "@kya-os/mcp-i";
|
|
|
74
155
|
|
|
75
156
|
// Initialize identity
|
|
76
157
|
const identity = await MCPIdentity.init({
|
|
77
|
-
name: "Calendar
|
|
158
|
+
name: "Calendar Assistant",
|
|
159
|
+
description: "Helps manage your calendar"
|
|
78
160
|
});
|
|
79
161
|
|
|
80
|
-
//
|
|
162
|
+
// Create MCP server with identity
|
|
81
163
|
const server = new Server({
|
|
82
|
-
name: "calendar-
|
|
83
|
-
version: "1.0.0"
|
|
84
|
-
identity, // Your server now has verifiable identity!
|
|
164
|
+
name: "calendar-assistant",
|
|
165
|
+
version: "1.0.0"
|
|
85
166
|
});
|
|
86
|
-
```
|
|
87
167
|
|
|
88
|
-
|
|
168
|
+
// Handle authentication challenges automatically
|
|
169
|
+
server.on("mcp-i:challenge", async (challenge) => {
|
|
170
|
+
return await identity.respondToChallenge(challenge);
|
|
171
|
+
});
|
|
89
172
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
173
|
+
// All responses are automatically signed
|
|
174
|
+
server.setRequestHandler('tools/call', async (request) => {
|
|
175
|
+
const result = { success: true };
|
|
176
|
+
return await identity.signResponse(result);
|
|
177
|
+
});
|
|
178
|
+
```
|
|
94
179
|
|
|
95
|
-
##
|
|
180
|
+
## Conformance Levels
|
|
96
181
|
|
|
97
|
-
|
|
182
|
+
This package implements **MCP-I Level 2** conformance:
|
|
183
|
+
- ✅ Cryptographic identity (Ed25519)
|
|
184
|
+
- ✅ Challenge-response authentication
|
|
185
|
+
- ✅ Replay protection
|
|
186
|
+
- ✅ Signed responses
|
|
187
|
+
- ✅ Timestamp validation
|
|
98
188
|
|
|
99
|
-
|
|
189
|
+
## API Reference
|
|
100
190
|
|
|
101
|
-
###
|
|
191
|
+
### `MCPIdentity.init(options?)`
|
|
192
|
+
Initialize or load MCP identity. Auto-registers if needed.
|
|
102
193
|
|
|
103
|
-
|
|
194
|
+
### `identity.respondToChallenge(challenge)`
|
|
195
|
+
Respond to an MCP-I authentication challenge.
|
|
104
196
|
|
|
105
|
-
###
|
|
197
|
+
### `identity.sign(message)`
|
|
198
|
+
Sign a message with Ed25519.
|
|
106
199
|
|
|
107
|
-
|
|
200
|
+
### `identity.verify(message, signature, publicKey?)`
|
|
201
|
+
Verify an Ed25519 signature.
|
|
108
202
|
|
|
109
|
-
|
|
203
|
+
### `identity.signResponse(response)`
|
|
204
|
+
Sign an MCP response with identity metadata.
|
|
110
205
|
|
|
111
|
-
|
|
206
|
+
### `identity.getCapabilities()`
|
|
207
|
+
Get MCP-I capability advertisement.
|
|
112
208
|
|
|
113
|
-
|
|
209
|
+
### `MCPIdentity.generateNonce()`
|
|
210
|
+
Generate a cryptographically secure nonce.
|
|
114
211
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
- [Report Issues](https://github.com/orgs/know-that-ai)
|
|
212
|
+
### `identity.destroy()`
|
|
213
|
+
Clean up resources (stops nonce cleanup timer).
|
|
118
214
|
|
|
119
|
-
|
|
215
|
+
## License
|
|
120
216
|
|
|
121
|
-
|
|
217
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge-response.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/challenge-response.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for challenge-response authentication
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const vitest_1 = require("vitest");
|
|
40
|
+
const index_1 = require("../index");
|
|
41
|
+
const crypto = __importStar(require("../crypto"));
|
|
42
|
+
// Mock axios for auto-registration
|
|
43
|
+
vitest_1.vi.mock('axios');
|
|
44
|
+
// Mock fs for identity persistence
|
|
45
|
+
vitest_1.vi.mock('fs', () => ({
|
|
46
|
+
existsSync: vitest_1.vi.fn(() => false),
|
|
47
|
+
readFileSync: vitest_1.vi.fn(),
|
|
48
|
+
writeFileSync: vitest_1.vi.fn()
|
|
49
|
+
}));
|
|
50
|
+
(0, vitest_1.describe)('MCPIdentity Challenge-Response', () => {
|
|
51
|
+
let identity;
|
|
52
|
+
let keyPair;
|
|
53
|
+
(0, vitest_1.beforeEach)(async () => {
|
|
54
|
+
// Mock environment to have pre-existing identity
|
|
55
|
+
keyPair = await crypto.generateKeyPair();
|
|
56
|
+
process.env.AGENT_DID = 'did:web:knowthat.ai:agents:test-agent';
|
|
57
|
+
process.env.AGENT_PUBLIC_KEY = keyPair.publicKey;
|
|
58
|
+
process.env.AGENT_PRIVATE_KEY = keyPair.privateKey;
|
|
59
|
+
process.env.AGENT_ID = 'agent-123';
|
|
60
|
+
process.env.AGENT_SLUG = 'test-agent';
|
|
61
|
+
identity = await index_1.MCPIdentity.init();
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.afterEach)(() => {
|
|
64
|
+
// Clean up environment
|
|
65
|
+
delete process.env.AGENT_DID;
|
|
66
|
+
delete process.env.AGENT_PUBLIC_KEY;
|
|
67
|
+
delete process.env.AGENT_PRIVATE_KEY;
|
|
68
|
+
delete process.env.AGENT_ID;
|
|
69
|
+
delete process.env.AGENT_SLUG;
|
|
70
|
+
});
|
|
71
|
+
(0, vitest_1.describe)('respondToChallenge', () => {
|
|
72
|
+
(0, vitest_1.it)('should successfully respond to a valid challenge', async () => {
|
|
73
|
+
const challenge = {
|
|
74
|
+
nonce: crypto.generateNonce(),
|
|
75
|
+
timestamp: Date.now(),
|
|
76
|
+
verifier_did: 'did:web:example.com:verifier',
|
|
77
|
+
scope: ['read', 'write']
|
|
78
|
+
};
|
|
79
|
+
const response = await identity.respondToChallenge(challenge);
|
|
80
|
+
(0, vitest_1.expect)(response).toMatchObject({
|
|
81
|
+
did: 'did:web:knowthat.ai:agents:test-agent',
|
|
82
|
+
nonce: challenge.nonce,
|
|
83
|
+
publicKey: keyPair.publicKey
|
|
84
|
+
});
|
|
85
|
+
(0, vitest_1.expect)(response.signature).toBeDefined();
|
|
86
|
+
(0, vitest_1.expect)(response.timestamp).toBeGreaterThanOrEqual(challenge.timestamp);
|
|
87
|
+
// Verify the signature
|
|
88
|
+
const messageComponents = [
|
|
89
|
+
challenge.nonce,
|
|
90
|
+
challenge.timestamp.toString(),
|
|
91
|
+
response.did,
|
|
92
|
+
challenge.verifier_did || '',
|
|
93
|
+
(challenge.scope || []).join(',')
|
|
94
|
+
];
|
|
95
|
+
const message = messageComponents.join(':');
|
|
96
|
+
const isValid = await identity.verify(message, response.signature);
|
|
97
|
+
(0, vitest_1.expect)(isValid).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
(0, vitest_1.it)('should reject expired challenges', async () => {
|
|
100
|
+
const challenge = {
|
|
101
|
+
nonce: crypto.generateNonce(),
|
|
102
|
+
timestamp: Date.now() - 120000, // 2 minutes ago
|
|
103
|
+
};
|
|
104
|
+
await (0, vitest_1.expect)(identity.respondToChallenge(challenge))
|
|
105
|
+
.rejects.toThrow('Challenge expired');
|
|
106
|
+
});
|
|
107
|
+
(0, vitest_1.it)('should reject challenges with future timestamps', async () => {
|
|
108
|
+
const challenge = {
|
|
109
|
+
nonce: crypto.generateNonce(),
|
|
110
|
+
timestamp: Date.now() + 60000, // 1 minute in future
|
|
111
|
+
};
|
|
112
|
+
await (0, vitest_1.expect)(identity.respondToChallenge(challenge))
|
|
113
|
+
.rejects.toThrow('Challenge timestamp is in the future');
|
|
114
|
+
});
|
|
115
|
+
(0, vitest_1.it)('should reject reused nonces when tracking is enabled', async () => {
|
|
116
|
+
const challenge = {
|
|
117
|
+
nonce: crypto.generateNonce(),
|
|
118
|
+
timestamp: Date.now(),
|
|
119
|
+
};
|
|
120
|
+
// First use should succeed
|
|
121
|
+
await identity.respondToChallenge(challenge);
|
|
122
|
+
// Second use should fail
|
|
123
|
+
await (0, vitest_1.expect)(identity.respondToChallenge(challenge))
|
|
124
|
+
.rejects.toThrow('Nonce already used');
|
|
125
|
+
});
|
|
126
|
+
(0, vitest_1.it)('should handle challenges without optional fields', async () => {
|
|
127
|
+
const challenge = {
|
|
128
|
+
nonce: crypto.generateNonce(),
|
|
129
|
+
timestamp: Date.now(),
|
|
130
|
+
};
|
|
131
|
+
const response = await identity.respondToChallenge(challenge);
|
|
132
|
+
(0, vitest_1.expect)(response).toMatchObject({
|
|
133
|
+
did: 'did:web:knowthat.ai:agents:test-agent',
|
|
134
|
+
nonce: challenge.nonce,
|
|
135
|
+
});
|
|
136
|
+
// Verify signature with empty optional fields
|
|
137
|
+
const messageComponents = [
|
|
138
|
+
challenge.nonce,
|
|
139
|
+
challenge.timestamp.toString(),
|
|
140
|
+
response.did,
|
|
141
|
+
'', // No verifier_did
|
|
142
|
+
'' // No scope
|
|
143
|
+
];
|
|
144
|
+
const message = messageComponents.join(':');
|
|
145
|
+
const isValid = await identity.verify(message, response.signature);
|
|
146
|
+
(0, vitest_1.expect)(isValid).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
(0, vitest_1.describe)('timestamp tolerance', () => {
|
|
150
|
+
(0, vitest_1.it)('should accept challenges within tolerance window', async () => {
|
|
151
|
+
// Create identity with 5 second tolerance
|
|
152
|
+
const strictIdentity = await index_1.MCPIdentity.init({
|
|
153
|
+
timestampTolerance: 5000
|
|
154
|
+
});
|
|
155
|
+
const challenge = {
|
|
156
|
+
nonce: crypto.generateNonce(),
|
|
157
|
+
timestamp: Date.now() - 4000, // 4 seconds ago
|
|
158
|
+
};
|
|
159
|
+
// Should succeed
|
|
160
|
+
const response = await strictIdentity.respondToChallenge(challenge);
|
|
161
|
+
(0, vitest_1.expect)(response).toBeDefined();
|
|
162
|
+
});
|
|
163
|
+
(0, vitest_1.it)('should reject challenges outside tolerance window', async () => {
|
|
164
|
+
// Create identity with 5 second tolerance
|
|
165
|
+
const strictIdentity = await index_1.MCPIdentity.init({
|
|
166
|
+
timestampTolerance: 5000
|
|
167
|
+
});
|
|
168
|
+
const challenge = {
|
|
169
|
+
nonce: crypto.generateNonce(),
|
|
170
|
+
timestamp: Date.now() - 6000, // 6 seconds ago
|
|
171
|
+
};
|
|
172
|
+
// Should fail
|
|
173
|
+
await (0, vitest_1.expect)(strictIdentity.respondToChallenge(challenge))
|
|
174
|
+
.rejects.toThrow('Challenge expired');
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
(0, vitest_1.describe)('nonce tracking', () => {
|
|
178
|
+
(0, vitest_1.it)('should allow disabling nonce tracking', async () => {
|
|
179
|
+
const identityNoTracking = await index_1.MCPIdentity.init({
|
|
180
|
+
enableNonceTracking: false
|
|
181
|
+
});
|
|
182
|
+
const challenge = {
|
|
183
|
+
nonce: crypto.generateNonce(),
|
|
184
|
+
timestamp: Date.now(),
|
|
185
|
+
};
|
|
186
|
+
// Should succeed multiple times
|
|
187
|
+
await identityNoTracking.respondToChallenge(challenge);
|
|
188
|
+
await identityNoTracking.respondToChallenge(challenge);
|
|
189
|
+
// No error thrown
|
|
190
|
+
(0, vitest_1.expect)(true).toBe(true);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
(0, vitest_1.describe)('getCapabilities', () => {
|
|
194
|
+
(0, vitest_1.it)('should advertise MCP-I capabilities', () => {
|
|
195
|
+
const capabilities = identity.getCapabilities();
|
|
196
|
+
(0, vitest_1.expect)(capabilities).toEqual({
|
|
197
|
+
version: '1.0',
|
|
198
|
+
did: 'did:web:knowthat.ai:agents:test-agent',
|
|
199
|
+
publicKey: keyPair.publicKey,
|
|
200
|
+
conformanceLevel: 2,
|
|
201
|
+
handshakeSupported: true,
|
|
202
|
+
handshakeEndpoint: '/_mcp-i/handshake',
|
|
203
|
+
verificationEndpoint: 'https://knowthat.ai/api/agents/did:web:knowthat.ai:agents:test-agent/verify'
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
(0, vitest_1.describe)('static methods', () => {
|
|
208
|
+
(0, vitest_1.it)('should generate nonces', () => {
|
|
209
|
+
const nonce1 = index_1.MCPIdentity.generateNonce();
|
|
210
|
+
const nonce2 = index_1.MCPIdentity.generateNonce();
|
|
211
|
+
(0, vitest_1.expect)(nonce1).toHaveLength(64);
|
|
212
|
+
(0, vitest_1.expect)(nonce2).toHaveLength(64);
|
|
213
|
+
(0, vitest_1.expect)(nonce1).not.toEqual(nonce2);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
//# sourceMappingURL=challenge-response.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenge-response.test.js","sourceRoot":"","sources":["../../src/__tests__/challenge-response.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/crypto.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|