Skip to main content
Glama
LesterAJohn

skeleton-mcp

by LesterAJohn

skeleton-mcp

Node.js MCP skeleton with:

  • Vault-backed secret management

  • Postgres-backed configuration management

  • Security and operational defaults for production-style patterns

Purpose

This repository is a starter template for building an MCP server that needs:

  • Multi-user support.

  • Secret reads and writes through Vault

  • Config reads and writes through Postgres

  • Tool-level authorization for mutating operations

  • Redacted tool output by default

  • Basic reliability controls for external secret writes

Design requirements:

  • Secrets are persistent in Vault.

  • Configuration is persistent in Postgres.

  • User-scoped behavior is mandatory, with default-user fallback where supported.

Related MCP server: mcp-server-toolkit

Skeleton Architecture

Runtime flow:

  1. src/index.js boots the app, creates services, and connects MCP stdio transport.

  2. src/config/env.js loads and validates environment configuration.

  3. src/services/configStore.js handles Postgres persistence.

  4. src/services/vault.js handles Vault operations and write retry queue.

  5. src/services/security.js redacts sensitive fields.

  6. src/mcp/server.js registers MCP tools and applies auth/error wrappers.

  7. src/http/server.js exposes MCP over HTTP with auth, limits, and access logs.

  8. src/http/index.js boots the dedicated HTTP MCP process.

  9. src/start-both.js starts stdio and HTTP as separate child processes.

Local infrastructure:

Registering The MCP Server

This repository can be registered with MCP clients in either stdio mode or HTTP mode.

For local development, stdio is the simplest option:

{
	"mcpServers": {
		"skeleton-mcp": {
			"command": "npm",
			"args": ["run", "start:stdio"],
			"cwd": "/Users/lesterjohn/Documents/GitHub/skeleton-mcp"
		}
	}
}

For HTTP-capable clients, use npm run start:http and point the client at the /mcp endpoint.

Codex

Use stdio for Codex unless you specifically need HTTP. Add the server to your Codex MCP configuration using the local workspace path:

  • Config file: ~/.codex/config.toml

  • Transport: stdio

{
	"mcpServers": {
		"skeleton-mcp": {
			"command": "npm",
			"args": ["run", "start:stdio"],
			"cwd": "/Users/lesterjohn/Documents/GitHub/skeleton-mcp"
		}
	}
}

If you prefer HTTP, run npm run start:http in this repository and configure Codex to send MCP requests to http://127.0.0.1:3000/mcp.

VS Code

Use stdio in VS Code for local workspace access, or HTTP if your setup routes MCP servers over a local endpoint:

  • Config file: .vscode/mcp.json

  • Transport: stdio or HTTP

{
	"command": "npm",
	"args": ["run", "start:stdio"],
	"cwd": "/Users/lesterjohn/Documents/GitHub/skeleton-mcp"
}

If your VS Code setup uses HTTP transport, point it at http://127.0.0.1:3000/mcp after starting npm run start:http.

Claude

For Claude Desktop, use stdio and add an MCP server entry that launches the process from this repository:

  • Config file: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Transport: stdio

{
	"mcpServers": {
		"skeleton-mcp": {
			"command": "npm",
			"args": ["run", "start:stdio"],
			"cwd": "/Users/lesterjohn/Documents/GitHub/skeleton-mcp"
		}
	}
}

If you are using a Claude setup that supports MCP over HTTP, point it at http://127.0.0.1:3000/mcp.

Tool Catalog

All tools return MCP text content containing JSON. Success payloads follow this shape:

{
	"ok": true,
	"status": 200,
	"data": {}
}

Errors follow this shape and set MCP isError=true:

{
	"ok": false,
	"status": 401,
	"error": "Unauthorized: invalid authorizationKey for mutating API operation"
}

If MCP_ADMIN_AUTH_KEY is configured, mutating tools (and mutating service_api_request calls) require authorizationKey.

service_query_suggestion

  • Category: advisory (read-only)

  • Risk: low

  • Use when: you want schema discovery for all MCP tools and recommendations on what tool sequence to run for an intent/workflow

  • Do not use when: you already know the exact specialized tool and validated endpoint path

  • Required permissions/prerequisites: none

  • Environment behavior:

    • Detects whether a workflow is mutating from operationType or method

    • Reports whether authorizationKey is required for the suggested mutating call when MCP_ADMIN_AUTH_KEY is configured

  • Parameters:

    • intent (optional string)

    • operationType (optional enum: discover|read|mutate|suspend_logging|resume_logging|get_drive_gpx|scoped)

    • method (optional string, normalized to uppercase)

    • path (optional string, normalized to leading slash)

    • includeExamples (optional boolean, default true)

    • includeToolSchemas (optional boolean, default true)

  • Expected response shape:

    • data.summary: intent + mutating/auth flags

    • data.recommendedOrder: ordered tool recommendations with reasons

    • data.safetyChecks: checklist for safer execution

    • data.toolSchemas: schema-like catalog for all operational tools (unless disabled)

    • data.examples: baseline read/mutate examples (unless disabled)

  • Common failures:

    • 500 for unexpected internal recommendation errors

  • Recommended tools:

    • Prerequisite: none

    • Follow-up: any tool listed in data.recommendedOrder

  • Example:

{
	"name": "service_query_suggestion",
	"arguments": {
		"intent": "discover endpoints then suspend logging for car 42",
		"operationType": "suspend_logging",
		"method": "PUT",
		"path": "/api/car/42/logging/suspend"
	}
}

Intent

Suggested tool sequence

Notes

Verify runtime and service connectivity

service_connection_info -> service_health_check

Baseline check before any operational request.

Discover supported routes before custom request

service_connection_info -> service_health_check -> service_list_endpoints -> service_api_request

Use discovered paths to reduce schema/path mistakes.

Suspend logging for a car

service_connection_info -> service_health_check -> service_suspend_logging

If MCP_ADMIN_AUTH_KEY is set, pass authorizationKey.

Resume logging for a car

service_connection_info -> service_health_check -> service_resume_logging

Prefer specialized tool over generic mutate calls.

Export drive GPX

service_connection_info -> service_health_check -> service_get_drive_gpx

Dedicated GPX path and payload handling.

Execute a generic read request

service_connection_info -> service_health_check -> service_list_endpoints -> service_api_request (GET)

Safer for non-destructive endpoint exploration.

Execute a generic mutating request

service_connection_info -> service_health_check -> service_list_endpoints -> service_api_request (`POST

PUT

Inspect user/app scope metadata

service_connection_info -> service_scope_info -> service_api_request

Use scope details for app/user-aware workflows.

service_connection_info

  • Category: read-only

  • Risk: low

  • Use when: you need runtime MCP + target-service connection metadata (server name/version, auth-gate status, scope model, service base URL/timeout)

  • Do not use when: you need health verification or endpoint discovery; prefer service_health_check or service_list_endpoints

  • Required permissions/prerequisites: none

  • Environment behavior: reports current process config (APP_NAME, MCP_CONFIG_DEFAULT_USER_ID, and admin-auth configured state)

  • Parameters: none

  • Expected response shape:

    • data.server: server metadata and scopeModel

    • data.service: service client connection info

  • Common failures:

    • 500 if service client metadata retrieval fails

  • Recommended tools:

    • Prerequisite: none

    • Follow-up: service_health_check, service_list_endpoints

  • Example:

{
	"name": "service_connection_info",
	"arguments": {}
}

service_scope_info

  • Category: read-only

  • Risk: low

  • Use when: you need app/user scoping details used for Postgres and Vault paths before making scoped calls

  • Do not use when: you only need default scope metadata; service_connection_info already includes default scope model

  • Required permissions/prerequisites: none

  • Environment behavior: defaults userId to MCP_CONFIG_DEFAULT_USER_ID when omitted

  • Parameters:

    • userId (optional string, non-empty)

  • Expected response shape:

    • data.appName

    • data.userId

    • data.userIdPathSegment

    • data.postgres.tableName, data.postgres.primaryKey, data.postgres.scope

    • data.vault.tokenIndexPath, data.vault.scope

  • Common failures:

    • 500 for unexpected normalization/path construction errors

  • Recommended tools:

    • Prerequisite: none

    • Follow-up: service_api_request (for scoped API calls)

  • Example:

{
	"name": "service_scope_info",
	"arguments": {
		"userId": "default"
	}
}

service_list_endpoints

  • Category: read-only

  • Risk: low

  • Use when: you want a safe discovery list of implemented/documented target endpoints

  • Do not use when: you need endpoint liveness; use service_health_check

  • Required permissions/prerequisites: none

  • Environment behavior: output depends on service adapter implementation bundled with current build

  • Parameters: none

  • Expected response shape:

    • data.endpoints: adapter-provided endpoint list

  • Common failures:

    • 500 if endpoint catalog cannot be produced

  • Recommended tools:

    • Prerequisite: service_connection_info

    • Follow-up: service_api_request, service_health_check

  • Example:

{
	"name": "service_list_endpoints",
	"arguments": {}
}

service_health_check

  • Category: read-only

  • Risk: low

  • Use when: you need reachability/health validation before operational calls

  • Do not use when: you need to retrieve business data; use specific service tools

  • Required permissions/prerequisites: network path to target service must be available

  • Environment behavior: uses configured service base URL and auth mode from runtime env

  • Parameters: none

  • Expected response shape:

    • data: adapter-specific health payload

  • Common failures:

    • 5xx if target service is down/unreachable

    • 401/403 when upstream service credentials are invalid

  • Recommended tools:

    • Prerequisite: service_connection_info

    • Follow-up: service_list_endpoints, service_api_request

  • Example:

{
	"name": "service_health_check",
	"arguments": {}
}

service_suspend_logging

  • Category: mutating

  • Risk: high

  • Use when: you intentionally need to disable logging for a specific car resource

  • Do not use when: you are exploring state only; use read-only tools first

  • Required permissions/prerequisites:

    • If MCP_ADMIN_AUTH_KEY is set, authorizationKey must match

    • Caller should validate target id and operational impact

  • Environment behavior: authorization enforcement is env-driven (MCP_ADMIN_AUTH_KEY)

  • Parameters:

    • carId (required, non-empty string or positive integer)

    • authorizationKey (optional unless admin key is configured)

  • Expected response shape:

    • data: adapter-specific suspend result

  • Common failures:

    • 401 invalid/missing authorizationKey when required

    • 404 car id not found

    • 409 invalid state transition (already suspended)

    • 5xx upstream service failure

  • Safety warning: this changes operational behavior; confirm rollback path before invoking

  • Recommended tools:

    • Prerequisite: service_health_check, service_list_endpoints

    • Follow-up: service_resume_logging, service_api_request (state verification)

  • Example:

{
	"name": "service_suspend_logging",
	"arguments": {
		"carId": 42,
		"authorizationKey": "<admin-key-if-required>"
	}
}

service_resume_logging

  • Category: mutating

  • Risk: high

  • Use when: you need to restore logging after a prior suspension

  • Do not use when: you only need status checks

  • Required permissions/prerequisites:

    • If MCP_ADMIN_AUTH_KEY is set, authorizationKey must match

    • Logging was previously suspended for the target resource

  • Environment behavior: authorization enforcement is env-driven (MCP_ADMIN_AUTH_KEY)

  • Parameters:

    • carId (required, non-empty string or positive integer)

    • authorizationKey (optional unless admin key is configured)

  • Expected response shape:

    • data: adapter-specific resume result

  • Common failures:

    • 401 invalid/missing authorizationKey when required

    • 404 car id not found

    • 409 invalid state transition (not suspended)

    • 5xx upstream service failure

  • Safety warning: operational state change; coordinate with incident/runbook procedures

  • Recommended tools:

    • Prerequisite: service_health_check

    • Follow-up: service_api_request (state verification)

  • Example:

{
	"name": "service_resume_logging",
	"arguments": {
		"carId": "42",
		"authorizationKey": "<admin-key-if-required>"
	}
}

service_get_drive_gpx

  • Category: read-only

  • Risk: medium (may contain sensitive location/history data)

  • Use when: you need a GPX export for a specific drive id

  • Do not use when: you only need summary metadata; use a lighter endpoint via service_api_request if available

  • Required permissions/prerequisites: drive id must exist and caller must be permitted by upstream service

  • Environment behavior: uses configured service auth and base URL

  • Parameters:

    • driveId (required, non-empty string or positive integer)

  • Expected response shape:

    • data: adapter-specific GPX payload/metadata

  • Common failures:

    • 404 drive id not found

    • 401/403 upstream authorization failure

    • 5xx upstream service failure

  • Recommended tools:

    • Prerequisite: service_health_check

    • Follow-up: service_api_request for related resource lookups

  • Example:

{
	"name": "service_get_drive_gpx",
	"arguments": {
		"driveId": 123
	}
}

service_api_request

  • Category: read-only or mutating (depends on method)

  • Risk: variable; high for POST|PUT|PATCH|DELETE

  • Use when: you need flexible access to supported target-service endpoints not covered by specialized tools

  • Do not use when: a specialized tool exists (service_suspend_logging, service_resume_logging, service_get_drive_gpx) because those provide clearer intent and safer contracts

  • Required permissions/prerequisites:

    • Mutating methods require authorizationKey if MCP_ADMIN_AUTH_KEY is set

    • path must target valid adapter-supported route behavior

  • Environment behavior:

    • method is normalized to uppercase

    • path is normalized to leading slash format

    • auth and host safeguards are enforced by adapter

  • Parameters:

    • method (required string, e.g. GET, POST)

    • path (required string; /-prefixed normalization applied)

    • query (optional object: string keys, scalar values string|number|boolean)

    • body (optional JSON value)

    • headers (optional object: string keys and string values)

    • authorizationKey (optional unless mutating call requires it)

  • Expected response shape:

    • data: adapter HTTP response payload

  • Common failures:

    • 400 invalid path/query/body for upstream API

    • 401 invalid/missing authorizationKey for required mutating call

    • 403 upstream access denied

    • 404 endpoint/resource not found

    • 429 upstream rate limiting

    • 5xx upstream/transport failure

  • Safety warning: treat mutating methods as destructive-capable operations; verify target path, method, and body before invocation

  • Recommended tools:

    • Prerequisite: service_list_endpoints, service_health_check

    • Follow-up: specialized read tools for validation, or another service_api_request GET for post-change verification

  • Examples:

{
	"name": "service_api_request",
	"arguments": {
		"method": "GET",
		"path": "/api/car/42"
	}
}
{
	"name": "service_api_request",
	"arguments": {
		"method": "PATCH",
		"path": "/api/car/42",
		"body": {
			"nickname": "track-ready"
		},
		"authorizationKey": "<admin-key-if-required>"
	}
}

Security Behavior

  • Sensitive fields are redacted unless MCP_ALLOW_SENSITIVE_OUTPUT=true.

  • Mutating operations can be access controlled with MCP_ADMIN_AUTH_KEY.

  • Vault write operations are serialized through an internal queue and retried with exponential backoff.

Environment Variables

Core:

  • APP_NAME

  • MCP_SERVER_NAME

  • MCP_SERVER_VERSION

  • MCP_ALLOW_SENSITIVE_OUTPUT

  • MCP_ADMIN_AUTH_KEY

  • MCP_TRANSPORT_MODE (stdio, http, or both)

  • MCP_CONFIG_DEFAULT_USER_ID

  • MCP_TOKEN_ROTATION_DEFAULT_INTERVAL_MS

  • MCP_TOKEN_ROTATION_USER_INTERVAL_CONFIG_KEY

  • MCP_VAULT_AGENT_AUTH_MODE_CONFIG_KEY

  • MCP_VAULT_AGENT_TOKEN_FILE_PATH_CONFIG_KEY

  • MCP_VAULT_AGENT_LISTENER_ADDR_CONFIG_KEY

HTTP transport:

  • MCP_HTTP_HOST

  • MCP_HTTP_PORT

  • MCP_HTTP_PATH

  • MCP_HTTP_HEALTH_PATH

  • MCP_HTTP_AUTH_MODE (token, oauth2, both)

  • MCP_HTTP_TOKEN_SOURCE (vault, env)

  • MCP_HTTP_AUTH_TOKENS (comma-separated bearer tokens)

  • MCP_HTTP_TRUST_PROXY

  • MCP_HTTP_ALLOWED_ORIGINS (comma-separated)

  • MCP_HTTP_ALLOWED_IPS (comma-separated)

  • MCP_HTTP_MAX_BODY_BYTES

  • MCP_HTTP_RATE_LIMIT_WINDOW_MS

  • MCP_HTTP_RATE_LIMIT_MAX_REQUESTS

  • MCP_HTTP_VAULT_TOKEN_INDEX_PATH

  • MCP_HTTP_VAULT_TOKEN_DEFAULT_USER_ID

  • MCP_HTTP_VAULT_TOKEN_REQUIRED_SCOPES

  • MCP_HTTP_VAULT_TOKEN_REQUIRED_AUDIENCE

  • MCP_HTTP_VAULT_TOKEN_CACHE_TTL_MS

  • MCP_HTTP_OAUTH2_INTROSPECTION_URL

  • MCP_HTTP_OAUTH2_CLIENT_ID

  • MCP_HTTP_OAUTH2_CLIENT_SECRET

  • MCP_HTTP_OAUTH2_REQUIRED_SCOPES

  • MCP_HTTP_OAUTH2_REQUIRED_AUDIENCE

  • MCP_HTTP_OAUTH2_TIMEOUT_MS

  • MCP_HTTP_OAUTH2_CACHE_TTL_MS

  • MCP_HTTP_TLS_ENABLED

  • MCP_HTTP_TLS_CERT_PATH

  • MCP_HTTP_TLS_KEY_PATH

Postgres:

  • POSTGRES_HOST

  • POSTGRES_PORT

  • POSTGRES_DB

  • POSTGRES_USER

  • POSTGRES_PASSWORD

Postgres config model:

  • Configuration data is app-scoped in ${APP_NAME}_config and user-scoped with composite key (user_id, key).

  • MCP config tools accept optional userId; when omitted, MCP_CONFIG_DEFAULT_USER_ID is used.

  • Seed records include:

    • default/sample.feature

    • default/app.defaults for future default parameters.

    • default/token.rotation.intervalMs

    • default/vault.agent.auth.mode

    • default/vault.agent.tokenFilePath

    • default/vault.agent.listener.addr

Vault:

  • VAULT_ADDR

  • VAULT_TOKEN

  • VAULT_AGENT_ENABLED

  • VAULT_AGENT_AUTH_MODE (none, file, listener, both)

  • VAULT_AGENT_TOKEN_FILE_PATH

  • VAULT_AGENT_LISTENER_ENABLED

  • VAULT_AGENT_LISTENER_ADDR

  • VAULT_UNSEAL_KEY

  • VAULT_KV_MOUNT

  • VAULT_WRITE_RETRY_ATTEMPTS

  • VAULT_WRITE_RETRY_BASE_DELAY_MS

  • VAULT_WRITE_RETRY_MAX_DELAY_MS

Naming defaults:

  • APP_NAME defaults to skeleton.

  • The Postgres config table defaults to ${APP_NAME}_config.

  • The Vault token index path defaults to ${APP_NAME}/users/${MCP_HTTP_VAULT_TOKEN_DEFAULT_USER_ID}/http/auth/token-index.

  • Set only APP_NAME to rename the app-scoped Vault/Postgres schema across local and external stores.

Reference values are in .env.example.

Quick Start

  1. Install dependencies.

  2. Copy .env.example to .env.

  3. Start local services with docker compose up -d.

  4. Resolve the managed unseal key: npm run vault:unseal-key -- --json.

  5. Initialize and unseal local Vault (first run):

docker exec -e VAULT_ADDR=http://127.0.0.1:8200 skeleton-mcp-vault vault operator init -key-shares=1 -key-threshold=1 -format=json
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 skeleton-mcp-vault vault operator unseal <unseal_key_from_init_or_env>
  1. Seed a test secret in Vault.

  2. Start the MCP server with npm start.

  3. Run tests with npm test.

External Services Mode

Use this mode when Vault and Postgres are already managed outside this repository.

Required environment variables:

  • POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD

  • VAULT_ADDR, VAULT_TOKEN

Run the app-only compose stack:

docker compose -f docker-compose.external.yml up -d

Notes:

  • The app still uses Vault for secrets and Postgres for config.

  • The external stack is the same MCP HTTP container, but it skips local Postgres/Vault containers.

  • If you keep Vault sealed, the app will still require whatever unseal process your external Vault uses.

Test Coverage Notes

Current automation includes listener-related coverage for Vault Agent runtime resolution.

  • tests/vault-agent-runtime.test.js validates:

    • listener mode resolution from Postgres defaults

    • both mode resolution (listener + file)

    • fallback to environment values when database mode is invalid

Transport scripts:

# stdio only (default)
npm run start:stdio

# HTTP transport only
npm run start:http

# run stdio + HTTP as two processes
npm run start:both

HTTP MCP Endpoint

Default endpoint values:

  • MCP URL: http://127.0.0.1:3000/mcp

  • Health URL: http://127.0.0.1:3000/healthz

HTTP transport security controls:

  • Every /mcp request requires Authorization: Bearer <token>.

  • For MCP_HTTP_AUTH_MODE=token, set MCP_HTTP_TOKEN_SOURCE=vault to validate tokens from Vault.

  • For MCP_HTTP_AUTH_MODE=oauth2, bearer tokens are validated by OAuth2 introspection.

  • For MCP_HTTP_AUTH_MODE=both, either token strategy can authorize requests.

  • Mutating tools still require authorizationKey when MCP_ADMIN_AUTH_KEY is set.

  • Request limits are enforced with:

    • MCP_HTTP_MAX_BODY_BYTES

    • MCP_HTTP_RATE_LIMIT_WINDOW_MS

    • MCP_HTTP_RATE_LIMIT_MAX_REQUESTS

  • Optional network restrictions:

    • MCP_HTTP_ALLOWED_ORIGINS

    • MCP_HTTP_ALLOWED_IPS

Vault Multi-User Token Model

Store HTTP bearer tokens in Vault at MCP_HTTP_VAULT_TOKEN_INDEX_PATH. If unset, seeding tools default to ${APP_NAME}/users/<user_id>/http/auth/token-index.

Default-user fallback behavior:

  • MCP_HTTP_VAULT_TOKEN_DEFAULT_USER_ID defaults to default.

  • If no non-default users exist in the token index, the default user is always used as fallback.

Supported index shape:

{
	"tokens": {
		"<sha256(token)>": {
			"userId": "user-123",
			"tokenId": "tok-123",
			"active": true,
			"scopes": ["mcp:invoke", "mcp:read"],
			"audience": ["codex", "claude"],
			"expiresAt": "2026-12-31T23:59:59Z"
		}
	}
}

Notes:

  • Store only token hashes in Vault index data, never plaintext tokens.

  • MCP_HTTP_VAULT_TOKEN_REQUIRED_SCOPES and MCP_HTTP_VAULT_TOKEN_REQUIRED_AUDIENCE enforce policy checks.

  • This keeps secrets in Vault under the app-prefixed root while configuration remains in the app-prefixed Postgres table.

Vault HTTP Token Seeding

Use the helper script to generate an opaque bearer token and store it in the Vault user token structure:

npm run vault:seed-http-token -- --user-id default --json

Useful options:

  • --user-id <id>: Vault user to seed.

  • --token-id <id>: Optional token id stored with the entry.

  • --scopes <list>: Comma or space separated scopes.

  • --audience <list>: Comma or space separated audience values.

  • --expires-at <value>: Optional ISO timestamp or unix seconds.

  • --path <vault-path>: Override the token index path.

The script writes the token record under the app-prefixed user structure and mirrors the token in the top-level token map for compatibility.

If you need to reseed a user, run the script again with the same --user-id and a new --token-id.

Vault OAuth Token Seeding

Use the helper script to store a provided OAuth access token in the Vault user token structure:

npm run vault:seed-oauth-token -- --token "$OAUTH_ACCESS_TOKEN" --user-id default --json

Useful options:

  • --token <value>: OAuth access token to seed.

  • --user-id <id>: Vault user to seed.

  • --token-id <id>: Optional token id stored with the entry.

  • --scopes <list>: Comma or space separated scopes.

  • --audience <list>: Comma or space separated audience values.

  • --expires-at <value>: Optional ISO timestamp or unix seconds.

  • --path <vault-path>: Override the token index path.

The script stores the provided token under the app-prefixed user structure, keeps the top-level token map aligned, and marks the entry as oauth2 in Vault metadata.

MCP Tool

The same capability is exposed as an MCP tool for controlled setup workflows:

  • vault_seed_http_token: generate a bearer token and store it in the Vault HTTP token index for a user.

  • vault_seed_oauth_token: store a provided OAuth access token in the Vault HTTP token index for a user.

For both tools, include app/user scope in requests so clients can reason about target storage:

  • appName determines app-level namespace defaults.

  • userId determines user-level namespace under ${APP_NAME}/users/<user_id>/....

The tool requires authorizationKey when MCP_ADMIN_AUTH_KEY is configured.

Vault Token Lifecycle MCP Tools

The skeleton exposes node-vault token lifecycle methods as MCP tools:

  • token_lookup_self -> tokenLookupSelf

  • token_renew_self -> tokenRenewSelf

  • token_create -> tokenCreate

  • token_revoke -> tokenRevoke

  • token_revoke_self -> tokenRevokeSelf

These tools are intended for controlled operational usage and are guarded by admin authorization when MCP_ADMIN_AUTH_KEY is configured.

Vault Agent Auto-Auth and Token Renewal

Vault Agent can own token auth/renewal while this service reads the sink token file.

  • Enable with VAULT_AGENT_ENABLED=true

  • Choose auth mode with VAULT_AGENT_AUTH_MODE:

    • file: use Vault Agent token sink file

    • listener: use Vault Agent listener endpoint

    • both: enable listener operations and file-based token read workflows

  • Configure sink file path with VAULT_AGENT_TOKEN_FILE_PATH

  • Enable listener with VAULT_AGENT_LISTENER_ENABLED=true

  • Configure listener with VAULT_AGENT_LISTENER_ADDR

  • Use vault_agent_token_read when application workflows need token sink visibility

When Vault Agent mode is enabled:

  • File mode refreshes token state from the configured token sink path.

  • Listener mode routes Vault operations through the configured Vault Agent listener.

  • Both mode supports listener operations and token sink read workflows.

Option 3: Postgres-Backed Non-Secret Vault Agent Settings

This skeleton supports storing non-secret Vault Agent runtime pointers/settings in Postgres while keeping token material in Vault.

  • Runtime settings are read from default user config scope (MCP_CONFIG_DEFAULT_USER_ID).

  • Key names are configurable with:

    • MCP_VAULT_AGENT_AUTH_MODE_CONFIG_KEY

    • MCP_VAULT_AGENT_TOKEN_FILE_PATH_CONFIG_KEY

    • MCP_VAULT_AGENT_LISTENER_ADDR_CONFIG_KEY

  • Recommended values in Postgres:

    • vault.agent.auth.mode

    • vault.agent.tokenFilePath

    • vault.agent.listener.addr

Rotation Time Configuration

Rotation interval supports both global defaults and user-scoped overrides:

  • Global default env variable: MCP_TOKEN_ROTATION_DEFAULT_INTERVAL_MS

  • User-scoped config key name: MCP_TOKEN_ROTATION_USER_INTERVAL_CONFIG_KEY (default token.rotation.intervalMs)

Effective value resolution is:

  1. User-scoped Postgres config (userId + key)

  2. Default user Postgres config (default + key)

  3. Global env default

Use token_rotation_config tool to inspect the resolved rotation interval for a user scope.

Minimal remote call example:

curl -i http://127.0.0.1:3000/mcp \
	-H "Authorization: Bearer replace-me-token" \
	-H "Accept: application/json, text/event-stream" \
	-H "Content-Type: application/json" \
	-d '{
		"jsonrpc": "2.0",
		"id": 1,
		"method": "initialize",
		"params": {
			"protocolVersion": "2025-11-25",
			"capabilities": {},
			"clientInfo": { "name": "client", "version": "1.0.0" }
		}
	}'

HTTPS Deployment Choice

This repository uses a reverse proxy (recommended): terminate TLS at a reverse proxy or load balancer.

  • Keep this app on internal HTTP.

  • Enforce HTTPS, client allowlists, and edge-level controls at the proxy/LB.

  • Forward traffic to MCP_HTTP_HOST:MCP_HTTP_PORT.

  • Keep MCP_HTTP_TLS_ENABLED=false in this process mode.

Popular patterns include Nginx, Traefik, Envoy, ALB/NLB, or Cloudflare Tunnel in front of /mcp.

Vault Production Migration (Raft)

The repository now includes a Vault production migration scaffold under vault-production:

Managed unseal key flow:

  • VAULT_UNSEAL_KEY is optional and can be injected at runtime.

  • If VAULT_UNSEAL_KEY is not set, npm run vault:unseal-key reads src/config/vault.unseal.key.json.

  • If the key file is missing or empty, a 24-character key is generated and saved to src/config/vault.unseal.key.json.

  • Both compose stacks run a one-shot vault-unseal-key-init service before Vault startup to ensure key material exists.

Run the conversion:

bash vault-production/scripts/convert-dev-to-prod.sh --init-keys-out vault-production/backups/vault-init.json

Common options:

# Use a different KV mount
bash vault-production/scripts/convert-dev-to-prod.sh --mount secret

# Migrate infra only (skip data movement)
bash vault-production/scripts/convert-dev-to-prod.sh --skip-export --skip-import

# Use when Raft Vault is already initialized
bash vault-production/scripts/convert-dev-to-prod.sh --skip-init

# Explicitly set key file path used by convert script
bash vault-production/scripts/convert-dev-to-prod.sh --unseal-key-path src/config/vault.unseal.key.json

# Post-conversion hardening bootstrap (audit, policy, AppRole)
bash vault-production/scripts/bootstrap-post-conversion.sh --vault-token <root_or_admin_token>

# CI-friendly machine output
bash vault-production/scripts/bootstrap-post-conversion.sh \
	--vault-token <root_or_admin_token> \
	--output json

VS Code Agent Structure

This repository includes a project agent structure for adapting the skeleton to additional service-backed MCP implementations:

Workspace custom agent:

Use this custom agent when you want GitHub Copilot in VS Code to:

  1. Configure new service adapters under src/services.

  2. Register matching MCP tools in src/mcp/server.js.

  3. Update env validation in src/config/env.js.

  4. Preserve authorization and redaction behavior.

  5. Add tests and documentation updates.

Test Coverage

Integration tests in tests/server.integration.test.js cover:

  • Healthcheck behavior

  • Authorization on mutating tools

  • Redaction behavior for secret output

HTTP transport tests in tests/http.integration.test.js cover:

  • Unauthorized requests are rejected

  • Authorized MCP initialization succeeds

  • Internal failures return JSON-RPC-compatible error responses

  • Health endpoint behavior

Vault token auth tests in tests/vault-token-auth.test.js cover:

  • Multi-user token index lookup by SHA-256 hash

  • Inactive token rejection

  • Scope/audience-aware authorization inputs

Production migration tests in tests/vault-production.test.js cover:

  • Presence of Vault production scaffold files

  • Raft config expectations

  • Non-dev Vault compose command validation

  • Conversion/bootstrap script help and bash syntax checks

Extend The Skeleton

  1. Add domain services under src/services.

  2. Register new tools in src/mcp/server.js.

  3. Add corresponding tests under tests.

  4. Keep mutating tools behind authorization checks.

  5. Keep secret-bearing fields redacted by default.

Notes

  • docker-compose.yml now runs Vault with Raft-backed storage for local persistence.

  • The managed key script is an automation helper and not a Vault KMS/HSM auto-unseal backend.

  • The migration scaffold starts with bootstrap-friendly defaults and still requires TLS, production auth methods, and credential rotation before real production use.

Available Tools

11 tools
connection_infoB

Return MCP server, Vault, and Postgres connection information with secret-safe values.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.4/5.0
Behavior3/5

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

With no annotations, the description carries full burden. It adds value by noting 'secret-safe values,' which implies masking of sensitive data. However, it does not disclose other behavioral traits like idempotency, read-only nature, or potential side effects, making it partially adequate.

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?

Single sentence, front-loaded with the verb 'Return,' and no extraneous words. Every word earns its place.

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

Completeness3/5

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

The tool has no parameters or output schema. The description explains the output category (connection info) and a safe-handling qualifier. However, without output schema, it could specify the structure or keys returned. Also, it does not differentiate from vault_connection_info, leaving some ambiguity.

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?

No parameters exist, and schema coverage is 100%. The description adds no parameter details, but none are needed. Baseline 4 is appropriate as the schema fully covers parameters.

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 states the tool returns connection information for MCP server, Vault, and Postgres, with secret-safe values. It uses a specific verb and resource list, distinguishing it from highly specialized siblings like vault_connection_info, though it could be more explicit about the scope.

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?

No guidance on when to use this tool versus its siblings (e.g., vault_connection_info) or when not to use it. The description lacks context on prerequisites or alternative tools, leaving the agent without decision-making support.

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

delete_configC

Delete a configuration value from Postgres by key.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYes
authorizationKeyNo

TDQS

C2.6/5.0
Behavior2/5

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

No annotations provided, so the description carries the full burden. It says 'Delete' (destructive), but does not disclose error behavior on nonexistent keys, authorization requirements, side effects, or idempotency. For a destructive operation, this is insufficient.

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

Conciseness3/5

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

The description is a single concise sentence, but it sacrifices necessary detail. It is not bloated, but the conciseness comes at the cost of completeness.

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?

No output schema exists, so the description should cover return values or error behavior. It does not. Given the complexity of a delete operation and the presence of sibling tools like set_config and get_config, the description is incomplete.

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%, so the description must explain parameters. It mentions 'by key' but does not explain the 'authorizationKey' parameter at all, leaving the agent with incomplete guidance.

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 states it deletes a configuration value from Postgres by key, using a specific verb and resource. It distinguishes from siblings like delete_secret by specifying 'configuration value' and 'Postgres', though it doesn't explicitly contrast with other delete tools.

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?

No guidance on when to use this tool versus alternatives like delete_secret or set_config. There is no mention of prerequisites, typical use cases, 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.

delete_secretC

Delete a Vault secret at path.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
authorizationKeyNo

TDQS

C2.4/5.0
Behavior2/5

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

With no annotations, the description carries full burden. It states only 'Delete,' implying a destructive action, but does not clarify whether deletion is permanent, what permissions are needed, or if the authorizationKey parameter is required. No hints about side effects or error states.

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

Conciseness3/5

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

The description is a single sentence, which is concise but too sparse to be helpful. It could be expanded slightly to include useful context without becoming verbose.

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 the tool is a mutation with no annotations, no output schema, and sibling tools that perform other CRUD operations, the description fails to cover return values, error handling, or authorization requirements. It is incomplete for safe agent use.

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 offers no explanation for either parameter ('path' or 'authorizationKey'). The agent receives no help on how to populate these fields beyond schema constraints (e.g., minLength).

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 uses the specific verb 'Delete' and identifies the resource as 'a Vault secret at path,' clearly distinguishing it from sibling tools like get_secret or set_secret.

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?

No guidance is provided on when to use this tool versus alternatives (e.g., set_secret with empty payload) or any prerequisites. The description lacks context about when deletion is appropriate or safe.

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

get_configC

Read a configuration value from Postgres by key.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYes

TDQS

C2.9/5.0
Behavior2/5

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

With no annotations, the description must bear full transparency. It indicates a read-only operation but omits details about return values, error handling, or what happens if the key does not exist.

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

Conciseness3/5

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

The description is a single concise sentence, but it is overly brief. It could include more context without being lengthy, so it is adequate but not optimal.

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?

For a tool with one parameter and no output schema, the description should clarify return format or potential issues like missing keys. It does not, leaving the agent with incomplete information.

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%, yet the description adds only 'by key' which offers little beyond the schema. The 'key' parameter remains undefined, forcing the agent to infer its meaning.

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 action (Read) and the resource (configuration value from Postgres by key), distinguishing it from sibling tools like delete_config or set_config.

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?

No guidance is provided on when to use this tool versus alternatives like list_configs or get_secret. The description does not mention prerequisites or exclusions.

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

get_secretC

Read a secret from Vault KV v2 by path.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

TDQS

C2.9/5.0
Behavior2/5

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

No annotations provided, so description carries full burden. It implies a read-only operation but does not disclose behavior on missing paths, versioning, or required permissions. Minimal disclosure for a tool accessing sensitive data.

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?

Single sentence, concise, no wasted words. However, it is so brief that it omits useful context. Still, it is not overly long.

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 output schema and a simple parameter, the description should at least mention return format, versioning, or error handling. For a vault tool, more context is needed for correct invocation.

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 coverage is 0% (no description for the 'path' parameter). The description adds only 'by path' without specifying format, allowed values, or path conventions. Fails to compensate for 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 clearly states the verb 'Read', the resource 'secret', the context 'from Vault KV v2', and the method 'by path'. It distinguishes from siblings like delete_secret and set_secret by emphasizing reading rather than modification.

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?

No explicit guidance on when to use this tool versus alternatives. Sibling tools include list_secrets and get_config, but the description does not differentiate from those or mention prerequisites like authentication.

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

healthcheckA

Run connectivity checks for Postgres and Vault.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior2/5

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

No annotations are provided, so the description must fully disclose behavior. It only states 'Run connectivity checks' without clarifying if it is read-only, whether it requires permissions, or if it has side effects. This is insufficient for safe agent invocation.

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 a single sentence that is front-loaded and contains no extraneous information. Every word is necessary.

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

Completeness3/5

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

For a simple healthcheck tool with no parameters and no output schema, the description covers the basic purpose but omits what the tool returns (e.g., success/failure, details). A more complete description would include output expectations.

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?

There are no parameters, and schema coverage is 100%. The description adds no parameter info, which is acceptable. Baseline is 3 per guidelines.

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 runs connectivity checks for two specific services (Postgres and Vault), using a specific verb and resource. It distinguishes from siblings like connection_info which likely provide details rather than active checks.

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 implies usage for verifying connectivity but does not explicitly state when to use it versus alternatives like connection_info, nor does it mention prerequisites 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.

list_configsA

List configuration records from Postgres, optionally filtered by key prefix.

ParametersJSON Schema
NameRequiredDescriptionDefault
prefixNo

TDQS

A4/5.0
Behavior4/5

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

Despite no annotations, the description indicates a read-only operation ('list') and mentions the source (Postgres) and optional filtering by key prefix. It does not detail pagination or limits, but this is a minor gap for a simple list 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?

A single sentence of 9 words, front-loaded with the verb and resource, delivering the core purpose efficiently without extraneous information.

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?

Given the simple interface (one optional parameter, no output schema), the description covers the essential behavior: listing configs from Postgres with optional prefix filtering. It does not mention return structure or pagination, but the tool's simplicity keeps it adequate.

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?

The description adds context that the optional prefix filters by 'key prefix', which the schema lacks. However, it does not specify format, case sensitivity, or behavior when omitted, leaving minor ambiguity.

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 action ('list') and resource ('configuration records'), and distinguishes from siblings like list_secrets by specifying the data source (Postgres) and the optional filtering by key prefix.

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?

No explicit guidance on when to use this tool over alternatives such as get_config or list_secrets, though the name and description imply its use for multiple configs.

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

list_secretsC

List child keys under a Vault path prefix.

ParametersJSON Schema
NameRequiredDescriptionDefault
prefixNo

TDQS

C2.7/5.0
Behavior2/5

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

No annotations provided. The description does not disclose whether the listing is recursive, paginated, or what happens on non-existent prefixes. Lacks details on authentication or rate limits.

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?

Very concise single sentence. No wasted words, but could benefit from minimal structuring (e.g., adding parameter details concisely).

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?

For a simple tool with 1 parameter and no output schema, the description is minimal. It leaves unanswered questions about output format and edge 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 does not explain the 'prefix' parameter beyond its name. No format, required separators, or examples provided.

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 states it lists child keys under a Vault path prefix, which is a specific verb+resource. It distinguishes from siblings like get_secret and delete_secret, though the meaning of 'child keys' could be clearer.

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?

No guidance on when to use this tool vs alternatives like list_configs or get_secret. No context on when not to use it or prerequisites.

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

set_configC

Create or update a configuration value in Postgres.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYes
valueNo
authorizationKeyNo

TDQS

C2.3/5.0
Behavior2/5

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

With no annotations, the description bears full burden for behavioral disclosure. 'Create or update' hints at idempotency but does not explain escalation of privileges, whether existing values are overwritten, or what happens if the key already exists. No side effects or destruction details are given.

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

Conciseness2/5

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

The description is very short (6 words), but at the expense of necessary detail. It is under-specified rather than concise; every sentence should earn its place, and this one fails to convey essential information.

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

Completeness1/5

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

Given 3 parameters with zero schema description, no output schema, and a tool that performs an upsert on a configuration store, the description lacks critical details about return values, error conditions, and behavior for missing keys or authorization failures. It is incomplete for reliable agent use.

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 coverage is 0%, and the description does not explain the purpose or constraints of the three parameters (key, value, authorizationKey). The agent has to infer their usage from names alone, which is insufficient for correct invocation.

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 'Create or update a configuration value in Postgres' clearly states the verb (create or update) and resource (configuration value), and distinguishes from sibling tools like get_config, delete_config, and list_configs. However, it could be more specific about the 'config' scope versus secrets.

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?

The description provides no guidance on when to use this tool versus alternatives like set_secret (for secrets) or when creation vs. update applies. There's no mention of preconditions, prerequisites, or exclusions.

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

set_secretC

Create or update a Vault secret at path.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
valueYes
authorizationKeyNo

TDQS

C2.7/5.0
Behavior2/5

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

No annotations provided. Description mentions create/update but does not disclose authorization requirements, destructive nature, idempotency, or behavior on conflicts. The authorizationKey parameter is not mentioned.

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

Conciseness3/5

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

Single sentence with no waste, but under-specified for the tool's complexity. Could be more informative without losing conciseness.

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?

No output schema, no parameter descriptions, no reference to sibling tools. For a tool with a required nested object and an authorization parameter, the description is insufficient.

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%. Description does not explain any of the three parameters (path, value, authorizationKey). No details on expected format or constraints beyond the schema.

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?

Description clearly states verb (create/update), resource (Vault secret), and scope (at path). Distinguishes from sibling tools like get_secret, delete_secret, list_secrets.

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?

No guidance on when to use this tool vs alternatives. Does not mention prerequisites, when not to use, or comparisons to set_config or other siblings.

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

vault_connection_infoA

Return active Vault configuration without exposing secret values.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations, the description carries the burden of behavioral disclosure. It explicitly states that secret values are not exposed, which is a key safety guarantee. However, it does not mention other traits like idempotency or authentication requirements.

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 a single sentence that is direct and free of extraneous content. It conveys the essential purpose without waste.

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?

Despite no parameters, the description lacks information about the return format or structure. Without an output schema, the agent does not know what fields or data shape to expect from 'active Vault configuration'. This is a significant gap for a tool that provides configuration data.

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 zero parameters, and schema coverage is 100%. The description adds no parameter information, but none is needed. Baseline score of 4 is appropriate for a param-free tool.

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 verb 'return' and the resource 'active Vault configuration' with the constraint 'without exposing secret values'. This distinguishes it from potentially related siblings like 'connection_info' or 'get_config' by emphasizing security and scope.

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?

No guidance is provided on when to use this tool versus its siblings (e.g., connection_info, get_config, list_configs). The description does not mention alternatives or context, leaving the agent to guess.

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. 11 tool updatesv0.1.0
    • First observedconnection_info
    • First observeddelete_config
    • First observeddelete_secret
    • First observedget_config
    • First observedget_secret
    • First observedhealthcheck
    • First observedlist_configs
    • First observedlist_secrets
    • First observedset_config
    • First observedset_secret
    • First observedvault_connection_info

TDQS

B3.4/5.0
Disambiguation5/5

Each tool targets a distinct resource and action: config operations, secret operations, connection info, and healthcheck. There is no overlap or ambiguity.

Naming Consistency5/5

All tool names follow the consistent verb_noun pattern in snake_case (e.g., delete_config, list_secrets). Even connection_info and healthcheck fit the style.

Tool Count5/5

11 tools are well-scoped for a server managing configurations and secrets across two backends, with connection info and healthcheck. Neither too many nor too few.

Completeness5/5

Full CRUD for configs and secrets (get, set, delete, list), plus connection info and healthcheck. No missing operations for the domain.

Maintenance

ActivityMaintained
ResponsivenessSyncing

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
    A production-ready Python template for building MCP servers with enterprise features including registry integration, configuration management, structured logging, and extensible patterns for tools, resources, and prompts.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Production-ready MCP server starter with authentication, observability, and a plugin system for building and deploying MCP servers quickly.
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    A starter template for building MCP servers. It provides a clean foundation for creating custom tools, resources, and prompts for AI assistants.
    4
    16
    -

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/LesterAJohn/skeleton-mcp'

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