Extensions

Build anything with SystemPrompt extensions: websites, MCP servers, background jobs, CLI tools. You own the binary, you control the code.

After Reading This

You will be able to:

  • Understand you own a complete Rust binary, not a hosted service
  • Identify the three extension patterns: library, MCP server, CLI binary
  • Recognize how the template enables deterministic agent execution
  • Choose the right extension type for your use case
  • Navigate to specific extension documentation

When you build with SystemPrompt, you own the binary. Not an account on a hosted service. Not a connection to a managed platform. A real Rust binary that compiles from source code you control, runs on infrastructure you choose, and executes functionality you define.

Extensions are how you add that functionality. Write Rust code that implements API routes, database schemas, background jobs, MCP tools, or custom CLI commands. Compile it into your binary. Deploy it wherever you want. The code runs deterministically, which means agents can execute your extensions with predictable, reproducible results.

After reading this guide, you will understand exactly how extensions, their boundaries, and the SystemPrompt template extend systemprompt-core to create a fully functional Rust binary completely owned by you.

Ownership Model

The SystemPrompt template is your project. When you clone it, you receive a Cargo workspace containing the source code for a complete application. The core framework, systemprompt-core, is a library dependency, not a service. Your template imports it, calls its functions, and compiles it into your binary.

This means you control everything:

  • Release cycle - Upgrade core when you choose, not when a provider forces you
  • Deployment - Run on bare metal, containers, or any cloud provider
  • Modification - Fork extensions, customize behavior, add proprietary features
  • Distribution - Ship your binary to customers, embed it in products, sell it

The template's entry point is a four-line main.rs that calls into the core runtime. You can add initialization logic, custom panic handlers, or environment setup without modifying core. The architecture gives you full control while providing a solid foundation.

The Template Wrapper

Your template's src/ directory contains two files that bootstrap the entire system. The main.rs entry point calls cli::run(), which handles argument parsing, configuration, and command execution. The lib.rs file re-exports extensions and solves a critical linker problem.

Rust's linker aggressively removes unused code. Extensions that register themselves at compile time can vanish from the final binary if nothing directly references them. The template's __force_extension_link() function prevents this by explicitly touching each extension, ensuring they survive optimization.

For the complete architecture, see Template Architecture.

Extension Types

SystemPrompt supports three extension patterns, each suited to different use cases.

Library Extensions

Library extensions compile directly into your main binary. They implement the Extension trait and register via the register_extension!() macro. At startup, the runtime discovers these extensions and calls their lifecycle hooks to set up schemas, routes, jobs, and providers.

The web extension is a library extension. It adds HTTP routes for content management, database tables for markdown storage, background jobs for content ingestion, and template providers for navigation and page data. All of this compiles into a single binary with no external dependencies.

Use library extensions when you want tight integration with the runtime, shared database connections, and coordinated lifecycle management.

MCP Servers

MCP extensions are standalone binaries that implement the Model Context Protocol. They run as separate processes, listening on TCP ports for requests from AI agents. Each MCP server exposes tools that agents can invoke to perform actions: query databases, call APIs, execute workflows.

The systemprompt MCP server demonstrates this pattern. It bootstraps from profiles and secrets, connects to the database, and serves tools over HTTP. Agents interact with it via the MCP protocol, invoking tools and receiving structured responses.

Use MCP extensions when you want isolated services, independent scaling, or separate deployment from the main runtime.

CLI Extensions

CLI extensions are standalone binaries for automation and scripting. They use clap for argument parsing and perform specific tasks: send Discord messages, sync data, generate reports. These tools share the workspace's dependencies but run independently.

The discord CLI extension shows this pattern. It loads configuration, connects to the Discord API, and sends messages to channels or users. Agents can invoke it via shell execution for notifications and integrations.

Use CLI extensions for utility commands, external integrations, or tools that agents execute via subprocess.

What You Can Build

Extensions unlock the full power of Rust for your agent workflows:

Capability Extension Type Example
API routes Library REST endpoints for content, links, search
Database tables Library Custom schemas with migrations
Background jobs Library Scheduled ingestion, cache refresh, pipelines
Template providers Library Navigation data, page metadata, component rendering
MCP tools MCP Server Database queries, API calls, workflow execution
CLI commands CLI Discord notifications, data sync, report generation
Static pages Library Feature pages, landing pages from configuration

The combination is powerful. A library extension stores content in the database, a background job ingests new files, a template provider renders navigation, and an MCP tool lets agents query the content. Everything compiles into binaries you deploy together or separately.

Extension Lifecycle

Extensions follow a declarative pattern. Instead of imperative startup code, you implement trait methods that return data structures describing your capabilities. The runtime interprets these declarations during startup.

Key lifecycle hooks include:

  • metadata() - Extension identity and version
  • schemas() - Database table definitions
  • router() - HTTP route handlers
  • jobs() - Background task implementations
  • page_data_providers() - Template data injection

For the complete reference, see Lifecycle Hooks.

Directory Structure

extensions/
├── web/                    # Library extension (compiles into binary)
│   ├── Cargo.toml
│   ├── src/
│   │   ├── lib.rs
│   │   ├── extension.rs   # Extension trait implementation
│   │   ├── api/           # HTTP handlers
│   │   ├── jobs/          # Background tasks
│   │   └── services/      # Business logic
│   └── schema/            # SQL migrations
├── mcp/
│   └── systemprompt/      # MCP server (standalone binary)
│       ├── Cargo.toml
│       └── src/
│           └── main.rs
└── cli/
    └── discord/           # CLI tool (standalone binary)
        ├── Cargo.toml
        └── src/
            └── main.rs

Guides

Guide Description
Template Architecture How the template wraps systemprompt-core
Lifecycle Hooks Extension trait methods and when they execute
Library Extensions Build extensions that compile into the binary
Web Extensions Page providers, renderers, and asset management
Background Jobs Scheduled tasks with cron expressions
MCP Extensions Standalone MCP servers for AI agents
CLI Extensions Command-line tools for automation

In this section