@kya-os/mcp-i 0.1.0-alpha.3.9 → 1.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 +350 -213
- package/dist/149.js +1 -0
- package/dist/189.js +1 -0
- package/dist/261.js +1 -0
- package/dist/28.js +1 -0
- package/dist/295.js +1 -0
- package/dist/460.js +1 -0
- package/dist/570.js +1 -0
- package/dist/634.js +1 -0
- package/dist/647.js +1 -0
- package/dist/67.js +1 -0
- package/dist/739.js +1 -0
- package/dist/742.js +1 -0
- package/dist/904.js +1 -0
- package/dist/938.js +1 -0
- package/dist/auth/api-key.d.ts +16 -0
- package/dist/auth/api-key.js +82 -0
- package/dist/auth/jwt.d.ts +43 -0
- package/dist/auth/jwt.js +51 -0
- package/dist/auth/oauth/factory.d.ts +12 -0
- package/dist/auth/oauth/factory.js +36 -0
- package/dist/auth/oauth/index.d.ts +5 -0
- package/dist/auth/oauth/index.js +27 -0
- package/dist/auth/oauth/providers/proxy-provider.d.ts +13 -0
- package/dist/auth/oauth/providers/proxy-provider.js +159 -0
- package/dist/auth/oauth/router.d.ts +4 -0
- package/dist/auth/oauth/router.js +294 -0
- package/dist/auth/oauth/storage/memory-storage.d.ts +12 -0
- package/dist/auth/oauth/storage/memory-storage.js +40 -0
- package/dist/auth/oauth/types.d.ts +112 -0
- package/dist/cache/__tests__/cloudflare-kv-nonce-cache.test.d.ts +4 -0
- package/dist/cache/__tests__/cloudflare-kv-nonce-cache.test.js +176 -0
- package/dist/cache/__tests__/concurrency.test.d.ts +5 -0
- package/dist/cache/__tests__/concurrency.test.js +300 -0
- package/dist/cache/__tests__/dynamodb-nonce-cache.test.d.ts +4 -0
- package/dist/cache/__tests__/dynamodb-nonce-cache.test.js +176 -0
- package/dist/cache/__tests__/memory-nonce-cache.test.d.ts +4 -0
- package/dist/cache/__tests__/memory-nonce-cache.test.js +132 -0
- package/dist/cache/__tests__/nonce-cache-factory-simple.test.d.ts +4 -0
- package/dist/cache/__tests__/nonce-cache-factory-simple.test.js +133 -0
- package/dist/cache/__tests__/nonce-cache-factory.test.d.ts +4 -0
- package/dist/cache/__tests__/nonce-cache-factory.test.js +252 -0
- package/dist/cache/__tests__/redis-nonce-cache.test.d.ts +4 -0
- package/dist/cache/__tests__/redis-nonce-cache.test.js +95 -0
- package/dist/cache/cloudflare-kv-nonce-cache.d.ts +14 -0
- package/dist/cache/cloudflare-kv-nonce-cache.js +93 -0
- package/dist/cache/dynamodb-nonce-cache.d.ts +15 -0
- package/dist/cache/dynamodb-nonce-cache.js +92 -0
- package/dist/cache/index.d.ts +16 -0
- package/dist/cache/index.js +32 -0
- package/dist/cache/memory-nonce-cache.d.ts +44 -0
- package/dist/cache/memory-nonce-cache.js +105 -0
- package/dist/cache/nonce-cache-factory.d.ts +20 -0
- package/dist/cache/nonce-cache-factory.js +208 -0
- package/dist/cache/redis-nonce-cache.d.ts +14 -0
- package/dist/cache/redis-nonce-cache.js +53 -0
- package/dist/compiler/compiler-context.d.ts +23 -0
- package/dist/compiler/compiler-context.js +24 -0
- package/dist/compiler/config/constants.d.ts +41 -0
- package/dist/compiler/config/constants.js +45 -0
- package/dist/compiler/config/index.d.ts +252 -0
- package/dist/compiler/config/index.js +15 -0
- package/dist/compiler/config/injection.d.ts +26 -0
- package/dist/compiler/config/injection.js +58 -0
- package/dist/compiler/config/schemas/experimental/index.d.ts +91 -0
- package/dist/compiler/config/schemas/experimental/index.js +16 -0
- package/dist/compiler/config/schemas/experimental/oauth.d.ts +74 -0
- package/dist/compiler/config/schemas/experimental/oauth.js +25 -0
- package/dist/compiler/config/schemas/index.d.ts +6 -0
- package/dist/compiler/config/schemas/index.js +17 -0
- package/dist/compiler/config/schemas/paths.d.ts +9 -0
- package/dist/compiler/config/schemas/paths.js +12 -0
- package/dist/compiler/config/schemas/transport/http.d.ts +82 -0
- package/dist/compiler/config/schemas/transport/http.js +33 -0
- package/dist/compiler/config/schemas/transport/stdio.d.ts +9 -0
- package/dist/compiler/config/schemas/transport/stdio.js +15 -0
- package/dist/compiler/config/schemas/webpack.d.ts +3 -0
- package/dist/compiler/config/schemas/webpack.js +15 -0
- package/dist/compiler/config/types.d.ts +1 -0
- package/dist/compiler/config/types.js +2 -0
- package/dist/compiler/config/utils.d.ts +20 -0
- package/dist/compiler/config/utils.js +36 -0
- package/dist/compiler/generate-env-code.d.ts +1 -0
- package/dist/compiler/generate-env-code.js +8 -0
- package/dist/compiler/generate-import-code.d.ts +1 -0
- package/dist/compiler/generate-import-code.js +24 -0
- package/dist/compiler/get-webpack-config/get-entries.d.ts +3 -0
- package/dist/compiler/get-webpack-config/get-entries.js +29 -0
- package/dist/compiler/get-webpack-config/get-externals.d.ts +7 -0
- package/dist/compiler/get-webpack-config/get-externals.js +88 -0
- package/dist/compiler/get-webpack-config/get-injected-variables.d.ts +8 -0
- package/dist/compiler/get-webpack-config/get-injected-variables.js +25 -0
- package/dist/compiler/get-webpack-config/index.d.ts +4 -0
- package/dist/compiler/get-webpack-config/index.js +101 -0
- package/dist/compiler/get-webpack-config/plugins.d.ts +8 -0
- package/dist/compiler/get-webpack-config/plugins.js +132 -0
- package/dist/compiler/get-webpack-config/resolve-tsconfig-paths.d.ts +9 -0
- package/dist/compiler/get-webpack-config/resolve-tsconfig-paths.js +40 -0
- package/dist/compiler/index.d.ts +6 -0
- package/dist/compiler/index.js +194 -0
- package/dist/compiler/on-first-build.d.ts +3 -0
- package/dist/compiler/on-first-build.js +58 -0
- package/dist/compiler/parse-xmcp-config.d.ts +9 -0
- package/dist/compiler/parse-xmcp-config.js +155 -0
- package/dist/compiler/start-http-server.d.ts +1 -0
- package/dist/compiler/start-http-server.js +34 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +38 -0
- package/dist/index.js.LICENSE.txt +49 -0
- package/dist/runtime/__tests__/audit.test.d.ts +4 -0
- package/dist/runtime/__tests__/audit.test.js +328 -0
- package/dist/runtime/__tests__/identity.test.d.ts +4 -0
- package/dist/runtime/__tests__/identity.test.js +164 -0
- package/dist/runtime/__tests__/mcpi-runtime.test.d.ts +4 -0
- package/dist/runtime/__tests__/mcpi-runtime.test.js +372 -0
- package/dist/runtime/__tests__/proof.test.d.ts +4 -0
- package/dist/runtime/__tests__/proof.test.js +302 -0
- package/dist/runtime/__tests__/session.test.d.ts +4 -0
- package/dist/runtime/__tests__/session.test.js +254 -0
- package/dist/runtime/__tests__/well-known.test.d.ts +4 -0
- package/dist/runtime/__tests__/well-known.test.js +312 -0
- package/dist/runtime/adapter-express.js +2 -0
- package/dist/runtime/adapter-express.js.LICENSE.txt +252 -0
- package/dist/runtime/adapter-nextjs.js +2 -0
- package/dist/runtime/adapter-nextjs.js.LICENSE.txt +53 -0
- package/dist/runtime/adapters/express/index.d.ts +2 -0
- package/dist/runtime/adapters/express/index.js +48 -0
- package/dist/runtime/adapters/nextjs/index.d.ts +8 -0
- package/dist/runtime/adapters/nextjs/index.js +18 -0
- package/dist/runtime/audit.d.ts +93 -0
- package/dist/runtime/audit.js +212 -0
- package/dist/runtime/debug.d.ts +118 -0
- package/dist/runtime/debug.js +612 -0
- package/dist/runtime/delegation-hooks.d.ts +85 -0
- package/dist/runtime/delegation-hooks.js +116 -0
- package/dist/runtime/demo.d.ts +71 -0
- package/dist/runtime/demo.js +135 -0
- package/dist/runtime/headers.d.ts +1 -0
- package/dist/runtime/headers.js +9 -0
- package/dist/runtime/http.js +2 -0
- package/dist/runtime/http.js.LICENSE.txt +252 -0
- package/dist/runtime/identity.d.ts +105 -0
- package/dist/runtime/identity.js +232 -0
- package/dist/runtime/index.d.ts +16 -0
- package/dist/runtime/index.js +56 -0
- package/dist/runtime/mcpi-runtime.d.ts +164 -0
- package/dist/runtime/mcpi-runtime.js +352 -0
- package/dist/runtime/proof.d.ts +87 -0
- package/dist/runtime/proof.js +223 -0
- package/dist/runtime/session.d.ts +88 -0
- package/dist/runtime/session.js +216 -0
- package/dist/runtime/stdio.js +2 -0
- package/dist/runtime/stdio.js.LICENSE.txt +1 -0
- package/dist/runtime/templates/home.d.ts +2 -0
- package/dist/runtime/templates/home.js +50 -0
- package/dist/runtime/transports/http/base-streamable-http.d.ts +25 -0
- package/dist/runtime/transports/http/base-streamable-http.js +16 -0
- package/dist/runtime/transports/http/http-context.d.ts +9 -0
- package/dist/runtime/transports/http/http-context.js +8 -0
- package/dist/runtime/transports/http/index.js +55 -0
- package/dist/runtime/transports/http/setup-cors.d.ts +4 -0
- package/dist/runtime/transports/http/setup-cors.js +24 -0
- package/dist/runtime/transports/http/stateless-streamable-http.d.ts +39 -0
- package/dist/runtime/transports/http/stateless-streamable-http.js +331 -0
- package/dist/runtime/transports/stdio/index.d.ts +1 -0
- package/dist/runtime/transports/stdio/index.js +51 -0
- package/dist/runtime/utils/server.d.ts +42 -0
- package/dist/runtime/utils/server.js +39 -0
- package/dist/runtime/utils/tools.d.ts +8 -0
- package/dist/runtime/utils/tools.js +115 -0
- package/dist/runtime/verifier-middleware.d.ts +76 -0
- package/dist/runtime/verifier-middleware.js +322 -0
- package/dist/runtime/well-known.d.ts +151 -0
- package/dist/runtime/well-known.js +258 -0
- package/dist/storage/config.d.ts +28 -0
- package/dist/storage/config.js +79 -0
- package/dist/storage/delegation.d.ts +59 -0
- package/dist/storage/delegation.js +130 -0
- package/dist/storage/merkle-verifier.d.ts +84 -0
- package/dist/storage/merkle-verifier.js +261 -0
- package/dist/test/__tests__/nonce-cache-integration.test.d.ts +1 -0
- package/dist/test/__tests__/nonce-cache-integration.test.js +116 -0
- package/dist/test/__tests__/nonce-cache.test.d.ts +1 -0
- package/dist/test/__tests__/nonce-cache.test.js +122 -0
- package/dist/test/__tests__/runtime-integration.test.d.ts +4 -0
- package/dist/test/__tests__/runtime-integration.test.js +192 -0
- package/dist/test/__tests__/test-infrastructure.test.d.ts +4 -0
- package/dist/test/__tests__/test-infrastructure.test.js +178 -0
- package/dist/test/deterministic-keys.d.ts +31 -0
- package/dist/test/deterministic-keys.js +108 -0
- package/dist/test/examples/test-usage-example.d.ts +140 -0
- package/dist/test/examples/test-usage-example.js +175 -0
- package/dist/test/index.d.ts +11 -0
- package/dist/test/index.js +27 -0
- package/dist/test/local-verification.d.ts +28 -0
- package/dist/test/local-verification.js +342 -0
- package/dist/test/mock-identity-provider.d.ts +96 -0
- package/dist/test/mock-identity-provider.js +243 -0
- package/dist/test/runtime-integration.d.ts +63 -0
- package/dist/test/runtime-integration.js +140 -0
- package/dist/test/test-environment.d.ts +26 -0
- package/dist/test/test-environment.js +50 -0
- package/dist/types/declarations.d.ts +1 -0
- package/dist/types/declarations.js +6 -0
- package/dist/types/middleware.d.ts +2 -0
- package/dist/types/middleware.js +2 -0
- package/dist/types/tool.d.ts +80 -0
- package/dist/types/tool.js +2 -0
- package/dist/utils/cli-icons.d.ts +3 -0
- package/dist/utils/cli-icons.js +7 -0
- package/dist/utils/constants.d.ts +6 -0
- package/dist/utils/constants.js +13 -0
- package/dist/utils/context.d.ts +33 -0
- package/dist/utils/context.js +58 -0
- package/dist/utils/file-watcher.d.ts +19 -0
- package/dist/utils/file-watcher.js +49 -0
- package/dist/utils/fs-utils.d.ts +2 -0
- package/dist/utils/fs-utils.js +22 -0
- package/dist/utils/path-validation.d.ts +3 -0
- package/dist/utils/path-validation.js +56 -0
- package/dist/utils/spawn-process.d.ts +9 -0
- package/dist/utils/spawn-process.js +50 -0
- package/dist/utils/subscribable.d.ts +12 -0
- package/dist/utils/subscribable.js +44 -0
- package/package.json +91 -77
- package/dist/cjs/auto.js +0 -16
- package/dist/cjs/cli-mode.d.ts +0 -16
- package/dist/cjs/cli-mode.js +0 -32
- package/dist/cjs/crypto.d.ts +0 -16
- package/dist/cjs/crypto.js +0 -212
- package/dist/cjs/dev-helper.d.ts +0 -3
- package/dist/cjs/dev-helper.js +0 -46
- package/dist/cjs/encrypted-storage.d.ts +0 -11
- package/dist/cjs/encrypted-storage.js +0 -73
- package/dist/cjs/index.d.ts +0 -56
- package/dist/cjs/index.js +0 -727
- package/dist/cjs/logger.d.ts +0 -32
- package/dist/cjs/logger.js +0 -85
- package/dist/cjs/nextjs.d.ts +0 -10
- package/dist/cjs/nextjs.js +0 -83
- package/dist/cjs/platform-info.d.ts +0 -36
- package/dist/cjs/platform-info.js +0 -274
- package/dist/cjs/polling.d.ts +0 -13
- package/dist/cjs/polling.js +0 -52
- package/dist/cjs/registry/index.d.ts +0 -12
- package/dist/cjs/registry/index.js +0 -56
- package/dist/cjs/registry/knowthat.d.ts +0 -17
- package/dist/cjs/registry/knowthat.js +0 -173
- package/dist/cjs/rotation.d.ts +0 -35
- package/dist/cjs/rotation.js +0 -102
- package/dist/cjs/storage.d.ts +0 -41
- package/dist/cjs/storage.js +0 -163
- package/dist/cjs/transport.d.ts +0 -35
- package/dist/cjs/transport.js +0 -300
- package/dist/cjs/types.d.ts +0 -206
- package/dist/cjs/vercel-adapter.d.ts +0 -8
- package/dist/cjs/vercel-adapter.js +0 -67
- package/dist/esm/auto.d.ts +0 -13
- package/dist/esm/auto.d.ts.map +0 -1
- package/dist/esm/auto.js +0 -30
- package/dist/esm/auto.js.map +0 -1
- package/dist/esm/cli-mode.d.ts +0 -52
- package/dist/esm/cli-mode.d.ts.map +0 -1
- package/dist/esm/cli-mode.js +0 -59
- package/dist/esm/cli-mode.js.map +0 -1
- package/dist/esm/crypto.d.ts +0 -51
- package/dist/esm/crypto.d.ts.map +0 -1
- package/dist/esm/crypto.js +0 -230
- package/dist/esm/crypto.js.map +0 -1
- package/dist/esm/dev-helper.d.ts +0 -15
- package/dist/esm/dev-helper.d.ts.map +0 -1
- package/dist/esm/dev-helper.js +0 -63
- package/dist/esm/dev-helper.js.map +0 -1
- package/dist/esm/encrypted-storage.d.ts +0 -19
- package/dist/esm/encrypted-storage.d.ts.map +0 -1
- package/dist/esm/encrypted-storage.js +0 -48
- package/dist/esm/encrypted-storage.js.map +0 -1
- package/dist/esm/index.d.ts +0 -129
- package/dist/esm/index.d.ts.map +0 -1
- package/dist/esm/index.js +0 -853
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/logger.d.ts +0 -46
- package/dist/esm/logger.d.ts.map +0 -1
- package/dist/esm/logger.js +0 -100
- package/dist/esm/logger.js.map +0 -1
- package/dist/esm/nextjs.d.ts +0 -22
- package/dist/esm/nextjs.d.ts.map +0 -1
- package/dist/esm/nextjs.js +0 -83
- package/dist/esm/nextjs.js.map +0 -1
- package/dist/esm/package.json +0 -1
- package/dist/esm/platform-info.d.ts +0 -74
- package/dist/esm/platform-info.d.ts.map +0 -1
- package/dist/esm/platform-info.js +0 -293
- package/dist/esm/platform-info.js.map +0 -1
- package/dist/esm/polling.d.ts +0 -29
- package/dist/esm/polling.d.ts.map +0 -1
- package/dist/esm/polling.js +0 -76
- package/dist/esm/polling.js.map +0 -1
- package/dist/esm/registry/index.d.ts +0 -43
- package/dist/esm/registry/index.d.ts.map +0 -1
- package/dist/esm/registry/index.js +0 -89
- package/dist/esm/registry/index.js.map +0 -1
- package/dist/esm/registry/knowthat.d.ts +0 -44
- package/dist/esm/registry/knowthat.d.ts.map +0 -1
- package/dist/esm/registry/knowthat.js +0 -220
- package/dist/esm/registry/knowthat.js.map +0 -1
- package/dist/esm/rotation.d.ts +0 -57
- package/dist/esm/rotation.d.ts.map +0 -1
- package/dist/esm/rotation.js +0 -133
- package/dist/esm/rotation.js.map +0 -1
- package/dist/esm/storage.d.ts +0 -65
- package/dist/esm/storage.d.ts.map +0 -1
- package/dist/esm/storage.js +0 -160
- package/dist/esm/storage.js.map +0 -1
- package/dist/esm/transport.d.ts +0 -52
- package/dist/esm/transport.d.ts.map +0 -1
- package/dist/esm/transport.js +0 -340
- package/dist/esm/transport.js.map +0 -1
- package/dist/esm/types.d.ts +0 -293
- package/dist/esm/types.d.ts.map +0 -1
- package/dist/esm/types.js +0 -5
- package/dist/esm/types.js.map +0 -1
- package/dist/esm/vercel-adapter.d.ts +0 -26
- package/dist/esm/vercel-adapter.d.ts.map +0 -1
- package/dist/esm/vercel-adapter.js +0 -80
- package/dist/esm/vercel-adapter.js.map +0 -1
- /package/dist/{cjs → auth/oauth}/types.js +0 -0
- /package/dist/{cjs/auto.d.ts → runtime/transports/http/index.d.ts} +0 -0
package/dist/esm/index.js
DELETED
|
@@ -1,853 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @kya-os/mcp-i - Optimized MCP Identity with production features
|
|
3
|
-
*
|
|
4
|
-
* Enable any MCP server to get a verifiable identity with just 2 lines of code:
|
|
5
|
-
*
|
|
6
|
-
* ```typescript
|
|
7
|
-
* import "@kya-os/mcp-i/auto"; // That's it! Your server now has identity
|
|
8
|
-
* ```
|
|
9
|
-
*/
|
|
10
|
-
import * as crypto from './crypto.js';
|
|
11
|
-
import { StorageFactory } from './storage.js';
|
|
12
|
-
import { generateClientInfo } from './platform-info.js';
|
|
13
|
-
import { TransportFactory } from './transport.js';
|
|
14
|
-
import { LoggerFactory, getLogger } from './logger.js';
|
|
15
|
-
import { KeyRotationManager } from './rotation.js';
|
|
16
|
-
import { loadIdentityFromEnv, showVercelDeveloperInstructions } from './vercel-adapter.js';
|
|
17
|
-
import { pollRegistrationStatus, isAsyncRegistrationResponse } from './polling.js';
|
|
18
|
-
// Re-export types and utilities
|
|
19
|
-
export * from './types.js';
|
|
20
|
-
export * from './vercel-adapter.js';
|
|
21
|
-
export { RegistryFactory, REGISTRY_TIERS, resolveRegistries } from './registry/index.js';
|
|
22
|
-
export { LoggerFactory, ConsoleLogger, SilentLogger } from './logger.js';
|
|
23
|
-
export { StorageFactory, MemoryStorage, FileStorage } from './storage.js';
|
|
24
|
-
export { TransportFactory, RuntimeDetector } from './transport.js';
|
|
25
|
-
export { KeyRotationManager } from './rotation.js';
|
|
26
|
-
export { initWithDevExperience, showAgentStatus } from './dev-helper.js';
|
|
27
|
-
export { pollRegistrationStatus, isAsyncRegistrationResponse } from './polling.js';
|
|
28
|
-
// Global identity instance
|
|
29
|
-
let globalIdentity = null;
|
|
30
|
-
export class MCPIdentity {
|
|
31
|
-
did;
|
|
32
|
-
publicKey;
|
|
33
|
-
privateKey;
|
|
34
|
-
timestampTolerance;
|
|
35
|
-
enableNonceTracking;
|
|
36
|
-
usedNonces = new Set();
|
|
37
|
-
nonceCleanupInterval;
|
|
38
|
-
encryptionPassword;
|
|
39
|
-
decryptedPrivateKey;
|
|
40
|
-
// Directory preferences
|
|
41
|
-
directories;
|
|
42
|
-
// Optimized storage
|
|
43
|
-
storage;
|
|
44
|
-
transport;
|
|
45
|
-
logger;
|
|
46
|
-
// Key rotation
|
|
47
|
-
rotationManager;
|
|
48
|
-
// Precomputed values
|
|
49
|
-
precomputed;
|
|
50
|
-
constructor(identity, options = {}) {
|
|
51
|
-
// Initialize logger first
|
|
52
|
-
if (options.logger) {
|
|
53
|
-
LoggerFactory.setLogger(options.logger);
|
|
54
|
-
}
|
|
55
|
-
else if (options.logLevel && options.logLevel !== 'silent') {
|
|
56
|
-
LoggerFactory.setLogger(LoggerFactory.createConsoleLogger(options.logLevel));
|
|
57
|
-
}
|
|
58
|
-
this.logger = getLogger();
|
|
59
|
-
// Core identity
|
|
60
|
-
this.did = identity.did;
|
|
61
|
-
this.publicKey = identity.publicKey;
|
|
62
|
-
this.privateKey = identity.privateKey;
|
|
63
|
-
// Store encryption password for later decryption
|
|
64
|
-
this.encryptionPassword = options.encryptionPassword;
|
|
65
|
-
// Security options
|
|
66
|
-
this.timestampTolerance = options.timestampTolerance || 60000; // 60 seconds
|
|
67
|
-
this.enableNonceTracking = options.enableNonceTracking !== false;
|
|
68
|
-
// Directory preferences
|
|
69
|
-
this.directories = identity.directories || 'verified';
|
|
70
|
-
// Initialize storage and transport - allow passing instances for testing
|
|
71
|
-
this.storage = (typeof options?.storage === 'object' && 'load' in options.storage)
|
|
72
|
-
? options.storage
|
|
73
|
-
: StorageFactory.create({
|
|
74
|
-
storage: options.storage,
|
|
75
|
-
customPath: options.persistencePath,
|
|
76
|
-
memoryKey: options.memoryKey || this.did,
|
|
77
|
-
encryptionPassword: options.encryptionPassword
|
|
78
|
-
});
|
|
79
|
-
this.transport = (typeof options?.transport === 'object' && 'post' in options.transport)
|
|
80
|
-
? options.transport
|
|
81
|
-
: TransportFactory.create({
|
|
82
|
-
transport: options.transport
|
|
83
|
-
});
|
|
84
|
-
// Precompute values for performance
|
|
85
|
-
this.precomputed = {
|
|
86
|
-
did: this.did,
|
|
87
|
-
publicKey: this.publicKey,
|
|
88
|
-
didBytes: new TextEncoder().encode(this.did),
|
|
89
|
-
signatureCache: new Map()
|
|
90
|
-
};
|
|
91
|
-
// Initialize key rotation if not in memory storage
|
|
92
|
-
if (options.storage !== 'memory') {
|
|
93
|
-
this.rotationManager = new KeyRotationManager(identity, this.transport, {});
|
|
94
|
-
}
|
|
95
|
-
// Start nonce cleanup if tracking is enabled
|
|
96
|
-
if (this.enableNonceTracking) {
|
|
97
|
-
this.startNonceCleanup();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Initialize MCP Identity - the main entry point
|
|
102
|
-
*/
|
|
103
|
-
static async init(options) {
|
|
104
|
-
// Configure logger based on logLevel before any logging
|
|
105
|
-
const logger = options?.logger || getLogger(options?.logLevel);
|
|
106
|
-
// Return existing global identity if already initialized
|
|
107
|
-
if (globalIdentity) {
|
|
108
|
-
return globalIdentity;
|
|
109
|
-
}
|
|
110
|
-
// Check for Vercel/serverless environment
|
|
111
|
-
const isVercel = process.env.VERCEL || process.env.VERCEL_ENV;
|
|
112
|
-
const isServerless = isVercel || process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.FUNCTIONS_WORKER_RUNTIME;
|
|
113
|
-
// Emit progress event
|
|
114
|
-
options?.onProgress?.({
|
|
115
|
-
stage: 'checking_existing',
|
|
116
|
-
progress: 10,
|
|
117
|
-
message: 'Checking for existing identity...'
|
|
118
|
-
});
|
|
119
|
-
// Try to load from environment variables first (for serverless)
|
|
120
|
-
let identity = null;
|
|
121
|
-
if (isServerless || options?.storage === 'memory') {
|
|
122
|
-
identity = loadIdentityFromEnv();
|
|
123
|
-
if (identity) {
|
|
124
|
-
logger.info('✅ Loaded existing identity from environment variables');
|
|
125
|
-
options?.onProgress?.({
|
|
126
|
-
stage: 'complete',
|
|
127
|
-
progress: 100,
|
|
128
|
-
message: 'Loaded existing identity from environment',
|
|
129
|
-
data: { did: identity.did }
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// Initialize storage - allow passing storage instance for testing
|
|
134
|
-
const storage = (typeof options?.storage === 'object' && 'load' in options.storage)
|
|
135
|
-
? options.storage
|
|
136
|
-
: StorageFactory.create({
|
|
137
|
-
storage: options?.storage,
|
|
138
|
-
customPath: options?.persistencePath,
|
|
139
|
-
memoryKey: options?.memoryKey,
|
|
140
|
-
encryptionPassword: options?.encryptionPassword
|
|
141
|
-
});
|
|
142
|
-
// Try to load from storage if not found in env
|
|
143
|
-
if (!identity) {
|
|
144
|
-
identity = await storage.load();
|
|
145
|
-
}
|
|
146
|
-
// Handle existing identity
|
|
147
|
-
if (identity) {
|
|
148
|
-
logger.info('Loaded existing identity:', identity.did);
|
|
149
|
-
options?.onProgress?.({
|
|
150
|
-
stage: 'complete',
|
|
151
|
-
progress: 100,
|
|
152
|
-
message: 'Loaded existing identity',
|
|
153
|
-
data: { did: identity.did }
|
|
154
|
-
});
|
|
155
|
-
globalIdentity = new MCPIdentity(identity, options);
|
|
156
|
-
return globalIdentity;
|
|
157
|
-
}
|
|
158
|
-
// No existing identity - need to create new one
|
|
159
|
-
logger.info('No existing identity found, creating new identity...');
|
|
160
|
-
// Initialize transport for registration - allow passing transport instance for testing
|
|
161
|
-
const transport = (typeof options?.transport === 'object' && 'post' in options.transport)
|
|
162
|
-
? options.transport
|
|
163
|
-
: TransportFactory.create({
|
|
164
|
-
transport: options?.transport
|
|
165
|
-
});
|
|
166
|
-
// Always use knowthat.ai as the registry
|
|
167
|
-
const apiEndpoint = options?.apiEndpoint || 'https://knowthat.ai';
|
|
168
|
-
logger.info('Registering with knowthat.ai...');
|
|
169
|
-
// Generate keys first
|
|
170
|
-
logger.info('Generating cryptographic keys...');
|
|
171
|
-
options?.onProgress?.({
|
|
172
|
-
stage: 'generating_keys',
|
|
173
|
-
progress: 30,
|
|
174
|
-
message: 'Generating cryptographic keys...'
|
|
175
|
-
});
|
|
176
|
-
const keyPair = await crypto.generateKeyPair();
|
|
177
|
-
options?.onProgress?.({
|
|
178
|
-
stage: 'generating_keys',
|
|
179
|
-
progress: 50,
|
|
180
|
-
message: 'Keys generated successfully'
|
|
181
|
-
});
|
|
182
|
-
// Prepare registration data with public key
|
|
183
|
-
const registrationData = {
|
|
184
|
-
name: options?.name || process.env.MCP_SERVER_NAME || 'Unnamed MCP Server',
|
|
185
|
-
description: options?.description,
|
|
186
|
-
repository: options?.repository,
|
|
187
|
-
publicKey: keyPair.publicKey,
|
|
188
|
-
directories: options?.directories,
|
|
189
|
-
isDraft: options?.mode !== 'production' // Default to draft mode for safety
|
|
190
|
-
};
|
|
191
|
-
logger.debug('Registration data:', {
|
|
192
|
-
name: registrationData.name,
|
|
193
|
-
hasDescription: !!registrationData.description,
|
|
194
|
-
hasRepository: !!registrationData.repository,
|
|
195
|
-
hasPublicKey: !!registrationData.publicKey,
|
|
196
|
-
directories: registrationData.directories,
|
|
197
|
-
isDraft: registrationData.isDraft
|
|
198
|
-
});
|
|
199
|
-
let response;
|
|
200
|
-
try {
|
|
201
|
-
// Register with knowthat.ai
|
|
202
|
-
options?.onProgress?.({
|
|
203
|
-
stage: 'registering',
|
|
204
|
-
progress: 60,
|
|
205
|
-
message: 'Registering with KYA-OS network...'
|
|
206
|
-
});
|
|
207
|
-
response = await autoRegister(transport, {
|
|
208
|
-
...registrationData,
|
|
209
|
-
apiEndpoint,
|
|
210
|
-
directories: options?.directories,
|
|
211
|
-
processingMode: options?.processingMode,
|
|
212
|
-
registryEndpoint: options?.registryEndpoint,
|
|
213
|
-
onProgress: options?.onProgress
|
|
214
|
-
});
|
|
215
|
-
options?.onProgress?.({
|
|
216
|
-
stage: 'registering',
|
|
217
|
-
progress: 80,
|
|
218
|
-
message: 'Registration successful'
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
catch (registrationError) {
|
|
222
|
-
logger.error('Failed to register with knowthat.ai:', registrationError.message);
|
|
223
|
-
// For development/testing, allow offline mode with a temporary DID
|
|
224
|
-
if (options?.mode === 'development' || process.env.NODE_ENV === 'development') {
|
|
225
|
-
logger.warn('Running in offline development mode with temporary identity');
|
|
226
|
-
// Generate a temporary development DID
|
|
227
|
-
const tempSlug = `temp-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
228
|
-
response = {
|
|
229
|
-
did: `did:web:localhost:agents:${tempSlug}`,
|
|
230
|
-
agent: {
|
|
231
|
-
id: tempSlug,
|
|
232
|
-
slug: tempSlug,
|
|
233
|
-
name: registrationData.name,
|
|
234
|
-
url: `http://localhost:3000/agents/${tempSlug}`,
|
|
235
|
-
claimUrl: `http://localhost:3000/agents/claim?did=${tempSlug}`
|
|
236
|
-
},
|
|
237
|
-
keys: {
|
|
238
|
-
publicKey: keyPair.publicKey,
|
|
239
|
-
privateKey: keyPair.privateKey
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
logger.warn('⚠️ Using temporary development identity. This will not persist across restarts.');
|
|
243
|
-
logger.warn('⚠️ To use a permanent identity, ensure you can connect to knowthat.ai');
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
// In production, registration is required
|
|
247
|
-
throw registrationError;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
// Create persisted identity
|
|
251
|
-
identity = {
|
|
252
|
-
did: response.did,
|
|
253
|
-
publicKey: keyPair.publicKey,
|
|
254
|
-
privateKey: keyPair.privateKey,
|
|
255
|
-
agentId: response.agent.id,
|
|
256
|
-
agentSlug: response.agent.slug,
|
|
257
|
-
registeredAt: new Date().toISOString(),
|
|
258
|
-
directories: options?.directories || 'verified'
|
|
259
|
-
};
|
|
260
|
-
// Save identity
|
|
261
|
-
options?.onProgress?.({
|
|
262
|
-
stage: 'saving',
|
|
263
|
-
progress: 90,
|
|
264
|
-
message: 'Saving identity...'
|
|
265
|
-
});
|
|
266
|
-
await storage.save(identity);
|
|
267
|
-
// Emit completion event with full data
|
|
268
|
-
options?.onProgress?.({
|
|
269
|
-
stage: 'complete',
|
|
270
|
-
progress: 100,
|
|
271
|
-
message: 'Identity created successfully',
|
|
272
|
-
data: {
|
|
273
|
-
did: identity.did,
|
|
274
|
-
publicKey: identity.publicKey,
|
|
275
|
-
agentId: identity.agentId,
|
|
276
|
-
agentSlug: identity.agentSlug,
|
|
277
|
-
claimUrl: response.agent.claimUrl
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
// Show enhanced developer instructions for Vercel/serverless
|
|
281
|
-
if (isServerless) {
|
|
282
|
-
showVercelDeveloperInstructions(identity, response.agent.claimUrl);
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
logger.info('✅ Success! Your agent has been registered.');
|
|
286
|
-
logger.info(`DID: ${response.did}`);
|
|
287
|
-
logger.info(`Profile: ${response.agent.url}`);
|
|
288
|
-
// Show claim URL if in draft mode
|
|
289
|
-
if (response.agent.claimUrl) {
|
|
290
|
-
logger.info(`Claim your agent: ${response.agent.claimUrl}`);
|
|
291
|
-
}
|
|
292
|
-
// Show directory submission info
|
|
293
|
-
if (options?.directories && options.directories !== 'none') {
|
|
294
|
-
const dirMessage = options.directories === 'verified'
|
|
295
|
-
? 'Your agent will be submitted to all verified directories'
|
|
296
|
-
: `Your agent will be submitted to: ${options.directories.join(', ')}`;
|
|
297
|
-
logger.info(dirMessage);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
// Create MCPIdentity instance
|
|
301
|
-
globalIdentity = new MCPIdentity(identity, options);
|
|
302
|
-
return globalIdentity;
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Enable automatic key rotation
|
|
306
|
-
*/
|
|
307
|
-
async enableAutoRotation(policy) {
|
|
308
|
-
if (!this.rotationManager) {
|
|
309
|
-
throw new Error('Key rotation not available in memory storage mode');
|
|
310
|
-
}
|
|
311
|
-
this.rotationManager.setupAutoRotation((result) => {
|
|
312
|
-
if (result.success) {
|
|
313
|
-
this.logger.info('Keys rotated successfully');
|
|
314
|
-
// Update storage with new keys
|
|
315
|
-
this.persistIdentity();
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
this.logger.error('Key rotation failed:', result.error);
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Manually rotate keys
|
|
324
|
-
*/
|
|
325
|
-
async rotateKeys(reason) {
|
|
326
|
-
if (!this.rotationManager) {
|
|
327
|
-
throw new Error('Key rotation not available in memory storage mode');
|
|
328
|
-
}
|
|
329
|
-
const result = await this.rotationManager.rotateKeys(reason);
|
|
330
|
-
if (result.success) {
|
|
331
|
-
await this.persistIdentity();
|
|
332
|
-
}
|
|
333
|
-
return result;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Check key health
|
|
337
|
-
*/
|
|
338
|
-
checkKeyHealth() {
|
|
339
|
-
if (!this.rotationManager) {
|
|
340
|
-
return null;
|
|
341
|
-
}
|
|
342
|
-
return this.rotationManager.checkKeyHealth();
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Get decrypted private key (lazy decryption)
|
|
346
|
-
*/
|
|
347
|
-
async getPrivateKey() {
|
|
348
|
-
if (this.decryptedPrivateKey) {
|
|
349
|
-
return this.decryptedPrivateKey;
|
|
350
|
-
}
|
|
351
|
-
if (this.encryptionPassword && this.privateKey.startsWith('enc:')) {
|
|
352
|
-
try {
|
|
353
|
-
this.decryptedPrivateKey = await crypto.decrypt(this.privateKey, this.encryptionPassword);
|
|
354
|
-
this.logger.debug('Private key decrypted successfully');
|
|
355
|
-
return this.decryptedPrivateKey;
|
|
356
|
-
}
|
|
357
|
-
catch (error) {
|
|
358
|
-
this.logger.error('Failed to decrypt private key:', error);
|
|
359
|
-
throw new Error('Invalid encryption password');
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return this.privateKey;
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Sign a message with caching
|
|
366
|
-
*/
|
|
367
|
-
async sign(message) {
|
|
368
|
-
const messageStr = typeof message === 'string' ? message : message.toString('base64');
|
|
369
|
-
// Check cache
|
|
370
|
-
const cached = this.precomputed.signatureCache.get(messageStr);
|
|
371
|
-
if (cached) {
|
|
372
|
-
return cached;
|
|
373
|
-
}
|
|
374
|
-
// Get decrypted private key
|
|
375
|
-
const privateKey = await this.getPrivateKey();
|
|
376
|
-
// Sign and cache
|
|
377
|
-
const signature = await crypto.sign(message, privateKey);
|
|
378
|
-
// Limit cache size
|
|
379
|
-
if (this.precomputed.signatureCache.size > 100) {
|
|
380
|
-
const firstKey = this.precomputed.signatureCache.keys().next().value;
|
|
381
|
-
if (firstKey) {
|
|
382
|
-
this.precomputed.signatureCache.delete(firstKey);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
this.precomputed.signatureCache.set(messageStr, signature);
|
|
386
|
-
// Track signature count for rotation
|
|
387
|
-
if (this.rotationManager) {
|
|
388
|
-
this.rotationManager.incrementSignatureCount();
|
|
389
|
-
}
|
|
390
|
-
return signature;
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Request edit access with claim URL support
|
|
394
|
-
*/
|
|
395
|
-
async requestEditAccess() {
|
|
396
|
-
const timestamp = Date.now();
|
|
397
|
-
const message = `edit-request:${this.did}:knowthat.ai:${timestamp}`;
|
|
398
|
-
const signature = await this.sign(message);
|
|
399
|
-
// Construct edit URL with proof of ownership
|
|
400
|
-
const baseUrl = 'https://knowthat.ai';
|
|
401
|
-
const editUrl = new URL(`${baseUrl}/agents/edit`);
|
|
402
|
-
editUrl.searchParams.set('did', this.did);
|
|
403
|
-
editUrl.searchParams.set('timestamp', timestamp.toString());
|
|
404
|
-
editUrl.searchParams.set('signature', signature);
|
|
405
|
-
// Also generate claim URL if agent is not yet claimed
|
|
406
|
-
const claimUrl = new URL(`${baseUrl}/agents/claim`);
|
|
407
|
-
claimUrl.searchParams.set('did', this.did);
|
|
408
|
-
claimUrl.searchParams.set('timestamp', timestamp.toString());
|
|
409
|
-
claimUrl.searchParams.set('signature', signature);
|
|
410
|
-
return {
|
|
411
|
-
editUrl: editUrl.toString(),
|
|
412
|
-
claimUrl: claimUrl.toString()
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Verify a signature
|
|
417
|
-
*/
|
|
418
|
-
async verify(message, signature, publicKey) {
|
|
419
|
-
return crypto.verify(message, signature, publicKey || this.publicKey);
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Respond to an MCP-I challenge
|
|
423
|
-
*/
|
|
424
|
-
async respondToChallenge(challenge) {
|
|
425
|
-
// Validate timestamp to prevent replay attacks
|
|
426
|
-
const now = Date.now();
|
|
427
|
-
const challengeAge = now - challenge.timestamp;
|
|
428
|
-
if (challengeAge > this.timestampTolerance) {
|
|
429
|
-
throw new Error('Challenge expired');
|
|
430
|
-
}
|
|
431
|
-
if (challengeAge < 0) {
|
|
432
|
-
throw new Error('Challenge timestamp is in the future');
|
|
433
|
-
}
|
|
434
|
-
// Check for nonce reuse if tracking is enabled
|
|
435
|
-
if (this.enableNonceTracking) {
|
|
436
|
-
if (this.usedNonces.has(challenge.nonce)) {
|
|
437
|
-
throw new Error('Nonce already used');
|
|
438
|
-
}
|
|
439
|
-
this.usedNonces.add(challenge.nonce);
|
|
440
|
-
}
|
|
441
|
-
// Create the message to sign
|
|
442
|
-
const messageComponents = [
|
|
443
|
-
challenge.nonce,
|
|
444
|
-
challenge.timestamp.toString(),
|
|
445
|
-
this.did,
|
|
446
|
-
challenge.verifier_did || '',
|
|
447
|
-
(challenge.scope || []).join(',')
|
|
448
|
-
];
|
|
449
|
-
const message = messageComponents.join(':');
|
|
450
|
-
// Sign the challenge
|
|
451
|
-
const signature = await this.sign(message);
|
|
452
|
-
// Return the response
|
|
453
|
-
return {
|
|
454
|
-
did: this.did,
|
|
455
|
-
signature,
|
|
456
|
-
timestamp: now,
|
|
457
|
-
nonce: challenge.nonce,
|
|
458
|
-
publicKey: this.publicKey
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* Get MCP-I capabilities for advertisement
|
|
463
|
-
*/
|
|
464
|
-
getCapabilities() {
|
|
465
|
-
return {
|
|
466
|
-
version: '1.0',
|
|
467
|
-
did: this.did,
|
|
468
|
-
publicKey: this.publicKey,
|
|
469
|
-
conformanceLevel: 2, // Level 2: Full crypto with challenge-response
|
|
470
|
-
handshakeSupported: true,
|
|
471
|
-
handshakeEndpoint: '/_mcp-i/handshake',
|
|
472
|
-
verificationEndpoint: `https://knowthat.ai/api/agents/${this.did}/verify`,
|
|
473
|
-
registry: 'knowthat.ai'
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Sign an MCP response with identity metadata
|
|
478
|
-
*/
|
|
479
|
-
async signResponse(response) {
|
|
480
|
-
const timestamp = new Date().toISOString();
|
|
481
|
-
const responseWithIdentity = {
|
|
482
|
-
...response,
|
|
483
|
-
_mcp_identity: {
|
|
484
|
-
did: this.did,
|
|
485
|
-
signature: '', // Will be filled below
|
|
486
|
-
timestamp,
|
|
487
|
-
conformanceLevel: 2
|
|
488
|
-
}
|
|
489
|
-
};
|
|
490
|
-
// Sign the response content (excluding the signature field)
|
|
491
|
-
const contentToSign = JSON.stringify({
|
|
492
|
-
...response,
|
|
493
|
-
_mcp_identity: {
|
|
494
|
-
did: this.did,
|
|
495
|
-
timestamp,
|
|
496
|
-
conformanceLevel: 2
|
|
497
|
-
}
|
|
498
|
-
});
|
|
499
|
-
responseWithIdentity._mcp_identity.signature = await this.sign(contentToSign);
|
|
500
|
-
return responseWithIdentity;
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* Generate a new nonce for challenges
|
|
504
|
-
*/
|
|
505
|
-
static generateNonce() {
|
|
506
|
-
return crypto.generateNonceSync();
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Get directory preferences
|
|
510
|
-
*/
|
|
511
|
-
getDirectories() {
|
|
512
|
-
return this.directories;
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* Clean up old nonces periodically to prevent memory leaks
|
|
516
|
-
*/
|
|
517
|
-
startNonceCleanup() {
|
|
518
|
-
// Clean up nonces older than 2x the timestamp tolerance
|
|
519
|
-
this.nonceCleanupInterval = setInterval(() => {
|
|
520
|
-
// In a production system, you'd track nonce timestamps
|
|
521
|
-
// For now, we'll clear all nonces periodically
|
|
522
|
-
if (this.usedNonces.size > 10000) {
|
|
523
|
-
this.usedNonces.clear();
|
|
524
|
-
}
|
|
525
|
-
}, this.timestampTolerance * 2);
|
|
526
|
-
}
|
|
527
|
-
/**
|
|
528
|
-
* Clean up resources
|
|
529
|
-
*/
|
|
530
|
-
destroy() {
|
|
531
|
-
if (this.nonceCleanupInterval) {
|
|
532
|
-
clearInterval(this.nonceCleanupInterval);
|
|
533
|
-
}
|
|
534
|
-
this.usedNonces.clear();
|
|
535
|
-
this.precomputed.signatureCache.clear();
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Helper to extract agent name from DID
|
|
539
|
-
*/
|
|
540
|
-
extractAgentName() {
|
|
541
|
-
// Try to get from persisted data or environment
|
|
542
|
-
return process.env.MCP_SERVER_NAME || 'Unknown Agent';
|
|
543
|
-
}
|
|
544
|
-
/**
|
|
545
|
-
* Helper to extract agent ID
|
|
546
|
-
*/
|
|
547
|
-
extractAgentId() {
|
|
548
|
-
return process.env.AGENT_ID || '';
|
|
549
|
-
}
|
|
550
|
-
/**
|
|
551
|
-
* Helper to extract agent slug
|
|
552
|
-
*/
|
|
553
|
-
extractAgentSlug() {
|
|
554
|
-
const parts = this.did.split(':');
|
|
555
|
-
return parts[parts.length - 1];
|
|
556
|
-
}
|
|
557
|
-
/**
|
|
558
|
-
* Persist full identity (for key rotation)
|
|
559
|
-
*/
|
|
560
|
-
async persistIdentity() {
|
|
561
|
-
try {
|
|
562
|
-
const identity = {
|
|
563
|
-
did: this.did,
|
|
564
|
-
publicKey: this.publicKey,
|
|
565
|
-
privateKey: this.privateKey,
|
|
566
|
-
agentId: this.extractAgentId(),
|
|
567
|
-
agentSlug: this.extractAgentSlug(),
|
|
568
|
-
registeredAt: new Date().toISOString(),
|
|
569
|
-
directories: this.directories
|
|
570
|
-
};
|
|
571
|
-
await this.storage.save(identity);
|
|
572
|
-
}
|
|
573
|
-
catch (error) {
|
|
574
|
-
this.logger.error('Failed to persist identity:', error);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Enable MCP Identity for any MCP server
|
|
580
|
-
*/
|
|
581
|
-
export async function enableMCPIdentity(options) {
|
|
582
|
-
const identity = await MCPIdentity.init(options);
|
|
583
|
-
// Try to patch MCP Server if available
|
|
584
|
-
try {
|
|
585
|
-
patchMCPServer(identity);
|
|
586
|
-
}
|
|
587
|
-
catch (error) {
|
|
588
|
-
const logger = getLogger();
|
|
589
|
-
logger.debug('MCP Server not found, identity initialized for manual use');
|
|
590
|
-
}
|
|
591
|
-
return identity;
|
|
592
|
-
}
|
|
593
|
-
/**
|
|
594
|
-
* Create MCP middleware for manual integration
|
|
595
|
-
*/
|
|
596
|
-
export function createMCPMiddleware(identity) {
|
|
597
|
-
return (server) => {
|
|
598
|
-
// Validate server object
|
|
599
|
-
if (!server || typeof server !== 'object') {
|
|
600
|
-
const logger = getLogger();
|
|
601
|
-
logger.warn('Invalid MCP Server object passed to middleware');
|
|
602
|
-
return;
|
|
603
|
-
}
|
|
604
|
-
// Check if methods exist before patching
|
|
605
|
-
if (!server.setRequestHandler || typeof server.setRequestHandler !== 'function') {
|
|
606
|
-
const logger = getLogger();
|
|
607
|
-
logger.warn('MCP Server missing setRequestHandler method');
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
|
-
// Store original methods
|
|
611
|
-
const originalSetRequestHandler = server.setRequestHandler.bind(server);
|
|
612
|
-
const originalConnect = server.connect ? server.connect.bind(server) : null;
|
|
613
|
-
// Patch setRequestHandler to wrap all responses
|
|
614
|
-
server.setRequestHandler = function (method, handler) {
|
|
615
|
-
// Add defensive check for undefined method
|
|
616
|
-
if (!method || typeof method !== 'string') {
|
|
617
|
-
const logger = getLogger();
|
|
618
|
-
logger.warn('setRequestHandler called with invalid method:', method);
|
|
619
|
-
return originalSetRequestHandler.call(this, method, handler);
|
|
620
|
-
}
|
|
621
|
-
const wrappedHandler = async (...args) => {
|
|
622
|
-
const result = await handler(...args);
|
|
623
|
-
// If result has content, sign it
|
|
624
|
-
if (result && typeof result === 'object' && 'content' in result) {
|
|
625
|
-
return await identity.signResponse(result);
|
|
626
|
-
}
|
|
627
|
-
return result;
|
|
628
|
-
};
|
|
629
|
-
return originalSetRequestHandler(method, wrappedHandler);
|
|
630
|
-
};
|
|
631
|
-
// Patch connect to advertise MCP-I capabilities
|
|
632
|
-
if (originalConnect) {
|
|
633
|
-
server.connect = async function (transport) {
|
|
634
|
-
// Add MCP-I capabilities to server info
|
|
635
|
-
if (this.serverInfo && this.serverInfo.capabilities) {
|
|
636
|
-
this.serverInfo.capabilities['mcp-i'] = identity.getCapabilities();
|
|
637
|
-
}
|
|
638
|
-
// Set up MCP-I handshake handler
|
|
639
|
-
this.setRequestHandler('mcp-i/challenge', async (request) => {
|
|
640
|
-
return identity.respondToChallenge(request.params);
|
|
641
|
-
});
|
|
642
|
-
// Call original connect
|
|
643
|
-
return originalConnect.call(this, transport);
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
/**
|
|
649
|
-
* Patch the MCP Server to automatically add identity
|
|
650
|
-
*/
|
|
651
|
-
function patchMCPServer(identity) {
|
|
652
|
-
try {
|
|
653
|
-
// Try to import the MCP SDK
|
|
654
|
-
const MCPModule = require('@modelcontextprotocol/sdk/server/index.js');
|
|
655
|
-
const OriginalServer = MCPModule.Server;
|
|
656
|
-
if (!OriginalServer) {
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
// Apply middleware
|
|
660
|
-
const middleware = createMCPMiddleware(identity);
|
|
661
|
-
// Patch the constructor
|
|
662
|
-
const OriginalConstructor = OriginalServer;
|
|
663
|
-
MCPModule.Server = function (...args) {
|
|
664
|
-
const instance = new OriginalConstructor(...args);
|
|
665
|
-
try {
|
|
666
|
-
middleware(instance, identity);
|
|
667
|
-
}
|
|
668
|
-
catch (error) {
|
|
669
|
-
const logger = getLogger();
|
|
670
|
-
logger.warn('Failed to apply MCP-I middleware:', error);
|
|
671
|
-
}
|
|
672
|
-
return instance;
|
|
673
|
-
};
|
|
674
|
-
// Copy static properties
|
|
675
|
-
Object.setPrototypeOf(MCPModule.Server, OriginalConstructor);
|
|
676
|
-
Object.setPrototypeOf(MCPModule.Server.prototype, OriginalConstructor.prototype);
|
|
677
|
-
const logger = getLogger();
|
|
678
|
-
logger.info('✨ MCP Server patched - all responses will be automatically signed');
|
|
679
|
-
}
|
|
680
|
-
catch (error) {
|
|
681
|
-
// MCP SDK not available, that's okay
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
// Helper function to determine which endpoint to use
|
|
685
|
-
function determineEndpoint(options) {
|
|
686
|
-
// Explicit configuration takes precedence
|
|
687
|
-
if (options.registryEndpoint === 'cli')
|
|
688
|
-
return true;
|
|
689
|
-
if (options.registryEndpoint === 'auto-register')
|
|
690
|
-
return false;
|
|
691
|
-
// Auto mode: use CLI endpoint if we're in a context that suggests CLI usage
|
|
692
|
-
if (options.registryEndpoint === 'auto' || !options.registryEndpoint) {
|
|
693
|
-
// Check if we have a progress callback (indicates CLI usage)
|
|
694
|
-
if (options.onProgress)
|
|
695
|
-
return true;
|
|
696
|
-
// Check if processingMode is explicitly set to sync (CLI preference)
|
|
697
|
-
if (options.processingMode === 'sync')
|
|
698
|
-
return true;
|
|
699
|
-
// Check if we're in a TTY environment (interactive terminal)
|
|
700
|
-
if (process.stdout?.isTTY)
|
|
701
|
-
return true;
|
|
702
|
-
}
|
|
703
|
-
return false;
|
|
704
|
-
}
|
|
705
|
-
// Helper function for CLI registration
|
|
706
|
-
async function registerViaCLI(transport, options) {
|
|
707
|
-
const logger = getLogger();
|
|
708
|
-
logger.debug('Using fast CLI registration endpoint');
|
|
709
|
-
const response = await transport.post(`${options.apiEndpoint}/api/agents/cli-register`, {
|
|
710
|
-
name: options.name,
|
|
711
|
-
description: options.description,
|
|
712
|
-
repository: options.repository,
|
|
713
|
-
publicKey: options.publicKey
|
|
714
|
-
}, {
|
|
715
|
-
timeout: 5000, // 5 second timeout for CLI endpoint
|
|
716
|
-
headers: {
|
|
717
|
-
'Content-Type': 'application/json',
|
|
718
|
-
'User-Agent': `@kya-os/mcp-i/${generateClientInfo().sdkVersion}`
|
|
719
|
-
}
|
|
720
|
-
});
|
|
721
|
-
logger.debug(`CLI registration completed in ${response.data.responseTime}ms`);
|
|
722
|
-
// Report progress
|
|
723
|
-
options.onProgress?.({
|
|
724
|
-
stage: 'registering',
|
|
725
|
-
progress: 80,
|
|
726
|
-
message: 'Registration successful',
|
|
727
|
-
data: {
|
|
728
|
-
did: response.data.did,
|
|
729
|
-
claimUrl: response.data.claimUrl
|
|
730
|
-
}
|
|
731
|
-
});
|
|
732
|
-
// Transform to match AutoRegisterResponse format
|
|
733
|
-
return {
|
|
734
|
-
success: response.data.success,
|
|
735
|
-
did: response.data.did,
|
|
736
|
-
agent: {
|
|
737
|
-
id: response.data.agent.id,
|
|
738
|
-
slug: response.data.agent.slug,
|
|
739
|
-
name: response.data.agent.name,
|
|
740
|
-
url: response.data.agent.url,
|
|
741
|
-
claimUrl: response.data.claimUrl
|
|
742
|
-
},
|
|
743
|
-
keys: response.data.keys || {
|
|
744
|
-
publicKey: options.publicKey || '',
|
|
745
|
-
privateKey: undefined
|
|
746
|
-
}
|
|
747
|
-
};
|
|
748
|
-
}
|
|
749
|
-
// Helper function for auto-registration (now supports async v2.0 API and CLI endpoint)
|
|
750
|
-
async function autoRegister(transport, options) {
|
|
751
|
-
const logger = getLogger();
|
|
752
|
-
// Determine which endpoint to use
|
|
753
|
-
const shouldUseCLI = determineEndpoint(options);
|
|
754
|
-
// Try CLI endpoint first if appropriate
|
|
755
|
-
if (shouldUseCLI) {
|
|
756
|
-
try {
|
|
757
|
-
return await registerViaCLI(transport, options);
|
|
758
|
-
}
|
|
759
|
-
catch (error) {
|
|
760
|
-
logger.debug(`CLI registration failed: ${error.message}, falling back to auto-register`);
|
|
761
|
-
// Fall through to auto-register
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
// Use auto-register endpoint
|
|
765
|
-
try {
|
|
766
|
-
const requestBody = {
|
|
767
|
-
metadata: {
|
|
768
|
-
name: options.name,
|
|
769
|
-
description: options.description,
|
|
770
|
-
repository: options.repository,
|
|
771
|
-
publicKey: options.publicKey,
|
|
772
|
-
version: '1.0.0',
|
|
773
|
-
isDraft: options.isDraft,
|
|
774
|
-
directories: options.directories || 'verified' // Default to all verified directories
|
|
775
|
-
},
|
|
776
|
-
clientInfo: generateClientInfo({
|
|
777
|
-
processingMode: options.processingMode === 'auto' ? undefined : options.processingMode,
|
|
778
|
-
customMetadata: {
|
|
779
|
-
source: 'auto-register'
|
|
780
|
-
}
|
|
781
|
-
})
|
|
782
|
-
};
|
|
783
|
-
logger.debug('Sending registration request to:', `${options.apiEndpoint}/api/agents/auto-register`);
|
|
784
|
-
const response = await transport.post(`${options.apiEndpoint}/api/agents/auto-register`, requestBody, {
|
|
785
|
-
timeout: 30000,
|
|
786
|
-
headers: {
|
|
787
|
-
'Content-Type': 'application/json',
|
|
788
|
-
'User-Agent': `@kya-os/mcp-i/${requestBody.clientInfo.sdkVersion}`
|
|
789
|
-
}
|
|
790
|
-
});
|
|
791
|
-
logger.debug('Registration response received:', {
|
|
792
|
-
status: response.status,
|
|
793
|
-
hasData: !!response.data,
|
|
794
|
-
isAsync: response.status === 202
|
|
795
|
-
});
|
|
796
|
-
// Check if we got an async response (v2.0 API)
|
|
797
|
-
if (response.status === 202 && isAsyncRegistrationResponse(response.data)) {
|
|
798
|
-
logger.info('Registration submitted, waiting for completion...');
|
|
799
|
-
// Report progress
|
|
800
|
-
options.onProgress?.({
|
|
801
|
-
stage: 'registering',
|
|
802
|
-
progress: 70,
|
|
803
|
-
message: 'Registration submitted, processing...',
|
|
804
|
-
data: { jobId: response.data.jobId }
|
|
805
|
-
});
|
|
806
|
-
// Poll for completion using simple 2-second intervals
|
|
807
|
-
const result = await pollRegistrationStatus(response.data.status, // Status URL
|
|
808
|
-
transport, {
|
|
809
|
-
pollInterval: 2000, // Fixed 2-second intervals
|
|
810
|
-
maxPollingTime: 60000, // 60 seconds max
|
|
811
|
-
logger,
|
|
812
|
-
onProgress: (message, progress) => {
|
|
813
|
-
// Update progress during polling
|
|
814
|
-
options.onProgress?.({
|
|
815
|
-
stage: 'registering',
|
|
816
|
-
progress: 70 + (progress || 0) * 0.1, // 70-80% during polling
|
|
817
|
-
message
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
});
|
|
821
|
-
logger.debug('Registration completed after polling:', {
|
|
822
|
-
hasDid: !!result.did,
|
|
823
|
-
hasAgent: !!result.agent
|
|
824
|
-
});
|
|
825
|
-
return result;
|
|
826
|
-
}
|
|
827
|
-
// Handle sync response (backward compatibility)
|
|
828
|
-
logger.debug('Got synchronous registration response');
|
|
829
|
-
return response.data;
|
|
830
|
-
}
|
|
831
|
-
catch (error) {
|
|
832
|
-
logger.error('Registration failed:', {
|
|
833
|
-
message: error.message,
|
|
834
|
-
status: error.status,
|
|
835
|
-
response: error.response
|
|
836
|
-
});
|
|
837
|
-
if (error.message?.includes('429')) {
|
|
838
|
-
throw new Error('Rate limit exceeded. Please try again later.');
|
|
839
|
-
}
|
|
840
|
-
// Provide more helpful error messages
|
|
841
|
-
if (error.message?.includes('500')) {
|
|
842
|
-
throw new Error('Server error during registration. This might be a temporary issue.\n' +
|
|
843
|
-
'Please try again in a few moments, or register manually at https://knowthat.ai/submit-agent');
|
|
844
|
-
}
|
|
845
|
-
if (error.message?.includes('400')) {
|
|
846
|
-
throw new Error('Invalid registration data. Please ensure all required fields are provided:\n' +
|
|
847
|
-
'- name: A unique name for your agent\n' +
|
|
848
|
-
'- publicKey: Generated automatically (check if generation succeeded)');
|
|
849
|
-
}
|
|
850
|
-
throw new Error(error.message || 'Failed to auto-register agent');
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
//# sourceMappingURL=index.js.map
|