praxis-agent 0.59.0 → 0.59.1

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 CHANGED
@@ -232,8 +232,12 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
232
232
  imports, memory, skills, commands, agents, hooks, settings, MCP servers,
233
233
  plugins, and append-only `praxis.transcript` JSONL sessions under `~/.praxis`,
234
234
  with bounded MCP connection, discovery, and tool operations plus safe
235
- disconnect recovery that never replays an already-dispatched call. Default
236
- tool selection defers `mcp__*` schemas behind a turn-scoped `ToolSearch`;
235
+ disconnect recovery that never replays an already-dispatched call. Stdio MCP
236
+ environment grants expand defined `${NAME}` references at launch without
237
+ exposing unrelated ambient credentials or shell-startup variables; reconnect
238
+ retains the derived grants, while reload derives them again from the current
239
+ environment. Default tool selection defers `mcp__*` schemas behind a
240
+ turn-scoped `ToolSearch`;
237
241
  each query activates at most eight deterministic matches for the next model
238
242
  request, and published MCP tool descriptions are capped at 2,048 Unicode
239
243
  code points. Text-only MCP results above 100,000 UTF-8 bytes are redacted
@@ -257,12 +257,12 @@ export function validateClaudeMcpConfiguration(resources) {
257
257
  });
258
258
  return { servers, warnings };
259
259
  }
260
- async function transport(serverName, config, cwd, configRoot) {
260
+ async function transport(serverName, config, cwd, configRoot, environment = process.env) {
261
261
  if (config.type === 'stdio') {
262
262
  return new StdioClientTransport({
263
263
  command: config.command,
264
264
  args: config.args,
265
- env: sanitizeChildEnvironment(config.env),
265
+ env: sanitizeChildEnvironment(config.env, environment),
266
266
  cwd: config.cwd ?? cwd,
267
267
  stderr: 'pipe',
268
268
  });
@@ -280,6 +280,21 @@ async function transport(serverName, config, cwd, configRoot) {
280
280
  ...(authProvider ? { authProvider } : {}),
281
281
  });
282
282
  }
283
+ function deriveMcpServerConfig(config, environment) {
284
+ if (config.type !== 'stdio')
285
+ return config;
286
+ const env = Object.fromEntries(Object.entries(config.env).map(([name, value]) => [
287
+ name,
288
+ value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/gu, (match, variable) => {
289
+ const replacement = environment[variable];
290
+ return Object.prototype.hasOwnProperty.call(environment, variable) &&
291
+ typeof replacement === 'string'
292
+ ? replacement
293
+ : match;
294
+ }),
295
+ ]));
296
+ return { ...config, env };
297
+ }
283
298
  function toolContent(result, sensitiveValues) {
284
299
  if (!Array.isArray(result.content)) {
285
300
  throw new Error('MCP tool result content must be an array');
@@ -883,7 +898,6 @@ export class ClaudeMcpToolRegistry {
883
898
  warn(`MCP server ${server.name} unavailable: ${error instanceof Error ? error.message : String(error)}`);
884
899
  continue;
885
900
  }
886
- this.serverSensitiveValues.set(server.name, configSensitiveValues(config, server.sensitiveValues ?? [], this.options.environment ?? process.env));
887
901
  await this.connectServer(server.name, config, server.sensitiveValues);
888
902
  }
889
903
  this.publishPrompts();
@@ -1091,7 +1105,10 @@ export class ClaudeMcpToolRegistry {
1091
1105
  async connectServer(serverName, config, additionalSensitiveValues = [], expectedGeneration = this.generation) {
1092
1106
  this.assertOpenGeneration(expectedGeneration);
1093
1107
  this.statuses.set(serverName, { name: serverName, status: 'failed' });
1094
- const sensitiveValues = configSensitiveValues(config, additionalSensitiveValues, this.options.environment ?? process.env);
1108
+ const environment = this.options.environment ?? process.env;
1109
+ const launchConfig = deriveMcpServerConfig(config, environment);
1110
+ const sensitiveValues = configSensitiveValues(launchConfig, additionalSensitiveValues, environment);
1111
+ this.serverSensitiveValues.set(serverName, sensitiveValues);
1095
1112
  const session = new McpServerSession({
1096
1113
  serverName,
1097
1114
  connectionTimeoutMs: this.timeouts.connectionTimeoutMs,
@@ -1099,7 +1116,7 @@ export class ClaudeMcpToolRegistry {
1099
1116
  ...(this.options.signal ? { lifetimeSignal: this.options.signal } : {}),
1100
1117
  createTransport: async () => {
1101
1118
  const configRoot = this.options.configRoot ?? join(homedir(), '.praxis');
1102
- return (await transport(serverName, config, this.options.cwd, configRoot));
1119
+ return (await transport(serverName, launchConfig, this.options.cwd, configRoot, environment));
1103
1120
  },
1104
1121
  configureClient: (client) => {
1105
1122
  client.setRequestHandler(ElicitRequestSchema, async (request) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "praxis-agent",
3
- "version": "0.59.0",
3
+ "version": "0.59.1",
4
4
  "description": "Local-first, single-user general agent for the command line.",
5
5
  "license": "MIT",
6
6
  "author": "wuqisen",