Simple MCP for local development (unsafe for production) with FireBird RDBMS 5 - with a small code gen
概要
A lightweight, pure-Rust MCP (Model Context Protocol) server for Firebird 5 databases. No external dependencies — no isql, no DLLs, no .so files. Just a single static binary. - firebird_query — Execute any SQL statement (SELECT, INSERT, UPDATE, DELETE, DDL) - firebird_count — Count rows in a table (with optional WHERE) - firebird_sample — Quick sample of table data - firebird_insert_batch — Batch insert multiple rows in one transaction - firebird_run_script — Execute multi-statement SQL scripts - firebird_execute_immediate — Execute statements with SET TERM blocks (procedures, functions, generators) - firebird_describe_table — Full schema of a table (columns, indexes, constraints, triggers, comments) - firebird_describe_database — Complete database overview with Health section (gstat-like) + Mermaid ER diagram - firebird_describe — Multi-object describe (tables, views, procedures, functions, triggers, sequences, domains) - firebird_list — List tables, views, procedures, functions,...
README
firebird-5-mcp
A lightweight, pure-Rust MCP (Model Context Protocol) server for Firebird 5 databases. No external dependencies — no isql, no DLLs, no .so files. Just a single static binary.
Features
Query & Data
firebird_query— Execute any SQL statement (SELECT, INSERT, UPDATE, DELETE, DDL)firebird_count— Count rows in a table (with optional WHERE)firebird_sample— Quick sample of table datafirebird_insert_batch— Batch insert multiple rows in one transactionfirebird_run_script— Execute multi-statement SQL scriptsfirebird_execute_immediate— Execute statements with SET TERM blocks (procedures, functions, generators)
Schema & Structure
firebird_describe_table— Full schema of a table (columns, indexes, constraints, triggers, comments)firebird_describe_database— Complete database overview with Health section (gstat-like) + Mermaid ER diagramfirebird_describe— Multi-object describe (tables, views, procedures, functions, triggers, sequences, domains)firebird_list— List tables, views, procedures, functions, domains, triggers, indexes, sequencesfirebird_find_column— Find columns by name pattern (LIKE) across all tables/viewsfirebird_check_duplicates— Check for duplicate values before creating unique index/constraint
DDL & Advanced
firebird_create_database— Create a new Firebird database filefirebird_create_trigger— Create BEFORE/AFTER INSERT/UPDATE/DELETE triggersfirebird_create_procedure— Create stored procedures (no isql needed)firebird_create_function— Create user-defined functionsfirebird_create_sequence— Create sequences (generators)firebird_alter_column_type— Change column type using domainsfirebird_drop— Drop tables, views, domains, triggers, procedures, functions, indexes, sequences
Code Generation
firebird_generate_dev— Generate development code from table schemas:- Java (JPA + Lombok)
- Go (sqlx)
- Rust (rsfbclient)
- TypeScript (interfaces)
- Protobuf (Connect-RPC/gRPC)
- OpenAPI 3.2.0 (YAML schemas)
- Lazarus/Delphi (.lfm forms with TFBDataSet)
- Svelte 5 (Page + Form using
@edujed/jedsvelted-ui)
firebird_generate_view_dto— Generate DTOs/records from views (resolved metadata):- Java (Lombok @Data)
- Go (sqlx tags)
- Rust (FromRow)
- TypeScript (interfaces)
- Protobuf (Connect-RPC/gRPC)
- OpenAPI 3.2.0 (YAML schemas)
- Lazarus/Delphi (.lfm forms with TFBDataSet)
- Svelte 5 (Page read-only using
@edujed/jedsvelted-ui)
Discovery
firebird_get_databases— List configured databasesfirebird_metadata_extract— Full DDL extraction (replacesisql -x)firebird_explain_plan— Get execution plan without running the query (rolled-back transaction)
Prerequisites
- Firebird 5 server running (or any version 3+)
- Rust toolchain (only if building from source)
- No
isql, no ODBC, no native libraries required
Setup
1. Configure your server and databases
Create a config.json file:
{
"server": {
"host": "localhost",
"port": 3050,
"user": "SYSDBA",
"password": "masterkey",
"allowed_paths": ["/path/to/databases"],
"databases": [
{
"name": "teste",
"description": "Local development database",
"path": "/path/to/databases/teste.fdb"
},
{
"name": "financeiro",
"description": "Financial database",
"path": "/path/to/databases/financeiro.fdb"
}
],
"default_database": "teste"
}
}
| Field | Description |
|---|---|
host |
Firebird server hostname |
port |
Firebird server port (default 3050) |
user |
Database username |
password |
Database password |
allowed_paths |
Directories where new databases can be created |
databases |
List of configured databases |
default_database |
Database to use when none is specified |
2. Build
Use the build script from the project root:
./scripts/build.sh rust # Current platform (binaries in bin/)
./scripts/build.sh rust all # All supported platforms
The script also packages the binaries into dist/ as compressed archives:
- Windows →
.zip(e.g.firebird-5-mcp-windows-amd64.zip) - Linux →
.tar.gz(e.g.firebird-5-mcp-linux-amd64.tar.gz)
./scripts/build.sh rust all
# Binaries in: bin/
# Archives in: dist/
Or build manually:
cd firebird-5-mcp
cargo build --release
# Binary will be at: firebird-5-mcp/target/release/firebird-5-mcp
Cross-compilation notes:
| Platform | Target | Requirements |
|---|---|---|
| linux/amd64 | x86_64-unknown-linux-gnu |
None (native on x86_64) |
| linux/arm64 | aarch64-unknown-linux-gnu |
aarch64-linux-gnu-gcc (sudo apt install gcc-aarch64-linux-gnu) |
| windows/amd64 | x86_64-pc-windows-gnu |
x86_64-w64-mingw32-gcc (sudo apt install gcc-mingw-w64-x86-64) |
| darwin/* | *-apple-darwin |
osxcross (skipped with a warning if not installed) |
| windows/arm64 | — | Not supported (no stable GNU target in Rust) |
3. Register in Zed Editor
Add to your Zed settings (~/.config/zed/settings.json):
{
"context_servers": {
"firebird-5-mcp": {
"command": "/path/to/firebird-5-mcp",
"enabled": true,
"env": {
"FIREBIRD_CONFIG": "/path/to/config.json"
},
"timeout": 30000
}
}
}
Configuration
config.json
Same format as the Go version. The Rust version is fully compatible with existing Go configs.
Database entry
{
"name": "teste",
"description": "Local development database",
"path": "/path/to/databases/teste.fdb"
}
Configuration file lookup
The server looks for config.json in this order:
FIREBIRD_CONFIGenvironment variable./config.json(current directory)~/.config/firebird-5-mcp/config.json
Environment variables
| Variable | Description |
|---|---|
FIREBIRD_CONFIG |
Path to config.json |
Tools
firebird_query
Executes a single SQL statement. For DML/DDL, the execution plan is appended to the result.
Arguments:
sql(required): The SQL statementdatabase(optional): Database name (defaults todefault_database)
Example:
{
"sql": "SELECT * FROM CLIENTS WHERE CITY = 'New York'",
"database": "shop"
}
Result:
### Query Results (3 rows)
Columns: ID (INT), NAME (VARCHAR), CITY (VARCHAR)
ID | NAME | CITY
--- | --- | ---
1 | Alice | New York
2 | Bob | NULL
3 | Charlie | New York
firebird_list
Lists database objects by type.
Arguments:
type(required): TABLES, PROCEDURES, FUNCTIONS, DOMAINS, TRIGGERS, INDEXES, or SEQUENCESdatabase(optional): Database name
Example:
{
"type": "TABLES",
"database": "shop"
}
Result:
### Tables and Views (5)
NAME | TYPE | COMMENT
--- | --- | ---
CLIENTS | TABLE | Customer records
ORDERS | TABLE | Order data
...
firebird_find_column
Finds columns by name pattern across all tables and views. Supports % wildcards.
Arguments:
column(required): Column name pattern (supports%wildcards). E.g.,EMAIL,%NOME%,IDdatabase(optional): Database name
Example:
{
"column": "%EMAIL%",
"database": "shop"
}
Result:
### Columns matching '%EMAIL%' (2 found)
TABLE | COLUMN | TYPE | NULL | VIEW
--- | --- | --- | --- | ---
USERS | EMAIL | VARCHAR(250) | NO |
VW_ACTIVE_USERS | EMAIL | VARCHAR(250) | YES | YES
firebird_check_duplicates
Checks for duplicate values in one or more columns. Use this BEFORE creating a unique index or constraint to verify data integrity. Supports composite keys.
Arguments:
table(required): Table name to checkcolumns(required): Array of column names to check (supports composite keys)limit(optional): Maximum number of duplicate combinations to return (default: 10)database(optional): Database name
Example:
{
"table": "CUSTOMERS",
"columns": ["TYPE_ID"],
"database": "shop"
}
Result (with duplicates):
### Duplicate Check: CUSTOMERS (TYPE_ID)
⚠️ 1 duplicate combination(s) found:
TYPE_ID | DUPLICATED_COUNT
--- | ---
2 | 5
#### Full rows for first duplicate (TYPE_ID = 2):
ID | TYPE_ID | PARENT_ID | IS_VERIFIED | ACTIVE | ...
--- | --- | --- | --- | --- | ---
2 | 2 | NULL | false | true | ...
3 | 2 | 2 | true | true | ...
4 | 2 | NULL | false | true | ...
5 | 2 | 4 | true | true | ...
6 | 2 | 4 | false | true | ...
💡 Fix duplicates before creating the unique index/constraint.
Result (no duplicates):
### Duplicate Check: CUSTOMERS (ID)
✅ No duplicates found. Safe to create unique index/constraint.
firebird_describe_table
Shows the full schema of a table or view.
Arguments:
table_name(required): Table or view namedatabase(optional): Database name
Result:
### Table: CLIENTS
#### Columns
NAME | TYPE | NULL | DEFAULT | POSITION
--- | --- | --- | --- | ---
ID | INTEGER | NO | - | 1
NAME | VARCHAR(100) | NO | - | 2
EMAIL | VARCHAR(255) | YES | - | 3
CREATED_AT | TIMESTAMP | NO | CURRENT_TIMESTAMP | 4
#### Indexes
NAME | UNIQUE | TYPE | COLUMNS
--- | --- | --- | ---
PK_CLIENTS | YES | 0 | ID
#### Constraints
NAME | TYPE
--- | ---
PK_CLIENTS | PRIMARY KEY
firebird_describe_database
Provides a complete overview of the database structure with a Health section (gstat-like info) and a Mermaid ER diagram.
Arguments:
database(optional): Database nameinclude_counts(optional): Include row counts (may be slow)include_describes(optional): Include column details
Result:
### Database: shop
#### Health
- **Path:** /database/shop.fdb
- **ODS Version:** 13.1
- **Page Size:** 32768 bytes
- **File Size:** 428 pages (~13.4 MB)
- **Dialect:** 3
- **Mode:** Online (Normal)
- **Read-Only:** NO
- **Forced Writes:** YES
- **Active Connections:** 1
- **Oldest Transaction:** 1063 (active: 1772, next: 1772)
- **Buffer Pool:** 2048 pages
#### Tables (26)
**USERS**
- ID (INTEGER, PK)
...
#### Relationships (Mermaid)
```mermaid
erDiagram
CUSTOMERS ||--o{ USERS : "FK_USR_CUST"
...
**Health section fields:**
| Field | Description |
|-------|-------------|
| Path | Database file path |
| ODS Version | On-Disk Structure version (13.1 = Firebird 5) |
| Page Size | Page size in bytes |
| File Size | Total pages and estimated size in MB |
| Dialect | SQL dialect (3 = ANSI) |
| Mode | Shutdown mode: Online (Normal), Multi-user, Single-user, Full |
| Read-Only | Whether the database is read-only |
| Forced Writes | Whether forced writes are enabled |
| Active Connections | Number of active user connections |
| Oldest Transaction | Oldest transaction ID (active and next) |
| Buffer Pool | Number of buffer pool pages |
### `firebird_describe`
Multi-object describe — accepts any mix of tables, views, procedures, functions, triggers, sequences, and domains.
**Arguments:**
- `objects` (required): Array of object names
- `database` (optional): Database name
**Example:**
```json
{
"objects": ["SAVE_USER", "USERS", "D_BOOL"],
"database": "shop"
}
Result (procedure with parameters):
### SAVE_USER (PROCEDURE)
#### Input Parameters
POSITION | NAME | DOMAIN
--- | --- | ---
0 | P_OPER | RDB$33
1 | P_ID | D_ID_NULL
2 | P_EMAIL | D_VC255
...
#### Output Parameters
POSITION | NAME | DOMAIN
--- | --- | ---
0 | ID | D_ID
1 | OK | D_BOOL
#### Source
CREATE PROCEDURE SAVE_USER (P_OPER RDB$33, P_ID D_ID_NULL, …) AS DECLARE VARIABLE V_AFF INT; BEGIN … END
firebird_generate_dev
Generates development code from table schemas.
Arguments:
tables(required): Array of table names (max 20)language(required):java,go,rust,typescript,protobuf,openapi,lazarus, orsveltedatabase(optional): Database nameinclude_fks(optional): If true, generates named FK relations (Java@ManyToOne) or FK comments
Example (Go):
{
"tables": ["USERS"],
"language": "go",
"database": "shop",
"include_fks": true
}
Result:
// User maps to table USERS
type User struct {
Id sql.NullInt32 `db:"ID" json:"id"`
CustomerId sql.NullInt32 `db:"CUSTOMER_ID" json:"customerId"` // FK → CUSTOMERS.ID
Email sql.NullString `db:"EMAIL" json:"email"`
PasswordHash sql.NullString `db:"PASSWORD_HASH" json:"passwordHash"`
Active bool `db:"ACTIVE" json:"active"`
CreatedAt *time.Time `db:"CREATED_AT" json:"createdAt"`
UpdatedAt *time.Time `db:"UPDATED_AT" json:"updatedAt"`
CreatedBy i32 `db:"CREATED_BY" json:"createdBy"`
UpdatedBy i32 `db:"UPDATED_BY" json:"updatedBy"`
DeletedAt *time.Time `db:"DELETED_AT" json:"deletedAt"`
}
Example (Java):
{
"tables": ["USERS"],
"language": "java",
"database": "shop",
"include_fks": true
}
Result:
@Entity
@Table(name = "USERS")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
@Id
@Column(name = "ID")
private Integer id;
@ManyToOne
@JoinColumn(name = "CUSTOMER_ID")
private Customer customer;
@Column(name = "EMAIL", length = 250)
private String email;
@Column(name = "PASSWORD_HASH", length = 250)
private String passwordHash;
@Column(name = "ACTIVE")
private Boolean active;
@Column(name = "CREATED_AT")
private LocalDateTime createdAt;
@Column(name = "UPDATED_AT")
private LocalDateTime updatedAt;
@Column(name = "CREATED_BY")
private Integer createdBy;
@Column(name = "UPDATED_BY")
private Integer updatedBy;
@Column(name = "DELETED_AT")
private LocalDateTime deletedAt;
}
Example (Rust):
{
"tables": ["USERS"],
"language": "rust",
"database": "shop",
"include_fks": true
}
Result:
// User maps to table USERS
#[derive(Debug, Clone, FromRow)]
pub struct User {
/// Column: ID
pub id: Option,
/// Column: CUSTOMER_ID — FK → CUSTOMERS.ID
pub customer_id: Option,
/// Column: EMAIL
pub email: Option,
/// Column: PASSWORD_HASH
pub password_hash: Option,
/// Column: ACTIVE
pub active: bool,
/// Column: CREATED_AT
pub created_at: NaiveDateTime,
/// Column: UPDATED_AT
pub updated_at: NaiveDateTime,
/// Column: CREATED_BY
pub created_by: i32,
/// Column: UPDATED_BY
pub updated_by: i32,
/// Column: DELETED_AT
pub deleted_at: NaiveDateTime,
}
// Example query (aliases must match field names for FromRow):
// SELECT ID AS id, CUSTOMER_ID AS customer_id, EMAIL AS email, ... FROM USERS
// let rows: Vec = conn.query(sql, ({}))?;
Example (TypeScript):
{
"tables": ["USERS"],
"language": "typescript",
"database": "shop",
"include_fks": true
}
Result:
export interface User {
id?: number;
/** FK → CUSTOMERS.ID */
customerId?: number;
email?: string;
passwordHash?: string;
active: boolean;
createdAt: string;
updatedAt: string;
createdBy: number;
updatedBy: number;
deletedAt: string;
}
Example (Protobuf):
{
"tables": ["USERS"],
"language": "protobuf",
"database": "shop",
"include_fks": true
}
Result:
syntax = "proto3";
package users;
// Nullable columns: ID, CUSTOMER_ID, EMAIL, PASSWORD_HASH
message User {
int32 id = 1;
// FK → CUSTOMERS.ID
int32 customer_id = 2;
string email = 3;
string password_hash = 4;
bool active = 5;
string created_at = 6;
string updated_at = 7;
int32 created_by = 8;
int32 updated_by = 9;
string deleted_at = 10;
}
Example (OpenAPI):
{
"tables": ["USERS"],
"language": "openapi",
"database": "shop",
"include_fks": true
}
Result:
User:
type: object
description: Schema for table USERS
required:
- active
- createdAt
- updatedAt
- createdBy
- updatedBy
- deletedAt
properties:
id:
type: integer
format: int32
nullable: true
customerId:
type: integer
format: int32
nullable: true
x-foreign-key: CUSTOMERS.ID
email:
type: string
nullable: true
passwordHash:
type: string
nullable: true
active:
type: boolean
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
createdBy:
type: integer
format: int32
updatedBy:
type: integer
format: int32
deletedAt:
type: string
format: date-time
Example (Lazarus/Delphi):
{
"tables": ["CUSTOMERS"],
"language": "lazarus",
"database": "shop"
}
Result:
object FormCustomer: TFormManutencao
Left = 0
Top = 0
Caption = 'FormCustomer'
ClientHeight = 400
ClientWidth = 600
LCLVersion = '3.0.0.0'
object FBDataSetCustomer: TFBDataSet
Left = 24
Top = 24
Connected = False
SQL.Strings = (
'SELECT * FROM CUSTOMERS'
)
end
object DataSourceCustomer: TDataSource
Left = 112
Top = 24
DataSet = FBDataSetCustomer
end
object Label_ID: TLabel
Left = 24
Top = 100
Width = 120
Height = 15
Caption = 'ID:'
ParentColor = False
end
object TDBEdit_ID: TDBEdit
Left = 24
Top = 121
Width = 120
Height = 23
DataSource = DataSourceCustomer
DataField = 'ID'
TabOrder = 0
end
object Label_IS_VERIFIED: TLabel
Left = 24
Top = 160
Width = 150
Height = 15
Caption = 'IS_VERIFIED:'
ParentColor = False
end
object TDBCheckBox_IS_VERIFIED: TDBCheckBox
Left = 24
Top = 181
Width = 150
Height = 23
DataSource = DataSourceCustomer
DataField = 'IS_VERIFIED'
TabOrder = 1
end
object Label_CREATED_AT: TLabel
Left = 24
Top = 220
Width = 150
Height = 15
Caption = 'CREATED_AT:'
ParentColor = False
end
object TDBDateTimePicker_CREATED_AT: TDBDateTimePicker
Left = 24
Top = 241
Width = 150
Height = 23
DataSource = DataSourceCustomer
DataField = 'CREATED_AT'
TabOrder = 2
Kind = dtkDate
end
...
end
Component mapping:
| Firebird Type | Lazarus Component | Width |
|---|---|---|
| INTEGER/BIGINT/SMALLINT | TDBEdit | 120 |
| VARCHAR/CHAR | TDBEdit | 80/250/450 (dynamic) |
| NUMERIC/DECIMAL | TDBEdit | 120 |
| BOOLEAN | TDBCheckBox | 150 |
| DATE/TIMESTAMP | TDBDateTimePicker | 150 |
| BLOB SUB_TYPE TEXT | TDBMemo | 450 |
| BLOB SUB_TYPE BINARY | TDBEdit | 250 |
Example (Svelte 5):
{
"tables": ["CUSTOMERS"],
"language": "svelte",
"database": "shop"
}
Result: Generates two components:
- Page —
PageShell+Tablewith search by PK and FKs:
<PageShell
title="Customer"
onSearch={search}
onClear={clear}
{loading}
{error}
skeletonVariant="table"
skeletonRows={5}
>
{#snippet searchFields()}
{/snippet}
{#snippet content(state)}
<Table
id="customer"
caption="Customer"
{data}
{columns}
{actions}
rowKey="id"
csvFileName="customer.csv"
onAdd={() => {}}
/>
{/snippet}
- Form — Fields with
$state(no event logic):
Field mapping:
| Firebird Type | Svelte Component | TS Type |
|---|---|---|
| BOOLEAN | SwitchField | boolean |
| DATE/TIMESTAMP | DateField | string |
| INTEGER/BIGINT/SMALLINT/NUMERIC/DECIMAL | NumericField | number |
| VARCHAR/CHAR/BLOB | EditField | string |
firebird_generate_view_dto
Generates DTOs/records from views using resolved metadata (executes SELECT FIRST 1 * FROM view to get accurate column types). Generated code is read-only (no entity annotations, no FKs).
Arguments:
views(required): Array of view names (max 20)language(required):java,go,rust,typescript,protobuf,openapi,lazarus, orsveltedatabase(optional): Database name
Example (Java):
{
"views": ["VW_ACTIVE_USERS"],
"language": "java",
"database": "shop"
}
Result:
@Data
public class VwActiveUsers {
private Long id;
private String email;
private String passwordHash;
private Boolean active;
private Long customerId;
private Long typeId;
private Boolean isActive;
private String fullName;
private java.time.LocalDateTime createdAt;
private java.time.LocalDateTime updatedAt;
private String createdBy;
private String updatedBy;
}
Example (Lazarus/Delphi):
{
"views": ["VW_ACTIVE_USERS"],
"language": "lazarus",
"database": "shop"
}
Result:
object FormVwActiveUsers: TFormConsulta
Left = 0
Top = 0
Caption = 'FormVwActiveUsers'
ClientHeight = 400
ClientWidth = 600
LCLVersion = '3.0.0.0'
object FBDataSetVwActiveUsers: TFBDataSet
Left = 24
Top = 24
Connected = False
SQL.Strings = (
'SELECT * FROM VW_ACTIVE_USERS'
)
end
object DataSourceVwActiveUsers: TDataSource
Left = 112
Top = 24
DataSet = FBDataSetVwActiveUsers
end
object Label_ID: TLabel
Left = 24
Top = 100
Width = 120
Height = 15
Caption = 'ID:'
ParentColor = False
end
object TDBEdit_ID: TDBEdit
Left = 24
Top = 121
Width = 120
Height = 23
DataSource = DataSourceVwActiveUsers
DataField = 'ID'
TabOrder = 0
end
object Label_ACTIVE: TLabel
Left = 24
Top = 160
Width = 150
Height = 15
Caption = 'ACTIVE:'
ParentColor = False
end
object TDBCheckBox_ACTIVE: TDBCheckBox
Left = 24
Top = 181
Width = 150
Height = 23
DataSource = DataSourceVwActiveUsers
DataField = 'ACTIVE'
TabOrder = 1
end
...
end
firebird_explain_plan
Gets the execution plan for a SQL statement without actually running it. The statement is executed inside a rolled-back transaction.
Arguments:
sql(required): The SQL statementdatabase(optional): Database name
Result:
Execution plan (the statement was executed inside a rolled-back transaction):
PLAN:
SORT
TABLE: CLIENTS (INDEX: PK_CLIENTS)
firebird_metadata_extract
Extracts complete database metadata (DDL) using system tables. Replaces isql -x.
Arguments:
database(optional): Database nameobjects(optional): Array of object names to filter (e.g.,["CLIENTS", "ORDERS"])
Result:
CREATE TABLE CLIENTS (
ID INTEGER NOT NULL,
NAME VARCHAR(100) NOT NULL,
EMAIL VARCHAR(255),
CREATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
CONSTRAINT PK_CLIENTS PRIMARY KEY (ID)
);
CREATE INDEX IDX_CLIENTS_EMAIL ON CLIENTS (EMAIL);
...
Project Structure
firebird-5-mcp/
├── Cargo.toml # Workspace manifest
├── crates/
│ ├── mcp-core/ # Reusable library (firebird-5-mcp-core)
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs # Public API
│ │ ├── config.rs # Config loading
│ │ ├── client.rs # Connection wrapper
│ │ ├── query.rs # SQL execution
│ │ ├── schema.rs # Schema introspection
│ │ ├── ddl.rs # DDL operations
│ │ ├── explain.rs # Execution plans
│ │ ├── metadata.rs # DDL extraction
│ │ ├── generator.rs# Code generation
│ │ └── types.rs # Type formatting
│ └── mcp-bin/ # MCP server binary (firebird-5-mcp)
│ ├── Cargo.toml
│ └── src/
│ ├── main.rs # JSON-RPC stdio loop
│ └── tools/
│ ├── mod.rs # Dispatch
│ ├── common.rs # Shared helpers
│ ├── definitions.rs # Tool schemas
│ ├── query_tools.rs # Query tools
│ ├── schema_tools.rs # Schema tools
│ ├── ddl_tools.rs # DDL tools
│ └── generator_tools.rs # Code generation
└── README.md
Design
The project is split into two crates:
-
firebird-5-mcp-core— A reusable library that provides:- Database connection management
- SQL query execution
- Schema introspection
- DDL operations
- Code generation
This library can be used in other Rust projects (e.g., desktop apps, CLI tools) without the MCP layer.
-
firebird-5-mcp— The MCP server binary that:- Implements the MCP protocol (JSON-RPC over stdio)
- Exposes the core library’s functionality as MCP tools
- Handles configuration and error reporting
Extending with new database engines
The core library is designed to be database-agnostic. To add support for a new database engine:
- Create a new crate (e.g.,
postgres-mcp-core) - Implement the same traits/interfaces
- Create a new MCP server binary (e.g.,
postgres-mcp)
Optimized Build for Deployment
The release profile is optimized for minimal binary size and maximum performance:
[profile.release]
opt-level = 3 # Maximum optimization
codegen-units = 1 # Best codegen (slower build, better runtime)
lto = "fat" # Aggressive link-time optimization
panic = "abort" # Smaller binary (no unwinding)
strip = true # Remove symbols from binary
debug = false # No debug info
Result: ~1.2MB static binary (vs ~8MB for the Go version)
Credits
- rsfbclient — Pure-Rust Firebird client driver (no native libraries required)
- jedSvelted-ui — Svelte 5 component library used by the Svelte code generator (
@edujed/jedsvelted-ui) - Model Context Protocol — The MCP specification
License
MIT — see LICENSE.
インストール
This server does not publish a one-line install command.
Open the repository installation guide