Documentation Index Fetch the complete documentation index at: https://mintlify.com/superset-sh/superset/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Superset uses the Model Context Protocol (MCP) to provide AI agents with tools and resources for interacting with the desktop app, managing workspaces, and automating workflows.
Packages :
packages/mcp - Superset cloud MCP server (workspace/device management)
packages/desktop-mcp - Desktop automation MCP server (UI testing, browser control)
MCP Protocol Basics
MCP servers expose tools and resources that AI agents can invoke:
Tools : Functions the agent can call (e.g., create_workspace, click, navigate)
Resources : Data the agent can read (e.g., workspace details, app context)
Prompts : Pre-configured prompts for common tasks
Server Initialization
MCP servers are created using @modelcontextprotocol/sdk:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
export function createMcpServer () : McpServer {
const server = new McpServer (
{ name: "my-server" , version: "1.0.0" },
{ capabilities: { tools: {} } }
);
registerTools ( server );
return server ;
}
Tools are registered with Zod schemas for input validation:
import { z } from "zod" ;
server . registerTool (
"tool_name" ,
{
description: "What this tool does" ,
inputSchema: {
param1: z . string (). describe ( "Description of param1" ),
param2: z . number (). optional (). describe ( "Optional parameter" ),
},
},
async ( args , extra ) => {
// Tool implementation
const result = await doSomething ( args . param1 , args . param2 );
return {
content: [
{ type: "text" , text: `Result: ${ result } ` }
],
};
}
);
Desktop MCP Server
Package : @superset/desktop-mcp
Source : packages/desktop-mcp/src/mcp/mcp-server.ts:5
Provides browser automation and UI testing tools.
Server Setup
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { ConnectionManager } from "./connection/index.js" ;
import { registerTools } from "./tools/index.js" ;
export function createMcpServer () : McpServer {
const server = new McpServer (
{ name: "desktop-automation" , version: "0.1.0" },
{ capabilities: { tools: {} } }
);
const connection = new ConnectionManager ();
registerTools ({
server ,
getPage : () => connection . getPage (),
consoleCapture: connection . consoleCapture ,
});
return server ;
}
Source : packages/desktop-mcp/src/mcp/tools/index.ts:20
All tools defined in packages/desktop-mcp/src/mcp/tools/:
take_screenshot - Capture app screenshots
inspect_dom - Inspect DOM elements
click - Click UI elements
type_text - Type text into inputs
send_keys - Send keyboard shortcuts
get_console_logs - Retrieve console logs
evaluate_js - Execute JavaScript in app
navigate - Navigate to URLs
get_window_info - Get window metadata
Source : packages/desktop-mcp/src/mcp/tools/click/click.ts:43
export function register ({ server , getPage } : ToolContext ) {
server . registerTool (
"click" ,
{
description: "Click on a UI element in the Electron app" ,
inputSchema: {
selector: z . string (). optional (). describe ( "CSS selector" ),
text: z . string (). optional (). describe ( "Visible text content" ),
testId: z . string (). optional (). describe ( "data-testid attribute" ),
x: z . number (). optional (). describe ( "X coordinate" ),
y: z . number (). optional (). describe ( "Y coordinate" ),
index: z . number (). int (). min ( 0 ). default ( 0 ),
fuzzy: z . boolean (). default ( true ),
},
},
async ( args ) => {
const page = await getPage ();
// Click by coordinates
if ( args . x !== undefined && args . y !== undefined ) {
await page . mouse . click ( args . x , args . y );
return {
content: [{ type: "text" , text: `Clicked at ( ${ args . x } , ${ args . y } )` }],
};
}
// Find element and click
const result = await page . evaluate ( /* ... */ );
await page . mouse . click ( result . x , result . y );
return {
content: [{ type: "text" , text: `Clicked < ${ result . tag } >` }],
};
}
);
}
Usage Example
Agents invoke desktop MCP tools via the protocol:
{
"method" : "tools/call" ,
"params" : {
"name" : "click" ,
"arguments" : {
"text" : "Create Workspace" ,
"fuzzy" : true
}
}
}
Superset MCP Server
Package : @superset/mcp
Source : packages/mcp/src/server.ts:4
Provides workspace, device, and task management tools.
Server Setup
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { registerTools } from "./tools" ;
export function createMcpServer () : McpServer {
const server = new McpServer (
{ name: "superset" , version: "1.0.0" },
{ capabilities: { tools: {} } }
);
registerTools ( server );
return server ;
}
Source : packages/mcp/src/tools/index.ts:20
All tools organized by category:
list_devices - List registered devices
list_workspaces - List workspaces on a device
create_workspace - Create new workspace(s)
switch_workspace - Switch active workspace
delete_workspace - Delete workspace
update_workspace - Update workspace config
list_projects - List projects
get_app_context - Get current app state
get_workspace_details - Get workspace metadata
start_agent_session - Start agent session on device
create_task - Create task
update_task - Update task
list_tasks - List tasks
get_task - Get task details
delete_task - Delete task
list_task_statuses - List available statuses
list_members - List organization members
Source : packages/mcp/src/tools/devices/create-workspace/create-workspace.ts:20
const workspaceInputSchema = z . object ({
name: z . string (). optional (). describe ( "Workspace name (auto-generated if not provided)" ),
branchName: z . string (). optional (). describe ( "Branch name (auto-generated if not provided)" ),
baseBranch: z . string (). optional (). describe ( "Branch to create from (defaults to main)" ),
});
export function register ( server : McpServer ) {
server . registerTool (
"create_workspace" ,
{
description: "Create one or more workspaces (git worktrees) on a device" ,
inputSchema: {
deviceId: z . string (). describe ( "Target device ID" ),
projectId: z . string (). describe ( "Project ID to create workspaces in" ),
workspaces: z
. array ( workspaceInputSchema )
. min ( 1 )
. max ( 5 )
. describe ( "Array of workspaces to create (1-5)" ),
},
},
async ( args , extra ) => {
const ctx = getMcpContext ( extra );
const deviceId = args . deviceId as string ;
const projectId = args . projectId as string ;
const workspaces = args . workspaces ;
return executeOnDevice ({
ctx ,
deviceId ,
tool: "create_workspace" ,
params: { projectId , workspaces },
});
}
);
}
Authentication Context
MCP tools use a context pattern for authentication:
import { getMcpContext } from "../../utils" ;
async ( args , extra ) => {
const ctx = getMcpContext ( extra );
if ( ! ctx . userId ) {
return {
content: [{ type: "text" , text: "Authentication required" }],
isError: true ,
};
}
// Use ctx.userId, ctx.organizationId, etc.
}
Building Custom MCP Servers
1. Create Server Structure
mkdir -p my-mcp-server/src/tools
cd my-mcp-server
bun init
package.json :
{
"name" : "my-mcp-server" ,
"version" : "1.0.0" ,
"type" : "module" ,
"bin" : {
"my-mcp-server" : "./dist/bin.js"
},
"dependencies" : {
"@modelcontextprotocol/sdk" : "^1.0.4" ,
"zod" : "^3.23.8"
}
}
src/tools/my-tool.ts :
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { z } from "zod" ;
export function register ( server : McpServer ) {
server . registerTool (
"my_tool" ,
{
description: "Does something useful" ,
inputSchema: {
input: z . string (). describe ( "Input parameter" ),
},
},
async ( args ) => {
const result = await processInput ( args . input as string );
return {
content: [
{ type: "text" , text: `Result: ${ result } ` }
],
};
}
);
}
async function processInput ( input : string ) : Promise < string > {
// Your logic here
return `Processed: ${ input } ` ;
}
src/tools/index.ts :
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { register as myTool } from "./my-tool" ;
import { register as anotherTool } from "./another-tool" ;
const allTools = [ myTool , anotherTool ];
export function registerTools ( server : McpServer ) {
for ( const register of allTools ) {
register ( server );
}
}
4. Create Server
src/server.ts :
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { registerTools } from "./tools/index.js" ;
export function createMcpServer () : McpServer {
const server = new McpServer (
{ name: "my-mcp-server" , version: "1.0.0" },
{ capabilities: { tools: {} } }
);
registerTools ( server );
return server ;
}
5. Create CLI Entry Point
src/bin.ts :
#!/usr/bin/env node
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
import { createMcpServer } from "./server.js" ;
const server = createMcpServer ();
const transport = new StdioServerTransport ();
await server . connect ( transport );
6. Build and Test
bun build src/bin.ts --outdir dist --target node
chmod +x dist/bin.js
Test with MCP Inspector :
npx @modelcontextprotocol/inspector dist/bin.js
MCP Server Configuration
Add your MCP server to .mcp.json:
{
"mcpServers" : {
"my-mcp-server" : {
"command" : "node" ,
"args" : [ "/path/to/my-mcp-server/dist/bin.js" ],
"env" : {
"API_KEY" : "your-api-key" ,
"LOG_LEVEL" : "debug"
}
}
}
}
For published packages :
{
"mcpServers" : {
"my-mcp-server" : {
"command" : "npx" ,
"args" : [ "-y" , "my-mcp-server@latest" ]
}
}
}
Server Lifecycle
Initialization
Server process starts via stdio transport
MCP SDK establishes connection
Tools are registered
Server sends initialized notification
Client sends tools/call request
Server validates input with Zod schema
Tool handler executes
Server returns result or error
Shutdown
Client closes connection
Server cleanup handlers run
Process exits
Testing MCP Servers
import { describe , test , expect } from "bun:test" ;
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { register } from "./my-tool" ;
describe ( "my_tool" , () => {
test ( "processes input correctly" , async () => {
const server = new McpServer (
{ name: "test" , version: "1.0.0" },
{ capabilities: { tools: {} } }
);
register ( server );
const result = await server . callTool ( "my_tool" , {
input: "test input"
});
expect ( result . content [ 0 ]. text ). toContain ( "Processed: test input" );
});
});
Integration Testing
Use @modelcontextprotocol/inspector for manual testing:
npx @modelcontextprotocol/inspector ./dist/bin.js
This opens a UI for invoking tools and inspecting responses.
Error Handling
server . registerTool (
"my_tool" ,
{ /* ... */ },
async ( args ) => {
if ( ! validateInput ( args . input )) {
return {
content: [
{ type: "text" , text: "Invalid input: must be non-empty" }
],
isError: true ,
};
}
// Normal execution
return {
content: [{ type: "text" , text: "Success" }],
};
}
);
Throw Errors for Server Issues
server . registerTool (
"my_tool" ,
{ /* ... */ },
async ( args ) => {
try {
const result = await dangerousOperation ();
return { content: [{ type: "text" , text: result }] };
} catch ( error ) {
// Let MCP SDK handle the error
throw new Error ( `Operation failed: ${ error . message } ` );
}
}
);
Best Practices
Use snake_case for tool names
Be descriptive: create_workspace not create
Prefix with category: github_create_issue
Always use Zod schemas
Provide clear descriptions for each parameter
Set reasonable defaults
Mark optional parameters explicitly
3. Error Messages
Return user-friendly error messages
Include context: what failed and why
Suggest fixes when possible
Start with action verb: “Create”, “List”, “Update”
Explain what the tool does in plain language
Include use cases in description
Always return { content: [...] }
Use type: "text" for messages
Set isError: true for user-facing errors
Example: Full Custom MCP Server
src/server.ts :
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" ;
import { z } from "zod" ;
export function createMcpServer () : McpServer {
const server = new McpServer (
{ name: "example-server" , version: "1.0.0" },
{ capabilities: { tools: {} } }
);
// Register a simple tool
server . registerTool (
"greet" ,
{
description: "Greet a user by name" ,
inputSchema: {
name: z . string (). describe ( "User's name" ),
formal: z . boolean (). default ( false ). describe ( "Use formal greeting" ),
},
},
async ( args ) => {
const greeting = args . formal
? `Good day, ${ args . name } `
: `Hey ${ args . name } !` ;
return {
content: [{ type: "text" , text: greeting }],
};
}
);
return server ;
}
src/bin.ts :
#!/usr/bin/env node
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
import { createMcpServer } from "./server.js" ;
const server = createMcpServer ();
const transport = new StdioServerTransport ();
await server . connect ( transport );
Next Steps
Desktop API Electron IPC APIs for local operations
tRPC Endpoints Cloud tRPC API reference
MCP SDK Docs Official MCP documentation
Example MCP Servers Reference implementations