servers / openislands

openislands MCP server

communitystdiolocalwrite capablehealthy

Local-first dashboards your AI agent builds and keeps maintaining, over data that never leaves your machine.


01Tools · 1

How to read this: tool names here are observed from a live tools/list handshake. The Risk label is a heuristic inferred from the tool name (write/destructive verbs), not from executing the tool — a conservative guess, not a verified capability. We never escalate risk from a description. Found one that's wrong? Tell us — we fix on report.

ToolRiskSide effectsApproval
execute
Run the OpenIslands API by writing a small async JavaScript program (Code Mode). One tool replaces the per-operation tools: write JS that calls the `oi` API, compose many steps in a single call (loops, conditionals, chaining), and `return` a value and/or `console.log` what you want back. It runs in a sandbox — no require / process / network, only `oi`. The result is { ok, result, logs, checkpoints_created? }; on a thrown error it's { ok:false, error, logs }. Read-many / write-one: read freely; every manifest change goes stage → apply (oi.app().patchManifest/replaceManifest returns a proposal_id, then oi.app().applyEdit(proposal_id) writes it and snapshots the prior state for rollback). If a stage returns ok:false, each error names the page/island/field — fix it and retry. type Verbosity = "concise" | "detailed"; declare const oi: { // workspace listApps(): Promise<{ ok: boolean; apps: { id: string; title: string; dir: string }[] }>; createApp(input: { id: string; title?: string }): Promise<{ ok: boolean; id?: string; dir?: string; error?: string }>; deleteApp(input: { id: string }): Promise<{ ok: boolean; archivedTo?: string; error?: string }>; // app-scoped API; omit `id` when the workspace has exactly one app, else pass it (see oi.listApps()). app(id?: string): AppApi; }; interface AppApi { // orient getOverview(opts?: { verbosity?: Verbosity }): Promise<Overview>; // START HERE: manifest + every dataset's live columns + actions/queries/connectors + checkpoint count getManifest(): Promise<Manifest>; // the raw manifest object listIslands(): Promise<{ ok; islands }>; // built-in island types + required fields + span range getIslandSchema(type: string): Promise<{ ok; schema; layout; notes }>; // JSON Schema + layout guidance for one island type (e.g. "metric.kpi", or "layout.row") getDataSchema(dataset: string): Promise<{ ok; dataset; columns }>; // columns + inferred types from the live data // read data (read-only, row-capped; pass verbosity:"detailed" for a bigger pull) runSql(input: { sql?: string; dataset?: string; limit?: number; verbosity?: Verbosity }): Promise<{ ok; rows; rowCount; truncated? }>; // one read-only SELECT over the dataset views, or a whole dataset previewDataset(dataset: string, opts?: { limit?: number; verbosity?: Verbosity }): Promise<{ ok; rows; rowCount; truncated? }>; // read a dataset/transform's rows back — alias for runSql({ dataset }); the findable way to verify computed values validateSql(sql: string): Promise<{ ok; columns?; error? }>; // dry-run a SELECT (catalog/parse/type errors) without running it validateManifest(manifest?: Manifest): Promise<{ ok; errors; warnings }>; // validate + check bindings vs data (current manifest if omitted) // edit the manifest — read-many / write-one. Nothing is written until applyEdit. patchManifest(patch: ManifestPatch): Promise<Proposal>; // PREFERRED: send only the sections that change replaceManifest(manifest: Manifest): Promise<Proposal>; // full rewrite applyEdit(proposalId: string): Promise<{ ok; checkpoint_id? }>; // write a staged proposal; snapshots prior state for rollback rollback(checkpointId?: string): Promise<{ ok; restored? }>; // restore a checkpoint byte-for-byte (latest if omitted) listCheckpoints(): Promise<{ ok; checkpoints: string[] }>; pruneCheckpoints(keep?: number): Promise<{ ok; kept; removed }>; // data actions (typed appends) + queries (typed reads) listActions(): Promise<{ ok; actions }>; // typed writes, dispatched by each action's declared mode (listActions/getOverview show it): insert/replace take rows, delete takes match, update takes match+set. Atomic by default: validates all calls first, rolls back every write if any fails. runActions(calls: { action: string; rows?: object[]; match?: object; set?: object }[], opts?: { atomic?: boolean }): Promise<{ ok; results?; checkpoint_ids?; failures? }>; listQueries(): Promise<{ ok; queries }>; runQuery(name: string, params?: object, opts?: { limit?: number; verbosity?: Verbosity }): Promise<{ ok; rows; columns }>; // connectors — provider sync. Keyless connectors (auth:"none", canSyncDirectly:true) need NO authorization: sync them directly with runSync. oauth2/bearer connectors need a human to connect via the dashboard Connect button first. listConnectors(): Promise<{ ok; connectors }>; runSync(name: string): Promise<{ ok; error? }>; } // Proposal: { ok; proposal_id?; diff; warnings?; errors? } — errors name the page/island/field on ok:false // ManifestPatch: { title?; icon?; datasets?: Record<name, spec|null>; actions?; queries?; connectors?; pages?: Page[]; remove_pages?: string[] } // null deletes a key; pages upsert by id Example — orient, add a KPI, apply: const app = oi.app(); const ov = await app.getOverview(); const page = ov.pages[0]; page.islands.push({ type: "metric.kpi", title: "Net worth", dataset: "net_worth_monthly", value: "net_worth_eur", format: "eur", span: 4 }); const staged = await app.patchManifest({ pages: [page] }); if (!staged.ok) return staged.errors; // each error names the page/island/field return await app.applyEdit(staged.proposal_id); Example — sanity-check every dataset in one call: const app = oi.app(); const ov = await app.getOverview(); const counts = {}; for (const name of Object.keys(ov.datasets)) counts[name] = (await app.runSql({ dataset: name, limit: 1 })).rowCount; return counts;
writetrueunknown

02Install & source
npx -y @openislands/mcp
npx

03Access granted
Query a database · destructive

The access this server can exercise, inferred from its verified tools — not a declared OAuth scope.


05Provenance & freshness
sourcesGitHub repo search [p4]
last_checked2026-08-16 20:13Z
next_check2026-08-16 23:10Z
cadenceevery 3h
verifiedtools_list:passed handshake:passed metadata:passed tools_list:passed handshake:passed metadata:passed tools_list:passed handshake:passed metadata:passed tools_list:passed
index_statusindex9 unique facts >= 5

06Badge

Add the “as seen on MCPExplorer” badge to your README. openislands MCP — as seen on mcpexplorer.com

[![openislands MCP — as seen on mcpexplorer.com](https://mcpexplorer.com/badge/openislands.svg)](https://mcpexplorer.com/servers/openislands)

Next step

This is one server. A loadout combines the right servers, governance, and proven plays for a whole job — assembled deliberately, not tool-dumped.

Explore loadouts →