Skip to main content
Version: Next

Contribution Types

Extensions provide functionality through contributions - well-defined extension points that integrate with the host application.

Why Contributions?

The contribution system provides several key benefits:

  • Transparency: Administrators can review exactly what functionality an extension provides before installation. The manifest.json documents all REST APIs, MCP tools, views, and other contributions in a single, readable location.

  • Security: Only contributions explicitly declared in the manifest are registered during startup. Extensions cannot expose functionality they haven't declared, preventing hidden or undocumented code from executing.

  • Discoverability: The manifest serves as a contract between extensions and the host application, making it easy to understand what an extension does without reading its source code.

How Contributions Work

Contributions are automatically discovered from source code at build time. Simply use the @extension_api, @tool, @prompt decorators in Python or define*() functions in TypeScript - the build system finds them and generates a manifest.json with all discovered contributions.

No manual configuration needed!

Backend Contributions

REST API Endpoints

Register REST APIs under /api/v1/extensions/:

from superset_core.api import RestApi, extension_api
from flask_appbuilder import expose

@extension_api(id="my_api", name="My Extension API")
class MyExtensionAPI(RestApi):
@expose("/endpoint", methods=["GET"])
def get_data(self):
return self.response(200, result={"message": "Hello"})

MCP Tools

Register MCP tools for AI agents:

from superset_core.mcp import tool

@tool(tags=["database"])
def query_database(sql: str, database_id: int) -> dict:
"""Execute a SQL query against a database."""
return execute_query(sql, database_id)

MCP Prompts

Register MCP prompts:

from superset_core.mcp import prompt

@prompt(tags={"analysis"})
async def analyze_data(ctx, dataset: str) -> str:
"""Generate analysis for a dataset."""
return f"Analyze the {dataset} dataset..."

See MCP Integration for more details.

Frontend Contributions

Views

Add panels or views to the UI using defineView():

import React from 'react';
import { defineView } from '@apache-superset/core';
import MyPanel from './MyPanel';

export const myView = defineView({
id: 'main',
title: 'My Panel',
location: 'sqllab.panels', // or dashboard.tabs, explore.panels, etc.
component: () => <MyPanel />,
});

Commands

Define executable commands using defineCommand():

import { defineCommand } from '@apache-superset/core';

export const copyQuery = defineCommand({
id: 'copy_query',
title: 'Copy Query',
icon: 'CopyOutlined',
execute: async () => {
// Copy the current query
navigator.clipboard.writeText(getCurrentQuery());
},
});

Add items to menus using defineMenu():

import { defineMenu } from '@apache-superset/core';

export const contextMenu = defineMenu({
id: 'clear_editor',
title: 'Clear Editor',
location: 'sqllab.editor.context',
action: () => {
clearEditor();
},
});

Editors

Replace the default text editor using defineEditor():

import React from 'react';
import { defineEditor } from '@apache-superset/core';
import MonacoEditor from './MonacoEditor';

export const monacoSqlEditor = defineEditor({
id: 'monaco_sql',
name: 'Monaco SQL Editor',
mimeTypes: ['text/x-sql'],
component: MonacoEditor,
});

All contributions are automatically discovered at build time and registered at runtime - no manual configuration needed!

Configuration

extension.json

Specify which files to scan for contributions:

{
"id": "my_extension",
"name": "My Extension",
"version": "1.0.0",
"backend": {
"entryPoints": ["my_extension.entrypoint"],
"files": ["backend/src/**/*.py"]
},
"frontend": {
"moduleFederation": {
"exposes": ["./index"]
}
}
}

Manual Contributions (Advanced)

Override auto-discovery by specifying contributions directly:

{
"backend": {
"contributions": {
"mcpTools": [
{ "id": "query_db", "name": "query_db", "module": "my_ext.tools.query_db" }
],
"restApis": [
{ "id": "my_api", "name": "My API", "module": "my_ext.api.MyAPI", "basePath": "/my_api" }
]
}
}
}