Skip to main content
Glama
appolabs

Appo MCP

Official
by appolabs

validate_setup

Validates @appolabs/appo SDK setup by analyzing package.json and optionally checking import patterns to confirm correct configuration.

Instructions

Validate @appolabs/appo SDK installation and configuration. Analyzes package.json and optionally checks import patterns.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
packageJsonYesContent of package.json file to analyze
tsConfigNoContent of tsconfig.json (optional)
sampleCodeNoSample code to check for proper SDK usage patterns

Implementation Reference

  • The main handler function 'validateSetup' that executes the tool logic. Parses package.json, checks for @appolabs/appo dependency, validates React version, TypeScript config, and sample code patterns.
    export async function validateSetup(
      args: Record<string, unknown>
    ): Promise<{ content: Array<{ type: "text"; text: string }> }> {
      const { packageJson, tsConfig, sampleCode } = args as unknown as ValidateSetupArgs;
    
      const result: ValidationResult = {
        isValid: true,
        errors: [],
        warnings: [],
        suggestions: [],
      };
    
      // Parse package.json
      let pkg: Record<string, unknown>;
      try {
        pkg = JSON.parse(packageJson);
      } catch {
        return {
          content: [
            {
              type: "text",
              text: "**Error:** Invalid package.json - could not parse JSON",
            },
          ],
        };
      }
    
      // Check for @appolabs/appo installation
      const dependencies = (pkg.dependencies || {}) as Record<string, string>;
      const devDependencies = (pkg.devDependencies || {}) as Record<string, string>;
      const allDeps = { ...dependencies, ...devDependencies };
    
      if (!allDeps["@appolabs/appo"]) {
        result.isValid = false;
        result.errors.push(
          "@appolabs/appo is not installed. Run: `npm install @appolabs/appo` or `pnpm add @appolabs/appo`"
        );
      } else {
        const version = allDeps["@appolabs/appo"];
        // Check version (basic semver check)
        if (version.startsWith("^0.") || version.startsWith("0.")) {
          result.warnings.push(
            `You're using version ${version} which may be a pre-release. Consider upgrading to stable v1.x.`
          );
        }
      }
    
      // Check for React (required for hooks)
      if (!allDeps["react"]) {
        result.warnings.push(
          "React is not listed as a dependency. The SDK hooks require React 16.8+."
        );
      } else {
        const reactVersion = allDeps["react"];
        const majorVersion = parseInt(reactVersion.replace(/[\^~]/, "").split(".")[0], 10);
        if (majorVersion < 16) {
          result.errors.push(
            `React ${reactVersion} is too old. The SDK requires React 16.8+ for hooks support.`
          );
          result.isValid = false;
        }
      }
    
      // Check for TypeScript (recommended)
      if (!allDeps["typescript"]) {
        result.suggestions.push(
          "Consider adding TypeScript for better type safety. The SDK provides full TypeScript definitions."
        );
      }
    
      // Validate tsconfig if provided
      if (tsConfig) {
        try {
          const ts = JSON.parse(tsConfig);
          const compilerOptions = ts.compilerOptions || {};
    
          // Check module resolution
          if (
            compilerOptions.moduleResolution &&
            !["node", "node16", "nodenext", "bundler"].includes(
              compilerOptions.moduleResolution.toLowerCase()
            )
          ) {
            result.warnings.push(
              `moduleResolution is set to "${compilerOptions.moduleResolution}". Consider using "bundler" or "node16" for better ESM support.`
            );
          }
    
          // Check strict mode
          if (!compilerOptions.strict) {
            result.suggestions.push(
              "Enable strict mode in tsconfig.json for better type checking with the SDK."
            );
          }
    
          // Check esModuleInterop
          if (!compilerOptions.esModuleInterop) {
            result.warnings.push(
              "Enable esModuleInterop in tsconfig.json for proper module imports."
            );
          }
        } catch {
          result.warnings.push("Could not parse tsconfig.json");
        }
      }
    
      // Validate sample code if provided
      if (sampleCode) {
        validateCodePatterns(sampleCode, result);
      }
    
      // Build output
      const output = buildValidationOutput(result);
    
      return {
        content: [{ type: "text", text: output }],
      };
    }
  • Helper function 'validateCodePatterns' that analyzes sample code for proper SDK usage patterns (imports, async/await, permission handling, error handling, useEffect cleanup).
    function validateCodePatterns(code: string, result: ValidationResult): void {
      // Check for correct import
      if (code.includes("@appolabs/appo")) {
        if (!code.includes("getAppo") && !code.includes("from '@appolabs/appo'")) {
          result.warnings.push(
            "Make sure to import `getAppo` from '@appolabs/appo' to access the SDK instance."
          );
        }
      }
    
      // Check for direct window.appo access
      if (code.includes("window.appo")) {
        result.warnings.push(
          "Avoid accessing `window.appo` directly. Use `getAppo()` from the SDK for type safety and proper initialization."
        );
      }
    
      // Check for async/await usage with SDK methods
      const asyncMethods = [
        "requestPermission",
        "getToken",
        "authenticate",
        "takePicture",
        "getCurrentPosition",
        "getStatus",
        "getInfo",
      ];
    
      for (const method of asyncMethods) {
        if (code.includes(`.${method}(`) && !code.includes(`await`) && !code.includes(".then(")) {
          result.warnings.push(
            `The method \`${method}\` returns a Promise. Make sure to use \`await\` or \`.then()\`.`
          );
          break;
        }
      }
    
      // Check for permission handling
      if (
        (code.includes("push.getToken") || code.includes("camera.takePicture") || code.includes("location.getCurrentPosition")) &&
        !code.includes("requestPermission")
      ) {
        result.suggestions.push(
          "Consider requesting permission before accessing protected features (push token, camera, location)."
        );
      }
    
      // Check for error handling
      if (code.includes("getAppo()") && !code.includes("try") && !code.includes("catch")) {
        result.suggestions.push(
          "Consider adding try/catch blocks around SDK calls to handle potential errors gracefully."
        );
      }
    
      // Check for cleanup in useEffect
      if (code.includes("useEffect") && code.includes("onMessage") && !code.includes("return")) {
        result.warnings.push(
          "When using `appo.push.onMessage()` in useEffect, make sure to return the unsubscribe function for cleanup."
        );
      }
    }
  • Helper function 'buildValidationOutput' that formats the validation result into a human-readable markdown string with errors, warnings, suggestions, and quick-start guide.
    function buildValidationOutput(result: ValidationResult): string {
      const sections: string[] = [];
    
      // Status header
      if (result.isValid && result.errors.length === 0) {
        sections.push("## ✅ Setup Validation Passed\n");
      } else {
        sections.push("## ❌ Setup Validation Failed\n");
      }
    
      // Errors
      if (result.errors.length > 0) {
        sections.push("### Errors\n");
        result.errors.forEach((e) => sections.push(`- ❌ ${e}`));
        sections.push("");
      }
    
      // Warnings
      if (result.warnings.length > 0) {
        sections.push("### Warnings\n");
        result.warnings.forEach((w) => sections.push(`- ⚠️ ${w}`));
        sections.push("");
      }
    
      // Suggestions
      if (result.suggestions.length > 0) {
        sections.push("### Suggestions\n");
        result.suggestions.forEach((s) => sections.push(`- 💡 ${s}`));
        sections.push("");
      }
    
      // If everything is good
      if (
        result.errors.length === 0 &&
        result.warnings.length === 0 &&
        result.suggestions.length === 0
      ) {
        sections.push(
          "Your @appolabs/appo setup looks good! The SDK is properly installed and configured."
        );
      }
    
      // Next steps
      sections.push("\n### Quick Start\n");
      sections.push("```tsx");
      sections.push("import { getAppo } from '@appolabs/appo';");
      sections.push("");
      sections.push("function MyComponent() {");
      sections.push("  const appo = getAppo();");
      sections.push("");
      sections.push("  // Check if running in native app");
      sections.push("  if (appo.isNative) {");
      sections.push("    // Use native features");
      sections.push("  }");
      sections.push("}");
      sections.push("```");
    
      return sections.join("\n");
    }
  • Type definitions for ValidateSetupArgs (packageJson, tsConfig, sampleCode) and ValidationResult (isValid, errors, warnings, suggestions).
    interface ValidateSetupArgs {
      packageJson: string;
      tsConfig?: string;
      sampleCode?: string;
    }
    
    interface ValidationResult {
      isValid: boolean;
      errors: string[];
      warnings: string[];
      suggestions: string[];
    }
  • Registration of the 'validate_setup' tool in the tools array, including its name, description, and inputSchema with packageJson (required), tsConfig, and sampleCode parameters.
    {
      name: "validate_setup",
      description:
        "Validate @appolabs/appo SDK installation and configuration. Analyzes package.json and optionally checks import patterns.",
      inputSchema: {
        type: "object",
        properties: {
          packageJson: {
            type: "string",
            description: "Content of package.json file to analyze",
          },
          tsConfig: {
            type: "string",
            description: "Content of tsconfig.json (optional)",
          },
          sampleCode: {
            type: "string",
            description: "Sample code to check for proper SDK usage patterns",
          },
        },
        required: ["packageJson"],
      },
    },
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 behavioral traits. It does not state whether the operation is read-only, requires any permissions, or has side effects. The term 'validate' implies inspection, but this is not explicit.

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 single, concise sentence that front-loads the core purpose. It is not verbose, but it could benefit from slightly more detail without becoming lengthy.

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 or annotations, the description is too sparse. It does not explain the format of validation results (e.g., boolean, list of issues) or any return value, leaving the agent uncertain about what to expect.

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 input schema has 100% description coverage, so the schema already documents each parameter. The description adds minimal context beyond 'optionally checks import patterns' for sampleCode, but this does not significantly enhance understanding over the schema.

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 validates the @appolabs/appo SDK installation and configuration, specifying it analyzes package.json and optionally checks import patterns. This distinguishes it from sibling tools like check_permissions or generate_component.

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 the tool is used for validating SDK setup, but it does not explicitly state when to use it vs. alternatives (e.g., diagnose_issue). It lacks guidance on exclusions or prerequisites.

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/appolabs/appo-mcp'

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