OpenL MCP Server
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| OPENL_TIMEOUT | No | Optional timeout in ms | 60000 |
| OPENL_BASE_URL | Yes | Base URL of OpenL Studio | |
| OPENL_PASSWORD | No | Password for basic auth | |
| OPENL_USERNAME | No | Username for basic auth | |
| OPENL_PERSONAL_ACCESS_TOKEN | No | Personal access token |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
| prompts | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| openl_get_startedA | Read-only. Call this FIRST, once per session, before any other openl_ tool. Returns the mandatory workflow protocol and a workspace orientation: when to call openl_get_project_agent_context (before working on or creating any project), how to discover the bundled OpenL reference documentation (openl_list_guides / openl_get_guides), and the edit → validate → save loop. Takes no arguments and never calls OpenL Studio. |
| openl_list_guidesA | List the OpenL reference documentation bundled with this server — METADATA ONLY (id, type, title, source path, size in bytes), never bodies; fetch bodies with openl_get_guides. The bundle embeds the OpenL Tablets docs at the release tag matching the targeted OpenL Studio version: 'specification' entries are config-file/project-layout specs (rules.xml, rules-deploy.xml, project structure, openl-maven-plugin), 'guide' entries are the Reference Guide chapters (table types, table properties, functions and data types, projects, BEX/function appendices). Filter with 'type' and/or case-insensitive 'search' over id+title; results are paginated (limit/offset). Read-only, local — never calls OpenL Studio. |
| openl_get_guidesA | Return the FULL markdown bodies of 1-5 bundled documents by the exact ids from openl_list_guides (e.g. 'spec/rules.xml', 'guide/introduction/basic-concepts'). Unknown ids fail with an error naming them — this tool never falls back to the index; look ids up with openl_list_guides first. Bodies are returned verbatim and are NOT truncated, so mind each entry's size_bytes from the index and request only what you need. Read-only, local — never calls OpenL Studio. |
| openl_get_project_agent_contextA | Resolve the agent guidance (AGENTS.md hierarchy) that applies to a project — call this BEFORE working on or creating anything in the project. Starting at the project directory — or the optional 'folder' sub-directory — this walks UP through every parent folder to the repository root, collects every AGENTS.md found, and returns them concatenated in ONE markdown document ordered from the root folder (lowest priority) down to the project folder (highest priority); on conflicting instructions, each later section overrides the earlier ones. AGENTS.md files live not only in the project but often in a workspace/monorepo root above it. Levels with no AGENTS.md are skipped (not an error); a project with none returns a short 'no files' note. When the guidance references bundled reference guides by id, those ids are listed at the end — fetch them with openl_get_guides. The search direction is fixed — to search a project's own subtree by glob/content instead, use openl_search_project_files. |
| openl_get_versionA | Report this MCP server's own version and build identity for diagnostics and bug reports: the package version, the build id (version plus the short commit it was built from, suffixed '.dirty' for a modified working tree), the full commit and its date, the branch or tag, the build timestamp, and the Node.js/platform/architecture it runs on. Quote 'build.id' when reporting a problem — nightly builds between two releases share the same version and are otherwise indistinguishable. Needs no OpenL Studio connection and returns no configuration, credentials, or URLs. A build.source of 'unavailable' means this install shipped without build metadata, so only the version is known. |
| openl_list_deploymentsA | List active deployments across production environments, optionally filtered by production repository ID and deployed project name. Returns deployment names, repositories, and deployed project revisions. |
| openl_deploy_projectA | Deploy a project to production environment. Publishes rules to a deployment repository for runtime execution. Use production repository name (not ID) - e.g., 'Production Deployment' instead of 'production-deploy'. |
| openl_redeploy_projectA | Redeploy an existing deployment with a new project version. Use this to update a deployment with a newer version of the project or rollback to a previous version. |
| openl_list_repositoriesA | List all design repositories in OpenL Studio. Returns repository information including 'id' (internal identifier) and 'name' (display name). Use the 'name' field when working with repositories in other tools. Either the 'id' or 'name' is accepted by other tools (case-insensitive). The actual values are usually short tokens like 'design' — never invent values such as 'Design Repository' or 'design-repo'. |
| openl_list_branchesA | List all Git branch names in a repository. Use this to see available branches before switching or comparing versions. Pass either the id or name from openl_list_repositories() — both are accepted (case-insensitive). Do not invent example values; call openl_list_repositories() first if not in context. |
| openl_list_repository_featuresA | Get features supported by a design repository (branching, searchable, etc.). Use this to check if a repository supports specific features like branching before performing operations that depend on those features. Pass either the id or name from openl_list_repositories() — both are accepted (case-insensitive). Do not invent example values; call openl_list_repositories() first if not in context. |
| openl_repository_project_revisionsA | Get revision history (commit history) of a project in the branch it is currently on. Addressing the project by its stable ID keeps history available after an unsaved rename. Returns revisions with commit hashes, authors, timestamps, and commit types, with pagination and optional search and technical-revision filters. Use the projectId returned by openl_list_projects; do not construct it from the displayed project name. |
| openl_list_deploy_repositoriesA | List all deployment repositories in OpenL Studio. Returns repository names, their types, and status information. Use this to discover all available deployment repositories before deploying projects. |
| openl_start_project_testsA | Start project test execution. For design repositories the project is automatically opened if closed; for repository 'local' the project is not opened (tests run directly). Returns execution status and metadata. Test results can be retrieved using openl_get_test_results_summary, openl_get_test_results, or openl_get_test_results_by_table. |
| openl_get_test_results_summaryA | Get brief test execution summary without detailed test cases. Returns aggregated statistics (execution time, total tests, passed, failed) without the testCases array. Use openl_start_project_tests() first to start test execution. |
| openl_get_test_resultsA | Get full test execution results with pagination support. Returns complete test execution summary including testCases array grouped by table. IMPORTANT: Pagination applies to test tables (not individual test cases). Each page returns test results aggregated by table (e.g., 'TestTable1' with 7 tests, 'TestTable2' with 8 tests). Supports filtering failures and pagination (page/offset/size). Use openl_start_project_tests() first to start test execution. |
| openl_get_test_results_by_tableB | Get test execution results filtered by specific table ID. Returns filtered test execution summary with only test cases for the specified table. Supports pagination (page/offset/size) for efficient data retrieval. Use openl_start_project_tests() first to start test execution. |
| openl_list_project_local_changesA | List local change history for a project. Returns list of workspace history items with versions, authors, timestamps, and comments. NOTE: Requires the project to be opened (openl_open_project first); not available for repository 'local' (local projects cannot be opened). Uses session-based project context; no projectId parameter. |
| openl_restore_project_local_changeA | Restore a project to a specified version from its local history. Use the historyId from openl_list_project_local_changes response. NOTE: Requires the project to be opened first; not available for repository 'local'. Uses session-based project context; no projectId parameter. |
| openl_read_project_fileA | Read any file in a project by its project-relative path — text or binary, and folder listings too. Maps to GET /projects/{projectId}/files/{path}. Behavior by path/params: (1) a FILE path returns its content — UTF-8 text is returned verbatim, while binary is returned as base64 'content' in a JSON text envelope with byte and MIME metadata (use encoding to force 'utf-8' or binary; default 'auto' detects); (2) a FILE path with view='meta' returns JSON metadata (name, size, extension, lastModified); (3) a FOLDER path (empty string for the root, or a path ending in '/') lists its entries (use recursive, viewMode FLAT/NESTED, extensions, namePattern, foldersOnly); (4) a FOLDER path with download=true returns a ZIP as base64 in the same JSON text envelope. Optional 'version' reads a historical revision; 'branch' pins the project branch. Optional byte range (offset/length) is applied client-side AFTER fetching the whole file (the backend does not support partial transfers), so the entire file is loaded into memory; for very large/binary files, bound the RETURNED size with offset/length and read in chunks (a full file's base64 can exceed MCP message limits). Use this to read AGENTS.md, README.md, schemas, manifests, or to inspect/export xlsx rule files. |
| openl_write_project_fileA | Create or replace a file in a project by its project-relative path. Provide UTF-8 text in 'content'. For binary files such as xlsx/images/zip, provide base64 bytes in 'blob'; its advertised JSON Schema uses contentEncoding='base64'. The legacy content + encoding='base64' form remains accepted. COMMIT: pass 'message' to commit the write to Git (a new revision is created); omit 'message' and the write stays in the project WORKING COPY (commit it later with openl_save_project). Committing saves ALL pending project changes and works only for design repositories (not 'local'). By default missing parent folders are created (createFolders=true). If the target file already EXISTS, behavior follows conflictPolicy: FAIL (default) returns an error; OVERWRITE replaces the file in place; SKIP leaves the existing file unchanged (reported skipped). Use 'branch' to pin the project's branch (omit for local/non-branch repositories). Use this to add or update docs, schemas, or manifests. (For a NEW file the tool POSTs/creates; OVERWRITE is performed via PUT/update — overwriting a module .xlsx replaces its bytes but to change a module's TABLES use openl_update_table / openl_append_table / openl_create_project_table.) |
| openl_delete_project_fileA | Delete a file or folder from a project by its project-relative path. Maps to DELETE /projects/{projectId}/files/{path}. The backend auto-cleans dangling references to the deleted resource from the project configuration. Like writes, the deletion is staged in the working copy — commit it with openl_save_project. Use 'branch' to pin the project's branch (omit for local/non-branch repositories). Use this to remove legacy assets or deprecate docs. This is a destructive operation. |
| openl_search_project_filesA | Search a project's files and folders by ant-glob path 'pattern' (e.g. 'rules//*.xlsx'), file 'extensions', resource 'type' (FILE/FOLDER/ANY), and/or a case-insensitive 'content' substring. Maps to POST /projects/{projectId}/file-search. CONTENT LIMITATION: Studio searches inside TEXT files only. It does not inspect binary formats such as XLSX/XLS/ZIP/images; find those only by path pattern, extension, or name, then read/download them separately. Combining content with a binary-only pattern or extension therefore returns no matches even when that text is visible in an Excel workbook. IMPORTANT: set recursive=true to search nested folders — by default (recursive omitted/false) only the project's TOP LEVEL is searched, and a '' glob alone does NOT descend (so a project-wide search needs recursive=true, and to match files in subfolders use a '/' pattern such as '/.xlsx', not '.xlsx'). Scope SUBTREE (default) searches within the project and may target a historical 'version'; scope ANCESTORS walks up to the repository root. Returns matching nodes (path, name, type, size, ...), paginated client-side via 'limit'/'offset' (the response carries pagination metadata; the server returns the full match set). Use 'branch' to pin the project's branch. Use this for questions like "where is portability loading mentioned in XML or Markdown?" (content, recursive=true) or "list every xlsx under rules" (pattern '**/*.xlsx', recursive=true, without content). |
| openl_copy_project_fileA | Copy a file within a project to a new project-relative path. Maps to POST /projects/{projectId}/file-copy. Intermediate destination folders are created automatically. There is NO overwrite option — if destinationPath already exists the call fails with HTTP 409; choose a different destination or delete the existing file first. The copy is staged in the working copy — commit it with openl_save_project. Use 'branch' to pin the project's branch. Use this to scaffold a new module from an existing one or clone a test set. |
| openl_move_project_fileA | Move or rename a file within a project. Maps to POST /projects/{projectId}/file-move. Intermediate destination folders are created automatically and the source file is deleted after the move. A destination collision fails with HTTP 409. The move is staged in the working copy — commit it with openl_save_project. Use 'branch' to pin the project's branch. Use this to rename a file or relocate it to another folder. |
| openl_list_projectsA | List projects with the Studio filters for repository, status, dependency, name, author, branch, tags, sorting, and response expansions. Results are paginated (default 50, maximum 200): when a complete inventory is required, follow pagination.has_more and call again with pagination.next_offset until has_more is false. Returns project names, status (OPENED/CLOSED), metadata, and a convenient 'projectId' field from API to use with other tools. For local-only projects, do not pass repository filter 'local' (it may fail); list every page without that filter and filter results by repository === 'local' client-side. For such projects, open/save/close do not work; table/rule/test tools work without opening. IMPORTANT: The 'projectId' is returned exactly as provided by the API and should be used without modification. Pass either the id or name from openl_list_repositories() — both are accepted (case-insensitive). Do not invent example values; call openl_list_repositories() first if not in context. Use this to discover and filter projects. |
| openl_get_projectB | Get comprehensive project information including details, modules, dependencies, and metadata. Returns full project structure, configuration, and status. |
| openl_project_statusA | Get the project's compile state, diagnostics, pending changes, and module/test summary. By default wait=true: a supplied branch switches the opened design project to that branch before validation; if Studio reports idle, the tool lazily starts compilation through the tables API; if compilation is already running, it waits for a terminal state (ok/warnings/errors) and emits progress notifications when available. Set wait=false only for a fast read-only snapshot, which may legitimately return idle or compiling and never switches branches. Edits made through the MCP table tools already trigger recompilation. |
| openl_open_projectA | Open a project for editing. Supports opening on specific branches or viewing specific Git revisions. Use this before making changes to project tables or rules. |
| openl_save_projectA | Save project changes to Git. Works only when project status is EDITING (after opening and making changes). Requires comment (used as revision/commit message). Creates a new revision and transitions project to OPENED. Optional closeAfterSave: true saves and closes in one request. Use after update_table, append_table, or other edits. Does not work for repository 'local'. |
| openl_close_projectA | Close a project. If the project has unsaved changes (status EDITING), you must either save (saveChanges: true with comment) or discard (discardChanges: true). When discarding, ask the user for confirmation and then call again with confirmDiscard: true. Prevents accidental data loss. |
| openl_create_project_branchA | Create a new branch in a project's repository from a specified revision. Allows branching from specific revisions, tags, or other branches. If no revision is specified, the HEAD revision will be used. |
| openl_create_projectA | Create a new OpenL project in a design repository and commit it. Two modes, selected by the |
| openl_list_project_branchesA | List branch metadata in the repository that hosts a project, including repository base and protected flags. scope='project' (default) returns branches that already hold the project and are candidates for switching or deletion. Inspect the flags before deletion: the base branch cannot be deleted, while a protected branch requires force and explicit confirmation. scope='repository' returns every repository branch, including branches that do not hold the project yet; use it to discover otherBranch values before openl_check_project_merge or openl_merge_project_branches. Unlike openl_list_branches, this tool is project-aware and returns safety metadata. |
| openl_check_project_mergeA | Check merge direction, branch relationship, permissions, and blockers without changing Git. This is not a conflict preview: status='mergeable' means the source has changes absent from the target, not that the merge is conflict-free; conflicts are discovered only by openl_merge_project_branches. status='up-to-date' means the target already contains the source. canMerge reports whether Studio permits the attempt after permission, protection, and lock checks. mode='receive' merges otherBranch into the project's current branch; mode='send' merges the current branch into otherBranch. Discover merge targets with openl_list_project_branches(scope='repository'), because a valid target may not hold the project yet. |
| openl_merge_project_branchesA | Attempt to merge project branches. The tool first repeats the relationship and permission precheck: up-to-date returns without a write, and permission/lock blockers fail before merge. The precheck does not predict conflicts, so an allowed attempt can still return status='conflicts'. mode='receive' merges otherBranch into the current branch; mode='send' merges the current branch into otherBranch. A conflict result creates read-only, session-bound conflict state: inspect it on this same MCP server, then hand resolution to the user in Studio or cancel the pending state. Never choose OURS or THEIRS automatically. force is only for an eligible protected-target bypass and requires confirmForce=true. |
| openl_get_merge_conflictsA | Get the pending merge conflicts stored in this Studio HTTP session: grouped file paths, BASE/OURS/THEIRS revision details, and the default merge commit message. This is read-only evidence for a user who will resolve the conflict manually in Studio; the MCP server intentionally does not expose conflict resolution. Available only after openl_merge_project_branches returns status='conflicts'; use the same MCP server instance throughout inspection. |
| openl_read_merge_conflict_fileA | Read one BASE, OURS, or THEIRS version of a conflicted file from the current session as read-only evidence for manual user resolution in Studio. Never infer or apply a winning side automatically. UTF-8 and base64 binary chunks are returned in a JSON text envelope with MIME and byte-range metadata. Both forms include nextOffset while more data remains. length targets at most 16000 bytes; a UTF-8 chunk may include up to 3 extra bytes to finish its last character. The backend still downloads the whole file before this client-side slice. Use the exact file path from openl_get_merge_conflicts. |
| openl_cancel_merge_conflictsA | Abort the pending merge-conflict workflow by clearing its session state. This does not modify files or branches, but the stored conflict analysis is discarded; run the merge again to recreate it. |
| openl_delete_projectA | Permanently delete a project through Studio. This may create a deletion commit in its design repository. Safety guard: confirmProjectName is required and must exactly match the project's current backend name; the handler reads the project immediately before deletion. An optional comment becomes the deletion commit message. |
| openl_delete_project_branchA | Delete a branch from the repository hosting a project. The tool first reads project-aware branch metadata: a base branch is always rejected, and a protected branch requires force=true plus confirmForce=true (and eligible Studio permissions). It then performs a safe-delete preflight against the repository base branch when the target is the project's current branch. A branch with commits absent from base, unsaved changes, or no authoritative divergence check is rejected unless confirmDataLoss=true explicitly acknowledges the reported risk. confirmBranchName must exactly equal branch. If the project is open on the deleted branch, Studio closes it first. Branch names containing '/' are supported. |
| openl_start_traceA | Start an interactive debug session for a table and run to the first stop. Returns the execution stack (status + frames root→current). Default stopAtEntry: true suspends at the entry of the first frame; from there use openl_step_trace / openl_resume_trace and openl_inspect_trace_frame. For test tables pass testRanges (e.g. '2'); for regular rules pass inputJson { params, runtimeContext? }; omitting both replays the previous run's remembered input. Cheapest way to understand a whole run: profiling: true with stopAtEntry: false and no breakpoints — completes in this one call and returns 'profile', a constant-size overview of the top-N slowest tables (selfMillis/totalMillis/count) plus nodeCount/distinctTables/totalMillis. For a profiling overview pass inputJson (or testRanges) together with profiling: true and stopAtEntry: false EXPLICITLY every time — do not rely on replay (omitting the input): a replay only reproduces the compact profile if the remembered run was itself a profiling run, otherwise it can return a much larger stack that overflows the response limit. Find the hot or unexpected table in profile.hotspots, then replay into it with a breakpoint to inspect live values. The executed 'tree' is omitted by default; set includeTree: true to get its ROOT node (one level — each step carries a childrenTotal count) and browse a branch level by level with openl_expand_trace_tree. One active session per user — starting a new one terminates the previous. Idle sessions are reaped after ~10 minutes. |
| openl_step_traceA | Step the suspended debug session once and return the new stack. For declarative rules (decision tables, spreadsheets, rating) the main move is type: 'out' — run the current frame to its own exit so its result is inspectable — combined with breakpoints; 'into'/'over' are advanced (imperative TBasic/loops). A step that finishes a frame first suspends at that frame's exit — the frame is still on the stack with completed: true and its result readable via openl_inspect_trace_frame (or pass withValues: true to bundle those variables into this response); the next step continues in the caller. An exception suspends at the throwing frame before it propagates. The stack is returned compact — steps only for the active frame; use openl_inspect_trace_frame for another frame's detail. Valid only while suspended. (openl_resume_trace differs: it runs to the next breakpoint or completion, not just to this frame's exit.) |
| openl_resume_traceA | Resume the suspended debug session and wait (inside this call — no agent-side polling) until it stops again: at the next breakpoint, at an exception, or at completion. Unlike openl_step_trace(out), which only runs the current frame to its exit, resume runs to the NEXT breakpoint or the end. Returns the stack (compact — steps for the active frame only) at the stop; on a terminal 'error' status it carries the structured 'error', and on 'completed' of a profiling run the constant-size 'profile' overview (set includeTree: true for the one-level 'tree' root, then drill in with openl_expand_trace_tree). On timeout (default 30s) the still-running status is returned — call openl_resume_trace again to keep waiting (it re-attaches without re-resuming), or openl_stop_trace to give up. |
| openl_inspect_trace_frameA | Freeze and read the full state of one suspended stack frame: input parameters, runtime context, result (for a completed frame), sub-steps with computed values, and for a decision table the killer feature — 'decision' (which rule fired and how each condition evaluated per rule) plus 'ruleNames' (all rules, for per-rule breakpoints). Values may come lazy (lazy: true + parameterId) — expand with openl_get_trace_value. By default the response is trimmed (no value JSON schemas); full: true lifts the trim. To surface an anomaly among many neutral factors, filter the steps: onlyExecutedSteps drops not-yet-computed ones, and excludeStepValues drops steps whose value is a neutral constant (e.g. [1] in rating) — lazy step values are resolved before the comparison, so a neutral factor that came lazy is dropped too. withHighlights: true additionally returns the A1-keyed cell highlight overlay and the raw table grid to merge it with. Valid only while suspended (a terminal session answers 409 — read its final state from the last returned stack). |
| openl_set_trace_breakpointsA | Read the active breakpoint keys and the available targets (rule tables, deduplicated by name; with an active session only tables reachable from the traced one). When 'set' is provided it REPLACES the whole set first (empty array clears all). Key forms: '' stops at entry of every same-named table version; '' at that exact table (uri from frames[].uri); '#R{r}C{c}' at a spreadsheet cell; '#rule' when ANY rule of that decision table fires; '#' when a specific rule fires (rule names from openl_inspect_trace_frame ruleNames/decision). Append '@N' to any key to break only on the table's N-th execution (0-based) — e.g. '#R48C0@3'; without it a cell breakpoint hits every pass of a table that runs many times (one per coverage/iteration). N matches frames[].instance and the 'instance' of an openl_watch_trace_cells series, so a watch outlier at instance 3 is reached with '@3'. Works without a session — set breakpoints before openl_start_trace; changes during a session apply at the next frame enter or line change. |
| openl_get_trace_valueA | Fetch the full value of a parameter that openl_inspect_trace_frame returned lazily (lazy: true with a parameterId). Valid while the debug session is alive. By default only name, description, and value are returned; withSchema: true adds the value's JSON Schema (large — request it only when the type structure itself matters). |
| openl_expand_trace_treeA | Load one level of a profiling run's executed call tree on demand. The tree is lazy: the /stack |
| openl_stop_traceA | Terminate the debug session and free its worker and lazy-value registry. Idempotent — succeeds even when no session is active. Breakpoints survive (they are session-scoped, not run-scoped). |
| openl_watch_trace_cellsA | Answer 'show me this factor across all coverages/iterations' in one call, without dumping frames. Watch SCALAR cells (a single number/string factor, e.g. '$VehiclePriceFactor') — NOT a cell whose value is a big aggregate object (a whole spreadsheet result like '$RateCardPremium'), which makes every captured point huge and can overflow the response; drill into an aggregate with a breakpoint + openl_inspect_trace_frame instead. Runs the table to completion and returns a WatchView: one 'series' per cell with a 'points' array holding the cell's value at each execution of its table (each point carries instance/label/ref/path; value is serialized like any traced value and may come lazy — expand a large one with openl_get_trace_value using its parameterId). Read the series, spot the outlier (e.g. 83.372 among 1.0s), then jump straight to that pass: set a breakpoint '<point.ref>@<point.instance>' (the '@N' suffix targets the N-th execution — same 0-based numbering as the series' 'instance') and replay + openl_inspect_trace_frame to see why. Value JSON Schemas are omitted by default (withSchema: true restores them). Captures cells inside lazy result branches too (nested SpreadsheetResult[]) — the run materializes the whole result. The server caps points per series for a cell deep in a combinatorial branch (benefit × gender × age-band …); each series reports 'total' (the full execution count) and WatchView.truncated flags that some late executions were dropped — inspect a specific one with a '@N' breakpoint. Pass testRanges for a test table or inputJson for a regular rule (omit both to replay the remembered input). This starts a fresh session (terminates any previous one) and clears breakpoints so the run reaches completion. |
| openl_list_tablesA | List tables/rules in a project with optional filters for kind, name, and properties. Results are paginated (default 50, maximum 200): when a complete inventory is required, follow pagination.has_more and call again with pagination.next_offset until has_more is false. Returns table metadata including 'tableId' (the 'id' field) which is required for calling get_table(), update_table(), append_table(), or run_project_tests(). Use the 'tableId' field from the response to reference specific tables in other API calls. IMPORTANT: a table id is derived from its location and changes when an edit relocates the table (it had no room to grow in place). After openl_update_table/openl_append_table, use the 'tableId' those tools return (or re-run openl_list_tables); an id from a listing taken before such an edit is stale. |
| openl_get_tableA | Get a table as its authoritative RawSource 2D cell matrix. Typed/parsed table views are intentionally unsupported because they are incomplete and cannot safely round-trip workbook content. startRow/maxRows read a large table in row slices (a windowed response carries totalRows), and styles=true adds each cell's Excel style. A window cannot replace the whole table: openl_update_table rejects totalRows and independently refuses a source with fewer rows than the live table, so removing the marker cannot erase omitted rows. For a large table whose complete response becomes a preview, use the narrow raw table action tools instead. A table id changes when an edit relocates the table; stale ids produced by this server are resolved automatically, otherwise refresh ids with openl_list_tables(). |
| openl_delete_tableA | Delete an ENTIRE table from a project. The whole table area is cleared from the sheet regardless of table type, so the table no longer exists once the project is recompiled. To remove only a row or column WITHIN a table, use openl_delete_table_rows / openl_delete_table_columns instead. If the given id went stale through an edit made via this server, it is resolved to the current id automatically. The studio does not auto-compile after the delete — run openl_project_status afterward to confirm the project still compiles (a dangling reference to the deleted table surfaces there). |
| openl_update_tableA | Replace the ENTIRE table RawSource matrix with a modified version. Typed table DTOs are intentionally unsupported. Use for modifying, reordering, or structural changes that preserve or add rows; row removal is rejected, so use openl_delete_table_rows with an explicit position/count. Prefer the narrow raw action tools for isolated edits and append_table for additions. Required workflow: call get_table() without styles=true, preserve the complete matrix including covered cells/spans, modify it, then pass the full RawSource object here. Before writing, the tool reads one live row to verify the submitted source is not shorter than the table; this prevents a sliced view from deleting unseen rows even if totalRows was removed. Studio table write APIs cannot change formatting, so cell style is read-only and rejected. The response returns the CURRENT tableId after relocation. The tool reads the table back to trigger recompilation, so openl_project_status reflects the change. |
| openl_append_tableA | Append RawSource rows to an existing table. Typed append DTOs are intentionally unsupported. Every row must cover ALL columns of the table; wrong-width rows are rejected before anything is written. Use { value: null } for a blank cell and preserve covered placeholders for merged regions. For modifying or reordering use a narrow raw action tool or update_table; remove rows/columns only with the corresponding delete action. The response returns the CURRENT tableId after relocation, and the read-back triggers recompilation. |
| openl_create_project_tableA | Create a table from its complete RawSource 2D cell matrix. Typed table creation DTOs are intentionally unsupported because they omit workbook features and do not round-trip reliably. Requires moduleName plus table { tableType: "RawSource", name, source }. By default moduleName identifies an existing module; pass modulePath ending in .xlsx to create a new module. Build the exact OpenL grid from the bundled guides or copy an existing raw source, including covered cells/spans where needed. Studio table write APIs cannot set cell formatting, so style is rejected. The response is metadata, not a compilation result; call openl_project_status afterward. |
| openl_append_table_rowsA | Add ONE OR MORE rows to the END of a table's raw source. 'cells' is a 2D array: outer = rows top to bottom, inner = that row's cells left to right (one per column; use { value: null } for blanks). Pass a single row to add one, several for a block. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_append_table_columnsA | Add ONE OR MORE columns to the END of a table's raw source. 'cells' is a 2D array: outer = columns left to right, inner = that column's cells top to bottom (one per row). Pass a single column to add one, several for a block. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_insert_table_rowsA | Insert ONE OR MORE rows at 'position' in a table's raw source, shifting the rows at and below it down. 'position' is 1..height (height appends to the end). 'cells' is a 2D array (rows × that row's cells). Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_insert_table_columnsA | Insert ONE OR MORE columns at 'position' in a table's raw source, shifting the columns at and to the right of it. 'position' is 1..width (width appends to the end). 'cells' is a 2D array (columns × that column's cells). Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_delete_table_rowsA | Delete ONE OR MORE rows starting at 'position' (1..height-1) from a table's raw source, shifting the rows below up. 'count' defaults to 1. The header row (0) cannot be deleted. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_delete_table_columnsA | Delete ONE OR MORE columns starting at 'position' (1..width-1) from a table's raw source, shifting the columns to the right left. 'count' defaults to 1. The leading-label column (0) cannot be deleted. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_update_table_rowA | Overwrite the cells of an existing row at 'position' (0..height-1) in a table's raw source, left to right. The table is not resized. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_update_table_columnA | Overwrite the cells of an existing column at 'position' (0..width-1) in a table's raw source, top to bottom. The table is not resized. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_update_table_cellA | Update the value of a single existing cell at ('row','column') in a table's raw source. 'value' is required: pass a string/number/boolean to set the cell, or null to clear it. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_merge_table_cellsA | Merge a rectangular range of cells into one in a table's raw source, keeping the value of the top-left cell at ('row','column'). The range ('rowspan'×'colspan') must cover more than one cell and stay within the table. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_unmerge_table_cellsA | Unmerge the merged cell that covers ('row','column') in a table's raw source, splitting it back into individual cells. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_update_table_rangeA | Overwrite a rectangular RANGE of cells in place, anchored at the top-left ('row','column'), in a table's raw source. 'cells' is a 2D array (rows × that row's cells); the range must cover more than one cell and fit within the table (not resized). For a single cell use openl_update_table_cell. Operates on the table's RAW source, so it works for any table type. Positions are 0-based (row 0 is the header row, column 0 carries the leading labels). An edit that relocates the table (it had no room to grow in place) CHANGES its location-derived id; the response always returns the table's CURRENT id as 'tableId' (plus previousTableId when it changed) — use it for subsequent calls. Note: the studio does not auto-compile after an edit; this tool reads the table back to trigger the recompile, so a subsequent openl_project_status reflects the change. |
| openl_run_tableA | Execute a regular (non-Test) table with caller-provided JSON and return its result. This is a single high-level operation: it starts Studio's asynchronous run and waits inside the tool call until the result is ready, emitting progress notifications instead of requiring agent-side polling. Pass inputJson as an object keyed by method parameter name or as { params: { parameterName: value }, runtimeContext? }; { params: [...] } is rejected because Studio silently runs it with null arguments. A top-level array is passed as the value of a single array-valued parameter, not as positional arguments. Set withSchema only when the result/parameter JSON Schemas are needed because they can be large. Studio permits one table run per HTTP session, so wait for an active call to finish before starting another. Use openl_start_project_tests and the test-result tools for Test tables. Cancelling the MCP call also cancels and clears the Studio run. |
| openl_get_table_dependenciesA | Get the table dependency graph as an adjacency list. Omit tableId for the whole project graph, optionally restricted by module and layer (executable, datatype, or all); provide tableId for its dependency/dependent neighborhood with optional direction and depth. Executable nodes include signatures, return types, and dimension properties; datatype nodes include inheritance and declared field references; vocabulary nodes include their value type, total value count, and a bounded first/last values preview. Dispatchers represent versioned executable tables, self-loops represent recursion or self-reference, and cycles are derived from dependency edges. JSON preserves the graph nodes directly. Markdown renders executable calls as a Mermaid flowchart and the data model, including declared fields, vocabulary value previews, and reference cardinalities, as a Mermaid ER diagram; vocabulary headers use Name, preview rows leave the redundant type column visually empty, and a + N more marker identifies a truncated middle. Inheritance is shown separately when present. Detailed Markdown adds per-node metadata, while concise Markdown stays textual. |
| openl_list_project_modulesA | List the modules declared by a project, including module names, rules-root paths/patterns, and modules matched by a pattern. Use the returned name when creating/copying a table, selecting a module graph, or listing worksheets. |
| openl_list_module_sheetsA | List worksheet names in a project module. First call openl_list_project_modules to get the exact moduleName. Use a returned sheet name as the destination sheet when creating or copying a table. |
| openl_list_table_property_definitionsA | List the properties Studio allows in the requested table context, including value type, whether multiple values are accepted, and allowed enum values. Omit tableType for entries inside a Properties table; provide a public table kind for properties that may be declared on that kind. |
| openl_copy_tableA | Copy a table inside the same project using Studio's server-side copy operation, preserving formatting, merged cells, comments, and complete table structure. Provide the destination module and new table name; optionally choose a sheet, create a new .xlsx module with modulePath, or replace the source properties. The copy remains in the working copy—use openl_save_project for Git-backed projects. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| append_table | Append complete raw source rows to an existing OpenL table safely |
| create_rule | Comprehensive guide for creating OpenL rules, spreadsheets, and data definitions from raw workbook source |
| create_rule_decision_tables | Create OpenL decision tables through their authoritative raw workbook layout |
| create_rule_spreadsheet | Create OpenL Spreadsheet tables through their authoritative raw workbook layout |
| create_test | Create OpenL test tables from their authoritative raw workbook source |
| datatype_vocabulary | Create and edit Datatype and Vocabulary tables through raw workbook source |
| deploy_project | OpenL deployment workflow with mandatory validation checks, test execution requirements, and environment selection (dev, test, staging, prod) |
| dimension_properties | Explanation of OpenL dimension properties for business versioning (state, country, lob, effectiveDate) vs Git versioning, with runtime selection logic |
| local_projects | Working with projects in repository 'local': no open/save/close, no Git; table/rule/test tools work directly without opening |
| project_agents_md | How to load and correctly apply a project's AGENTS.md guidance with openl_get_project_agent_context: walk up to the repo root, read every applicable file, and apply nearest-file-wins precedence |
| project_history | Guide for viewing a project's committed Git history with openl_repository_project_revisions and its local workspace changes with openl_list_project_local_changes, and when to use each |
| run_test | Test selection logic and workflow for running OpenL tests efficiently based on scope (single table, multiple tables, or all tests) |
| update_test | Update OpenL test cases through the authoritative raw table source |
| validate_after_edit | Workflow for validating OpenL projects after editing tables/rules: call openl_project_status, branch on compileState, surface errors with location, and re-validate after fixes |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/openl-tablets/openl-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server