Skip to main content
ClaudeWave
aoreshkov avatar
aoreshkov

oracle-forms-mcp

Ver en GitHub

MCP server that exposes Oracle Forms modules (.fmb/.mmb/.pll/.olb) — blocks, triggers, PL/SQL, object XML — to AI assistants for legacy modernization and code review.

MCP ServersRegistry oficial3 estrellas0 forksKotlinApache-2.0Actualizado today
ClaudeWave Trust Score
95/100
Verified
Passed
  • Open-source license (Apache-2.0)
  • Actively maintained (<30d)
  • Clear description
  • Topics declared
  • Documented (README)
Last scanned: 9/13/2026
Install in Claude Code / Claude Desktop
Method: Manual
Claude Code CLI
git clone https://github.com/aoreshkov/oracle-forms-mcp
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Clone https://github.com/aoreshkov/oracle-forms-mcp and follow its README for install instructions.
Casos de uso

Resumen de MCP Servers

# Oracle Forms MCP

[![CI](https://github.com/aoreshkov/oracle-forms-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/aoreshkov/oracle-forms-mcp/actions/workflows/ci.yml)
[![CodeQL](https://github.com/aoreshkov/oracle-forms-mcp/actions/workflows/codeql.yml/badge.svg)](https://github.com/aoreshkov/oracle-forms-mcp/actions/workflows/codeql.yml)
[![Release](https://img.shields.io/github/v/release/aoreshkov/oracle-forms-mcp)](https://github.com/aoreshkov/oracle-forms-mcp/releases/latest)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
[![Kotlin](https://img.shields.io/badge/kotlin-2.4-7F52FF.svg?logo=kotlin)](https://kotlinlang.org)

An [MCP](https://modelcontextprotocol.io) server that serves the content of Oracle Forms modules
(`.fmb` forms, `.mmb` menus, `.pll` PL/SQL libraries, `.olb` object libraries) found in a
directory, so AI assistants can inspect blocks, items, triggers, program units, and raw object
XML without opening Forms Builder.

<!-- mcp-name: io.github.aoreshkov/oracle-forms-mcp -->

Built as a Kotlin Multiplatform core (pure `@Serializable` models and ports) with a JVM MCP
server on top: declarative tool adapters over a single `FormsService`, stdio and HTTP transports,
and a fingerprint-based on-disk cache. Oracle tool conversion feeds a streaming StAX parser that
turns Forms XML into a structured index.

## Why

Oracle Forms applications from the 1990s–2000s are still running critical business processes, but
their logic is locked inside binary `.fmb`/`.pll` modules that only Forms Builder can open. That
makes them opaque to modern AI tooling and painful to review, document, or migrate.

Oracle Forms MCP turns those modules into structured, queryable content so an AI assistant can:

- **Understand a legacy app** — enumerate blocks, items, triggers, and program units without a Forms IDE.
- **Review & document PL/SQL** — pull decoded trigger and program-unit bodies straight into the model's context.
- **Assist modernization** — feed decades-old business logic to an assistant for migration to APEX,
  Java, or a rewrite, and search across every module's source.
- **Capture & retain knowledge** — let the assistant record notes, tags, and cross-references on
  individual elements that persist across sessions and re-indexing, building up a durable map of a
  form no one fully remembers.

It is aimed at developers and teams doing Oracle Forms **modernization, reverse engineering, code
review, and documentation** — anyone who needs to read Forms logic faster than opening it by hand.

## See it work

<!-- TODO: record a short asciinema/GIF of a Claude session and embed it here:
     ![demo](docs/demo.gif)   (drop the file at docs/demo.gif or an assets/ path) -->

A typical session against the bundled `sample-forms` directory:

```text
You:  What does ORDERS.fmb do?
AI →  list_modules                 → ORDERS.fmb (NOT_CACHED), MAINMENU.mmb, UTILS.pll …
AI →  fetch_module ORDERS.fmb      → converted + indexed (2 blocks, 3 triggers, 3 program units)
AI →  get_module_overview ORDERS   → blocks, triggers, LOVs, record groups, windows, canvases …
You:  Show me the validation logic on the ORDERS block.
AI →  list_triggers block=ORDERS   → WHEN-VALIDATE-ITEM (on ORDER_ID), WHEN-VALIDATE-RECORD
AI →  get_trigger ORDERS WHEN-VALIDATE-ITEM  → the decoded PL/SQL body
You:  Where else is the CALC_TOTAL procedure called?
AI →  search_source "calc_total" scope=plsql  → hits across triggers and program units
You:  That validation is the legacy pre-2010 path — note it so we remember.
AI →  annotate_element ORDERS trigger WHEN-VALIDATE-ITEM kind=note "Legacy pre-2010 validation path" → saved
      (next session)  get_trigger ORDERS WHEN-VALIDATE-ITEM → body + the stored note inline
```

## How it works

1. `list_modules` scans the configured `--forms-dir` (non-recursive) and reports each module's
   cache status: `NOT_CACHED`, `CACHED`, `STALE` (source changed on disk), or `SOURCE_MISSING`.
   A production forms directory holds thousands of modules, so the answer is filtered and paged:
   narrow with `pattern`/`type`/`status`, follow `nextCursor` for the rest, and read
   `countsByStatus` for the shape of the whole match.
2. `fetch_module` produces the module's text form in the cache and indexes it:
   - **`ORACLE_HOME` set** — binaries are converted with the Oracle tools in
     `%ORACLE_HOME%\bin`: `frmf2xml` for `.fmb`/`.mmb`/`.olb` (XML), `frmcmp_batch`
     (`Module_Type=LIBRARY Script=YES`) for `.pll` (a `.pld` text dump).
   - **`ORACLE_HOME` not set** — pre-converted files are expected next to the modules
     (`orders_fmb.xml`, `dupes_fmb.xml`, `picker_fmb.xml`, `toolbar_fmb.xml`,
     `mainmenu_mmb.xml`, `objects_olb.xml`, `utils.pld`) and copied into the cache.
3. A single StAX pass parses the XML into a structured index (blocks with items, triggers with
   decoded PL/SQL, program units, LOVs, record groups, windows, canvases, …). PL/SQL bodies are
   extracted to `.sql` sidecar files; every named XML element gets a line-range reference so
   `get_object_xml` can slice it back out of the converted file.
4. The other tools read the cached index. Caching is fingerprint-based (size + mtime + sha256 of
   the source file): editing a module marks it `STALE` and read tools ask for a re-fetch.
5. `annotate_element` and `relate_elements` let the assistant write durable meta-information back
   about individual elements (notes, tags, summaries, classifications, cross-references). This is
   kept in a **separate** store — not the derived index — so it survives re-fetching, and the read
   tools surface it inline. An annotation made before a source change is flagged, never dropped.

## Tools

| Tool | What it returns |
|---|---|
| `list_modules` | Modules in the forms dir with type, size, and cache status; filter by `pattern`/`regex`, `type`, `status` and page via `limit`/`cursor` |
| `fetch_module` | Converts + indexes one module (idempotent; progress notifications) |
| `get_module_overview` | Names of every section + counts — the first call after a fetch (`verbosity=detailed` adds window and canvas objects) |
| `list_blocks` | Blocks with base table, item count, trigger count |
| `get_block` | One block: items with type, property class, prompt and trigger names (`verbosity=detailed` adds data type, column, canvas, visible/required/LOV); flags subclassed blocks/items |
| `list_triggers` | Triggers with level/scope; filter by block, item, or level (`verbosity=detailed` adds a PL/SQL preview) |
| `get_trigger` | One trigger's decoded PL/SQL body; `resolve` follows a subclassing pointer into a cached parent module |
| `list_program_units` | Procedures, functions, package specs/bodies with line counts |
| `get_program_unit` | One program unit's PL/SQL (disambiguate spec/body via `unitType`); `resolve` as for `get_trigger` |
| `search_source` | Line search over one fetched module: extracted PL/SQL (`plsql`), the raw XML (`xml`), or both; paginated via `offset`/`nextOffset` |
| `search_modules` | The same search across **every cached module** — cross-form calls, shared `:GLOBAL`s, subclassing pointers; reports the modules it could not reach; paged via an opaque `cursor` |
| `read_source` | A line range of a cached file, by `uri` or `file` — the converted XML or an extracted PL/SQL sidecar |
| `get_object_xml` | The raw XML fragment of any named object — the escape hatch |

### Where an object's meaning lives

Two Forms properties carry more meaning than anything else in a module, and both used to be
reachable only one `get_object_xml` call at a time.

An item's **property class** is usually its role: Forms shops name their classes for what the
object does, so a push button is an *LOV* button and a text item is a *filter* field only because
of the class it inherits. `get_block` reports `propertyClass` on every item and block, confirmed
against the classes the module actually declares.

A window's **modality** decides how a form is read — a modal window is a dialog, so the code that
fills it and the code that consumes the result sit on opposite sides of one interaction.
`get_module_overview(verbosity: "detailed")` returns the window and canvas objects behind two of
its name lists: modality, size, toolbar canvases, and the window each canvas sits on.

A property Forms did not write comes back as `null`, meaning the object keeps the Forms default —
never `false`.

### Reading around a result

Everything indexed is a line range into a file the cache owns, and those ranges used to name a
path with no way to resolve it. Every result that points at a file now carries a `source`:

```jsonc
"source": {
  "uri": "oracleforms://ORDERS.fmb/plsql/triggers/ORDERS.ORDER_ID.WHEN-VALIDATE-ITEM.sql",
  "file": "plsql/triggers/ORDERS.ORDER_ID.WHEN-VALIDATE-ITEM.sql",
  "startLine": 1, "endLine": 3
}
```

`read_source` takes either form back, so a search hit can be read in context and a truncated
fragment continued. The same files are readable as MCP resources —
`oracleforms://{module}/converted` for the converted text form and
`oracleforms://{module}/plsql/{category}/{name}` for one extracted block of PL/SQL — and every
such result also carries a `resource_link` content block, so a client can follow it without
parsing JSON. Reads are capped by lines *and* characters; a cut resource read says so in the text
it returns and names the call that continues it.

Paths stay cache-relative and URIs stay layout-independent: an absolute host path would mean
nothing to a client talking to the container image or over HTTP.

### Subclassed (inherited) objects

Forms lets a block, item, trigger or program unit be **subclassed** from another module, or copied
in with an **object group** (typically from an `.olb`). Either way the child stores only what it
overrides, so its PL/SQL body is genuinely empty in its own file while the code that runs lives in
the parent. Served naively that is not merely incomplete but wrong —
aiclaudekotlinkotlin-multiplatformlegacy-modernizationllmmcpmcp-servermodel-context-protocoloracleoracle-formsplsql

Lo que la gente pregunta sobre oracle-forms-mcp

¿Qué es aoreshkov/oracle-forms-mcp?

+

aoreshkov/oracle-forms-mcp es mcp servers para el ecosistema de Claude AI. MCP server that exposes Oracle Forms modules (.fmb/.mmb/.pll/.olb) — blocks, triggers, PL/SQL, object XML — to AI assistants for legacy modernization and code review. Tiene 3 estrellas en GitHub y su última actualización registrada es del 2026-09-12.

¿Cómo se instala oracle-forms-mcp?

+

Puedes instalar oracle-forms-mcp clonando el repositorio (https://github.com/aoreshkov/oracle-forms-mcp) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.

¿Es seguro usar aoreshkov/oracle-forms-mcp?

+

Nuestro agente de seguridad ha analizado aoreshkov/oracle-forms-mcp y le ha asignado un Trust Score de 95/100 (tier: Verified). Revisa el desglose completo de comprobaciones superadas y flags en esta página.

¿Quién mantiene aoreshkov/oracle-forms-mcp?

+

aoreshkov/oracle-forms-mcp es mantenido por aoreshkov. La última actividad registrada en GitHub es del 2026-09-12, con 0 issues abiertos.

¿Hay alternativas a oracle-forms-mcp?

+

Sí. En ClaudeWave puedes explorar mcp servers similares en /categories/mcp, ordenados por popularidad o actividad reciente.

Despliega oracle-forms-mcp en tu cloud

Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.

¿Mantienes este repo? Añade un badge a tu README

Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.

Featured on ClaudeWave: aoreshkov/oracle-forms-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/aoreshkov-oracle-forms-mcp)](https://claudewave.com/repo/aoreshkov-oracle-forms-mcp)
<a href="https://claudewave.com/repo/aoreshkov-oracle-forms-mcp"><img src="https://claudewave.com/api/badge/aoreshkov-oracle-forms-mcp" alt="Featured on ClaudeWave: aoreshkov/oracle-forms-mcp" width="320" height="64" /></a>

Más MCP Servers

Alternativas a oracle-forms-mcp