npm package: @lvasko/local-secret-store
Description: Windows-focused local secret store for MCP tools and other local automation
Latest version: 0.2.2

# Local Secret Store

Windows-focused local secret store for values that multiple MCP servers need to read at runtime, such as Jira PATs, Tempo tokens, Confluence PATs, API keys, or other per-user secrets.

The values are stored under the current Windows user profile and protected with DPAPI, so the file contents are not plain text.

## Requirements

- Windows
- Node.js
- PowerShell 7 or Windows PowerShell

The package automatically tries these PowerShell executables in order:

- `PWSH_PATH`, if you set it explicitly
- `pwsh.exe`
- standard Windows PowerShell

## Storage

Secrets are stored under:

```text
C:\Users\<user>\.codex\secrets\local-secret-store
```

Each secret is stored as a DPAPI-protected blob plus a small metadata file.

## CLI

Primary usage is through `npx`:

```powershell
npx @lvasko/local-secret-store@latest set jira-prod-pat "your-token-here"
npx @lvasko/local-secret-store@latest get jira-prod-pat --preview
npx @lvasko/local-secret-store@latest list
npx @lvasko/local-secret-store@latest delete jira-prod-pat
```

Clipboard-based setup:

```powershell
npx @lvasko/local-secret-store@latest set-from-clipboard confluence-client-a-pat --clear-clipboard
npx @lvasko/local-secret-store@latest set-from-clipboard tempo-prod-token --replace-clipboard "Secret automatically removed from clipboard"
npx @lvasko/local-secret-store@latest set-from-clipboard api-key --trim-end
```

`set-from-clipboard` reads the current clipboard value, stores it, and then optionally clears or replaces the clipboard.

`get` prints the raw secret to stdout. For manual checks, prefer `--preview`:

```powershell
npx @lvasko/local-secret-store@latest get jira-prod-pat --preview
```

If you need the raw secret for scripting, use:

```powershell
npx @lvasko/local-secret-store@latest get jira-prod-pat
```

If you are developing from a local checkout instead of `npx`, the equivalent command is:

```powershell
node .\src\cli.js get jira-prod-pat --preview
```

## Smoke Test

To verify the package works on a fresh Windows machine:

```powershell
npx @lvasko/local-secret-store@latest smoke
```

or from the repo checkout:

```powershell
npm run --workspace ./packages/local-secret-store smoke
```

The smoke test verifies:

- PowerShell can be resolved
- DPAPI encryption works
- a temporary secret can be stored, read, listed, and deleted

Quick runtime test that simulates how an MCP server would consume a secret:

```powershell
node .\src\use-secret-store.js jira-prod-pat
```

Or:

```powershell
$env:SECRET_NAME = "jira-prod-pat"
node .\src\use-secret-store.js
```

## Library API

Other MCP servers can use the store directly:

```js
import { readSecret, maskSecretValue } from "@lvasko/local-secret-store";

const jiraToken = await readSecret(process.env.JIRA_TOKEN_SECRET_NAME);
console.log(maskSecretValue(jiraToken));
```

Available functions:

- `storeSecret(name, value, options?)`
- `readSecret(name)`
- `listSecrets()`
- `deleteSecret(name)`
- `maskSecretValue(value, options?)`
- `readClipboardText()`
- `writeClipboardText(value)`
- `clearClipboardText(replacementText?)`

## MCP Usage Example

The secret store is meant to stay outside MCP. Each MCP server only gets a secret name, not the secret itself.

Confluence example:

```toml
[mcp_servers.confluence-client]
command = "npx"
args = ["-y", "@lvasko/confluence-rw-mcp@latest"]

[mcp_servers.confluence-client.env]
CONFU_BASE_URL = "https://confluence.client.local"
CONFU_DEPLOYMENT_TYPE = "ON_PREM"
CONFU_CERT_PATH = "C:\\certs\\client-ca.crt"
CONFU_ALLOWED_READ_PAGE_IDS = '["123456","234567"]'
CONFU_ALLOWED_WRITE_PAGE_IDS = '["345678"]'
CONFU_PAT_SECRET_NAME = "confluence-client-a-pat"
```

Jira and Tempo example:

```toml
[mcp_servers.jira-client.env]
JIRA_BASE_URL = "https://jira.client.local"
JIRA_TOKEN_SECRET_NAME = "jira-prod-pat"

[mcp_servers.tempo-client.env]
TEMPO_BASE_URL = "https://tempo.client.local"
TEMPO_TOKEN_SECRET_NAME = "tempo-prod-token"
```

The MCP server resolves the secret at runtime:

```js
import { readSecret } from "@lvasko/local-secret-store";

const token = await readSecret(process.env.JIRA_TOKEN_SECRET_NAME);
```

## Security Notes

- Do not store raw secrets in Codex config files.
- Do not log the raw secret value.
- The secret file is protected for the current Windows user, but any code running under the same user can still read it.
- `--clear-clipboard` is the safest clipboard option after setup. `--replace-clipboard` is useful if you want a visible reminder instead of an empty clipboard.