SOURCE_URL: https://majikah.solutions/products/majik-signature/docs/mjksig-cli-mcp
---
title: "Majik Signature CLI (mjksig) & MCP Server (mjksig-mcp)"
id: "mjksig-cli-mcp"
group: "majik-signature"
type: "products"
version: "0.15.0"
lastUpdated: "2026-09-24T00:00:00.000Z"
difficulty: "Intermediate"
time: "15 minutes"
tags: [majik-signature, cli, mcp, model-context-protocol, automation, ci-cd, trusted-timestamps, batch-signing, ai-agents, key-management, contact-management, manifest-signing, detached-signatures, windows]
---
# Majik Signature CLI (mjksig) & MCP Server (mjksig-mcp)
> This guide covers installation (none required — both ship bundled with the app), every mjksig CLI command and flag — including detached signatures, folder/manifest signing and cosigning, expiring signatures, and signing-order verification — key and contact management, batch signing behavior, the mjksig-mcp MCP server's full tool set, exact configuration snippets for Claude Desktop, Cursor, VS Code (Copilot), Windsurf, and Codex CLI, and the underlying security/trust model.
## Overview
mjksig and mjksig-mcp let scripts, CI pipelines, and AI agents request signing, sealing, verification, folder-manifest, key management, contact management, and Trusted Timestamp actions from Majik Signature — without ever giving them your private key. Both tools relay requests over a local named pipe to the desktop app, which still requires your explicit, in-app approval before anything is actually signed, sealed, or changed, and private key export remains a CLI-only, interactive-only operation with no MCP equivalent.
### What This Is
mjksig is a command-line interface for Majik Signature, and mjksig-mcp is a Model Context Protocol server that exposes the same capabilities as callable tools for AI agents (Claude Desktop, Cursor, VS Code, Windsurf, Codex CLI, and any other MCP-compatible client). Both are bundled automatically with the Microsoft Store build of Majik Signature — there is nothing separate to install. As of v0.15.0, both remain Windows-only.
> **NOTE:** If you already have Majik Signature installed from the Microsoft Store, mjksig and mjksig-mcp are already on your PATH. Neither requires the app to be open ahead of time — the app launches automatically (hidden, in the background) the first time a command needs it.
### The Trust Model
Automation reaches the request, never the key. Both tools talk to the already-running (or auto-launched) Majik Signature desktop app over a local named pipe (\\.\pipe\majik-signature-cli on Windows). Only the desktop app process ever touches your decrypted signing keys. When a request would actually produce a signature, seal, or account change, the app brings its own window to the front so any unlock prompt, passphrase entry, or Credential Store dialog happens somewhere you can see and approve it — the same way a manual, in-app signature works today.
### Which Actions Require Approval
| Action | Approval Required? | Why |
| --- | --- | --- |
| sign / sign_file | Yes | Produces a new signature — key material is used. Applies whether signing a single file, a detached sidecar, or a folder manifest. |
| seal / seal_file | Yes | Locks the file and applies a seal signature |
| verify / verify_file | No | Read-only — checks existing embedded, detached, or manifest signatures |
| can-sign / can_sign | No | Read-only — allowlist/seal permission check |
| tsa-quota / tsa_quota | No | Read-only — reads your credit balance |
| key --list / --get / --card, key_list / key_get / key_card | No | Read-only — public account metadata and shareable invite-key cards only |
| key --unlock, key_unlock | Yes (passphrase prompt) | Requires the account's passphrase, entered live in the app |
| key --lock / --set, key_lock / key_set_active | Minimal / none | Idempotent state changes; may prompt for unlock if the target account is currently locked |
| key create / key import / key delete | Yes | Creates, restores, or permanently removes key material — interactive confirmation required; not exposed via MCP |
| key --dangerous | Yes (CLI-only) | Exports raw private key material in plaintext. Interactive terminal and typed fingerprint confirmation required. Never reachable via MCP. |
| contact --list / --get / --card / --invite-key, contact_get / contact_card / contact_invite_key | No | Read-only — public contact metadata and invite keys only |
| contact-rename / contact-import, contact_rename / contact_import_invite / contact_import_card | No | Modifies your local contact list only; imports public material |
| contact-delete | Yes (typed confirmation) | Permanently removes a saved contact; requires typing the fingerprint to confirm |
> ⚠️ **WARNING:** No script, pipeline, or AI agent can ever complete a signature, account change, or private key export without you approving it live in the app or terminal. If you see an unexpected unlock prompt appear, you can always decline it — declining causes the CLI or MCP call to fail cleanly rather than silently succeed.
### The CLI: mjksig
mjksig exposes signing subcommands (sign, seal, verify, can-sign, tsa-quota) alongside key and contact management subcommands (key, key create, key import, key delete, contact, contact-rename, contact-delete, contact-import). Run mjksig --help or mjksig --help at any time for the full flag reference.
### mjksig Subcommands
| Command | Purpose | Approval |
| --- | --- | --- |
| sign | Sign a file, folder, or archive — supports --detached, --as-map/--cosign-map, --bundle, --valid-until | Required |
| seal | Seal an already-signed file | Required |
| verify | Verify embedded, detached, or manifest signature(s) — supports --order/--strict | None |
| can-sign | Preflight allowlist/seal permission check | None |
| tsa-quota | Show remaining Trusted Timestamp credits | None |
| key | Inspect or manage Majik Key accounts (--list, --active/--id, --unlock, --lock, --set, --card, --dangerous) | Varies — see approval matrix |
| key create | Create a new account from a typed or generated recovery phrase | Required |
| key import | Restore an account from a mnemonic backup file | Required |
| key delete --id | Permanently remove an account and its key material | Required (typed confirmation) |
| contact | Inspect or manage saved contacts (--list, --id, --card, --invite-key) | None |
| contact-rename / contact-delete / contact-import | Rename, remove, or add a saved contact | None / typed confirmation for delete |
### Using: mjksig sign
1. **Basic signature**
*Signs with your active Majik Key*
- mjksig sign report.pdf
2. **Custom output path**
*-o / --output*
- mjksig sign report.pdf -o ./out/report-signed.pdf
3. **Sign with a specific account**
*-a / --account*
- mjksig sign report.pdf --account
4. **Seal immediately after signing**
*--seal locks the file against further signers*
- mjksig sign report.pdf --seal
5. **Request a Trusted Timestamp**
*--tsa uses a TSA timestamp instead of a local one (consumes TSA quota)*
- mjksig sign report.pdf --tsa
6. **Combine flags in one call**
*Sign, timestamp, and seal in a single step*
- mjksig sign report.pdf --tsa --seal
7. **Name expected co-signers**
*--signers accepts a comma-delimited list for a multi-party envelope*
- mjksig sign contract.pdf --signers ,
### Example: sign, timestamp, and seal in one command
```bash
mjksig sign report.pdf --tsa --seal
```
### Using: mjksig sign — Detached, Manifest, and Expiring Signatures
1. **Produce a detached signature**
*--detached writes a separate .mjksig sidecar instead of embedding into the original file. Combine with --seal to lock the detached envelope against further co-signers.*
- mjksig sign report.pdf --detached --seal
2. **Sign a whole folder as one manifest**
*--as-map treats the folder as one logical signing subject and produces a .mjksmap manifest; you become the first signer. Mutually exclusive with --cosign-map.*
- mjksig sign ./contracts --as-map
3. **Cosign an existing manifest**
*--cosign-map adds your signature to an existing .mjksmap instead of starting a new one.*
- mjksig sign ./contracts --cosign-map ./contracts/signatures.mjksmap
4. **Bundle a manifest with its files**
*--bundle (with --as-map or --cosign-map) also produces a .zip containing the original files plus the .mjksmap.*
- mjksig sign ./contracts --as-map --bundle
5. **Set a signature expiration**
*--valid-until (ISO 8601) applies the same expiration to every signature produced in the run.*
- mjksig sign contract.pdf --valid-until 2027-01-01T00:00:00Z
> **NOTE:** A signature's expiration (--valid-until) makes an expired status visible the next time the file is verified — it does not technically lock the file or prevent it from being opened or used. Treat it as a freshness signal your workflow can check for, not an access control.
> **NOTE:** --as-map and --detached cannot be combined — a manifest is already a detached format by nature. --as-map and --cosign-map are also mutually exclusive: a folder-signing run either establishes a new manifest or cosigns an existing one, not both.
### Using: mjksig verify
1. **Verify against the embedded signature (default)**
*--against self — trust-on-first-use*
- mjksig verify incoming/file.pdf
2. **Verify against your own account**
*--against account*
- mjksig verify incoming/file.pdf --against account --account
3. **Verify against a saved contact**
*--against contact requires --contact*
- mjksig verify incoming/vendor-invoice.pdf --against contact --contact
> **NOTE:** verify is read-only and never triggers an approval prompt, regardless of which client (CLI or MCP) is calling it.
### Using: mjksig verify — Detached, Manifest, and Signing Order
1. **Verify a detached signature**
*--detached checks the original file against a separate .mjksig sidecar instead of an embedded signature.*
- mjksig verify report.pdf --detached report.pdf.mjksig
2. **Verify a folder against a manifest**
*--map checks every file in a folder against an existing .mjksmap. A .zip archive containing its own .mjksmap at the root is detected and verified automatically, without --map.*
- mjksig verify ./contracts --map ./contracts/signatures.mjksmap
3. **Require a specific signing order**
*--order (comma-delimited contact IDs and/or fingerprints) checks that signing happened in that sequence.*
- mjksig verify report.pdf --order alice,bob,carol
4. **Reject signers outside the expected order**
*--strict (used with --order) also fails verification if anyone outside the given order signed the file.*
- mjksig verify report.pdf --order alice,bob,carol --strict
> **NOTE:** --detached and --map cannot be combined on a verify call — pick one verification source.
### Preflight permission check before a batch job
```bash
mjksig can-sign contract.pdf --account
```
can-sign runs the exact same allowlist and sealing check that sign performs automatically before producing a signature. It just exposes that check on its own, as a read-only command — useful before a large batch job so a permission problem fails fast instead of surfacing mid-batch. sign will still stop cleanly on its own if permission is denied, with or without running can-sign first.
### Check remaining Trusted Timestamp credits
```bash
mjksig tsa-quota
```
tsa-quota prints your free daily remaining credits, free daily limit, paid credit balance, total available, and when your free allowance next resets — shown as human-readable relative time (e.g. "resets in 6 hours") rather than a raw ISO timestamp.
### Key Management: mjksig key
mjksig key inspects and manages Majik Key accounts. mjksig key create, mjksig key import, and mjksig key delete handle account lifecycle separately.
### Using: mjksig key
1. **List all accounts**
*--list*
- mjksig key --list
2. **Get info on the active account**
*--active*
- mjksig key --active
3. **Get info on a specific account**
*--id *
- mjksig key --id
4. **Unlock an account**
*--active --unlock (prompts for passphrase)*
- mjksig key --active --unlock
5. **Make an account active**
*--id --set*
- mjksig key --id --set
6. **Export a shareable contact card**
*--active --card [path] — a PNG encoding your public invite key; no private material. Defaults to the Downloads folder if no path is given.*
- mjksig key --active --card
### Using: mjksig key create / import / delete
1. **Generate a brand-new account**
*--generate creates a phrase locally, shows it once, and requires typing back 3 random words as a write-it-down safety check. --strength 128 (12 words) or 256 (24 words); language defaults to English.*
- mjksig key create --generate --strength 256 --label "Main Account"
2. **Create from a phrase you already have**
*Single masked-line entry (12 or 24 words)*
- mjksig key create --label "Recovered Account"
3. **Enter a phrase word-by-word**
*--word-by-word, one masked prompt per word*
- mjksig key create --word-by-word --strength 256
4. **Import from a backup file**
*Accepts a .json or .png backup*
- mjksig key import ./backup.json
5. **Import using an embedded passphrase**
*--use-embedded-passphrase skips the passphrase prompt*
- mjksig key import ./backup.json --use-embedded-passphrase
6. **Permanently delete an account**
*Requires typing the last 8 characters of the fingerprint to confirm; refuses to run non-interactively; cannot delete the active account.*
- mjksig key delete --id
> ⚠️ **WARNING:** mjksig key --dangerous --i-understand-the-risk exports an account's raw private key material as plaintext JSON. It requires an interactive terminal, typing the account's fingerprint to confirm, and an explicit y/N prompt before printing (and again before optionally writing to disk with --output). This is the only operation in the entire CLI/MCP surface that touches unencrypted key material directly, and it is not — and will not be — exposed as an MCP tool.
### Contact Management: mjksig contact
mjksig contact mirrors the key commands for people you've saved as trusted signers — every value here is public material (fingerprints, labels, invite keys), never anything private.
### Using: mjksig contact
1. **List all saved contacts**
*--list*
- mjksig contact --list
2. **Get info on a specific contact**
*--id *
- mjksig contact --id
3. **Export a contact's shareable card**
*--id --card [path]*
- mjksig contact --id --card
4. **Get a contact's invite key as text**
*--id --invite-key (also copies to clipboard)*
- mjksig contact --id --invite-key
5. **Rename a contact**
*contact-rename*
- mjksig contact-rename --id --label "Legal Team"
6. **Delete a contact**
*contact-delete — requires typing the last 8 characters of the fingerprint to confirm*
- mjksig contact-delete --id
7. **Import a contact from an invite key**
*contact-import --invite-key*
- mjksig contact-import --invite-key
8. **Import a contact from a card file**
*contact-import --card*
- mjksig contact-import --card ./their-card.png
### Batch Signing & Progress Streaming
Point sign or verify at a folder or archive instead of a single file, and mjksig streams live progress from the app as each file completes — a spinner, an elapsed-time counter, and a progress bar, updated per file rather than only at the end. When the batch finishes, the CLI prints a summary table (total files, signed/processed count, error count) followed by a per-file status table: green for success, yellow for anything flagged unknown or unsigned, red for errors.
> **NOTE:** TSA-related fields — the Trusted Timestamp line and TSA authority — render in Majikah's brand accent color in the terminal output, matching the amber used across the rest of the ecosystem.
> **NOTE:** Manifest verification (--map) reports through the same batch summary format. If the manifest lists files that weren't actually provided in the folder, the summary calls out how many are missing and names them.
### The MCP Server: mjksig-mcp
The Model Context Protocol (MCP) is an open standard that lets AI agents call external tools directly with structured arguments, rather than a person copy-pasting commands for an agent to run. mjksig-mcp implements an MCP server over stdio. It launched with five tools mapping onto the original CLI commands, and has since grown to include full key and contact management. Every tool routes through the same named-pipe bridge and approval flow as the CLI — an agent gets no more direct access to your key than a terminal command does.
### Available MCP Tools — Signing
| Tool | Maps To | Description | Approval |
| --- | --- | --- | --- |
| sign_file | mjksig sign | Sign a file, folder, or archive. Supports seal_after_sign, use_tsa, detached, as_map/cosign_map_path, bundle, and valid_until in one call. | Required |
| seal_file | mjksig seal | Seal an already-signed file. | Required |
| verify_file | mjksig verify | Verify embedded, detached, or manifest signature(s), optionally against a specific signing order (expected_order, strict_order). | None |
| can_sign | mjksig can-sign | Check allowlist/seal permission ahead of time. | None |
| tsa_quota | mjksig tsa-quota | Check remaining Trusted Timestamp credits. | None |
### Available MCP Tools — Key & Contact Management
| Tool | Maps To | Description | Approval |
| --- | --- | --- | --- |
| key_list / key_get | mjksig key --list / --id | List all accounts, or get one account's fingerprint, label, and active/locked status. No private material. | None |
| key_unlock | mjksig key --unlock | Unlock an account. Prompts for a passphrase in the app. | Yes (passphrase prompt) |
| key_lock | mjksig key --lock | Lock an account. | None / idempotent |
| key_set_active | mjksig key --set | Make an account the active signing account. | Minimal — may prompt for unlock |
| key_card | mjksig key --card | Export an account's contact card as a PNG (public invite key only). | None |
| contact_get | mjksig contact --id | Get info about a saved contact. | None |
| contact_card | mjksig contact --card | Export a contact's card as a PNG. | None |
| contact_invite_key | mjksig contact --invite-key | Get a contact's invite key as text. | None |
| contact_rename | mjksig contact-rename | Rename a saved contact's label. | None |
| contact_import_invite | mjksig contact-import --invite-key | Import a contact from an invite key string. | None |
| contact_import_card | mjksig contact-import --card | Import a contact from a .png contact card file on disk. | None |
> ⚠️ **WARNING:** There is no dangerous_export, key_export, or equivalent MCP tool, and there won't be. Every key/contact tool above deals strictly in public, shareable material — fingerprints, labels, invite keys, lock status. Raw private key export (mjksig key --dangerous) stays a CLI-only, interactive-terminal-only, explicitly-confirmed operation with no MCP path.
> **NOTE:** Tool descriptions are written specifically so an agent combines flags correctly in a single call. A request like "sign and seal this with a TSA timestamp" should become one sign_file call with both seal_after_sign=true and use_tsa=true set — not a sign_file call followed by a separate seal_file call. The same applies to the newer folder/expiry options: "sign this folder as a manifest and bundle it, expiring at year end" becomes one sign_file call with as_map=true, bundle=true, and a computed valid_until date.
Every tool call returns two content blocks: a markdown table for a human reading the chat, and a structured JSON object for anything downstream that needs to parse the result programmatically. The JSON is enriched with human-readable _relative sibling fields next to every ISO timestamp (resets_at becomes resets_at_relative: "in 6 hours", for example); the original ISO fields are left untouched for exact-time parsing.
### Setting Up MCP in Your Client
Every client points at the same command, mjksig-mcp — nothing to build, no arguments required. Add the relevant snippet below to your client's config file. All paths shown are for Windows, since mjksig-mcp currently ships Windows-only.
### Client Configuration
1. **Claude Desktop**
*%APPDATA%\Claude\claude_desktop_config.json*
- { "mcpServers": { "majik-signature": { "command": "mjksig-mcp" } } }
2. **Cursor**
*%USERPROFILE%\.cursor\mcp.json — same format as Claude Desktop. A project-level .cursor/mcp.json in your repo root works too and takes priority over the global file.*
- { "mcpServers": { "majik-signature": { "command": "mjksig-mcp" } } }
3. **VS Code (GitHub Copilot)**
*.vscode\mcp.json — the root key is servers, not mcpServers, and each entry needs an explicit "type": "stdio" field. The server only loads while Copilot Chat is in Agent mode.*
- { "servers": { "majik-signature": { "type": "stdio", "command": "mjksig-mcp" } } }
4. **Windsurf**
*%USERPROFILE%\.codeium\windsurf\mcp_config.json — same format as Claude Desktop and Cursor. Restart Windsurf fully after saving; it does not hot-reload this file.*
- { "mcpServers": { "majik-signature": { "command": "mjksig-mcp" } } }
5. **Codex CLI**
*%USERPROFILE%\.codex\config.toml — TOML, not JSON, and the table name is snake_case: mcp_servers, not mcpServers.*
- [mcp_servers.majik-signature]
command = "mjksig-mcp"
### Claude Desktop config
```json
{
"mcpServers": {
"majik-signature": {
"command": "mjksig-mcp"
}
}
}
```
### VS Code (Copilot) config
```json
{
"servers": {
"majik-signature": {
"type": "stdio",
"command": "mjksig-mcp"
}
}
}
```
### Codex CLI config
```toml
[mcp_servers.majik-signature]
command = "mjksig-mcp"
```
> **NOTE:** You don't need Majik Signature open before using mjksig or mjksig-mcp — if it isn't already running, both launch it automatically the first time a command needs it.
### Real-World Workflows
- Client handoff — sign and seal an entire delivery folder in one command: mjksig sign ./final_delivery --tsa --seal
- Inbound file trust — verify a vendor or contractor's file against a known contact before trusting it downstream: mjksig verify incoming/file.pdf --against contact --contact
- Preflight for large batches — check permission before a co-signing run touches 200 files: mjksig can-sign contract.pdf --account
- Quota-aware automation — run mjksig tsa-quota before a batch job that would use more Trusted Timestamps than you have free credits for
- Agent-driven signing — ask an agent in Claude Desktop or Cursor to "sign and seal this render with a trusted timestamp"; the agent calls sign_file once with both flags set, Majik Signature surfaces itself for approval, you approve once, done
- Approved resource library — sign a whole approved asset folder once as a manifest (mjksig sign ./approved-assets --as-map), then verify the entire folder against that manifest before an agent or pipeline touches anything in it: mjksig verify ./approved-assets --map ./approved-assets/signatures.mjksmap
- Multi-stage approval chain — require a contract to be signed by Legal and then Finance, in that order, before it counts as approved: mjksig verify contract.pdf --order legal,finance --strict
- Building a trusted-signer roster — import a new vendor or teammate's public invite key as a contact (mjksig contact-import --invite-key ), then reference that contact by name in every future verification, via the CLI or through an agent using contact_import_invite
### FAQ: Does the AI agent get access to my private key?
No. An agent using mjksig-mcp can request that something be signed, or manage keys and contacts by their public metadata — it never receives, handles, or has any path to your decrypted private key. Only the Majik Signature desktop app process ever holds that, and only after you've unlocked your account there.
### FAQ: Can an agent export my private key material through MCP?
No. The dangerous export flow (mjksig key --dangerous --i-understand-the-risk) is CLI-only, requires an interactive terminal and a typed fingerprint confirmation, and has no MCP-tool equivalent. It was deliberately left off the MCP surface.
### FAQ: What happens if I run a command while the app is closed?
Majik Signature launches automatically. You don't need to have it open ahead of time for mjksig or mjksig-mcp to work.
### FAQ: Is mjksig available for macOS or Linux?
Not yet. As of v0.15.0, this remains Windows-only, bundled with the Microsoft Store build of Majik Signature.
### FAQ: Is can-sign's check different from what happens during a real sign?
No — it's the identical allowlist and sealing check that sign runs automatically by default before producing any signature. can-sign just exposes that same check as its own read-only command, so you can confirm permission ahead of time without attempting a real signature.
### FAQ: If a signature expires, does the file get locked or become unusable?
No. An expiration set with --valid-until makes the expired status visible the next time someone verifies the file — it doesn't technically prevent anyone from opening, using, or acting on the file itself.
### FAQ: Should I sign a folder as a manifest, or sign each file individually?
If the folder is meant to be trusted as one unit — a delivery, an approved asset library — --as-map signs it once as a manifest, and --map verification confirms every file present is part of that approved set. If files need to travel or be trusted independently of each other, sign them individually instead.
### Key Takeaways
- mjksig (CLI) and mjksig-mcp (MCP server) both ship bundled with the Microsoft Store build of Majik Signature — nothing to install separately, Windows-only for now.
- Both talk to the already-running (or auto-launched) desktop app over a local named pipe. The private key never leaves the app's process, and any action that creates a signature, seal, or account change requires explicit in-app approval.
- Read-only operations (verify, can-sign, tsa-quota, and key/contact lookups) skip approval entirely, since nothing is being created or changed.
- As of v0.15.0: detached signatures, whole-folder .mjksmap manifest signing and cosigning with optional .zip bundling, expiring signatures, multi-signer signing-order verification, and full key and contact management are available through both the CLI and MCP.
- Private key export remains a CLI-only, interactive, explicitly-confirmed operation with no MCP equivalent — every key/contact MCP tool deals strictly in public, shareable material.
- The CLI streams live batch progress and prints color-coded status tables; the MCP server returns both a markdown table and machine-parseable JSON with relative-time fields.
- MCP tool descriptions are written so an agent combines flags correctly in one call — "sign and seal with a TSA timestamp" becomes a single sign_file call, not several.
- can-sign / can_sign exposes the exact same permission check sign performs automatically — a way to confirm permission ahead of time, not a separate rule set.