diff --git a/.gitignore b/.gitignore index 2bef4966..b632d47d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ **/node_modules **/.turbo .env - +**/.vscode **/log_iterations.json **/log_autonomous.txt diff --git a/packages/mcp/categories.json b/packages/mcp/categories.json index c6a7a77e..6b946563 100644 --- a/packages/mcp/categories.json +++ b/packages/mcp/categories.json @@ -36,7 +36,7 @@ "knowledge": { "name": "knowledge", "description": "AI-powered assistance, documentation, help guides, and educational resources for Starknet ecosystem and MCP servers", - "mcps": ["mcp-doc", "starknet-knowledge"] + "mcps": ["mcp-doc", "starknet-knowledge", "assist-with-dojo"] }, "tokens": { "name": "tokens", diff --git a/packages/mcp/mcps.json b/packages/mcp/mcps.json index 2c7fc235..6d5ef280 100644 --- a/packages/mcp/mcps.json +++ b/packages/mcp/mcps.json @@ -562,5 +562,20 @@ "mist_cash_get_chamber_info" ] } + }, + "assist-with-dojo": { + "client": { + "command": "npx", + "args": ["-y", "@kasarlabs/assist-with-dojo-mcp@latest"], + "transport": "stdio", + "env": { + "CAIRO_CODER_API_KEY": "" + } + }, + "description": "AI-powered assistance for Dojo game engine development on Starknet. Use for: learning about Dojo, understanding Dojo concepts, building games with Dojo, getting Dojo best practices", + "promptInfo": { + "expertise": "Dojo game engine, ECS architecture, onchain gaming on Starknet, Dojo toolchain, and Dojo development patterns", + "tools": ["assist-with-dojo"] + } } } diff --git a/packages/mcp/mcps.local.json b/packages/mcp/mcps.local.json index cf2e889e..2ba3cfd3 100644 --- a/packages/mcp/mcps.local.json +++ b/packages/mcp/mcps.local.json @@ -539,6 +539,21 @@ ] } }, + "assist-with-dojo": { + "client": { + "command": "node", + "args": ["../mcps/assist-with-dojo/build/index.js"], + "transport": "stdio", + "env": { + "CAIRO_CODER_API_KEY": "" + } + }, + "description": "AI-powered assistance for Dojo game engine development on Starknet. Use for: learning about Dojo, understanding Dojo concepts, building games with Dojo, getting Dojo best practices", + "promptInfo": { + "expertise": "Dojo game engine, ECS architecture, onchain gaming on Starknet, Dojo toolchain, and Dojo development patterns", + "tools": ["assist-with-dojo"] + } + }, "mist-cash": { "client": { "command": "node", diff --git a/packages/mcps/assist-with-dojo/.env.example b/packages/mcps/assist-with-dojo/.env.example new file mode 100644 index 00000000..d4613119 --- /dev/null +++ b/packages/mcps/assist-with-dojo/.env.example @@ -0,0 +1,9 @@ +# Cairo Coder API Configuration +# Copy this file to .env and fill in your actual API key + +# Your Cairo Coder API key (required) +# Get it from: https://cairo-coder.com/ +CAIRO_CODER_API_KEY=your-api-key-here + +# Your Cairo Coder Endpoint (if deployed locally) +CAIRO_CODER_API_ENDPOINT=http://localhost:3001 \ No newline at end of file diff --git a/packages/mcps/assist-with-dojo/.eslintrc.js b/packages/mcps/assist-with-dojo/.eslintrc.js new file mode 100644 index 00000000..46567e82 --- /dev/null +++ b/packages/mcps/assist-with-dojo/.eslintrc.js @@ -0,0 +1,23 @@ +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + extends: ['eslint:recommended', '@typescript-eslint/recommended'], + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module', + }, + env: { + node: true, + es6: true, + }, + rules: { + // Personnalisez vos règles ici + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'warn', + 'prefer-const': 'error', + 'no-var': 'error', + }, + ignorePatterns: ['dist/', 'node_modules/', '*.js'], +}; diff --git a/packages/mcps/assist-with-dojo/.gitignore b/packages/mcps/assist-with-dojo/.gitignore new file mode 100644 index 00000000..494ca540 --- /dev/null +++ b/packages/mcps/assist-with-dojo/.gitignore @@ -0,0 +1,86 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +dist/ +build/ +*.tsbuildinfo + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ +*.lcov + +# nyc test coverage +.nyc_output + +# Dependency directories +node_modules/ +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +# Nuxt.js build output +.nuxt + +# Storybook build outputs +.out +.storybook-out + +# Temporary folders +tmp/ +temp/ \ No newline at end of file diff --git a/packages/mcps/assist-with-dojo/README.md b/packages/mcps/assist-with-dojo/README.md new file mode 100644 index 00000000..80b44a0b --- /dev/null +++ b/packages/mcps/assist-with-dojo/README.md @@ -0,0 +1,144 @@ +# Starknet Knowledge MCP Server + +A Model Context Protocol (MCP) server providing access to Starknet ecosystem knowledge and documentation via the Cairo Coder API. + +## Quick Start + +Use this MCP server directly with npx: + +```bash +npx -y @kasarlabs/assist-with-dojo-mcp +``` + +## Configuration + +The server supports two modes of operation: + +### Mode 1: Public Cairo Coder API (Default) + +Use the official Cairo Coder API with your API key. + +**Environment Variables:** + +- `CAIRO_CODER_API_KEY`: Your Cairo Coder API key (required) + +**MCP Client Setup:** + +```json +{ + "mcpServers": { + "assist-with-dojo": { + "command": "npx", + "args": ["-y", "@kasarlabs/assist-with-dojo-mcp"], + "env": { + "CAIRO_CODER_API_KEY": "your-api-key-here" + } + } + } +} +``` + +### Mode 2: Local/Custom Endpoint + +Use a local or custom Cairo Coder API endpoint (no API key required). + +**Environment Variables:** + +- `CAIRO_CODER_API_ENDPOINT`: Your local endpoint URL (e.g., "http://localhost:8000") + +**MCP Client Setup:** + +```json +{ + "mcpServers": { + "assist-with-dojo": { + "command": "npx", + "args": ["-y", "@kasarlabs/assist-with-dojo-mcp"], + "env": { + "CAIRO_CODER_API_ENDPOINT": "http://localhost:8000" + } + } + } +} +``` + +> **Note:** When using `CAIRO_CODER_API_ENDPOINT`, the server automatically switches to local mode and no API key is required or used. + +## Available Tools + +### assist-with-dojo + +Get information about the Starknet ecosystem, protocols, and general knowledge. + +**Parameters:** + +- `query` (string, required): Your question about Starknet ecosystem +- `context` (string, optional): Additional context or specific topic area + +**Examples:** + +```typescript +// General ecosystem question +{ + "query": "What are the main DEXs on Starknet?" +} + +// Specific protocol information +{ + "query": "How does AVNU handle token routing?", + "context": "I'm building a swap aggregator" +} +``` + +## What You Can Learn About + +- **Starknet Ecosystem**: Protocols, dApps, and services on Starknet +- **DeFi Protocols**: Information about DEXs, lending platforms, and yield farming +- **Technical Concepts**: Understanding of Starknet-specific features and technologies +- **Recent Updates**: Latest news and developments in the Starknet ecosystem +- **Best Practices**: Recommendations based on ecosystem standards + +## Tips for Better Results + +- Be specific about what aspect of the ecosystem you're interested in +- Mention specific protocols or concepts when relevant +- Provide context about your use case for more targeted responses +- Ask about recent developments or protocol comparisons + +## Development + +### Prerequisites + +- Node.js >= 18 +- npm or yarn + +### Local Installation + +```bash +git clone +cd ask-starknet/packages/mcps/assist-with-dojo +npm install +``` + +### Available Scripts + +```bash +npm run build # Build the project +npm run dev # Start in development mode +npm start # Start in production mode +``` + +## License + +MIT + +## Support + +For issues and questions: + +- GitHub Issues: [Create an issue](https://github.com/kasarlabs/ask-starknet/issues) +- MCP Documentation: [Model Context Protocol](https://modelcontextprotocol.io/) + +## Contributing + +Contributions are welcome! Please check the contribution guidelines before submitting a PR. diff --git a/packages/mcps/assist-with-dojo/package.json b/packages/mcps/assist-with-dojo/package.json new file mode 100644 index 00000000..9795d5d6 --- /dev/null +++ b/packages/mcps/assist-with-dojo/package.json @@ -0,0 +1,71 @@ +{ + "name": "@kasarlabs/assist-with-dojo-mcp", + "version": "0.1.0", + "description": "MCP server for Starknet ecosystem knowledge and documentation", + "type": "module", + "main": "build/index.js", + "exports": { + ".": { + "import": "./build/index.js", + "types": "./build/index.d.ts" + } + }, + "bin": { + "assist-with-dojo-mcp": "./build/index.js" + }, + "files": [ + "build", + "README.md", + "LICENSE" + ], + "scripts": { + "build": "tsc && chmod +x build/index.js", + "start": "node build/index.js", + "dev": "tsx src/index.ts", + "lint": "eslint src/**/*.ts", + "lint:fix": "eslint src/**/*.ts --fix", + "clean": "rm -rf build node_modules", + "prepublishOnly": "npm run clean && npm install && npm run build", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "mcp", + "starknet", + "knowledge", + "documentation", + "ecosystem", + "blockchain", + "cli", + "npx" + ], + "author": "KasarLabs", + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "1.22.0", + "dotenv": "^16.5.0", + "zod": "^3.24.2" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.0.0", + "tsx": "^4.7.0", + "typescript": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "repository": { + "type": "git", + "url": "https://github.com/kasarlabs/ask-starknet", + "directory": "packages/mcps/assist-with-dojo" + }, + "bugs": { + "url": "https://github.com/kasarlabs/ask-starknet/issues" + }, + "homepage": "https://github.com/kasarlabs/ask-starknet/tree/main/packages/mcps/assist-with-dojo#readme" +} diff --git a/packages/mcps/assist-with-dojo/src/index.ts b/packages/mcps/assist-with-dojo/src/index.ts new file mode 100644 index 00000000..2e022c11 --- /dev/null +++ b/packages/mcps/assist-with-dojo/src/index.ts @@ -0,0 +1,228 @@ +#!/usr/bin/env node + +import 'dotenv/config'; +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import packageJson from '../package.json' with { type: 'json' }; +import { assistWithDojoSchema, type AssistWithDojoInput } from './schemas.js'; + +/** + * Represents a message in the Dojo assistant conversation + */ +interface DojoAssistantMessage { + role: 'user' | 'assistant' | 'system'; + content: string; +} + +/** + * Request payload for the Dojo assistant API + */ +interface DojoAssistantRequest { + messages: DojoAssistantMessage[]; +} + +/** + * Response from the Dojo assistant API + */ +interface DojoAssistantResponse { + choices: Array<{ + message: { + content: string; + role: string; + }; + }>; +} + +/** + * MCP Server implementation for Dojo assistant API integration + * Provides AI-powered assistance for Dojo development + */ +class DojoAssistantMCPServer { + private server: McpServer; + private apiKey: string; + private apiUrl: string; + private isLocalMode: boolean; + + /** + * Initializes the Dojo Assistant MCP Server + * @throws {Error} If CAIRO_CODER_API_KEY environment variable is not set when using public API + */ + constructor() { + this.server = new McpServer({ + name: 'assist-with-dojo-mcp', + version: packageJson.version, + }); + + // Check if local endpoint is specified + const localEndpoint = process.env.CAIRO_CODER_API_ENDPOINT; + + if (localEndpoint) { + // Local mode: use custom endpoint, no API key required + this.isLocalMode = true; + this.apiUrl = `${localEndpoint}/v1/chat/completions`; + this.apiKey = ''; + console.error( + `Assist-with-dojo MCP server configured for local mode: ${this.apiUrl}` + ); + } else { + // Public API mode: use official endpoint, API key required + this.isLocalMode = false; + this.apiUrl = 'https://api.cairo-coder.com/v1/chat/completions'; + this.apiKey = process.env.CAIRO_CODER_API_KEY || ''; + console.error( + 'Assist-with-dojo MCP server configured for public API mode' + ); + } + + this.setupToolHandlers(); + } + + /** + * Sets up the tool handlers for the MCP server + * Configures the assist-with-dojo tool + */ + private setupToolHandlers(): void { + this.server.tool( + 'assist-with-dojo', + `Provides expert responses to queries about Dojo and all its components. + +Call this tool when the user needs to: +- **Understand Dojo core concepts** and architecture +- **Work with Dojo components**: Katana (local development node), Torii (indexer), Sozo (CLI tool), Saya (settlement layer), Cainome (bindings generator) +- **Learn about Dojo SDKs**: dojo.js, dojo.c, dojo.unity, dojo.rust, dojo.godot, dojo.bevy, dojo.unreal +- **Use Dojo libraries**: Origami (game primitives) and Alexandria (standard library) +- **Build onchain games** with the Dojo framework +- **Deploy and manage** Dojo worlds and contracts + +This tool has access to comprehensive Dojo documentation, component guides, SDK references, and library documentation.`, + assistWithDojoSchema.shape, + async (args: AssistWithDojoInput) => { + return await this.handleDojoAssistance(args); + } + ); + } + + /** + * Handles Dojo assistance requests by calling the Dojo assistant API + * @param args - The arguments containing query and optional conversation history + * @returns The response from the Dojo assistant API or an error message + */ + private async handleDojoAssistance(args: AssistWithDojoInput) { + try { + const { query, history } = args; + + if (!query) { + throw new Error('Query parameter is required'); + } + + // Validate API key is available in public API mode + if (!this.isLocalMode && !this.apiKey) { + throw new Error( + 'CAIRO_CODER_API_KEY environment variable is required when using public API' + ); + } + + // Add context to guide the backend towards Dojo-specific responses + let contextualMessage = `As a Dojo expert, answer the following question:\n\n${query}`; + + if (history && history.length > 0) { + contextualMessage = `Previous conversation context:\n${history.join('\n')}\n\nCurrent query: ${contextualMessage}`; + } + + const requestBody: DojoAssistantRequest = { + messages: [ + { + role: 'user', + content: contextualMessage, + }, + ], + }; + + // Prepare headers based on mode + const headers: Record = { + 'Content-Type': 'application/json', + mcp: 'true', + }; + + // Only add API key header in public API mode + if (!this.isLocalMode && this.apiKey) { + headers['x-api-key'] = this.apiKey; + } + + const response = await fetch(this.apiUrl, { + method: 'POST', + headers, + body: JSON.stringify(requestBody), + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error( + `API request failed: ${response.status} ${response.statusText} - ${errorText}` + ); + } + + const data = (await response.json()) as DojoAssistantResponse; + + if (!data.choices || data.choices.length === 0) { + throw new Error('No response received from Dojo assistant API'); + } + + const assistantResponse = data.choices[0].message.content; + + return { + content: [ + { + type: 'text' as const, + text: assistantResponse, + }, + ], + }; + } catch (error) { + const errorMessage = + error instanceof Error ? error.message : 'Unknown error occurred'; + + return { + content: [ + { + type: 'text' as const, + text: `Error: ${errorMessage}`, + }, + ], + isError: true, + }; + } + } + + /** + * Starts the MCP server with stdio transport + * @throws {Error} If the server fails to start + */ + async run(): Promise { + const transport = new StdioServerTransport(); + console.error('AssistWithDojo server running on stdio'); + await this.server.connect(transport); + + // Handle graceful shutdown + process.on('SIGINT', async () => { + await this.server.close(); + process.exit(0); + }); + } +} + +/** + * Main entry point for the application + * Creates and starts the Dojo Assistant MCP server + */ +async function main() { + const server = new DojoAssistantMCPServer(); + await server.run(); +} + +main().catch((error) => { + console.error('Fatal error in main():', error); + process.exit(1); +}); + +export default DojoAssistantMCPServer; diff --git a/packages/mcps/assist-with-dojo/src/schemas.ts b/packages/mcps/assist-with-dojo/src/schemas.ts new file mode 100644 index 00000000..3ea066f0 --- /dev/null +++ b/packages/mcps/assist-with-dojo/src/schemas.ts @@ -0,0 +1,21 @@ +import { z } from 'zod'; + +/** + * Schema for the assist-with-dojo tool + * Specialized for Dojo game engine, its components, SDKs, and onchain game development + */ +export const assistWithDojoSchema = z.object({ + query: z + .string() + .describe( + "The user's question about Dojo game engine and its ecosystem. Use this for understanding Dojo core concepts, components (Katana, Torii, Sozo, Saya, Cainome), SDKs (dojo.js, dojo.c, dojo.unity, dojo.rust, dojo.godot, dojo.bevy, dojo.unreal), libraries (Origami, Alexandria), building onchain games, and deploying Dojo worlds (e.g., 'How do I use Katana for local development?' or 'Explain Dojo's ECS architecture')." + ), + history: z + .array(z.string()) + .optional() + .describe( + 'Optional: The preceding conversation history about Dojo. This can help the tool understand the context of the discussion and provide more accurate answers.' + ), +}); + +export type AssistWithDojoInput = z.infer; diff --git a/packages/mcps/assist-with-dojo/tsconfig.json b/packages/mcps/assist-with-dojo/tsconfig.json new file mode 100644 index 00000000..206174e4 --- /dev/null +++ b/packages/mcps/assist-with-dojo/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Node", + "outDir": "./build", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "resolveJsonModule": true, + "verbatimModuleSyntax": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "build"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8bf5a62..6a7be84e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -200,6 +200,37 @@ importers: specifier: ^5.8.2 version: 5.9.3 + packages/mcps/assist-with-dojo: + dependencies: + '@modelcontextprotocol/sdk': + specifier: 1.22.0 + version: 1.22.0(@cfworker/json-schema@4.1.1) + dotenv: + specifier: ^16.5.0 + version: 16.6.1 + zod: + specifier: ^3.24.2 + version: 3.25.76 + devDependencies: + '@types/node': + specifier: ^20.0.0 + version: 20.19.26 + '@typescript-eslint/eslint-plugin': + specifier: ^6.0.0 + version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/parser': + specifier: ^6.0.0 + version: 6.21.0(eslint@8.57.1)(typescript@5.9.3) + eslint: + specifier: ^8.0.0 + version: 8.57.1 + tsx: + specifier: ^4.7.0 + version: 4.21.0 + typescript: + specifier: ^5.0.0 + version: 5.9.3 + packages/mcps/avnu: dependencies: '@avnu/avnu-sdk':