
Company News
AWS Security Hub Adds Socket for Supply Chain Security
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.
MCP server for Sqemo - query and edit ERDs with your team's naming standards
A local stdio MCP server that lets AI agents read and edit Sqemo ERDs.
It works with both local .erd.json files and ERDs saved on the Sqemo server, and it can
generate and check physical names against your team's word list and naming rules.
.mcp.json){
"mcpServers": {
"sqemo": { "command": "npx", "args": ["-y", "sqemo-mcp"] }
}
}
For local development (working from a checkout of this repository):
{
"mcpServers": {
"sqemo": { "command": "node", "args": ["./mcp/dist/index.js"] }
}
}
Server tools (
list_erds, etc.) need either a populatedDEFAULT_SUPABASE_ANON_KEYinsrc/auth/defaults.tsor theERDMAKER_SUPABASE_ANON_KEYenvironment variable (otherwise they returnnot_configured). Local-file tools work without any of this.
Add the same mcpServers entry to the config file. Claude Desktop has no project working
directory, so use an absolute path instead of ./mcp/... when registering a local build.
%APPDATA%\Claude\claude_desktop_config.json~/Library/Application Support/Claude/claude_desktop_config.jsoncodex mcp add sqemo -- npx -y sqemo-mcp
Or add the equivalent TOML to ~/.codex/config.toml:
[mcp_servers.sqemo]
command = "npx"
args = ["-y", "sqemo-mcp"]
Most other MCP clients (Cursor, etc.) use the same mcpServers JSON as Claude Code.
npx sqemo-mcp login # pick Google, GitHub, or email + password
npx sqemo-mcp logout # remove stored credentials
login asks how you want to sign in. Options 1 and 2 (Google / GitHub) open a
browser tab, complete a PKCE OAuth flow, and hand the session back through a
one-shot loopback server on 127.0.0.1; option 3 takes an email and password in
the terminal. Only a refresh token is ever stored.
Before the npm package is available (local development), use
node mcp/dist/index.js login / logout.
~/.erdmaker/credentials.json (mode 0600 on POSIX);
your password itself is never stored.--password forces the email +
password path, --provider google|github forces a browser path.printf 'email\npassword\n' | npx sqemo-mcp login127.0.0.1). Over SSH, use --password or the SQEMO_EMAIL /
SQEMO_PASSWORD environment variables.| Variable | Purpose |
|---|---|
ERDMAKER_HOME | Override the credentials directory (default ~/.erdmaker) |
ERDMAKER_SUPABASE_URL | Override the Supabase URL (default: the Sqemo production server) |
ERDMAKER_SUPABASE_ANON_KEY | Override the Supabase anon (publishable) key |
ERDMAKER_MAX_REQUESTS_PER_MINUTE | Per-minute cap on Supabase requests (default 120, 0 disables) |
ERDMAKER_MAX_REQUESTS_PER_DAY | Daily cap on Supabase requests (default 10000, 0 disables). Tracked in ERDMAKER_HOME/usage.json |
If the connection settings are empty, server tools return a not_configured error.
The two caps are a safety net against an agent stuck in a loop flooding requests. When exceeded, tools fail with a
rate_limitederror that instructs the agent to stop and notify the user. For intentional bulk work, raise the caps via the environment variables above or set them to0.
Independent of the MCP server, two offline, file-based subcommands are available (no login required).
# Check naming standards — exits with code 1 on violations, failing CI
npx sqemo-mcp lint schema.erd.json
# Export the schema — result goes to stdout
npx sqemo-mcp export schema.erd.json --format sql --dialect postgres > schema.sql
npx sqemo-mcp export schema.erd.json --format dbml > schema.dbml
lint: checks logical names for unregistered words (missing from the word list) and
physical-name drift (mismatch with the standard-generated name; manualOverride and FK
columns excluded). Exit codes: 0 = clean, 1 = violations, 2 = argument/file error.
Violations and the summary go to stderr. The unregistered-word check only runs when
namingRules.unknownWordMode === "warn"; projects set to keep/romanize do not
flag unregistered words.export: --format sql|dbml (default sql); for sql, pick a dialect with --dialect
(defaults to the project dialect). Output on stdout, errors on stderr (exit code 2).GitHub Actions example:
- run: npx sqemo-mcp lint schema.erd.json
# .github/workflows/schema-drift.yml
- run: npx sqemo-mcp lint erd/app.erd.json --db "$DATABASE_URL" --ignore "flyway_*"
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} # read-only account recommended
SQEMO_EMAIL: ${{ secrets.SQEMO_EMAIL }} # Sqemo Pro account (password sign-in;
SQEMO_PASSWORD: ${{ secrets.SQEMO_PASSWORD }} # OAuth-only accounts: set a password first)
No database credentials ever reach Sqemo servers — introspection runs inside your CI job
and queries only information_schema. Prefer zero credentials in CI? Compare against a
dump instead: npx sqemo-mcp lint erd/app.erd.json --schema schema.sql --dialect postgres.
source parameterMost read/write tools take the target ERD as source — specify exactly one of the two
(passing both is rejected at the schema level).
{ "file": "C:/path/to/model.erd.json" } — a local file{ "erdId": "<uuid>" } — a server ERD (get ids from list_erds)Exception: the three dictionary lookup tools (
search_dictionary·check_naming·generate_physical_name) also accept{ "workspaceId": "<uuid>" }— they check against the latest workspace-standard master (word list + naming rules), not a project's cached copy. Get ids fromlist_workspaces. Write tools do not accept theworkspaceIdsource (lookup only).
diff_erdsadditionally accepts{sql, dialect?}and{dbml}text sources for before/after — useful as a dry run before a full-replaceimport_sql/import_dbml.
You can query and check your team's naming standard directly, without a project:
list_workspaces
→ [{ "workspaceId": "…", "name": "Our Team", "role": "owner",
"glossary": { "version": 7, "updatedAt": "…" } }]
check_naming { source: { workspaceId: "…" }, logicalName: "member number" }
→ checked against the latest workspace-standard master (not a project cache)
glossary: null means the workspace has no standard yet (create one by linking a standard
in the web app). Editing the standard master directly is not supported, but you can request
new words through the proposal queue: submit with propose_dictionary_word → the owner
approves/rejects in the web app → check status with list_proposals, withdraw with
withdraw_proposal. Proposal sources accept {workspaceId} or a standard-linked ERD
({file}/{erdId}). Submitting and listing proposals is workspace-member only — a shared
editor of a standard-linked ERD who is not a member gets no_permission.
| Tool | Description |
|---|---|
list_erds | List server ERDs (role: owner/editor, shared). Owner and shared editors can both write. Requires login |
list_workspaces | List my workspaces (owner first) + whether a standard (word list + naming rules) exists. Requires login |
get_erd_overview | Name, dialect, entity/relationship/domain/word-list stats, subject areas, standard link status |
list_entities | List entities (logical name, physical name, attribute count) |
get_entity | Entity detail (attributes, keys, domains, logical/physical mapping). Prefers entityId; falls back to exact logicalName match |
list_relationships | List relationships (endpoint entity names, cardinality, identifying flag) |
list_domains | List domain definitions (name, data type). Accepts the {workspaceId} source (standard domain dictionary) |
search_dictionary | Partial-match word-list search (logical/physical/abbreviation/English/synonyms, max 50). Accepts {workspaceId} |
check_naming | Check a logical name against the naming standard (+ optional physicalName comparison). Accepts {workspaceId} |
generate_physical_name | Logical name → physical name (unregistered words reported in warnings). Accepts {workspaceId} |
export_sql | Generate CREATE TABLE SQL — 7 dialects (mysql/postgres/cubrid/oracle/sqlserver/sqlite/h2) |
export_dbml | Generate DBML text |
validate_erd | Validate the project ({ valid, errors }) |
lint_erd | Full project lint — structure (PK, attributes, descriptions, domains), referential integrity, duplicate physical names, naming standard (unregistered words, drift) |
diff_erds | Compare two sources (unchanged omitted) — before/after each accept {file}, {erdId}, {sql, dialect?}, {dbml}. Dry run before imports. Summary is entity-based |
check_db_drift | Check drift between the ERD and a live database or schema dump (Pro) |
list_proposals | List the workspace-standard proposal queue (word/domain, mine flag, status filter). Requires login |
| Tool | Description |
|---|---|
create_erd | Create a new ERD, empty or from SQL/DBML text — target: {file} or {server:true}; a given dialect becomes the project dialect |
upsert_entity / delete_entity | Create/update/delete entities (physical table and name derived automatically) |
upsert_attribute / delete_attribute | Edit attributes — setting PK forces nullable=false and propagates to child FKs; with a domain, the domain decides the data type |
upsert_relationship / delete_relationship | Edit relationships (FKs derived automatically; specify cardinality or ends; onDelete/onUpdate referential actions and constraintName supported — noAction/empty string revert to defaults) |
upsert_domain / delete_domain | Edit domain definitions (existing description preserved when omitted) |
upsert_dictionary_word / delete_dictionary_word | Edit the word list — rejected for standard-linked (glossaryLink) dictionaries |
update_naming_rules | Partially edit naming rules (delimiter, case, unknown-word handling). Existing physical names are not regenerated retroactively (noted in warnings). Rejected for standard-linked ERDs |
import_sql / import_dbml | Fully replace an existing ERD with the parse result (ids preserved). Rejected when zero tables |
introspect_db | Import a live PostgreSQL/MySQL schema into an ERD (read-only, Pro) |
auto_layout | Auto-arrange entities/tables (dagre) — view: logical/physical/both (default). Reference copies, notes, and waypoints preserved |
propose_dictionary_word | Propose a word for the standard's word list (owner approves in the web app). Duplicates: already_exists / already_proposed |
withdraw_proposal | Withdraw your own pending proposal (others' or processed ones: not_found) |
Writing to a server ERD is allowed for the owner or a shared editor.
Concurrent saves on shared ERDs go through CAS 3-way auto-merge; merge conflicts return
save_conflict. Saves are protected by a version CAS — if another session saved first,
save_conflict is returned. Standard-linked dictionaries stay locked to the standard
master (dictionary_is_linked). When an auto-merge pulls in another session's word list
changes, write-tool results include a note in warnings (e.g. existing physical names are
not regenerated automatically). Every write-tool result always includes warnings: string[].
Every tool error is returned as { code, message } — handle errors by code.
| code | Meaning |
|---|---|
not_configured | Supabase connection settings missing |
not_authenticated | Login required (npx sqemo-mcp login) |
no_permission | Write attempted on a server ERD where you are neither owner nor shared editor |
save_conflict | Version CAS conflict — re-fetch and retry |
not_found | Target (file/ERD/entity/attribute/…) not found |
dictionary_is_linked | Attempted to edit a standard-linked dictionary |
invalid_project_file | Not a valid .erd.json |
validation_failed | Project/input validation failed |
unsupported_dialect | Unsupported SQL dialect |
invalid_source | Invalid source/input combination (empty SQL, zero-table import, …) |
already_exists | The proposed word is already in the standard word list |
already_proposed | A pending proposal for the same word already exists |
plan_limit_exceeded | Plan quantity limit reached (cloud projects, snapshots, members, …) or a Team-only feature |
rate_limited | Requests exceeded the per-minute/daily cap — the agent may be stuck in a loop; stop and notify the user. For intentional bulk work, adjust the caps via environment variables |
internal_error | Unexpected internal failure (anything not covered above) |
cd mcp
npm install
npm test # vitest
npm run lint # tsc --noEmit
npm run build # tsup → dist/index.js
FAQs
MCP server for Sqemo - query and edit ERDs with your team's naming standards
We found that sqemo-mcp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.

Research
/Security News
Popular npm packages keyv and cacheable compromised.

Security News
A misconfiguration gave three Anthropic models internet access, and one, believing it was in a simulation, shipped a credential-stealing package to PyPI.