Skip to main content
Glama

local_ydb_prepare_auth_config

Generate a hardened YDB config from the current static-node config. Use before writing dynamic auth config and applying auth hardening.

Instructions

Generate a hardened YDB config from the current static-node config. Use before local_ydb_write_dynamic_auth_config and local_ydb_apply_auth_hardening; without confirm=true this returns the planned write only.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
profileNoNamed profile from local-ydb.config.json. Defaults to config.defaultProfile.
configPathNoExplicit local-ydb config file path to load for this tool call. Useful when the MCP server should pick up a different config without restart.
confirmNoMust be true to write the hardened config file. Omit or false for plan-only output.
configHostPathNoHost path for the generated hardened config. Defaults to profile.authConfigPath when present.
sidNoSID to place into viewer, monitoring, administration, and register_dynamic_node_allowed_sids. Defaults to profile.dynamicNodeAuthSid or root@builtin.

Implementation Reference

  • The core handler: generates a hardened YDB config from the current static-node config, enforcing user token requirements, setting allowed SIDs for viewer/monitoring/administration/dynamic registration, and optionally extracting the root password. Uses Ruby to parse/modify YAML via docker exec.
    export async function prepareAuthConfig(
      ctx: ToolkitContext,
      options: MutatingOptions & { configHostPath?: string; sid?: string } = {}
    ) {
      const configHostPath = options.configHostPath ?? ctx.profile.authConfigPath;
      const sid = options.sid ?? ctx.profile.dynamicNodeAuthSid ?? "root@builtin";
      const rootSid = ctx.profile.rootUser;
      if (!configHostPath) {
        return planOnly(
          ctx,
          "Prepare auth config requires configHostPath directly or through the selected profile.",
          "medium",
          [],
          ["No changes."],
          ["Provide configHostPath and rerun."]
        );
      }
    
      const rootPasswordFile = ctx.profile.rootPasswordFile ?? "";
      const targetCommand = commandForStaticGeneratedConfigPath(ctx.profile.staticContainer);
      const script = [
        "set -euo pipefail",
        `install -d -m 0700 ${shellQuote(dirname(configHostPath))}`,
        rootPasswordFile ? `install -d -m 0700 ${shellQuote(dirname(rootPasswordFile))}` : ":",
        "tmp=$(mktemp)",
        "trap 'rm -f \"$tmp\"' EXIT",
        `target=$(${targetCommand})`,
        `docker exec ${shellQuote(ctx.profile.staticContainer)} cat "$target" > "$tmp"`,
        [
          "ruby -ryaml -e",
          shellQuote([
            "config = YAML.load_file(ARGV[0])",
            "domains = config.fetch(\"domains_config\")",
            "security = domains[\"security_config\"] ||= {}",
            "allowed_sids = [ARGV[2], ARGV[4]].reject(&:empty?).uniq",
            "security[\"enforce_user_token_requirement\"] = true",
            "security[\"viewer_allowed_sids\"] = allowed_sids",
            "security[\"monitoring_allowed_sids\"] = allowed_sids",
            "security[\"administration_allowed_sids\"] = allowed_sids",
            "security[\"register_dynamic_node_allowed_sids\"] = allowed_sids",
            "File.write(ARGV[1], YAML.dump(config))",
            "File.chmod(0600, ARGV[1])",
            "if !ARGV[3].empty?",
            "  root = Array(security[\"default_users\"]).find { |user| user[\"name\"] == \"root\" }",
            "  raise \"root password not found in security_config.default_users\" unless root && root[\"password\"]",
            "  File.write(ARGV[3], \"#{root[\"password\"]}\\n\")",
            "  File.chmod(0600, ARGV[3])",
            "end"
          ].join("; ")),
          "\"$tmp\"",
          shellQuote(configHostPath),
          shellQuote(sid),
          shellQuote(rootPasswordFile),
          shellQuote(rootSid)
        ].join(" ")
      ].join("\n");
    
      return runMutating(ctx, {
        summary: `Prepare hardened auth config at ${configHostPath}.`,
        risk: "medium",
        specs: [bash(script, {
          redactions: pathRedactions(configHostPath, rootPasswordFile)
        })],
        rollback: [
          `rm -f ${configHostPath}`,
          ...(rootPasswordFile ? [`rm -f ${rootPasswordFile}`] : [])
        ],
        verification: [
          `test -s ${configHostPath}`,
          ...(rootPasswordFile ? [`test -s ${rootPasswordFile}`] : [])
        ]
      }, options);
    }
  • Input schema definition for the tool, declaring optional configHostPath and sid parameters plus standard profile/configPath/confirm properties.
    export function prepareAuthConfigSchema(): Tool["inputSchema"] {
      return {
        type: "object",
        properties: {
          profile: profileProperty(),
          configPath: configPathProperty(),
          confirm: confirmProperty("write the hardened config file"),
          configHostPath: {
            type: "string",
            description:
              "Host path for the generated hardened config. Defaults to profile.authConfigPath when present.",
          },
          sid: {
            type: "string",
            description:
              "SID to place into viewer, monitoring, administration, and register_dynamic_node_allowed_sids. Defaults to profile.dynamicNodeAuthSid or root@builtin.",
          },
        },
        additionalProperties: false,
      };
    }
  • Zod validation schema for the tool's arguments, extending MutatingArgs with optional configHostPath and sid fields.
    export const PrepareAuthConfigArgs = MutatingArgs.extend({
      configHostPath: z.string().optional(),
      sid: z.string().optional(),
    });
  • Tool registration in the MCP registry: defines the tool name, group (auth), description, input schema, annotations, and handler that delegates to prepareAuthConfig from @local-ydb-toolkit/core.
    defineTool({
      group: "auth",
      name: "local_ydb_prepare_auth_config",
      description:
        "Generate a hardened YDB config from the current static-node config. Use before local_ydb_write_dynamic_auth_config and local_ydb_apply_auth_hardening; without confirm=true this returns the planned write only.",
      inputSchema: prepareAuthConfigSchema(),
      annotations: mutatingAnnotations(),
      handler: withContext(PrepareAuthConfigArgs, (context, parsed) =>
        prepareAuthConfig(context, parsed),
      ),
    }),
Behavior4/5

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

Annotations provide basic safety hints, but the description adds valuable behavioral context: without confirm=true it returns a planned write only. This explains the non-destructive nature and conditional execution.

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?

Two concise sentences, front-loaded with purpose and usage, no unnecessary words.

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 description lacks details about the output format (no output schema) and what 'hardened' means. For a prepare tool with 5 parameters, more context on the generated config would be helpful.

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 coverage is 100%, so parameters are well-documented. The description does not add significant meaning beyond the schema; it only reinforces the confirm parameter's role.

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 generates a hardened YDB config from a static-node config, and distinguishes it from sibling tools by positioning it as a preparation step before write/apply.

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

Usage Guidelines5/5

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

Explicitly says 'Use before local_ydb_write_dynamic_auth_config and local_ydb_apply_auth_hardening', providing clear ordering and context. Also mentions the confirm flag for plan-only vs execution.

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

Install Server

Other Tools

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/astandrik/local-ydb-toolkit'

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