Skip to main content
Glama
zeroai-tech

handshake-mcp

by zeroai-tech

Handshake

An encrypted credential vault for people who work with AI agents.

An agent can use a credential. Only a person can unlock the vault.

curl -fsSL https://raw.githubusercontent.com/zeroai-tech/handshake/main/install.sh | bash
handshake setup

Then, from anywhere:

handshake unlock                                  # passphrase + code from your phone
handshake run -e OPENAI_API_KEY -- claude         # key exists only inside that process
handshake log                                     # what was read, when, and why

Why this exists

Agent CLIs inherit your shell environment. That is the whole problem in one sentence.

When you run Claude Code, Codex, Gemini CLI, Aider, or any tool that executes code on your behalf, it starts with a copy of everything you have exported. Your OPENAI_API_KEY is there. So is the AWS key you exported in 2023 and forgot, the production database URL, and the Stripe secret. A .env file is no better: it is one cat away from any process allowed to read your project directory, which is exactly the permission you granted when you let an agent edit your code.

The usual fix is a cloud secret manager. It solves a real problem — durability, rotation, team access — but for this particular threat it mostly moves the credential. You now hold a long-lived token that fetches every secret, and that token sits in the same environment, readable by the same processes.

Handshake takes a narrower position: the open state should be deliberate, brief, and visible.

  • Credentials sit encrypted in a database you control. The host cannot read them. Neither can anyone who steals the token used to reach the host.

  • Opening the vault needs a passphrase and a code from your phone. The passphrase can be remembered by your OS keychain; the six-digit code cannot be remembered by anything, which is precisely the point — a human is in the loop at least once per session.

  • Unlocking produces a session token that expires and is pinned to your network. Agents spend that token. They cannot mint one.

  • Every read is appended to a log with the reason the caller gave. Afterwards you can answer the question that actually matters: what did that agent touch?

It was built in one sitting because the author was about to wipe a laptop that held the only copy of every credential for a working company. That deadline shaped two decisions worth naming: recovery is taken as seriously as encryption, and the tool must run on a machine with nothing installed on it.


Related MCP server: onepassword-mcp-server

Install

One command. It installs into ~/.handshake/app, keeps its own Python environment so nothing touches your system, puts handshake on your PATH, and registers itself with any agent CLI you have.

curl -fsSL https://raw.githubusercontent.com/zeroai-tech/handshake/main/install.sh | bash

Re-run it any time to update.

git clone https://github.com/zeroai-tech/handshake.git ~/.handshake/app
cd ~/.handshake/app
python3 -m venv .venv && ./.venv/bin/pip install -e .
ln -s ~/.handshake/app/bin/handshake ~/.local/bin/handshake
handshake agents          # register with your agent CLIs

Set it up

handshake setup

That is the whole thing. It takes about a minute and walks through three steps:

  1. Where the vault lives. Pick a backend from the list. If you are not sure, choose Cloudflare D1 — the free tier is ample and it survives your laptop. SQLite is fine for trying it out.

  2. Create the vault. You choose a passphrase, then a QR code appears in your terminal. Scan it with Google Authenticator, 1Password, Aegis, Raivo — any TOTP app. Type the 6-digit code back. Nothing is created until that code checks out, so you cannot end up with a vault whose 2FA does not work.

  3. Wire up your agents. It finds Claude Code, Codex, Gemini CLI, Cursor and Windsurf and registers the MCP server with whichever are present.

Then it prints a recovery card: three recovery shares plus the address of your vault. Photograph it or print it before you close the window — the shares are generated once and stored nowhere, by anyone, including us.

The shares are not a backup code — they are the vault. Any two of them rebuild your master key with no passphrase and no authenticator. Get them off the machine (a photo, paper, a printer) and keep the three apart. Never paste that screen anywhere: not into a chat or an AI assistant, not a note in your password manager, not a support ticket. Anywhere it lands, someone owns your vault. Setup makes you confirm you have saved them before it continues.

If they ever do leak and the vault is still empty or small, the fix is quick: handshake init --force mints a fresh key and fresh shares.

Why can't this be fully automated? Because the point of the tool is that a machine cannot open your vault alone. The passphrase has to come out of your head and the code has to come off your phone. If a script could do it, so could anything else running on your machine.

Adding credentials

put adds a new credential, and updates one that already exists — the same command either way, so re-running is always safe.

handshake unlock                                    # start a session first
export HANDSHAKE_SESSION=<the token it prints>      # saves typing -s every time

handshake put openai/api-key                        # prompts, so it stays out of history
handshake put openai/api-key --value sk-...         # or pass it directly
handshake put db/prod-url --category prod --note "read replica"
cat key.pem | handshake put ssh/deploy-key --value -   # a whole file

Names are yours to choose. A category/name shape (prod/stripe, dev/openai) keeps handshake list readable once you have thirty of them, but nothing enforces it.

Bring a whole .env file in at once:

handshake import-env .env
handshake import-env .env.production --prefix prod/ --category prod
handshake import-env .env --skip-existing            # only add what is missing

It ignores comments and blank lines, handles export FOO=bar, and strips quotes the way a shell would. Once it is in the vault, delete the file.

Bringing in an existing vault from another backend — see Storage backends — is handshake export then handshake import.

Everyday use

handshake list                          # names and notes, never values
handshake get openai/api-key            # print one value
handshake get openai/api-key --reason "deploying the worker"
handshake rm old/key                    # asks first; -y to skip
handshake log                           # who read what, when, and why
handshake status                        # is anything open?
handshake lock                          # close the session now

Prefer run over get whenever you are launching something. The value goes into that one process and nowhere else — not your shell history, not your scrollback, not your environment:

handshake run -e OPENAI_API_KEY -- claude
handshake run -e OPENAI_API_KEY -e ANTHROPIC_API_KEY -- aider
handshake run -e DATABASE_URL=prod/postgres -- ./migrate.sh

Use VAR=secret-name when the environment variable is not named the same as the secret.

Sessions

A session lasts 30 minutes by default, then everything locks again.

handshake unlock --ttl 7200      # two hours instead
handshake unlock --remember      # save the passphrase to your OS keychain
handshake forget                 # stop saving it

--remember puts the passphrase in the macOS Keychain or your Linux secret service — never in a file, never encoded in a config. The 6-digit code is still required every time, which is what makes saving the passphrase safe: on its own it opens nothing.

Housekeeping

handshake passwd                 # change the passphrase; secrets are untouched
handshake recover                # lost the passphrase or the phone? use two shares
handshake export --out backup.json   # encrypted backup, safe to store anywhere
handshake agents                 # re-register with agent CLIs after installing one

passwd re-wraps the small per-secret keys rather than re-encrypting your data, so it is quick and cannot corrupt a value even if it is interrupted. Your authenticator code is unchanged by it.

Using it with an agent

bin/handshake-mcp.mjs is an MCP server exposing status, list, get, put and log.

It has no unlock tool. Not disabled, not permission-gated — absent. There is no way to pass a passphrase or a code through it. An agent can spend a session you opened; it can never open one. That asymmetry is the security model, so it is enforced by what the interface does not contain rather than by a check someone can be talked out of.

handshake setup registers it automatically with Claude Code, Codex, Gemini CLI, Cursor and Windsurf. Run handshake agents again after installing a new one. Anything else that speaks MCP over stdio can point at ~/.handshake/app/bin/handshake-mcp.mjs; for agents that speak no MCP at all, handshake run covers the same ground with no integration whatsoever.

A workflow that keeps the blast radius small:

  1. You run handshake unlock in a terminal and paste the token into the chat.

  2. The agent calls handshake_get with a stated reason when it needs something.

  3. You run handshake lock when the task is done, or let the TTL do it.

  4. handshake log afterwards shows exactly what was touched.


Threat model

Security tools that do not say what they don't protect against are marketing. Here is the honest table.

Someone who has

Can they read your secrets?

Your database (D1/Supabase/Postgres dump)

No. Ciphertext only. The key was never sent there.

The hosting API token

No. They can delete or corrupt the vault; they cannot decrypt it.

Your laptop, powered off

No. No plaintext at rest, no key file.

Your laptop, while a session is open

Yes, if they also have the session token. It is in the terminal that opened it.

A session token, used from another network

No. The binding refuses it.

Your passphrase, and nothing else

No. They still need a code from your phone.

Your phone, and nothing else

No. They still need the passphrase.

Your passphrase and your phone

Yes. That is what being you means.

Two of your three recovery shares

Yes. Store them apart, in different places.

One recovery share

No — mathematically, not merely in practice.

Root on your machine while unlocked

Yes. Nothing in userspace survives this. Not a solvable problem here.

What Handshake does not do. It does not stop a malicious agent from exfiltrating a credential you deliberately handed it — once a secret is in a process's environment, that process has it. What it does is make the window short, the scope explicit, and the access recorded, so the damage is bounded and the forensics exist. Treat handshake run -e ONE_KEY as the norm and --session sprayed across a long chat as the thing to avoid.

It also does not protect against you choosing "password123". The KDF is tuned to make guessing expensive, not free.


How it is built

Key hierarchy

passphrase ──scrypt(N=2^18, r=8, p=1)──▶ KEK          derived on use, stored nowhere
                                          │
                                          ├─AES-256-GCM─▶ wraps DEK₁ ─▶ encrypts secret 1
                                          ├─AES-256-GCM─▶ wraps DEK₂ ─▶ encrypts secret 2
                                          └─AES-256-GCM─▶ wraps DEK₃ ─▶ encrypts secret 3

Envelope encryption, one data key per secret. Compromising a single plaintext tells an attacker nothing about the others, and changing your passphrase re-wraps n small keys instead of re-encrypting n secrets — so passwd is fast and cannot corrupt a value even if it dies halfway.

Each secret's name is bound in as AES-GCM additional authenticated data. A wrapped key lifted from staging/db and pasted over prod/db fails to authenticate rather than quietly decrypting. There is a test for this, because it is the kind of thing that silently stops being true during a refactor.

scrypt at N=2¹⁸ costs about 0.9 seconds and ~256 MB per attempt on a current laptop. That is unnoticeable when you unlock once a session, and it caps an offline attacker at roughly four thousand guesses an hour per core. scrypt rather than Argon2id for one reason: it is in Python's standard library. argon2-cffi wants a compiler, and a recovery tool that cannot be installed on a freshly wiped machine is worse than no recovery tool. That is a real trade — Argon2id is the better primitive — and it is made deliberately.

The passphrase is verified without being stored. The vault holds HMAC-SHA256(KEK, "handshake-verifier-v1" || salt). Reversing it means breaking HMAC; guessing it means paying the scrypt cost per attempt.

Sessions

unlock prints a token exactly once. What is written to disk is its SHA-256, plus the KEK sealed under SHA-256("session-key:" || token). Without the token the session file is inert — a stolen laptop yields nothing unless the thief also has the token out of your terminal scrollback.

Three conditions must all hold for a session to be spendable: the token matches, it has not expired (30 minutes by default), and you are still on the same network. Fail any one and you authenticate again.

"Same network" means the same /24, or the same /64 on IPv6 — not the same address. Large egress pools hand out a different address per connection, and CGNAT, corporate proxies, mobile carriers and CI runners all do it; comparing exact addresses logs people out while they sit perfectly still. We found this the honest way, by watching a macOS CI runner move from …117.183 to …117.182 between two calls and kill its own session. The prefix keeps the property that matters — a token replayed from another network is refused — without the false positives. handshake unlock --strict-ip restores exact matching if you are on a fixed address and want it.

The binding is best-effort in one further respect: if the public IP cannot be determined at all, the session is simply not network-bound rather than refusing to work on a train.

Recovery

init prints three Shamir shares over GF(256) with a threshold of two. Any two rebuild the KEK; any one reveals nothing — not "not much", nothing, as a property of the polynomial. They are generated once and stored nowhere.

The shares rebuild the key, not the address. On a wiped machine you need both, so init prints the backend connection details on the same card. Print it. That card is the entire disaster-recovery plan.

Audit log

Append-only: timestamp, action, secret name, IP, success, and the reason the caller supplied. list deliberately returns metadata only and never ciphertext, so listing cannot be turned into bulk extraction.


Storage backends

The vault is portable across all four. handshake export emits the ciphertext as-is — no key needed, nothing decrypted — and handshake import loads it elsewhere.

Backend

Setup

Needs a driver?

Use it when

sqlite

none

no

Trying it out; air-gapped; the disk is already backed up

d1

Cloudflare account

no (HTTPS)

Recommended. Free tier is ample; reachable from a bare machine

supabase

paste one SQL block

no (PostgREST)

You already run Supabase

postgres

a database

yes (psycopg)

Neon, RDS, self-hosted, or Supabase's direct connection

handshake connect                 # interactive picker
handshake connect --backend d1    # or name it

Two notes that matter.

Supabase: use the service-role key, not the anon key, and run handshake setup-sql to get DDL that enables Row Level Security with no policies. That denies anon and authenticated everything while service-role (which bypasses RLS by design) keeps working. Without it, anyone holding your project's public anon key can list your ciphertext. They still cannot decrypt it, but there is no reason to publish it.

Every backend's connection credential is the one secret that cannot live in the vault it opens. That is not a flaw in this design; it is true of every system of this shape. Keep it on the recovery card.


Development

./.venv/bin/python tests/test_vault.py     # unit: crypto, Shamir, TOTP, backends
./.venv/bin/python tests/e2e.py            # full CLI through a pty, incl. failure paths

The e2e suite asserts the negatives as hard as the positives: a forged token is refused, a wrong code is refused, list never emits a value, an export contains no plaintext, and a lock actually ends the session.

Contributions welcome — see CONTRIBUTING.md. If you are adding a backend, note that the interface in hsvault/backends/base.py is a repository, not a SQL passthrough. That is intentional: eleven methods can be audited for leaks; query(sql) cannot.


Security reporting

Please use GitHub's private vulnerability reporting rather than a public issue. See SECURITY.md.

Handshake has not had a third-party audit. The cryptography is standard constructions from cryptography and the Python standard library, assembled conservatively, and the assembly is what would benefit from review. Read hsvault/crypto.py — it is about 140 lines and it is all there.


Licence

Apache 2.0. See LICENSE.

Built at ZeroAI and released for anyone who has the same problem.

Available Tools

5 tools
handshake_getA

Read ONE credential by name. Requires an open session token. Every read is written to an append-only audit log with the reason given, so always pass a truthful reason.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesexact secret name, from handshake_list
reasonYeswhy it is needed — recorded permanently
sessionYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It discloses a critical non-obvious behavior: every read is written to an append-only audit log with the reason, and warns users to pass a truthful reason. This goes well beyond a simple 'read' and reveals the side-effectful nature of the operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no wasted words. The core action is front-loaded ('Read ONE credential by name'), followed immediately by the prerequisite and the behavioral caveat. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-by-name tool with three required parameters and no output schema, the description covers the essential contextual basis: what it does, the session prerequisite, the audit-log side effect, and how to supply the reason. Combined with the schema's parameter descriptions, an agent has enough information to invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67%: name and reason are described in the schema, but session is not. The description adds important semantics by stating it 'Requires an open session token' and re-emphasizing that the reason is recorded permanently. This compensates for the schema gap on session and reinforces the meaning of reason.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Read ONE credential by name.' The emphasis on 'ONE' clearly distinguishes this from handshake_list, which would be the sibling for reading multiple credentials. This makes the tool's purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for using the tool: read a single named credential, requiring an open session token and a truthful reason because of audit logging. However, it does not explicitly state when not to use this tool or name alternatives like handshake_list for enumeration, leaving some routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

handshake_listA

List the NAMES of stored credentials (never values). Requires an open session token.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionYestoken from `handshake unlock`

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral disclosure burden. It does disclose that values are never returned and that an open session is required, which is useful. It does not address side effects, failure behavior, or whether the operation is strictly read-only, though 'List' strongly implies a read operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that front-loads the core purpose ('List the NAMES of stored credentials') and immediately warns about the critical limitation ('never values'), followed by the required precondition. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter list operation, the description conveys the return content (names only), the security boundary (no values), and the invocation precondition (open session token). It could be improved by describing the error case for an invalid or expired session, but the tool is otherwise adequately specified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the only parameter, session, is already documented as 'token from `handshake unlock`'. The description adds the nuance that the session must be open, but otherwise does not meaningfully extend the schema's parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List') and resource ('stored credentials'), and clarifies the scope to names only, explicitly excluding values. This distinguishes it from sibling tools like handshake_get, which likely retrieves credential values.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear precondition ('Requires an open session token') and the 'never values' caveat implies that value retrieval belongs to another tool. However, it does not explicitly name alternatives such as handshake_get or state when this tool is preferred over handshake_status or handshake_log.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

handshake_logC

Recent access log — who read which credential, when, from where.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
sessionYes

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden, but it only states what the log contains and that it is recent. It does not disclose whether the operation is read-only, how the session filter behaves, whether results are paginated or ordered, or any authentication expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a compact single line that front-loads the purpose and contains no redundant words. However, its brevity contributes to the lack of parameter and usage details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations, no output schema, and 0% parameter description coverage, the description is too sparse for safe invocation. It doesn't explain the required 'session' parameter, the meaning of 'limit', or what the returned log looks like.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description adds no meaning for the two parameters. Neither 'session' nor 'limit' is explained, leaving the agent without a way to know what values are valid or what each parameter controls.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as an access log for credential reads and specifies the content dimensions (who, which credential, when, from where). This distinguishes it from sibling tools like handshake_list and handshake_get, though it lacks an explicit action verb such as 'list' or 'retrieve'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance about when to use handshake_log instead of siblings like handshake_status, handshake_list, handshake_get, or handshake_put. No contexts, exclusions, or prerequisites are mentioned, so the agent must guess the appropriate scenario.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

handshake_putB

Store or update one credential. Requires an open session token.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
noteNo
valueYes
sessionYes
categoryNo

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description carries the full burden of behavioral disclosure. It mentions the session-token requirement and that the operation can create or update, but does not explain overwrite semantics, permissions, return value, or idempotency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no wasted words; the key auth requirement is front-loaded and the operation is described clearly. Might be slightly richer with more behavior detail, but the prose itself is well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a 5-parameter write operation with no annotations, no output schema, and 0% schema coverage, so the description needs to carry more weight. It omits return behavior, overwrite semantics, and parameter details, leaving an agent under-informed for reliable invocation in varied cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description only hints at session/name/value ('credential', 'session token'), leaving note and category unexplained. The parameter names are somewhat self-evident, but the description does not compensate for the missing schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Store or update') with a clear object ('one credential'), making the operation's purpose unmistakable. This clearly distinguishes it from the sibling read/list/status/log tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Store or update one credential' implies a write operation distinct from handshake_list/get/log, but there is no explicit guidance on when to use this tool versus alternatives. No exclusions or scenarios are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

handshake_statusA

Is the vault open? Shows whether a session is live, how long is left, and how many secrets exist. Needs no token — call this first when a credential is needed.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It conveys that this is a read-only session check, requires no token, and reports session liveness, remaining time, and secret count. It does not cover exact response formatting or error cases, but it is sufficient for a zero-input status tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short, information-dense sentences. The opening question immediately conveys intent, and the second sentence provides output details, auth requirements, and usage ordering without wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no parameters, no output schema, and low complexity, the description explains what the tool returns, that it needs no token, and when to call it. It is largely complete, though it could slightly clarify the format or units of 'how long is left.'

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has no parameters, so the schema is trivially complete. The description adds relevant context by stating that no token is needed, reinforcing that no input is required. This meets the baseline for zero-parameter tools.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: checking whether the vault/session is live, with time remaining and secret count. It distinguishes itself from sibling data-access tools by being a status-only check and by saying to call it first when a credential is needed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit situational guidance: 'Needs no token — call this first when a credential is needed.' This tells the agent when to invoke it and establishes ordering relative to credential access, though it does not explicitly name alternative tools or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 5 tool updatesv1.0.0
    • First observedhandshake_get
    • First observedhandshake_list
    • First observedhandshake_log
    • First observedhandshake_put
    • First observedhandshake_status

TDQS

A3.6/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: session status, listing names, reading a single credential, writing a credential, and viewing the audit log. There is no meaningful overlap or ambiguity between them.

Naming Consistency4/5

All tools share the handshake_ prefix and use lowercase snake_case, which is predictable. However, status and log are nouns while list, get, and put are verbs, so the naming pattern is not perfectly uniform.

Tool Count5/5

Five tools is a well-scoped set for a credential vault with auditing. Each tool serves an essential function without redundancy or bloat.

Completeness3/5

The set covers status checking, listing, reading, writing, and audit logging, which handles the core workflow. However, there is no delete/remove operation for credentials, which is a notable lifecycle gap for a secrets vault.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Encrypted credential vault with a 21-tool MCP server. Store and manage LLM API keys, service API keys, and OAuth credentials — then let your AI agent list, reveal, rotate, rename, pause, and proxy calls through them.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Credential vault for LLM agents that stores credentials encrypted and exposes MCP tools for authenticated HTTP requests, web scraping, and credential management, preventing AI assistants from seeing secrets.
    Apache 2.0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zeroai-tech/handshake'

If you have feedback or need assistance with the MCP directory API, please join our Discord server