Skip to main content
Glama
dojoengine

Sensei MCP

by dojoengine

dojo_logic

Provides expert guidance for implementing Dojo systems and game logic, including contract functions, state changes, and World contract interactions, tailored for Cairo development on Starknet.

Instructions

Expert guidance on implementing Dojo systems and game logic. Use this when writing contract functions, implementing game mechanics, handling state changes, or working with the World contract to read/write models.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The handler function that executes the 'dojo_logic' tool (and all similar prompt-based tools). It substitutes input variables into the prompt template from the corresponding .txt file, detects Dojo-related tools via name matching ('dojo_*'), appends Dojo documentation references and topic-specific nudges (e.g., systems docs for 'logic'), and returns formatted text.
    const toolHandler = async (
      inputs: Record<string, string>,
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      _extra: Record<string, unknown>,
    ): Promise<CallToolResult> => {
      const span = Logger.span('toolExecution', { tool: toolName });
      try {
        let finalContent = processedContent;
    
        // Replace each variable with its value
        for (const variable of variables) {
          const value = inputs[variable] || '';
          const pattern = new RegExp(`\\{\\{${variable}\\}\\}`, 'g');
          finalContent = finalContent.replace(pattern, value);
        }
    
        // If there's a generic input and no specific {{input}} variable,
        // append it to the end
        if (inputs.input && !variables.includes('input')) {
          finalContent = `${finalContent}\n\n${inputs.input}`;
        }
    
        // Add the Dojo documentation nudge if this is a Dojo-related tool
        // We determine this based on the tool name or the input content
        const topic = toolName.toLowerCase().includes('dojo')
          ? toolName.replace('dojo_', '')
          : undefined;
    
        // Use the input content for context if available
        const inputContext = inputs.input || '';
    
        // If this is for Dojo, first add documentation references to the content
        if (toolName.toLowerCase().includes('dojo')) {
          finalContent = addDojoDocReferences(finalContent);
        }
    
        // Then add the documentation nudge based on the content and topic
        finalContent = addDojoDocsNudge(finalContent + inputContext, topic);
    
        span.end('success');
        return {
          content: [
            {
              type: 'text' as const,
              text: finalContent,
            },
          ],
        };
      } catch (error) {
        Logger.error(`Tool execution failed: ${toolName}`, error);
        span.end('error');
        throw error;
      }
  • Dynamically generates the Zod input schema for the tool based on variables ({{var}}) extracted from the prompt template. All vars are optional strings; adds dummy if none.
    export function generateInputSchema(variables: string[]): ZodRawShape {
      const schemaObj: Record<string, z.ZodTypeAny> = {};
    
      // Add all other variables
      for (const variable of variables) {
        schemaObj[variable] = z.string().optional();
      }
    
      // Add a dummy parameter to ensure the schema is not empty
      if (Object.keys(schemaObj).length === 0) {
        schemaObj._ = z
          .string()
          .optional()
          .describe('Dummy parameter for no-parameter tools');
      }
    
      return schemaObj;
    }
  • src/prompts.ts:474-485 (registration)
    Registers the tool with the MCP server inside registerPrompt, called for each prompts/*.txt file with register_as_tool: true in metadata. Uses filename or metadata.tool_name as toolName (e.g., 'dojo_logic').
    if (metadata.description) {
      // With description
      server.tool(
        toolName,
        metadata.description,
        schemaObj as ZodRawShape,
        toolHandler,
      );
    } else {
      // Without description
      server.tool(toolName, schemaObj, toolHandler);
    }
  • Dojo-specific helper called in handler for 'dojo_*' tools. For topic='logic' (from dojo_logic toolName.replace('dojo_','')), or logic keywords, appends nudge to verify against Dojo Systems documentation.
    export function addDojoDocsNudge(content: string, topic?: string): string {
      // Keywords that indicate code writing or verification tasks
      const modelKeywords = [
        'model',
        'models',
        'entity',
        'entities',
        'data structure',
        'schema',
      ];
      const logicKeywords = [
        'system',
        'systems',
        'logic',
        'game logic',
        'function',
        'functions',
        'contract',
      ];
      const configKeywords = [
        'config',
        'configuration',
        'scarb',
        'toml',
        'profile',
        'deployment',
      ];
    
      // Check if the content contains any of the keywords
      const hasModelKeywords = modelKeywords.some((keyword) =>
        content.toLowerCase().includes(keyword.toLowerCase()),
      );
      const hasLogicKeywords = logicKeywords.some((keyword) =>
        content.toLowerCase().includes(keyword.toLowerCase()),
      );
      const hasConfigKeywords = configKeywords.some((keyword) =>
        content.toLowerCase().includes(keyword.toLowerCase()),
      );
    
      // Customize nudge based on the specific topic
      let nudge = '';
    
      if (topic) {
        // If a specific topic is provided
        if (topic.toLowerCase().includes('model')) {
          nudge =
            '\n\nπŸ“š **Verify your model code against the [Dojo Models documentation](https://www.dojoengine.org/framework/models). Make sure to implement proper traits and follow entity relationships best practices.**';
        } else if (
          topic.toLowerCase().includes('logic') ||
          topic.toLowerCase().includes('system')
        ) {
          nudge =
            '\n\nπŸ“š **Verify your system logic against the [Dojo Systems documentation](https://www.dojoengine.org/framework/world/systems). Ensure correct world state management and authorization patterns.**';
        } else if (topic.toLowerCase().includes('config')) {
          nudge =
            '\n\nπŸ“š **Verify your configuration against the [Dojo Config documentation](https://www.dojoengine.org/framework/config). Check for proper Scarb.toml setup and profile configuration.**';
        }
      } else {
        // Determine topic based on keyword presence
        if (hasModelKeywords) {
          nudge =
            '\n\nπŸ“š **Verify your model code against the [Dojo Models documentation](https://www.dojoengine.org/framework/models). Make sure to implement proper traits and follow entity relationships best practices.**';
        } else if (hasLogicKeywords) {
          nudge =
            '\n\nπŸ“š **Verify your system logic against the [Dojo Systems documentation](https://www.dojoengine.org/framework/world/systems). Ensure correct world state management and authorization patterns.**';
        } else if (hasConfigKeywords) {
          nudge =
            '\n\nπŸ“š **Verify your configuration against the [Dojo Config documentation](https://www.dojoengine.org/framework/config). Check for proper Scarb.toml setup and profile configuration.**';
        }
      }
    
      // Add a general Dojo nudge if no specific topic was detected
      if (!nudge && (hasModelKeywords || hasLogicKeywords || hasConfigKeywords)) {
        nudge =
          '\n\nπŸ“š **Verify your Dojo code against the [official documentation](https://www.dojoengine.org/overview). Follow best practices for building provable games and applications.**';
      }
    
      return nudge ? content + nudge : content;
    }
  • Dojo-specific helper called in handler for 'dojo_*' tools before nudge. Detects code patterns (e.g., #[dojo::contract] for systems/logic) and appends relevant documentation links.
    export function addDojoDocReferences(content: string): string {
      // Don't modify content that already has documentation references
      if (
        content.includes('dojoengine.org/framework') ||
        content.includes('dojoengine.org/toolchain')
      ) {
        return content;
      }
    
      // Check for different types of Dojo content
      const hasModelContent =
        content.includes('#[dojo::model]') ||
        content.includes('#[key]') ||
        content.includes('derive(Model') ||
        content.includes('derive(Drop, Serde)');
    
      const hasSystemContent =
        content.includes('#[dojo::contract]') ||
        content.includes('world.read_model') ||
        content.includes('world.write_model') ||
        content.includes('self.world(');
    
      const hasConfigContent =
        content.includes('Scarb.toml') ||
        content.includes('dojo_') ||
        content.includes('[writers]') ||
        content.includes('[target.starknet-contract]');
    
      // Add appropriate documentation references based on content type
      if (hasModelContent) {
        return (
          content +
          '\n\n---\n**Reference Documentation:**\n' +
          '- [Models Overview](https://www.dojoengine.org/framework/models)\n' +
          '- [Entities in Dojo](https://www.dojoengine.org/framework/models/entities)\n' +
          '- [Model Introspection](https://www.dojoengine.org/framework/models/introspect)'
        );
      } else if (hasSystemContent) {
        return (
          content +
          '\n\n---\n**Reference Documentation:**\n' +
          '- [Systems](https://www.dojoengine.org/framework/world/systems)\n' +
          '- [World API](https://www.dojoengine.org/framework/world/api)\n' +
          '- [Authorization](https://www.dojoengine.org/framework/authorization)'
        );
      } else if (hasConfigContent) {
        return (
          content +
          '\n\n---\n**Reference Documentation:**\n' +
          '- [Configuration Guide](https://www.dojoengine.org/framework/config)\n' +
          '- [Sozo Commands](https://www.dojoengine.org/toolchain/sozo)\n' +
          '- [World Contract](https://www.dojoengine.org/framework/world)'
        );
      }
    
      // If content has cairo code but not specific Dojo patterns, add general Dojo reference
      if (
        content.includes('fn ') &&
        content.includes('struct ') &&
        content.includes('impl ')
      ) {
        return (
          content +
          '\n\n---\n**Reference Documentation:**\n' +
          '- [Dojo Documentation](https://www.dojoengine.org/overview)'
        );
      }
    
      return content;
    }
Install Server

Other Tools

Related 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/dojoengine/sensei-mcp'

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