neozip-mcp 0.1.0-beta
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/.cursor/mcp.json.global.example +10 -0
- package/CHANGELOG.md +16 -0
- package/DOCUMENTATION.md +40 -0
- package/LICENSE +16 -0
- package/README.md +223 -0
- package/SECURITY.md +37 -0
- package/dist/account/account-state.js +86 -0
- package/dist/account/format-account-status.js +37 -0
- package/dist/account/identity-provision.js +75 -0
- package/dist/account/identity-wrap.js +69 -0
- package/dist/account/profile-crypto.js +47 -0
- package/dist/account/profile-store.js +108 -0
- package/dist/account/require-account.js +29 -0
- package/dist/account/token-service-identity.js +395 -0
- package/dist/account/types.js +2 -0
- package/dist/account/wallet-evm.js +39 -0
- package/dist/archive/blockchain-status.js +303 -0
- package/dist/archive/crypto-self.js +114 -0
- package/dist/archive/detect-text.js +56 -0
- package/dist/archive/embed-metadata.js +283 -0
- package/dist/archive/encryption.js +166 -0
- package/dist/archive/extract-entry-buffer.js +18 -0
- package/dist/archive/find-entry.js +21 -0
- package/dist/archive/grep-content.js +141 -0
- package/dist/archive/identity-key.js +176 -0
- package/dist/archive/manifest.js +55 -0
- package/dist/archive/merkle.js +31 -0
- package/dist/archive/metadata-paths.js +14 -0
- package/dist/archive/mint-archive.js +61 -0
- package/dist/archive/open-archive.js +23 -0
- package/dist/archive/read-entry-buffer.js +11 -0
- package/dist/archive/read-entry-content.js +51 -0
- package/dist/archive/recipient-access.js +26 -0
- package/dist/archive/recipient-decrypt.js +21 -0
- package/dist/archive/recipient-lookup.js +55 -0
- package/dist/archive/timestamp-network.js +54 -0
- package/dist/config/capabilities.js +37 -0
- package/dist/config/index.js +74 -0
- package/dist/connect-cli.js +312 -0
- package/dist/connection/coordinator.js +74 -0
- package/dist/connection/credentials.js +29 -0
- package/dist/connection/crypto.js +56 -0
- package/dist/connection/dump.js +79 -0
- package/dist/connection/incomplete-setup.js +81 -0
- package/dist/connection/interactive.js +814 -0
- package/dist/connection/legacy-profile-reader.js +47 -0
- package/dist/connection/magic-link.js +138 -0
- package/dist/connection/migrate.js +76 -0
- package/dist/connection/onboarding.js +524 -0
- package/dist/connection/origin.js +63 -0
- package/dist/connection/phase.js +93 -0
- package/dist/connection/phone.js +20 -0
- package/dist/connection/promote-active.js +53 -0
- package/dist/connection/reset.js +20 -0
- package/dist/connection/setup-guidance.js +154 -0
- package/dist/connection/status-report.js +40 -0
- package/dist/connection/store.js +352 -0
- package/dist/connection/token-auth.js +42 -0
- package/dist/connection/types.js +2 -0
- package/dist/connection/wallet-setup.js +70 -0
- package/dist/constants/wallet-identity.js +11 -0
- package/dist/index.js +47 -0
- package/dist/load-env.js +16 -0
- package/dist/neozipkit-node.js +11 -0
- package/dist/register/resources.js +14 -0
- package/dist/register/tools.js +77 -0
- package/dist/resources/zip-resource.js +40 -0
- package/dist/resources/zip-uri.js +23 -0
- package/dist/security/auth.js +28 -0
- package/dist/security/capabilities.js +85 -0
- package/dist/security/rate-limiter.js +43 -0
- package/dist/security/resource-limiter.js +44 -0
- package/dist/security/sandbox.js +61 -0
- package/dist/server.js +32 -0
- package/dist/startup-account-gate.js +101 -0
- package/dist/startup-summary.js +40 -0
- package/dist/token-service/require-configured.js +23 -0
- package/dist/tools/account.js +504 -0
- package/dist/tools/compress.js +237 -0
- package/dist/tools/connect-status.js +143 -0
- package/dist/tools/extract.js +62 -0
- package/dist/tools/grep-entries.js +42 -0
- package/dist/tools/identity-status.js +157 -0
- package/dist/tools/info.js +147 -0
- package/dist/tools/list.js +118 -0
- package/dist/tools/lookup-recipient.js +37 -0
- package/dist/tools/mint.js +41 -0
- package/dist/tools/read-entry.js +35 -0
- package/dist/tools/search-entries.js +71 -0
- package/dist/tools/stamp.js +60 -0
- package/dist/tools/test.js +90 -0
- package/dist/tools/token-service-account.js +143 -0
- package/dist/tools/upgrade.js +60 -0
- package/dist/tools/verify.js +75 -0
- package/dist/tools/wallet-config-status.js +119 -0
- package/dist/tools/wallet-info.js +64 -0
- package/dist/translators/index.js +106 -0
- package/dist/types/index.js +7 -0
- package/dist/util/mask.js +30 -0
- package/dist/util/token-service-fetch.js +23 -0
- package/dist/vendor/neozipkit-pro.js +3 -0
- package/docs/NEOZIP_CONNECTION_STORE.md +238 -0
- package/docs/NEOZIP_CONNECT_CLI.md +185 -0
- package/docs/OPERATIONS.md +992 -0
- package/docs/examples/CLAUDE.md.example +22 -0
- package/docs/examples/claude/skills/neozip-mcp/SKILL.md +54 -0
- package/docs/examples/claude/skills/neozip-notarization/SKILL.md +75 -0
- package/docs/examples/mcp.json.claude.example +11 -0
- package/docs/examples/neozip-mcp-cursor-rule.mdc +31 -0
- package/docs/installation-guides/INSTALL_CLAUDE_CODE.md +286 -0
- package/docs/installation-guides/INSTALL_CLAUDE_WORKSPACE.md +301 -0
- package/docs/installation-guides/README.md +76 -0
- package/package.json +99 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { getAddress } from "ethers";
|
|
2
|
+
import { fetchCryptoSelf } from "../archive/crypto-self.js";
|
|
3
|
+
import { evmIdentityFromMnemonic, evmIdentityFromPrivateKey, generateEvmIdentity, } from "../account/wallet-evm.js";
|
|
4
|
+
import { getActiveConnection, readActiveConnectionSecrets, saveEvmWallet, } from "./store.js";
|
|
5
|
+
import { needsPhoneVerification } from "./phone.js";
|
|
6
|
+
export const WALLET_SETUP_HINT = "Configure a Data Wallet first: neozip-connect wallet create --ack-backup, wallet import-mnemonic, or wallet import-key. Or use finish --create-wallet to generate one (no recovery phrase shown).";
|
|
7
|
+
export async function fetchServerLinkedWalletAddress(baseUrl, accessToken) {
|
|
8
|
+
const result = await fetchCryptoSelf({
|
|
9
|
+
tokenServiceAccessToken: accessToken,
|
|
10
|
+
tokenServiceUrl: baseUrl,
|
|
11
|
+
}, { serverUrl: baseUrl });
|
|
12
|
+
if (!result.ok)
|
|
13
|
+
return null;
|
|
14
|
+
try {
|
|
15
|
+
return getAddress(result.data.evmAddress);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function validateWalletImportAgainstServer(input) {
|
|
22
|
+
if (input.force)
|
|
23
|
+
return;
|
|
24
|
+
const serverAddress = await fetchServerLinkedWalletAddress(input.origin, input.accessToken);
|
|
25
|
+
if (!serverAddress)
|
|
26
|
+
return;
|
|
27
|
+
const derived = getAddress(input.derivedAddress);
|
|
28
|
+
if (derived.toLowerCase() !== serverAddress.toLowerCase()) {
|
|
29
|
+
throw new Error(`Imported wallet (${derived}) differs from the wallet linked on Token Service (${serverAddress}). ` +
|
|
30
|
+
"Restore the correct recovery phrase or private key, or pass --force to replace the server wallet.");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function requireWalletPreconditions(conn, secrets) {
|
|
34
|
+
if (!secrets?.accessToken || !conn.emailVerified) {
|
|
35
|
+
throw new Error("Verify email first. Run neozip-connect verify.");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export async function requirePhonePreconditions(conn, origin) {
|
|
39
|
+
if (await needsPhoneVerification(conn, origin)) {
|
|
40
|
+
throw new Error("Phone verification required. Run neozip-connect phone request and phone verify.");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function walletAlreadyConfigured(conn, secrets) {
|
|
44
|
+
return Boolean(secrets?.evmPrivateKeyHex && conn.evmAddress);
|
|
45
|
+
}
|
|
46
|
+
export async function saveImportedWallet(connectionId, evm) {
|
|
47
|
+
return saveEvmWallet(connectionId, evm.privateKey, evm.address);
|
|
48
|
+
}
|
|
49
|
+
export function createLocalWalletIdentity() {
|
|
50
|
+
const evm = generateEvmIdentity();
|
|
51
|
+
if (!evm.mnemonic) {
|
|
52
|
+
throw new Error("Failed to generate recovery phrase for new Data Wallet");
|
|
53
|
+
}
|
|
54
|
+
return evm;
|
|
55
|
+
}
|
|
56
|
+
export function importWalletFromMnemonic(mnemonic) {
|
|
57
|
+
return evmIdentityFromMnemonic(mnemonic);
|
|
58
|
+
}
|
|
59
|
+
export function importWalletFromPrivateKey(privateKey) {
|
|
60
|
+
return evmIdentityFromPrivateKey(privateKey);
|
|
61
|
+
}
|
|
62
|
+
export function activeWalletContext() {
|
|
63
|
+
const conn = getActiveConnection();
|
|
64
|
+
const secrets = readActiveConnectionSecrets();
|
|
65
|
+
if (!conn || !secrets) {
|
|
66
|
+
throw new Error("No active connection. Run neozip-connect first.");
|
|
67
|
+
}
|
|
68
|
+
return { conn, secrets, origin: conn.tokenServiceOrigin };
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=wallet-setup.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Wallet-encrypted X25519 identity key wrap format (Token Service API_IDENTITY.md). */
|
|
2
|
+
export const WRAP_FORMAT_VERSION = 1;
|
|
3
|
+
export const WRAP_KDF_INFO = "NeoZip/WalletEncIK/v1";
|
|
4
|
+
export const WRAP_AEAD = "AES-256-GCM";
|
|
5
|
+
export const WRAP_KDF_SALT_LEN = 32;
|
|
6
|
+
export const WRAP_IV_LEN = 12;
|
|
7
|
+
/** SPKI-DER prefix for X25519 public keys (12 bytes). */
|
|
8
|
+
export const X25519_SPKI_PREFIX = Buffer.from("302a300506032b656e032100", "hex");
|
|
9
|
+
/** neozipkit-pro identity type for Token Service email recipients. */
|
|
10
|
+
export const TOKEN_SERVICE_RECIPIENT_IDENTITY_TYPE = "zipstamp";
|
|
11
|
+
//# sourceMappingURL=wallet-identity.js.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./load-env.js";
|
|
3
|
+
import { loadConfig } from "./config/index.js";
|
|
4
|
+
import { createServer } from "./server.js";
|
|
5
|
+
import { logStartupSummary } from "./startup-summary.js";
|
|
6
|
+
import { assertAccountReadyForStartup } from "./startup-account-gate.js";
|
|
7
|
+
// MCP over stdio: only JSON-RPC must go to stdout.
|
|
8
|
+
const rawStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
9
|
+
process.stdout.write = function (chunk, encodingOrCb, cb) {
|
|
10
|
+
const buf = typeof chunk === "string" ? chunk : chunk.toString();
|
|
11
|
+
const isJsonRpc = buf.trimStart().startsWith("{") && buf.includes('"jsonrpc"');
|
|
12
|
+
if (isJsonRpc) {
|
|
13
|
+
return rawStdoutWrite(chunk, encodingOrCb, cb);
|
|
14
|
+
}
|
|
15
|
+
const done = typeof encodingOrCb === "function"
|
|
16
|
+
? encodingOrCb
|
|
17
|
+
: typeof cb === "function"
|
|
18
|
+
? cb
|
|
19
|
+
: undefined;
|
|
20
|
+
const ok = process.stderr.write(chunk, typeof encodingOrCb === "function"
|
|
21
|
+
? undefined
|
|
22
|
+
: encodingOrCb, done);
|
|
23
|
+
if (!ok && done)
|
|
24
|
+
process.nextTick(() => done());
|
|
25
|
+
return ok;
|
|
26
|
+
};
|
|
27
|
+
const config = loadConfig();
|
|
28
|
+
if (config.capabilitiesMode === "auto") {
|
|
29
|
+
console.error(`[neozip-mcp] Capabilities (auto): ${config.capabilities.join(", ")}`);
|
|
30
|
+
}
|
|
31
|
+
if (config.debug) {
|
|
32
|
+
console.error(`[neozip-mcp] Config: capabilities=${config.capabilities.join(",")}`);
|
|
33
|
+
console.error(`[neozip-mcp] Sandbox paths: ${config.sandboxPaths.join(", ")}`);
|
|
34
|
+
console.error(`[neozip-mcp] Rate limits: zip=${config.rateLimit}/min, blockchain=${config.blockchainRateLimit}/min`);
|
|
35
|
+
}
|
|
36
|
+
async function main() {
|
|
37
|
+
await assertAccountReadyForStartup(config);
|
|
38
|
+
await logStartupSummary(config);
|
|
39
|
+
const server = createServer(config);
|
|
40
|
+
await server.start({ transportType: "stdio" });
|
|
41
|
+
console.error("[neozip-mcp] Server ready (stdio)");
|
|
42
|
+
}
|
|
43
|
+
main().catch((err) => {
|
|
44
|
+
console.error(`[neozip-mcp] Fatal: ${err instanceof Error ? err.message : String(err)}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
package/dist/load-env.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
|
+
import path from "path";
|
|
3
|
+
// Base defaults from .env; .env.local fills gaps for local dev.
|
|
4
|
+
// Do not override vars already set (e.g. NEOZIP_MCP_* from .cursor/mcp.json).
|
|
5
|
+
dotenv.config();
|
|
6
|
+
const local = dotenv.config({
|
|
7
|
+
path: path.resolve(process.cwd(), ".env.local"),
|
|
8
|
+
});
|
|
9
|
+
if (local.parsed) {
|
|
10
|
+
for (const [key, value] of Object.entries(local.parsed)) {
|
|
11
|
+
if (process.env[key] === undefined) {
|
|
12
|
+
process.env[key] = value;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=load-env.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as neozipNode from "neozipkit/node";
|
|
2
|
+
function resolveZipkitNode() {
|
|
3
|
+
const d = neozipNode.default;
|
|
4
|
+
if (typeof d === "function")
|
|
5
|
+
return d;
|
|
6
|
+
if (d && typeof d.default === "function")
|
|
7
|
+
return d.default;
|
|
8
|
+
throw new Error("Could not resolve ZipkitNode from neozipkit/node");
|
|
9
|
+
}
|
|
10
|
+
export const ZipkitNode = resolveZipkitNode();
|
|
11
|
+
//# sourceMappingURL=neozipkit-node.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { registerZipResources } from "../resources/zip-resource.js";
|
|
2
|
+
export function registerResources(deps) {
|
|
3
|
+
const hasZipAccess = deps.capabilities.isToolEnabled("list") ||
|
|
4
|
+
deps.capabilities.isToolEnabled("read_entry") ||
|
|
5
|
+
deps.capabilities.isToolEnabled("info");
|
|
6
|
+
if (!hasZipAccess)
|
|
7
|
+
return;
|
|
8
|
+
registerZipResources(deps.server, {
|
|
9
|
+
sandbox: deps.sandbox,
|
|
10
|
+
resourceLimiter: deps.resourceLimiter,
|
|
11
|
+
config: deps.config,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { errorResult } from "../types/index.js";
|
|
2
|
+
import { compressParameters, executeCompress } from "../tools/compress.js";
|
|
3
|
+
import { extractParameters, executeExtract } from "../tools/extract.js";
|
|
4
|
+
import { listParameters, executeList } from "../tools/list.js";
|
|
5
|
+
import { infoParameters, executeInfo } from "../tools/info.js";
|
|
6
|
+
import { testParameters, executeTest } from "../tools/test.js";
|
|
7
|
+
import { readEntryParameters, executeReadEntry } from "../tools/read-entry.js";
|
|
8
|
+
import { searchEntriesParameters, executeSearchEntries } from "../tools/search-entries.js";
|
|
9
|
+
import { grepEntriesParameters, executeGrepEntries } from "../tools/grep-entries.js";
|
|
10
|
+
import { mintParameters, executeMint } from "../tools/mint.js";
|
|
11
|
+
import { verifyParameters, executeVerify } from "../tools/verify.js";
|
|
12
|
+
import { stampParameters, executeStamp } from "../tools/stamp.js";
|
|
13
|
+
import { upgradeTimestampedParameters, executeUpgradeTimestamped } from "../tools/upgrade.js";
|
|
14
|
+
import { tokenServiceStatusParameters, executeTokenServiceStatus, tokenServiceRegisterParameters, executeTokenServiceRegister, tokenServiceVerifyParameters, executeTokenServiceVerify, } from "../tools/token-service-account.js";
|
|
15
|
+
import { walletInfoParameters, executeWalletInfo } from "../tools/wallet-info.js";
|
|
16
|
+
import { walletConfigStatusParameters, executeWalletConfigStatus, } from "../tools/wallet-config-status.js";
|
|
17
|
+
import { connectStatusParameters, executeConnectStatus, } from "../tools/connect-status.js";
|
|
18
|
+
import { identityStatusParameters, executeIdentityStatus, } from "../tools/identity-status.js";
|
|
19
|
+
import { lookupRecipientParameters, executeLookupRecipient, } from "../tools/lookup-recipient.js";
|
|
20
|
+
import { accountStatusParameters, executeAccountStatus, accountListParameters, executeAccountList, accountCreateParameters, executeAccountCreate, accountSelectParameters, executeAccountSelect, accountRegisterEmailParameters, executeAccountRegisterEmail, accountVerifyEmailParameters, executeAccountVerifyEmail, accountRequestPhoneOtpParameters, executeAccountRequestPhoneOtp, accountVerifyPhoneParameters, executeAccountVerifyPhone, accountCreateWalletParameters, executeAccountCreateWallet, accountImportWalletParameters, executeAccountImportWallet, accountLinkWalletParameters, executeAccountLinkWallet, accountProvisionIdentityParameters, executeAccountProvisionIdentity, accountRemoveParameters, executeAccountRemove, accountLogoutParameters, executeAccountLogout, accountInitializeParameters, executeAccountInitialize, } from "../tools/account.js";
|
|
21
|
+
function registerTool(deps, toolName, description,
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
parameters, execute) {
|
|
24
|
+
if (!deps.capabilities.isToolEnabled(toolName))
|
|
25
|
+
return;
|
|
26
|
+
deps.server.addTool({
|
|
27
|
+
name: toolName,
|
|
28
|
+
description,
|
|
29
|
+
parameters,
|
|
30
|
+
execute: async (args) => {
|
|
31
|
+
const check = deps.rateLimiter.check(toolName);
|
|
32
|
+
if (!check.allowed) {
|
|
33
|
+
return errorResult(`Rate limit exceeded. Retry after ${Math.ceil((check.retryAfterMs || 0) / 1000)}s.`);
|
|
34
|
+
}
|
|
35
|
+
return execute(args);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export function registerTools(deps) {
|
|
40
|
+
const { sandbox, resourceLimiter, config, auth } = deps;
|
|
41
|
+
registerTool(deps, "compress", "Create a ZIP archive from files or directories. Defaults to Zstandard compression. Blockchain options require neozip-connect: options.timestamp (verified email), options.tokenize (wallet; supersedes timestamp), options.recipientEmails (full profile). timestamp and tokenize are mutually exclusive. Call connect_status before compress to see readiness and the next neozip-connect command. Set options.password for password ZIPs. recipientEmails is not combinable with timestamp or tokenize.", compressParameters, (args) => executeCompress(args, sandbox, resourceLimiter, config, auth));
|
|
42
|
+
registerTool(deps, "extract", "Extract a ZIP archive to a directory. Pass options.password for ZipCrypto, WinZip AES-256, or NeoZip AES-256 encrypted entries. Supports overwrite control and timestamp preservation.", extractParameters, (args) => executeExtract(args, sandbox, resourceLimiter, config));
|
|
43
|
+
registerTool(deps, "list", "List the contents of a ZIP archive. Pass options.password for encrypted archives. JSON format includes per-entry encryptionScheme, archiveKind, and blockchain verification for timestamped/tokenized archives.", listParameters, (args) => executeList(args, sandbox, resourceLimiter, config));
|
|
44
|
+
registerTool(deps, "info", "Get detailed metadata about a ZIP archive including file count, sizes, compression ratio, methods, encryption status, comment, merkle root, and blockchain timestamp/token verification when metadata is present. Use options.format=json for AI-friendly structured output.", infoParameters, (args) => executeInfo(args, sandbox, resourceLimiter, config));
|
|
45
|
+
registerTool(deps, "test", "Test ZIP integrity (per-entry checksums). Pass options.password for encrypted archives; set options.verifyPassword true to decrypt and verify the password. For timestamped or tokenized archives, also verifies blockchain status via Token Service / on-chain checks.", testParameters, (args) => executeTest(args, sandbox, resourceLimiter, config));
|
|
46
|
+
registerTool(deps, "read_entry", "Read the text contents of a specific file inside a ZIP archive without extracting the entire package. Pass options.password for encrypted entries. Supports chunking to fit LLM context limits.", readEntryParameters, (args) => executeReadEntry(args, sandbox, resourceLimiter, config));
|
|
47
|
+
registerTool(deps, "search_entries", "Perform a keyword or regex search across file names inside a ZIP archive. Pass options.password when the archive is encrypted.", searchEntriesParameters, (args) => executeSearchEntries(args, sandbox, resourceLimiter, config));
|
|
48
|
+
registerTool(deps, "grep_entries", "Search for text strings or regex matches inside file bodies within a ZIP archive without extracting them. Pass options.password for encrypted archives.", grepEntriesParameters, (args) => executeGrepEntries(args, sandbox, resourceLimiter, config));
|
|
49
|
+
registerTool(deps, "mint", "Mint a ZIP file's merkle root as an NFT on the blockchain (Base network). Requires wallet configuration.", mintParameters, (args) => executeMint(args, auth, resourceLimiter, config, config.network));
|
|
50
|
+
registerTool(deps, "verify", "Verify a tokenized ZIP file's authenticity by checking its TOKEN.NZIP metadata against the blockchain. Pass options.password if payload entries are encrypted.", verifyParameters, (args) => executeVerify(args, sandbox, resourceLimiter, config));
|
|
51
|
+
registerTool(deps, "stamp", "Submit a ZIP file's merkle root to the NeoZip Token Service for blockchain timestamping.", stampParameters, (args) => executeStamp(args, sandbox, resourceLimiter, config));
|
|
52
|
+
registerTool(deps, "upgrade_timestamped", "Upgrade Timestamped archive: replace META-INF/TS-SUBMIT.NZIP with META-INF/TIMESTAMP.NZIP once the Token Service batch is confirmed on-chain. Enables independent blockchain verification without live Token Service calls.", upgradeTimestampedParameters, (args) => executeUpgradeTimestamped(args, sandbox, resourceLimiter, config));
|
|
53
|
+
registerTool(deps, "token_service_status", "Check NeoZip Token Service email verification status for timestamping. Reports connect profile email and Token Service URL when configured.", tokenServiceStatusParameters, (args) => executeTokenServiceStatus(args, resourceLimiter, config));
|
|
54
|
+
registerTool(deps, "token_service_register", "Register an email with the NeoZip Token Service and send a 6-digit verification code. Use token_service_verify after the user receives the code.", tokenServiceRegisterParameters, (args) => executeTokenServiceRegister(args, resourceLimiter, config));
|
|
55
|
+
registerTool(deps, "token_service_verify", "Verify a NeoZip Token Service email with the 6-digit code from the registration email. Required before timestamping via compress or stamp.", tokenServiceVerifyParameters, (args) => executeTokenServiceVerify(args, resourceLimiter, config));
|
|
56
|
+
registerTool(deps, "lookup_recipient", "Look up a recipient's Token Service X25519 public key by verified email (GET /crypto/public). Use before compress with options.recipientEmails. Does not return private keys.", lookupRecipientParameters, (args) => executeLookupRecipient(args, resourceLimiter, config));
|
|
57
|
+
registerTool(deps, "wallet_info", "Display wallet and network status including masked key, address, balance, and supported networks.", walletInfoParameters, (args) => executeWalletInfo(args, auth, resourceLimiter, config.network));
|
|
58
|
+
registerTool(deps, "wallet_config_status", "Report how wallet, Token Service, and identity credentials are configured (sources and readiness flags; no secret values).", walletConfigStatusParameters, (args) => executeWalletConfigStatus(args, config, auth));
|
|
59
|
+
registerTool(deps, "connect_status", "Fast neozip-connect readiness check: phase, store health, compress/blockchain tool readiness, interactive and scriptable next commands. Call before compress with timestamp/tokenize/recipientEmails. No network calls.", connectStatusParameters, (args) => executeConnectStatus(args, config, auth));
|
|
60
|
+
registerTool(deps, "identity_status", "Query Token Service GET /crypto/self for provisioned X25519 identity (requires NEOZIP_TOKEN_SERVICE_ACCESS_TOKEN in MCP env).", identityStatusParameters, (args) => executeIdentityStatus(args, resourceLimiter, config));
|
|
61
|
+
registerTool(deps, "account_status", "NeoZip account setup phase, masked profile metadata, and nextSteps (no secrets). Use first when onboarding.", accountStatusParameters, (args) => executeAccountStatus(args));
|
|
62
|
+
registerTool(deps, "account_list", "List local NeoZip MCP profiles on this machine (no secrets).", accountListParameters, (args) => executeAccountList(args));
|
|
63
|
+
registerTool(deps, "account_create", "Create a new local profile shell and set it active (~/.neozip/mcp/).", accountCreateParameters, (args) => executeAccountCreate(args));
|
|
64
|
+
registerTool(deps, "account_select", "Set the active profile for subsequent account_* tools and config merge.", accountSelectParameters, (args) => executeAccountSelect(args));
|
|
65
|
+
registerTool(deps, "account_register_email", "Register email with Token Service (app OTP delivery for MCP). Requires active profile.", accountRegisterEmailParameters, (args) => executeAccountRegisterEmail(args, resourceLimiter));
|
|
66
|
+
registerTool(deps, "account_verify_email", "Verify email OTP; persist Bearer token to encrypted profile store (never returned in output).", accountVerifyEmailParameters, (args) => executeAccountVerifyEmail(args, resourceLimiter));
|
|
67
|
+
registerTool(deps, "account_request_phone_otp", "Request SMS OTP for phone verification when Token Service requires it (requires verified email).", accountRequestPhoneOtpParameters, (args) => executeAccountRequestPhoneOtp(args, resourceLimiter));
|
|
68
|
+
registerTool(deps, "account_verify_phone", "Verify phone SMS OTP and persist phoneE164/phoneVerifiedAt to encrypted profile store.", accountVerifyPhoneParameters, (args) => executeAccountVerifyPhone(args, resourceLimiter));
|
|
69
|
+
registerTool(deps, "account_create_wallet", "Generate a local EOA Data Wallet; store encrypted private key (never returned).", accountCreateWalletParameters, (args) => executeAccountCreateWallet(args));
|
|
70
|
+
registerTool(deps, "account_import_wallet", "Import mnemonic or hex private key into encrypted profile (prefer account_create_wallet in agents).", accountImportWalletParameters, (args) => executeAccountImportWallet(args));
|
|
71
|
+
registerTool(deps, "account_link_wallet", "Ensure and attach Data Wallet on Token Service (signed challenges in-process).", accountLinkWalletParameters, (args) => executeAccountLinkWallet(args, resourceLimiter));
|
|
72
|
+
registerTool(deps, "account_provision_identity", "Provision X25519 identity key on Token Service for recipient encryption.", accountProvisionIdentityParameters, (args) => executeAccountProvisionIdentity(args, resourceLimiter));
|
|
73
|
+
registerTool(deps, "account_remove", "Delete a profile and its encrypted secrets (requires confirm: true).", accountRemoveParameters, (args) => executeAccountRemove(args));
|
|
74
|
+
registerTool(deps, "account_logout", "Log out of NeoZip: clear stored credentials for the active profile (~/.neozip/mcp/), deselect profile, and end the session (like Vercel MCP logout). Reload MCP after logout. Does not delete the profile shell.", accountLogoutParameters, (args) => executeAccountLogout(args));
|
|
75
|
+
registerTool(deps, "account_initialize", "Guided account setup orchestrator (auto runs next safe step; returns account_status JSON).", accountInitializeParameters, (args) => executeAccountInitialize(args, resourceLimiter));
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { openArchive } from "../archive/open-archive.js";
|
|
2
|
+
import { readEntryContent } from "../archive/read-entry-content.js";
|
|
3
|
+
import { buildArchiveManifest } from "../archive/manifest.js";
|
|
4
|
+
import { parseZipResourceUri } from "./zip-uri.js";
|
|
5
|
+
export function registerZipResources(server, deps) {
|
|
6
|
+
server.addResourceTemplate({
|
|
7
|
+
name: "zip-entry",
|
|
8
|
+
uriTemplate: "zip://{+path}",
|
|
9
|
+
description: "Read a file inside a ZIP archive without full extraction. URI format: zip://{archivePath}/{internalEntryPath}",
|
|
10
|
+
mimeType: "text/plain",
|
|
11
|
+
arguments: [
|
|
12
|
+
{
|
|
13
|
+
name: "path",
|
|
14
|
+
description: "Archive path and internal entry, e.g. /home/user/archive.nzip/src/index.js",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "password",
|
|
18
|
+
description: "Optional password for password-protected entries (required when archive uses ZipCrypto, WinZip AES, or NeoZip AES).",
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
load: async (args) => {
|
|
22
|
+
const { archivePath, entryPath } = parseZipResourceUri(`zip://${args.path}`);
|
|
23
|
+
const { zip, entries } = await openArchive(archivePath, deps.sandbox, deps.resourceLimiter, deps.config, { password: args.password });
|
|
24
|
+
if (!entryPath) {
|
|
25
|
+
const manifest = buildArchiveManifest(archivePath, entries);
|
|
26
|
+
return {
|
|
27
|
+
text: JSON.stringify(manifest, null, 2),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const readResult = await readEntryContent(zip, entries, deps.config, {
|
|
31
|
+
entryPath,
|
|
32
|
+
translate: true,
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
text: readResult.content,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=zip-resource.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function parseZipResourceUri(uri) {
|
|
2
|
+
if (!uri.startsWith("zip://")) {
|
|
3
|
+
throw new Error(`Invalid zip resource URI: ${uri}`);
|
|
4
|
+
}
|
|
5
|
+
const rest = decodeURIComponent(uri.slice("zip://".length));
|
|
6
|
+
const archiveMatch = rest.match(/^(.+?\.(?:zip|nzip))(?:\/(.*))?$/i);
|
|
7
|
+
if (!archiveMatch) {
|
|
8
|
+
throw new Error(`Cannot parse archive path from URI: ${uri}`);
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
archivePath: archiveMatch[1],
|
|
12
|
+
entryPath: archiveMatch[2] ?? "",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function buildZipResourceUri(archivePath, entryPath) {
|
|
16
|
+
const encodedArchive = encodeURIComponent(archivePath.replace(/\\/g, "/"));
|
|
17
|
+
if (!entryPath) {
|
|
18
|
+
return `zip://${encodedArchive}`;
|
|
19
|
+
}
|
|
20
|
+
const normalizedEntry = entryPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
21
|
+
return `zip://${encodedArchive}/${normalizedEntry}`;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=zip-uri.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class AuthGuard {
|
|
2
|
+
constructor(config) {
|
|
3
|
+
this.apiKey = config.apiKey;
|
|
4
|
+
this.walletKey = config.walletKey;
|
|
5
|
+
}
|
|
6
|
+
requireWalletKey() {
|
|
7
|
+
if (!this.walletKey) {
|
|
8
|
+
throw new Error("Wallet private key required for blockchain operations. " +
|
|
9
|
+
"Run neozip-connect finish to create and link a wallet.");
|
|
10
|
+
}
|
|
11
|
+
return this.walletKey;
|
|
12
|
+
}
|
|
13
|
+
hasWalletKey() {
|
|
14
|
+
return !!this.walletKey;
|
|
15
|
+
}
|
|
16
|
+
getWalletKey() {
|
|
17
|
+
return this.walletKey;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Mask a private key for display (show first 6 and last 4 chars)
|
|
21
|
+
*/
|
|
22
|
+
static maskKey(key) {
|
|
23
|
+
if (key.length <= 10)
|
|
24
|
+
return "****";
|
|
25
|
+
return key.slice(0, 6) + "..." + key.slice(-4);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const TOOL_GROUPS = {
|
|
2
|
+
zip: [
|
|
3
|
+
"compress",
|
|
4
|
+
"extract",
|
|
5
|
+
"list",
|
|
6
|
+
"info",
|
|
7
|
+
"test",
|
|
8
|
+
"read_entry",
|
|
9
|
+
"search_entries",
|
|
10
|
+
"grep_entries",
|
|
11
|
+
"upgrade_timestamped",
|
|
12
|
+
"token_service_status",
|
|
13
|
+
"lookup_recipient",
|
|
14
|
+
"wallet_config_status",
|
|
15
|
+
"identity_status",
|
|
16
|
+
"connect_status",
|
|
17
|
+
],
|
|
18
|
+
blockchain: [
|
|
19
|
+
"mint",
|
|
20
|
+
"verify",
|
|
21
|
+
"stamp",
|
|
22
|
+
"upgrade_timestamped",
|
|
23
|
+
"wallet_info",
|
|
24
|
+
"wallet_config_status",
|
|
25
|
+
"identity_status",
|
|
26
|
+
"token_service_status",
|
|
27
|
+
"token_service_register",
|
|
28
|
+
"token_service_verify",
|
|
29
|
+
"connect_status",
|
|
30
|
+
],
|
|
31
|
+
account: [
|
|
32
|
+
"account_status",
|
|
33
|
+
"account_list",
|
|
34
|
+
"account_create",
|
|
35
|
+
"account_select",
|
|
36
|
+
"account_register_email",
|
|
37
|
+
"account_verify_email",
|
|
38
|
+
"account_create_wallet",
|
|
39
|
+
"account_import_wallet",
|
|
40
|
+
"account_link_wallet",
|
|
41
|
+
"account_provision_identity",
|
|
42
|
+
"account_remove",
|
|
43
|
+
"account_logout",
|
|
44
|
+
"account_initialize",
|
|
45
|
+
"wallet_config_status",
|
|
46
|
+
"identity_status",
|
|
47
|
+
"connect_status",
|
|
48
|
+
],
|
|
49
|
+
readonly: [
|
|
50
|
+
"list",
|
|
51
|
+
"info",
|
|
52
|
+
"test",
|
|
53
|
+
"verify",
|
|
54
|
+
"wallet_info",
|
|
55
|
+
"wallet_config_status",
|
|
56
|
+
"identity_status",
|
|
57
|
+
"read_entry",
|
|
58
|
+
"search_entries",
|
|
59
|
+
"grep_entries",
|
|
60
|
+
"upgrade_timestamped",
|
|
61
|
+
"token_service_status",
|
|
62
|
+
"lookup_recipient",
|
|
63
|
+
"connect_status",
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
export class CapabilityScope {
|
|
67
|
+
constructor(capabilities) {
|
|
68
|
+
this.enabledTools = new Set();
|
|
69
|
+
for (const group of capabilities) {
|
|
70
|
+
const tools = TOOL_GROUPS[group];
|
|
71
|
+
if (tools) {
|
|
72
|
+
for (const tool of tools) {
|
|
73
|
+
this.enabledTools.add(tool);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
isToolEnabled(toolName) {
|
|
79
|
+
return this.enabledTools.has(toolName);
|
|
80
|
+
}
|
|
81
|
+
getEnabledTools() {
|
|
82
|
+
return [...this.enabledTools];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export class RateLimiter {
|
|
2
|
+
constructor(defaultLimit, blockchainLimit) {
|
|
3
|
+
this.buckets = new Map();
|
|
4
|
+
this.defaultLimit = defaultLimit;
|
|
5
|
+
this.blockchainLimit = blockchainLimit;
|
|
6
|
+
}
|
|
7
|
+
check(toolName) {
|
|
8
|
+
const limit = RateLimiter.BLOCKCHAIN_TOOLS.has(toolName)
|
|
9
|
+
? this.blockchainLimit
|
|
10
|
+
: this.defaultLimit;
|
|
11
|
+
const now = Date.now();
|
|
12
|
+
const intervalMs = 60000;
|
|
13
|
+
let bucket = this.buckets.get(toolName);
|
|
14
|
+
if (!bucket) {
|
|
15
|
+
bucket = { tokens: limit, lastRefill: now };
|
|
16
|
+
this.buckets.set(toolName, bucket);
|
|
17
|
+
}
|
|
18
|
+
const elapsed = now - bucket.lastRefill;
|
|
19
|
+
if (elapsed >= intervalMs) {
|
|
20
|
+
bucket.tokens = limit;
|
|
21
|
+
bucket.lastRefill = now;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const refill = (elapsed / intervalMs) * limit;
|
|
25
|
+
bucket.tokens = Math.min(limit, bucket.tokens + refill);
|
|
26
|
+
bucket.lastRefill = now;
|
|
27
|
+
}
|
|
28
|
+
if (bucket.tokens >= 1) {
|
|
29
|
+
bucket.tokens -= 1;
|
|
30
|
+
return { allowed: true };
|
|
31
|
+
}
|
|
32
|
+
const retryAfterMs = Math.ceil(((1 - bucket.tokens) / limit) * intervalMs);
|
|
33
|
+
return { allowed: false, retryAfterMs };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
RateLimiter.BLOCKCHAIN_TOOLS = new Set([
|
|
37
|
+
"mint", "verify", "stamp", "upgrade_timestamped", "wallet_info",
|
|
38
|
+
"token_service_register", "token_service_verify",
|
|
39
|
+
"account_register_email", "account_verify_email", "account_create_wallet",
|
|
40
|
+
"account_import_wallet", "account_link_wallet", "account_provision_identity",
|
|
41
|
+
"account_logout", "account_initialize",
|
|
42
|
+
]);
|
|
43
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
export class ResourceLimiter {
|
|
3
|
+
constructor(maxFileSize, maxEntries, timeoutSeconds) {
|
|
4
|
+
this.maxFileSize = maxFileSize;
|
|
5
|
+
this.maxEntries = maxEntries;
|
|
6
|
+
this.timeoutMs = timeoutSeconds * 1000;
|
|
7
|
+
}
|
|
8
|
+
async checkFileSize(filePath) {
|
|
9
|
+
try {
|
|
10
|
+
const stats = await fs.promises.stat(filePath);
|
|
11
|
+
if (stats.size > this.maxFileSize) {
|
|
12
|
+
const sizeMB = (stats.size / 1024 / 1024).toFixed(1);
|
|
13
|
+
const maxMB = (this.maxFileSize / 1024 / 1024).toFixed(1);
|
|
14
|
+
throw new Error(`File size ${sizeMB} MB exceeds limit of ${maxMB} MB`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
if (err instanceof Error && err.message.includes("exceeds limit"))
|
|
19
|
+
throw err;
|
|
20
|
+
// File may not exist yet (output), that's fine
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
checkEntryCount(count) {
|
|
24
|
+
if (count > this.maxEntries) {
|
|
25
|
+
throw new Error(`ZIP contains ${count} entries, exceeding limit of ${this.maxEntries}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async withTimeout(operation, label) {
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
31
|
+
try {
|
|
32
|
+
return await Promise.race([
|
|
33
|
+
operation(),
|
|
34
|
+
new Promise((_, reject) => {
|
|
35
|
+
controller.signal.addEventListener("abort", () => reject(new Error(`Operation "${label}" timed out after ${this.timeoutMs / 1000}s`)));
|
|
36
|
+
}),
|
|
37
|
+
]);
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
clearTimeout(timer);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=resource-limiter.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as os from "os";
|
|
4
|
+
const DENY_LIST = [
|
|
5
|
+
path.join(os.homedir(), ".ssh"),
|
|
6
|
+
path.join(os.homedir(), ".gnupg"),
|
|
7
|
+
path.join(os.homedir(), ".aws"),
|
|
8
|
+
"/etc/shadow",
|
|
9
|
+
"/etc/passwd",
|
|
10
|
+
];
|
|
11
|
+
const DENY_WRITE_LIST = [
|
|
12
|
+
path.join(os.homedir(), ".neozip", "wallet.json"),
|
|
13
|
+
];
|
|
14
|
+
export class PathSandbox {
|
|
15
|
+
constructor(allowedPaths) {
|
|
16
|
+
this.allowedRoots = allowedPaths.map((p) => path.resolve(p));
|
|
17
|
+
}
|
|
18
|
+
async validatePath(targetPath, write = false) {
|
|
19
|
+
const resolved = path.resolve(targetPath);
|
|
20
|
+
if (resolved.includes("\0")) {
|
|
21
|
+
throw new Error("Path contains null bytes");
|
|
22
|
+
}
|
|
23
|
+
const normalized = path.normalize(resolved);
|
|
24
|
+
let realPath;
|
|
25
|
+
try {
|
|
26
|
+
realPath = await fs.promises.realpath(normalized);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// File may not exist yet (e.g. output path); validate the parent
|
|
30
|
+
const parent = path.dirname(normalized);
|
|
31
|
+
try {
|
|
32
|
+
const realParent = await fs.promises.realpath(parent);
|
|
33
|
+
realPath = path.join(realParent, path.basename(normalized));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
realPath = normalized;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
for (const denied of DENY_LIST) {
|
|
40
|
+
if (realPath.startsWith(denied + path.sep) || realPath === denied) {
|
|
41
|
+
throw new Error(`Access denied: ${targetPath} is in a restricted location`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (write) {
|
|
45
|
+
for (const denied of DENY_WRITE_LIST) {
|
|
46
|
+
if (realPath === denied) {
|
|
47
|
+
throw new Error(`Write access denied: ${targetPath}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const inAllowed = this.allowedRoots.some((root) => realPath.startsWith(root + path.sep) || realPath === root);
|
|
52
|
+
if (!inAllowed) {
|
|
53
|
+
throw new Error(`Path outside sandbox: ${targetPath} is not within allowed directories`);
|
|
54
|
+
}
|
|
55
|
+
return realPath;
|
|
56
|
+
}
|
|
57
|
+
async validatePaths(paths, write = false) {
|
|
58
|
+
return Promise.all(paths.map((p) => this.validatePath(p, write)));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=sandbox.js.map
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FastMCP } from "fastmcp";
|
|
2
|
+
import { PathSandbox } from "./security/sandbox.js";
|
|
3
|
+
import { CapabilityScope } from "./security/capabilities.js";
|
|
4
|
+
import { RateLimiter } from "./security/rate-limiter.js";
|
|
5
|
+
import { ResourceLimiter } from "./security/resource-limiter.js";
|
|
6
|
+
import { AuthGuard } from "./security/auth.js";
|
|
7
|
+
import { registerTools } from "./register/tools.js";
|
|
8
|
+
import { registerResources } from "./register/resources.js";
|
|
9
|
+
export function createServer(config) {
|
|
10
|
+
const server = new FastMCP({
|
|
11
|
+
name: "NeoZip MCP Server",
|
|
12
|
+
version: "0.2.0",
|
|
13
|
+
});
|
|
14
|
+
const sandbox = new PathSandbox(config.sandboxPaths);
|
|
15
|
+
const capabilities = new CapabilityScope(config.capabilities);
|
|
16
|
+
const rateLimiter = new RateLimiter(config.rateLimit, config.blockchainRateLimit);
|
|
17
|
+
const resourceLimiter = new ResourceLimiter(config.maxFileSize, config.maxEntries, config.timeoutSeconds);
|
|
18
|
+
const auth = new AuthGuard(config);
|
|
19
|
+
const deps = {
|
|
20
|
+
server,
|
|
21
|
+
config,
|
|
22
|
+
capabilities,
|
|
23
|
+
rateLimiter,
|
|
24
|
+
sandbox,
|
|
25
|
+
resourceLimiter,
|
|
26
|
+
auth,
|
|
27
|
+
};
|
|
28
|
+
registerTools(deps);
|
|
29
|
+
registerResources(deps);
|
|
30
|
+
return server;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=server.js.map
|