🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@synchronex/mcp-proxy

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@synchronex/mcp-proxy - npm Package Compare versions

Comparing version
1.0.1
to
1.1.0
+4
-2
dist/src/types.d.ts

@@ -15,4 +15,6 @@ export type CredentialMap = Record<string, string>;

category: 'desler' | 'third-party';
command: string;
args: string[];
serverType?: 'stdio' | 'http';
command?: string;
args?: string[];
url?: string;
credentialKeys: string[];

@@ -19,0 +21,0 @@ multiAccount: boolean;

@@ -6,2 +6,3 @@ import fs from 'node:fs';

import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { resolveProfile } from './resolver.js';

@@ -41,3 +42,3 @@ import { getCredentials } from './vault.js';

}
function buildEnv(server, profile) {
function requiredCredentials(server, profile) {
const credentials = getCredentials(profile, server.id);

@@ -47,8 +48,37 @@ if (!credentials) {

}
return credentials;
}
function buildEnv(server, profile) {
return {
...process.env,
...(server.baseEnv ?? {}),
...credentials,
...requiredCredentials(server, profile),
};
}
// For http servers, credentialKeys are literal HTTP header names (e.g.
// 'Authorization', 'X-Sendinel-Project-Id') — the credential map's values go
// straight onto the request, unlike stdio's process-env merge in buildEnv.
function buildHttpHeaders(server, profile) {
return { ...requiredCredentials(server, profile) };
}
function buildTransport(server, profile) {
if (server.serverType === 'http') {
if (!server.url) {
throw new Error(`Server "${server.id}" is serverType "http" but has no url configured`);
}
return new StreamableHTTPClientTransport(new URL(server.url), {
requestInit: { headers: buildHttpHeaders(server, profile) },
});
}
if (!server.command || !server.args) {
throw new Error(`Server "${server.id}" is serverType "stdio" but has no command/args configured`);
}
return new StdioClientTransport({
command: server.command,
args: server.args,
env: buildEnv(server, profile),
cwd: process.cwd(),
stderr: 'pipe',
});
}
async function getClient(serverName, profile) {

@@ -63,9 +93,3 @@ cleanupIdleClients();

const server = getServer(serverName);
const transport = new StdioClientTransport({
command: server.command,
args: server.args,
env: buildEnv(server, profile),
cwd: process.cwd(),
stderr: 'pipe',
});
const transport = buildTransport(server, profile);
const client = new Client({ name: 'synchronex-mcp-proxy', version: '1.0.0' });

@@ -72,0 +96,0 @@ await client.connect(transport);

@@ -32,3 +32,8 @@ import fs from 'node:fs';

export function deriveMasterKey(passphrase) {
return scryptSync(passphrase, 'synchronex-mcp-vault', KEY_BYTES);
// SYNC-1536: random per-derivation salt, not a fixed constant — the derived
// key is written to disk and reused directly (readMasterKey), never
// re-derived from the passphrase later, so the salt need not persist.
// A fixed salt let an attacker precompute rainbow tables once and reuse
// them against every Synchronex install.
return scryptSync(passphrase, randomBytes(16), KEY_BYTES);
}

@@ -39,3 +44,3 @@ export function writeMasterKey(key, dryRun = false) {

return;
fs.writeFileSync(MASTER_KEY_PATH, key);
fs.writeFileSync(MASTER_KEY_PATH, key, { mode: 0o600 });
}

@@ -72,3 +77,3 @@ export function encryptVault(data, masterKey) {

return;
fs.writeFileSync(VAULT_PATH, encryptVault(data, readMasterKey()));
fs.writeFileSync(VAULT_PATH, encryptVault(data, readMasterKey()), { mode: 0o600 });
}

@@ -79,3 +84,3 @@ export function initializeVault(passphrase, dryRun = false) {

if (!dryRun && !fs.existsSync(VAULT_PATH)) {
fs.writeFileSync(VAULT_PATH, encryptVault({ profiles: {}, shared: {} }, key));
fs.writeFileSync(VAULT_PATH, encryptVault({ profiles: {}, shared: {} }, key), { mode: 0o600 });
}

@@ -82,0 +87,0 @@ }

{
"name": "@synchronex/mcp-proxy",
"version": "1.0.1",
"version": "1.1.0",
"mcpName": "ai.synchronex/mcp-proxy",

@@ -38,4 +38,4 @@ "description": "Credential-aware MCP proxy - schema caching plus per-project credential routing",

"devDependencies": {
"@types/node": "^25.5.2",
"tsx": "^4.22.4",
"@types/node": "^25.9.5",
"tsx": "^4.23.1",
"typescript": "^5.9.3",

@@ -42,0 +42,0 @@ "vitest": "^4.1.2"

@@ -27,2 +27,15 @@ # @synchronex/mcp-proxy

## Upstream servers: stdio and http
Each `servers.json` entry declares `serverType: 'stdio' | 'http'` (defaults to
`'stdio'` for entries written before this existed):
- `stdio` spawns `command`/`args` as a local process; `credentialKeys` become
env vars merged into the child process's environment.
- `http` connects via MCP Streamable HTTP to `url`; `credentialKeys` are
literal HTTP header names (e.g. `Authorization`, `X-Sendinel-Project-Id`)
sent as-is from the vault credential map — no local process, no npx.
See `docs/brain/ops/mcp-proxy.md` for server-classification guidance.
## Terminal session attribution

@@ -29,0 +42,0 @@