Skip to main content
Glama
pingidentity

PingOne Advanced Identity Cloud MCP Server

Official
by pingidentity

Create AM Script

createScript

Creates a new script for Scripted Decision Nodes to define custom authentication logic in PingOne journeys.

Instructions

Create a new Scripted Decision Node script for use in authentication journeys. Use getScriptedDecisionNodeBindings to see available variables and allowed imports before writing the script.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
realmYesThe realm to create the script in
nameYesThe name of the script
descriptionNoOptional description of the script
scriptYesThe JavaScript source code for the script

Implementation Reference

  • The main tool definition and handler function for 'createScript'. Defines the tool's name, title, description, scopes, input schema (realm, name, description, script), and the toolFunction that makes an authenticated POST request to AM to create a script.
    export const createScriptTool = {
      name: 'createScript',
      title: 'Create AM Script',
      description:
        'Create a new Scripted Decision Node script for use in authentication journeys. Use getScriptedDecisionNodeBindings to see available variables and allowed imports before writing the script.',
      scopes: SCOPES,
      annotations: {
        destructiveHint: false,
        openWorldHint: true
      },
      inputSchema: {
        realm: z.enum(REALMS).describe('The realm to create the script in'),
        name: z.string().min(1).describe('The name of the script'),
        description: z.string().optional().describe('Optional description of the script'),
        script: z.string().min(1).describe('The JavaScript source code for the script')
      },
      async toolFunction({
        realm,
        name,
        description,
        script
      }: {
        realm: string;
        name: string;
        description?: string;
        script: string;
      }) {
        try {
          const url = `${buildAMRealmUrl(realm, 'scripts')}?_action=create`;
    
          const payload = {
            context: 'AUTHENTICATION_TREE_DECISION_NODE',
            name,
            description: description || '',
            language: 'JAVASCRIPT',
            script: encodeBase64(script),
            evaluatorVersion: '2.0'
          };
    
          const { data, response } = await makeAuthenticatedRequest(url, SCOPES, {
            method: 'POST',
            headers: AM_SCRIPT_HEADERS_V2,
            body: JSON.stringify(payload)
          });
    
          const scriptData = data as { _id: string; name: string };
          const transactionId = response.headers.get('x-forgerock-transactionid') || 'unknown';
    
          return createToolResponse(
            `Script "${scriptData.name}" created successfully.\n` +
              `Script ID: ${scriptData._id}\n` +
              `Transaction ID: ${transactionId}`
          );
        } catch (error: any) {
          return createToolResponse(`Failed to create script "${name}" in realm "${realm}": ${error.message}`);
        }
      }
    };
  • Input schema for createScript using Zod: realm (enum from REALMS), name (string), description (optional string), script (string - the JavaScript source code).
    inputSchema: {
      realm: z.enum(REALMS).describe('The realm to create the script in'),
      name: z.string().min(1).describe('The name of the script'),
      description: z.string().optional().describe('Optional description of the script'),
      script: z.string().min(1).describe('The JavaScript source code for the script')
    },
  • src/index.ts:27-44 (registration)
    Generic tool registration loop: allTools.forEach calls server.registerTool with the tool's name, config, and toolFunction. createScript is registered here as part of the AM tools collection.
    allTools.forEach((tool) => {
      const toolConfig: ToolConfig = {
        title: tool.title,
        description: tool.description
      };
    
      // Only add inputSchema if it exists (some tools like getLogSources don't have one)
      if ('inputSchema' in tool && tool.inputSchema) {
        toolConfig.inputSchema = tool.inputSchema;
      }
    
      // Add annotations if present
      if ('annotations' in tool && tool.annotations) {
        toolConfig.annotations = tool.annotations;
      }
    
      server.registerTool(tool.name, toolConfig, tool.toolFunction as any);
    });
  • getAllTools collects all tools including AM tools (via amTools) that contains createScriptTool. AM tools are conditionally included only in non-Docker mode.
    export function getAllTools(): Tool[] {
      const isDockerMode = process.env.DOCKER_CONTAINER === 'true';
    
      const tools: Tool[] = [
        ...(Object.values(managedObjectTools) as Tool[]),
        ...(Object.values(logTools) as Tool[]),
        ...(Object.values(themeTools) as Tool[]),
        ...(Object.values(esvTools) as Tool[]),
        ...(Object.values(featureManagementTools) as Tool[])
      ];
    
      // Only include AM tools in non-Docker mode (requires browser-based PKCE auth)
      if (!isDockerMode) {
        tools.push(...(Object.values(amTools) as Tool[]));
        tools.push(...(Object.values(applicationTools) as Tool[]));
      }
    
      return tools;
    }
  • Uses helper utilities: buildAMRealmUrl to construct the URL, AM_SCRIPT_HEADERS_V2 for request headers, encodeBase64 to encode the script content, and makeAuthenticatedRequest to perform the API call.
    const url = `${buildAMRealmUrl(realm, 'scripts')}?_action=create`;
    
    const payload = {
      context: 'AUTHENTICATION_TREE_DECISION_NODE',
      name,
      description: description || '',
      language: 'JAVASCRIPT',
      script: encodeBase64(script),
      evaluatorVersion: '2.0'
    };
    
    const { data, response } = await makeAuthenticatedRequest(url, SCOPES, {
      method: 'POST',
      headers: AM_SCRIPT_HEADERS_V2,
      body: JSON.stringify(payload)
Behavior3/5

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

Annotations indicate non-destructive (destructiveHint=false) and possible side effects (openWorldHint=true). The description adds the action of creating a script but omits details like idempotency, error handling, or effects on existing journeys. The prerequisite reference adds minimal context.

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 sentences with clear front-loading of purpose. Every word adds value; no redundancy or filler.

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 references getScriptedDecisionNodeBindings for preconditions but does not explain the return value or failure modes (e.g., duplicate names). For a creation tool with no output schema, more detail on expected output or side effects would improve completeness.

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?

Input schema covers all 4 parameters with descriptions (100% coverage). The description does not add extra meaning beyond the schema; it mentions the script is for Scripted Decision Node, which is already implied by the tool name. Baseline 3 is appropriate.

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 creates a new script for Scripted Decision Nodes in authentication journeys, using specific verbs and resource. It distinguishes from siblings like updateScript and deleteScript.

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 explicitly advises using getScriptedDecisionNodeBindings to check available variables and imports before writing the script, providing a clear prerequisite. It does not discuss when not to use, but for a creation tool this is sufficient.

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/pingidentity/aic-mcp-server'

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