feat: add Appium MCP Server documentation and tests

- Add comprehensive test suite for Appium MCP Server configuration
- Document MCP server marketplace item structure
- Provide guidance for adding new MCP servers to marketplace
- Include example configuration for Appium MCP Server

Addresses #9479
This commit is contained in:
Roo Code 2025-11-21 17:59:42 +00:00
parent 852e293610
commit 247368c7c6
2 changed files with 519 additions and 0 deletions

View file

@ -0,0 +1,211 @@
# Adding MCP Servers to the Roo Code Marketplace
## Overview
The Roo Code Marketplace provides a centralized location for discovering and installing MCP (Model Context Protocol) servers. This document describes how MCP servers are configured and provides guidance for requesting new servers to be added.
## MCP Server Configuration Structure
MCP servers in the marketplace are defined with the following structure:
```typescript
interface McpMarketplaceItem {
id: string // Unique identifier for the server
name: string // Display name
description: string // Brief description of functionality
author?: string // Author/organization name
authorUrl?: string // Link to author's website or GitHub
url: string // Repository URL
type: "mcp" // Item type (always "mcp" for servers)
tags?: string[] // Searchable tags
prerequisites?: string[] // Installation requirements
content: string | McpInstallationMethod[] // Server configuration
parameters?: McpParameter[] // Configurable parameters
}
```
### Basic MCP Server Configuration
For a simple MCP server that runs via NPX:
```json
{
"id": "example-mcp",
"name": "Example MCP Server",
"description": "An example MCP server for demonstration",
"url": "https://github.com/example/example-mcp",
"type": "mcp",
"content": "{\"command\": \"npx\", \"args\": [\"-y\", \"@example/mcp-server\"]}"
}
```
### MCP Server with Parameters
For servers that require configuration:
```json
{
"id": "configurable-mcp",
"name": "Configurable MCP Server",
"description": "MCP server with user-configurable options",
"url": "https://github.com/example/configurable-mcp",
"type": "mcp",
"content": "{\"command\": \"npx\", \"args\": [\"-y\", \"@example/mcp-server\"], \"env\": {\"API_KEY\": \"{{API_KEY}}\"}}",
"parameters": [
{
"name": "API Key",
"key": "API_KEY",
"placeholder": "Enter your API key",
"optional": false
}
]
}
```
### Multiple Installation Methods
For servers with different installation options:
```json
{
"id": "multi-install-mcp",
"name": "Multi-Install MCP Server",
"description": "MCP server with multiple installation methods",
"url": "https://github.com/example/multi-mcp",
"type": "mcp",
"content": [
{
"name": "NPX (Recommended)",
"content": "{\"command\": \"npx\", \"args\": [\"-y\", \"@example/mcp\"]}"
},
{
"name": "Docker",
"content": "{\"command\": \"docker\", \"args\": [\"run\", \"-p\", \"3000:3000\", \"example/mcp:latest\"]}",
"prerequisites": ["Docker installed and running"]
},
{
"name": "Global Install",
"content": "{\"command\": \"example-mcp\", \"args\": []}",
"prerequisites": ["Install globally first: npm install -g @example/mcp"]
}
]
}
```
## Example: Appium MCP Server Configuration
The Appium MCP Server, as requested in issue #9479, would be configured as follows:
```json
{
"id": "appium-mcp",
"name": "Appium MCP Server",
"description": "MCP server for Mobile Development and Automation | iOS, Android, Simulator, Emulator, and Real Devices",
"author": "Appium Contributors",
"authorUrl": "https://github.com/appium",
"url": "https://github.com/appium/appium-mcp",
"type": "mcp",
"tags": ["mobile", "automation", "ios", "android", "testing", "appium"],
"prerequisites": [
"Node.js 16+ and npm installed",
"Appium installed globally or locally",
"Platform-specific requirements (Xcode for iOS, Android SDK for Android)"
],
"content": "{\"command\": \"npx\", \"args\": [\"-y\", \"@appium/mcp-server\"], \"env\": {\"APPIUM_HOST\": \"localhost\", \"APPIUM_PORT\": \"4723\"}}",
"parameters": [
{
"name": "Appium Host",
"key": "APPIUM_HOST",
"placeholder": "localhost",
"optional": true
},
{
"name": "Appium Port",
"key": "APPIUM_PORT",
"placeholder": "4723",
"optional": true
}
]
}
```
## MCP Server Capabilities
When documenting an MCP server for the marketplace, include information about its capabilities:
### Tools
List the tools/commands the server exposes:
- `launch_app` - Launch a mobile application
- `find_element` - Find UI elements
- `take_screenshot` - Capture device screen
- etc.
### Resources
List the resources available:
- `device_list` - Available devices
- `session_info` - Current session details
- etc.
### Prompts
List any pre-configured prompts:
- `test_login_flow` - Automate login testing
- `validate_ui_elements` - Check UI consistency
- etc.
## How to Request a New MCP Server
To request a new MCP server be added to the marketplace:
1. **Open an Issue**: Create a GitHub issue in the Roo Code repository
2. **Provide Information**:
- Server name and description
- GitHub repository URL
- Installation command (NPX, Docker, etc.)
- Any required configuration parameters
- Prerequisites for installation
- List of capabilities (tools, resources, prompts)
3. **Include Examples**: Provide example use cases or documentation links
4. **Test the Server**: Confirm the server works with the MCP protocol
## Technical Implementation
The marketplace items are fetched from a remote API endpoint managed by the Roo Code team. The actual configuration data is stored server-side and retrieved by the extension at runtime.
### API Endpoints
- Modes: `https://api.roocode.com/api/marketplace/modes`
- MCP Servers: `https://api.roocode.com/api/marketplace/mcps`
### Local Testing
For development and testing, you can mock MCP server configurations using the test framework as shown in `src/services/marketplace/__tests__/appium-mcp-server.spec.ts`.
## Best Practices
1. **Clear Naming**: Use descriptive, unique IDs and names
2. **Comprehensive Descriptions**: Explain what the server does and its use cases
3. **Document Prerequisites**: List all requirements for successful installation
4. **Provide Parameters**: Allow users to configure server behavior
5. **Tag Appropriately**: Use relevant tags for discoverability
6. **Test Thoroughly**: Ensure the server configuration works before submission
## Security Considerations
- Never include sensitive information (API keys, passwords) in the configuration
- Use parameter placeholders for user-specific values
- Verify server authenticity through official repository URLs
- Review server permissions and capabilities before installation
## Support
For questions about adding MCP servers to the marketplace:
- Open a GitHub issue with the "enhancement" label
- Join the community discussions
- Refer to the MCP protocol documentation

View file

@ -0,0 +1,308 @@
// npx vitest services/marketplace/__tests__/appium-mcp-server.spec.ts
import { SimpleInstaller } from "../SimpleInstaller"
import { MarketplaceItem } from "@roo-code/types"
import * as fs from "fs/promises"
import * as path from "path"
import * as vscode from "vscode"
import { vi, describe, it, expect, beforeEach } from "vitest"
// Mock fs module
vi.mock("fs/promises")
// Mock vscode module
vi.mock("vscode", () => ({
workspace: {
workspaceFolders: [
{
uri: {
fsPath: "/test/workspace",
},
},
],
},
}))
describe("Appium MCP Server Installation", () => {
let installer: SimpleInstaller
const mockFs = fs as any
const mockContext = {
globalStorageUri: { fsPath: "/test/global" },
storageUri: { fsPath: "/test/storage" },
} as any
beforeEach(() => {
vi.clearAllMocks()
installer = new SimpleInstaller(mockContext, undefined)
// Mock file operations
mockFs.access.mockResolvedValue(undefined)
mockFs.writeFile.mockResolvedValue(undefined)
mockFs.readFile.mockResolvedValue("{}")
mockFs.mkdir.mockResolvedValue(undefined)
})
describe("Appium MCP Server Configuration", () => {
it("should define Appium MCP Server marketplace item correctly", () => {
// This is the expected configuration for Appium MCP Server
const appiumMcpItem: MarketplaceItem = {
id: "appium-mcp",
name: "Appium MCP Server",
description:
"MCP server for Mobile Development and Automation | iOS, Android, Simulator, Emulator, and Real Devices",
author: "Appium Contributors",
authorUrl: "https://github.com/appium",
url: "https://github.com/appium/appium-mcp",
type: "mcp",
tags: ["mobile", "automation", "ios", "android", "testing", "appium"],
content: JSON.stringify({
command: "npx",
args: ["-y", "@appium/mcp-server"],
env: {
APPIUM_HOST: "localhost",
APPIUM_PORT: "4723",
},
}),
prerequisites: [
"Node.js 16+ and npm installed",
"Appium installed globally or locally",
"Platform-specific requirements (Xcode for iOS, Android SDK for Android)",
],
}
// Validate the structure
expect(appiumMcpItem.id).toBe("appium-mcp")
expect(appiumMcpItem.type).toBe("mcp")
expect(appiumMcpItem.name).toBe("Appium MCP Server")
expect(appiumMcpItem.url).toBe("https://github.com/appium/appium-mcp")
expect(appiumMcpItem.tags).toContain("mobile")
expect(appiumMcpItem.tags).toContain("automation")
expect(appiumMcpItem.prerequisites).toBeDefined()
expect(appiumMcpItem.prerequisites?.length).toBeGreaterThan(0)
})
it("should support alternative Appium MCP installation methods", () => {
// Alternative installation method using multiple configurations
const appiumMcpWithMethods: MarketplaceItem = {
id: "appium-mcp",
name: "Appium MCP Server",
description: "MCP server for Mobile Development and Automation",
url: "https://github.com/appium/appium-mcp",
type: "mcp",
content: [
{
name: "Default (NPX)",
content: JSON.stringify({
command: "npx",
args: ["-y", "@appium/mcp-server"],
}),
},
{
name: "Docker",
content: JSON.stringify({
command: "docker",
args: ["run", "-p", "4723:4723", "appium/appium-mcp:latest"],
}),
prerequisites: ["Docker installed and running"],
},
{
name: "Global NPM Install",
content: JSON.stringify({
command: "appium-mcp",
args: [],
}),
prerequisites: ["Install globally first: npm install -g @appium/mcp-server"],
},
],
}
// Validate multiple installation methods
expect(Array.isArray(appiumMcpWithMethods.content)).toBe(true)
if (Array.isArray(appiumMcpWithMethods.content)) {
expect(appiumMcpWithMethods.content).toHaveLength(3)
expect(appiumMcpWithMethods.content[0].name).toBe("Default (NPX)")
expect(appiumMcpWithMethods.content[1].name).toBe("Docker")
expect(appiumMcpWithMethods.content[2].name).toBe("Global NPM Install")
}
})
})
describe("Installing Appium MCP Server", () => {
it("should install Appium MCP Server to project configuration", async () => {
const appiumMcpItem: MarketplaceItem = {
id: "appium-mcp",
name: "Appium MCP Server",
description: "MCP server for Mobile Development and Automation",
url: "https://github.com/appium/appium-mcp",
type: "mcp",
content: JSON.stringify({
command: "npx",
args: ["-y", "@appium/mcp-server"],
env: {
APPIUM_HOST: "localhost",
APPIUM_PORT: "4723",
},
}),
}
// Mock existing MCP configuration
mockFs.readFile.mockResolvedValue(
JSON.stringify({
mcpServers: {
"existing-server": {
command: "node",
args: ["server.js"],
},
},
}),
)
const result = await installer.installItem(appiumMcpItem, {
target: "project",
})
expect(result.filePath).toContain("mcp.json")
expect(mockFs.writeFile).toHaveBeenCalled()
// Verify the written content includes Appium MCP
const writtenContent = mockFs.writeFile.mock.calls[0][1]
const writtenData = JSON.parse(writtenContent)
expect(writtenData.mcpServers["appium-mcp"]).toBeDefined()
expect(writtenData.mcpServers["appium-mcp"].command).toBe("npx")
expect(writtenData.mcpServers["appium-mcp"].args).toContain("-y")
expect(writtenData.mcpServers["appium-mcp"].args).toContain("@appium/mcp-server")
expect(writtenData.mcpServers["appium-mcp"].env.APPIUM_HOST).toBe("localhost")
expect(writtenData.mcpServers["appium-mcp"].env.APPIUM_PORT).toBe("4723")
})
it("should install Appium MCP Server with parameters", async () => {
const appiumMcpItem: MarketplaceItem = {
id: "appium-mcp",
name: "Appium MCP Server",
description: "MCP server for Mobile Development and Automation",
url: "https://github.com/appium/appium-mcp",
type: "mcp",
content: JSON.stringify({
command: "npx",
args: ["-y", "@appium/mcp-server"],
env: {
APPIUM_HOST: "{{APPIUM_HOST}}",
APPIUM_PORT: "{{APPIUM_PORT}}",
PLATFORM_NAME: "{{PLATFORM_NAME}}",
},
}),
parameters: [
{
name: "Appium Host",
key: "APPIUM_HOST",
placeholder: "localhost",
optional: false,
},
{
name: "Appium Port",
key: "APPIUM_PORT",
placeholder: "4723",
optional: false,
},
{
name: "Platform",
key: "PLATFORM_NAME",
placeholder: "iOS or Android",
optional: true,
},
],
}
const result = await installer.installItem(appiumMcpItem, {
target: "project",
parameters: {
APPIUM_HOST: "127.0.0.1",
APPIUM_PORT: "4444",
PLATFORM_NAME: "iOS",
},
})
expect(result.filePath).toContain("mcp.json")
expect(mockFs.writeFile).toHaveBeenCalled()
// Verify parameters were properly substituted
const writtenContent = mockFs.writeFile.mock.calls[0][1]
const writtenData = JSON.parse(writtenContent)
expect(writtenData.mcpServers["appium-mcp"].env.APPIUM_HOST).toBe("127.0.0.1")
expect(writtenData.mcpServers["appium-mcp"].env.APPIUM_PORT).toBe("4444")
expect(writtenData.mcpServers["appium-mcp"].env.PLATFORM_NAME).toBe("iOS")
})
it("should handle Appium MCP Server with multiple capabilities", () => {
// Test configuration with advanced Appium capabilities
const appiumMcpAdvanced: MarketplaceItem = {
id: "appium-mcp",
name: "Appium MCP Server",
description: "MCP server for Mobile Development and Automation",
url: "https://github.com/appium/appium-mcp",
type: "mcp",
content: JSON.stringify({
command: "npx",
args: ["-y", "@appium/mcp-server"],
env: {
APPIUM_HOST: "localhost",
APPIUM_PORT: "4723",
CAPABILITIES: JSON.stringify({
platformName: "iOS",
platformVersion: "15.0",
deviceName: "iPhone 13",
automationName: "XCUITest",
app: "/path/to/app.ipa",
}),
},
}),
}
// Parse and validate the capabilities
const content = JSON.parse(appiumMcpAdvanced.content as string)
const capabilities = JSON.parse(content.env.CAPABILITIES)
expect(capabilities.platformName).toBe("iOS")
expect(capabilities.deviceName).toBe("iPhone 13")
expect(capabilities.automationName).toBe("XCUITest")
})
})
describe("Appium MCP Server Features", () => {
it("should support mobile automation tools and commands", () => {
// Define expected Appium MCP capabilities
const expectedTools = [
"launch_app",
"install_app",
"uninstall_app",
"find_element",
"click_element",
"send_keys",
"swipe",
"scroll",
"take_screenshot",
"get_device_info",
"get_orientation",
"set_orientation",
"start_recording",
"stop_recording",
"push_file",
"pull_file",
"get_logs",
"execute_script",
]
// This represents what the MCP server should expose
const appiumMcpCapabilities = {
tools: expectedTools,
resources: ["device_list", "app_list", "session_info", "element_tree"],
prompts: ["test_login_flow", "validate_ui_elements", "perform_gesture", "capture_performance_metrics"],
}
expect(appiumMcpCapabilities.tools).toContain("launch_app")
expect(appiumMcpCapabilities.tools).toContain("find_element")
expect(appiumMcpCapabilities.tools).toContain("take_screenshot")
expect(appiumMcpCapabilities.resources).toContain("device_list")
expect(appiumMcpCapabilities.prompts).toContain("test_login_flow")
})
})
})