Documentation Index
Fetch the complete documentation index at: https://mintlify.com/QwenLM/qwen-code/llms.txt
Use this file to discover all available pages before exploring further.
Creating Your First Extension
This guide walks you through creating a complete Qwen Code extension from scratch. You’ll learn how to set up the project structure, add an MCP server with custom tools, create commands, and configure everything properly.
Prerequisites
Before starting, ensure you have:
- Qwen Code installed and working
- Node.js 20+ (if creating MCP servers)
- Basic understanding of TypeScript/JavaScript
- A text editor or IDE
Quick Start: Using Templates
The fastest way to start is using the built-in templates:
# List available templates
qwen extensions new --help
# Create from template
qwen extensions new my-extension mcp-server
Available templates:
mcp-server - MCP server with example tools
commands - Custom command examples
skills - Skill examples
agent - Subagent examples
context - Context provider example
Manual Setup
To create an extension manually:
Step 1: Create the Extension Directory
mkdir my-first-extension
cd my-first-extension
Step 2: Create the Manifest File
Create qwen-extension.json:
{
"name": "my-first-extension",
"version": "1.0.0"
}
Naming rules:
- Use lowercase letters, numbers, and dashes only
- No spaces or underscores
- Must be unique among your installed extensions
- Directory name should match the
name field
Step 3: Add an MCP Server (Optional)
MCP servers provide tools the AI can use. Let’s create a simple server.
Create Package Files
Create package.json:
{
"name": "my-first-extension",
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "tsc"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.11.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^20.11.25",
"typescript": "~5.4.5"
}
}
Create tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["server.ts"]
}
Create the MCP Server
Create server.ts:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
const server = new McpServer({
name: 'my-first-extension',
version: '1.0.0',
});
// Register a simple tool
server.registerTool(
'get_greeting',
{
description: 'Returns a greeting message',
inputSchema: z.object({
name: z.string().describe('Name to greet'),
}).shape,
},
async ({ name }) => {
return {
content: [
{
type: 'text',
text: `Hello, ${name}! Welcome to my extension.`,
},
],
};
},
);
// Register a prompt
server.registerPrompt(
'greeting-prompt',
{
title: 'Greeting Generator',
description: 'Generate a creative greeting',
argsSchema: {
name: z.string(),
style: z.enum(['formal', 'casual', 'funny']).optional(),
},
},
({ name, style }) => ({
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Generate a ${style || 'friendly'} greeting for ${name}.`,
},
},
],
}),
);
const transport = new StdioServerTransport();
await server.connect(transport);
Update the Manifest
Update qwen-extension.json to reference the MCP server:
{
"name": "my-first-extension",
"version": "1.0.0",
"mcpServers": {
"myServer": {
"command": "node",
"args": ["${extensionPath}${/}dist${/}server.js"],
"cwd": "${extensionPath}"
}
}
}
Variable substitution:
${extensionPath} - Full path to extension directory
${workspacePath} - Current workspace directory
${/} or ${pathSeparator} - OS-specific path separator
Build the Server
npm install
npm run build
This compiles server.ts to dist/server.js.
Step 4: Add Custom Commands (Optional)
Create a commands directory:
Create commands/utils/summarize.md:
---
description: Summarize the content of a file
---
Please provide a concise summary of the following file:
File: {{args}}
!{cat {{args}}}
Create commands/search.md:
---
description: Search for pattern and provide analysis
---
Search for: `{{args}}`
Results:
!{grep -r "{{args}}" . --include="*.ts" --include="*.js"}
Please analyze these search results and provide insights.
Command naming:
- Top-level files:
/search
- Nested files:
/utils:summarize
- If conflicts exist:
/my-first-extension.search
Step 5: Add a Skill (Optional)
Create a skill directory:
mkdir -p skills/code-reviewer
Create skills/code-reviewer/SKILL.md:
---
name: code-reviewer
description: Performs thorough code reviews focusing on best practices, potential bugs, and improvements
license: MIT
---
# Code Reviewer Skill
This skill helps review code for quality, correctness, and maintainability.
## Review Focus Areas
### Code Quality
- Readability and clarity
- Naming conventions
- Code organization
- Documentation completeness
### Potential Issues
- Logic errors
- Edge cases not handled
- Performance concerns
- Security vulnerabilities
### Best Practices
- Design patterns
- SOLID principles
- Error handling
- Testing coverage
## Output Format
Provide reviews in this structure:
1. **Summary**: Overall assessment
2. **Strengths**: What's done well
3. **Issues**: Problems found (severity: critical/major/minor)
4. **Suggestions**: Specific improvements
5. **Examples**: Code snippets showing improvements
Update qwen-extension.json:
{
"name": "my-first-extension",
"version": "1.0.0",
"mcpServers": { ... },
"commands": "commands",
"skills": "skills"
}
Step 6: Add a Subagent (Optional)
Create an agents directory:
Create agents/test-writer.md:
---
name: test-writer
description: Specialized in writing comprehensive unit tests and test suites
color: green
tools:
- Read
- Write
- Grep
- Bash
modelConfig:
model: qwen3-coder-plus
temperature: 0.7
---
You are a testing specialist focused on creating high-quality test suites.
## Your Expertise
- Writing unit tests with proper coverage
- Creating integration tests
- Test-driven development (TDD)
- Mocking and stubbing strategies
- Testing edge cases and error conditions
## Testing Approach
1. **Understand the Code**: Read and analyze the implementation
2. **Identify Test Cases**: Consider normal, edge, and error cases
3. **Write Clear Tests**: Use descriptive names and arrange-act-assert pattern
4. **Ensure Coverage**: Test all critical paths and branches
5. **Use Best Practices**: Follow framework conventions and patterns
## Test Structure
For each function or module:
- Test the happy path
- Test boundary conditions
- Test error handling
- Test integration points
- Mock external dependencies
Always run tests after writing them to ensure they pass.
Update qwen-extension.json:
{
"name": "my-first-extension",
"version": "1.0.0",
"mcpServers": { ... },
"commands": "commands",
"skills": "skills",
"agents": "agents"
}
Step 7: Add Context (Optional)
Create QWEN.md:
# My First Extension
This extension provides development tools and AI assistants.
## Available Tools
### get_greeting
Returns a greeting message. Use this when the user wants a friendly greeting.
Example: "Can you greet John?"
## Custom Commands
- `/search <pattern>` - Search codebase and analyze results
- `/utils:summarize <file>` - Summarize file contents
## Guidelines
- Always be helpful and concise
- Use tools when appropriate
- Provide code examples when explaining concepts
Update qwen-extension.json:
{
"name": "my-first-extension",
"version": "1.0.0",
"contextFileName": "QWEN.md",
"mcpServers": { ... },
"commands": "commands",
"skills": "skills",
"agents": "agents"
}
Step 8: Add Settings (Optional)
If your extension needs configuration, add settings:
{
"name": "my-first-extension",
"version": "1.0.0",
"settings": [
{
"name": "API Key",
"description": "Your API key for the external service",
"envVar": "MY_EXTENSION_API_KEY",
"sensitive": true
},
{
"name": "Base URL",
"description": "Base URL for API requests",
"envVar": "MY_EXTENSION_BASE_URL",
"sensitive": false
}
],
"contextFileName": "QWEN.md",
"mcpServers": {
"myServer": {
"command": "node",
"args": ["${extensionPath}${/}dist${/}server.js"],
"cwd": "${extensionPath}",
"env": {
"API_KEY": "${MY_EXTENSION_API_KEY}",
"BASE_URL": "${MY_EXTENSION_BASE_URL}"
}
}
}
}
Settings are:
- Prompted during installation
- Stored securely (sensitive values in system keychain)
- Passed as environment variables to MCP servers
- Manageable via
qwen extensions settings command
Testing Your Extension
Link for Development
Create a symlink to your extension for development:
This allows you to test changes without reinstalling. However, you’ll need to restart Qwen Code sessions to see changes (except for runtime commands which hot-reload).
Test the Extension
Restart Qwen Code and try:
# Test MCP tool
"Can you greet Alice?"
# Test command
/search "TODO"
# Test agent
/agents manage
# Select and interact with test-writer
# View skills
/skills
Unlink When Done
To remove the symlink:
qwen extensions uninstall my-first-extension
Final Directory Structure
Your complete extension:
my-first-extension/
├── qwen-extension.json
├── package.json
├── tsconfig.json
├── server.ts
├── dist/
│ └── server.js # Built by `npm run build`
├── QWEN.md
├── commands/
│ ├── search.md
│ └── utils/
│ └── summarize.md
├── skills/
│ └── code-reviewer/
│ └── SKILL.md
└── agents/
└── test-writer.md
Next Steps