Skip to content

Plugins

The OpenBI MCP Server has zero hard dependencies on any specific BI platform. All platform-specific logic ships as plugins — isolated .NET assemblies loaded at runtime using AssemblyLoadContext.


Plugin types

Four extensibility interfaces can be implemented as plugins:

Interface Purpose Resolved from
ISiteConnectionFactory Creates connections to a BI platform (download, upload, query) sites/*.jsonsiteConnectionFactoryName
IOpenBIConverterFactory Converts platform artifacts ↔ OpenBI model sites/*.jsonsiteConverterFactoryName
ISiteRegistry Provides the list of registered sites appsettings.jsonSiteRegistry:ImplementationType
ISecretsVaultRepository Reads connection secrets appsettings.jsonSecretsVault:ImplementationType

A single plugin DLL can implement multiple interfaces — for example, OpenBI.Connectors.CoCoBI.dll can export both a ISiteConnectionFactory and a custom ISiteRegistry.


Plugin folder layout

Plugins live inside the build output directory, not the project source folder.

bin/Debug/net9.0/
└── plugins/
    ├── MyOrg.Connectors.MyPlatform/
    │   ├── MyOrg.Connectors.MyPlatform.dll
    │   ├── MyOrg.Connectors.MyPlatform.deps.json   ← required
    │   └── (all transitive dependencies)
    └── MyOrg.Converters.MyPlatform/
        ├── MyOrg.Converters.MyPlatform.dll
        ├── MyOrg.Converters.MyPlatform.deps.json
        └── (all transitive dependencies)

Warning

The deps.json file is required. Without it the plugin loader cannot resolve transitive dependencies and the plugin will be skipped with a warning.


Building and installing a plugin

Use dotnet publish to produce the self-contained plugin folder:

# Build connector plugin
dotnet publish MyOrg.Connectors.MyPlatform \
  -c Release \
  -o "path/to/OpenBI.MCP.Server/bin/Release/net9.0/plugins/MyOrg.Connectors.MyPlatform"

# Build converter plugin
dotnet publish MyOrg.Converters.MyPlatform \
  -c Release \
  -o "path/to/OpenBI.MCP.Server/bin/Release/net9.0/plugins/MyOrg.Converters.MyPlatform"

For debug builds, replace Release with Debug and adjust the output path accordingly.


How the plugin loader works

At server startup, before any DI resolution, PluginLoader performs the following steps:

  1. Scans every subdirectory of {AppContext.BaseDirectory}/plugins/.
  2. For each subdirectory, locates the *.deps.json file.
  3. Creates an isolated PluginLoadContext (a custom AssemblyLoadContext) backed by an AssemblyDependencyResolver pointing at that deps.json.
  4. Loads the primary *.dll from that context.
  5. Reflects all public types that implement any of the four extensibility interfaces.
  6. Registers them by their assembly-qualified name in the in-memory PluginTypeRegistry.

Plugins with missing deps.json, missing DLLs, or load errors are skipped with a warning — they do not crash the server.

Shared assembly isolation

Assemblies that form the OpenBI contract boundaries (OpenBI, OpenBI.MCP.Interfaces, OpenBI.Connectors.Interfaces, OpenBI.Converters.Interfaces) are always resolved from the default AssemblyLoadContext. This prevents type identity mismatches when the server checks whether a plugin type implements an interface — both sides must see the exact same Type object.

All other assemblies (vendor SDKs, HTTP clients, etc.) are loaded privately inside the plugin's own ALC, preventing version conflicts between plugins.


Type name format

When referencing a plugin type in appsettings.json or sites/*.json, use the standard .NET assembly-qualified name:

Namespace.ClassName, AssemblyName

Example:

"siteConnectionFactoryName": "MyOrg.Connectors.MyPlatform.MyConnectionFactory, MyOrg.Connectors.MyPlatform"

You do NOT need the full Version=... suffix — the plugin loader resolves by name only.


Implementing a connector plugin

A minimal connector plugin implements ISiteConnectionFactory from OpenBI.Connectors.Interfaces:

// Reference: OpenBI.Connectors.Interfaces (NuGet)
public class MyPlatformSiteConnectionFactory : ISiteConnectionFactory
{
    public string FactoryName => "MyPlatform";

    public Task<ISiteConnection> CreateConnectionAsync(
        SiteManifest site,
        ISecretsVaultRepository secrets,
        CancellationToken ct)
    {
        // Read credentials from secrets, return a connection
        return Task.FromResult<ISiteConnection>(new MyPlatformSiteConnection(site, secrets));
    }
}

Then reference the package in your .csproj:

<PackageReference Include="OpenBI.Connectors.Interfaces" />

See the OpenBI.Connectors.Interfaces package for full interface documentation.