@norbix.ai/mcp
v0.8.0
Published
Norbix MCP server — manage projects, integrations, databases, membership, notifications and every other Norbix Hub/API endpoint from Claude, Cursor, VS Code, Windsurf or any MCP client.
Readme
Norbix MCP Server (@norbix.ai/mcp)
Work with your Norbix backend from any AI tool that speaks MCP — Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, and others. Create projects, manage integrations, query databases, manage users, read logs — everything your API key is allowed to do.
Built on the official @norbix.ai/ts SDK. Covers every
Norbix Hub and API endpoint (640+) through a small tool set.
What you need
- A Norbix API key (service user). In the Norbix dashboard, open your project → Membership → Service users. Create a service user, give it a role (for example Project Administrator for full project access), and issue an API key. The key's permissions decide what the MCP server can do.
- Your Norbix Hub endpoint (for example
https://hub.norbix.ai, or your own host on a self-hosted install). The server calls/echoon startup to discover the rest (API URL, versions, regions).
Configuration (environment variables)
| Variable | Required | Meaning |
| --- | --- | --- |
| NORBIX_API_KEY | yes | Service-user API key (sent as Authorization: Bearer). |
| NORBIX_HUB_URL | yes | Norbix Hub endpoint. |
| NORBIX_PROJECT_ID | no | Default project to work in. You can also switch at any time with the norbix_set_project tool. |
| NORBIX_API_URL | no | API endpoint. Discovered from /echo when not set. |
| NORBIX_ENV | no | Project environment (e.g. DEV). Default is PROD. |
| NORBIX_REGION | no | Region code (e.g. nb-eu-germany). |
These are the same variables the @norbix.ai/ts SDK uses.
Install
The server is published on npm as
@norbix.ai/mcp. Nothing to
install by hand — MCP clients start it with npx (Node.js 18 or newer):
npx -y @norbix.ai/mcp --help # usage and env variables
npx -y @norbix.ai/mcp --versionOr install it globally and use the norbix-mcp command:
npm install -g @norbix.ai/mcp
norbix-mcp --helpBuild from source
git clone [email protected]:norbix-code/mcp.git && cd mcp
npm ci
npm run build
node dist/index.js --helpIDE / client setup
Claude Desktop
claude_desktop_config.json → mcpServers:
{
"mcpServers": {
"norbix": {
"command": "npx",
"args": ["-y", "@norbix.ai/mcp"],
"env": {
"NORBIX_API_KEY": "your-api-key",
"NORBIX_HUB_URL": "https://hub.norbix.ai",
"NORBIX_PROJECT_ID": "your-project-id"
}
}
}
}Claude Code
claude mcp add norbix \
-e NORBIX_API_KEY=your-api-key \
-e NORBIX_HUB_URL=https://hub.norbix.ai \
-e NORBIX_PROJECT_ID=your-project-id \
-- npx -y @norbix.ai/mcpCursor
.cursor/mcp.json (project) or ~/.cursor/mcp.json (global):
{
"mcpServers": {
"norbix": {
"command": "npx",
"args": ["-y", "@norbix.ai/mcp"],
"env": {
"NORBIX_API_KEY": "your-api-key",
"NORBIX_HUB_URL": "https://hub.norbix.ai",
"NORBIX_PROJECT_ID": "your-project-id"
}
}
}
}VS Code (GitHub Copilot agent mode)
.vscode/mcp.json:
{
"servers": {
"norbix": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@norbix.ai/mcp"],
"env": {
"NORBIX_API_KEY": "your-api-key",
"NORBIX_HUB_URL": "https://hub.norbix.ai"
}
}
}
}Windsurf
~/.codeium/windsurf/mcp_config.json — same JSON shape as Cursor.
Until the package is published, replace
"command": "npx", "args": [...]with"command": "node", "args": ["/path/to/sdks/norbix-mcp/dist/index.js"].
Remote mode (Streamable HTTP)
For a hosted, shared MCP endpoint:
NORBIX_HUB_URL=https://hub.norbix.ai norbix-mcp --http --port 3010- Endpoint:
POST http://host:3010/mcp(stateless Streamable HTTP). - Each request may carry its own key:
Authorization: Bearer <norbix-api-key>. This overridesNORBIX_API_KEY, so one instance can serve many users. - Health check:
GET /healthz.
Tools
Discovery + generic call — reaches every endpoint:
norbix_search_endpoints— find endpoints by keyword ("push template","invite user", …)norbix_describe_endpoint— full request/response field shapes, nested types, enums, and the known subtypes of a polymorphic fieldnorbix_call_endpoint— execute any endpoint by name with a JSON bodynorbix_set_project— set/switch the active project
Curated shortcuts: norbix_echo, norbix_get_projects, norbix_get_project,
norbix_create_project, norbix_get_project_environments,
norbix_get_integrations, norbix_get_integration, norbix_save_integration,
norbix_test_integration, norbix_get_code_functions, norbix_get_code_function_qualifiers,
norbix_invoke_code_function, norbix_get_code_function_event_sample,
norbix_get_code_function_runs, norbix_get_marketplace_integrations,
norbix_save_marketplace_integration, norbix_test_marketplace_integration,
norbix_invoke_marketplace_function, norbix_get_marketplace_function_runs,
norbix_get_database_schemas,
norbix_find_documents, norbix_find_one_document, norbix_insert_document,
norbix_update_document, norbix_get_taxonomy_terms, norbix_get_roles, norbix_get_policies,
norbix_get_logs, norbix_list_service_api_keys.
Typical flow the model follows for anything not curated:
norbix_search_endpoints("archive email template") →
norbix_describe_endpoint("archiveEmailTemplate") →
norbix_call_endpoint({ name: "archiveEmailTemplate", body: { id: "…" } }).
A polymorphic body lists its subtypes. Example — a scheduled task (only
EmailCampaign runs today; cron is 5 fields in UTC; initiatorUserId is
you or a project service user): norbix_describe_endpoint("saveSchedulerTask")
shows types.SchedulerTaskRequest.subtypes.EmailCampaignSchedulerTaskRequest
(type, campaign?, databaseIntegrationId?), then
{ "name": "saveSchedulerTask", "body": {
"name": "Weekly digest", "cron": "0 9 * * 1", "initiatorUserId": "usr_…",
"isEnabled": true, "stopOnError": false,
"task": { "type": "EmailCampaign",
"campaign": { "source": "AllUsers", "templateId": "tmpl_…" } } } }The scheduler module switch (enableScheduler / disableScheduler) is PUT.
Cloud functions (@norbix.ai/ts 4.19.0): norbix_get_code_functions
lists the functions a code integration may call, norbix_get_code_function_qualifiers
their aliases and versions, norbix_invoke_code_function calls one by hand
(functionRef, payload, invocationType: "Sync" | "Async", runAsUserId),
norbix_get_code_function_event_sample returns the envelope a function receives
with sample data (source, event, schemaId) — the fixture for a local run —
and norbix_get_code_function_runs the last runs of a trigger or task. The
envelope itself (CodeFunctionEventDto: specVersion, event, source,
context.runAs.accessToken, data.{database,user,file,payment,ai,task,payload},
config) is in norbix_describe_endpoint("getCodeFunctionEventSample").
Marketplace (@norbix.ai/ts 4.21.0): norbix_save_marketplace_integration
enables a listing as a connection (empty integration.viewId → the answer's id
is the minted int_…), norbix_test_marketplace_integration runs its validation
steps (steps[]; functions can be added once every requiredForFunctions step
succeeded), norbix_invoke_marketplace_function calls a function by hand
(functionViewId, payload), and norbix_get_marketplace_function_runs lists
the last runs of a trigger or task. Listings, functions (saveMarketplaceFunction
with arguments and inputs) and the rest of the 23 routes are reached with
norbix_search_endpoints("marketplace").
Database tools
Six shortcuts cover the everyday database work. Everything else in the Database module (95 endpoints: schemas and drafts, records, taxonomies and terms, triggers, aggregates, database integrations) is reached with the generic trio.
| Tool | SDK method | Route | Input |
| --- | --- | --- | --- |
| norbix_get_database_schemas | hub.database.getDatabaseSchemas | GET /{version}/database/schemas | body (paging) |
| norbix_find_documents | api.database.find | GET /{version}/database/collections/{collectionName} | collectionName, filter?, sortBy?, sortOrder?, pageSize?, startingAfter?, endingBefore?, expandReferences?, databaseIntegrationId?, body? (any other FindRequest field) |
| norbix_find_one_document | api.database.findOne | GET /{version}/database/collections/{collectionName}/{id} | collectionName, id, expandReferences?, databaseIntegrationId? |
| norbix_insert_document | api.database.insertOne | POST /{version}/database/collections/{collectionName} | collectionName, document, databaseIntegrationId? |
| norbix_update_document | api.database.updateOne | PUT /{version}/database/collections/{collectionName}/{id} | collectionName, id, update, arrayFilters?, databaseIntegrationId? |
| norbix_get_taxonomy_terms | api.database.findTerms | GET /{version}/database/taxonomies/{taxonomyName}/terms | taxonomyName, filter?, pageSize?, sortDescending?, databaseIntegrationId? |
The Api record endpoints expect the document, the update and the filter as a JSON string. The typed shortcuts accept an object or a string and send the string, so this works in one call:
{ "name": "norbix_insert_document", "arguments": {
"collectionName": "products", "document": { "title": "Lamp", "price": 12 } } }{ "name": "norbix_update_document", "arguments": {
"collectionName": "products", "id": "…", "update": { "price": 10 } } }update is the plain field document — the gateway applies it with $set.
A $ operator in it ($set, $inc, …) is refused with
CM-ERRORS-DATABASE-035. An update-many or delete-many call with an empty
filter {} is refused (CM-ERRORS-DATABASE-037) unless the body also has
allRecords: true.
References. A user, role, taxonomy (term), collection or file
field stores ids. Pass expandReferences: true to norbix_find_documents or
norbix_find_one_document and each such field comes back as
{ "id": "…", "display": … } (an array of them when the field is multiple):
{ "name": "norbix_find_one_document", "arguments": {
"collectionName": "posts", "id": "…", "expandReferences": true } }{ "author": { "id": "usr_…", "display": "Jane Doe" },
"tags": [ { "id": "6650…", "display": { "title": { "en": "News" }, "slug": "news" } },
{ "id": "6651…", "display": null } ] }display is the target's displayField (a user property, a role name, a
term's title and slug, a record's chosen field). It is null when the target
is gone or when your API key may not read the target — the two cases look
the same on purpose. Default is off: the stored ids only.
Arrays inside a document. norbix_update_document takes arrayFilters
for positional paths: update: { "items.$[i].qty": 2 } with
arrayFilters: [ { "i.sku": "A1" } ].
For anything else, search the database group:
norbix_search_endpoints({ query: "taxonomy term", group: "database" })norbix_describe_endpoint({ name: "saveSchemaTrigger" })norbix_call_endpoint({ name: "getDatabaseSchemas", surface: "api" })— a few names exist on both the Hub (admin plane) and the Api (data plane); passsurfacefor those.
Which tools work depends on the API key's role: the Hub tools need a
project role with database permissions, the Api tools need permissions on the
collection. An error answer carries status, code, errors (per field)
and payload (the gateway's body).
Keeping the endpoint manifest in sync
The tool catalog is generated from the norbix-js SDK source and committed
under src/manifest/. After endpoints change (backend regenerates DTOs →
norbix-js runs npm run generate-endpoints):
npm run generate-manifest && npm run build && npm testgenerate-manifest reads ../norbix-js; from a worktree, point it at a
checkout of the released SDK: NORBIX_JS_DIR=/path/to/norbix-js npm run generate-manifest.
Keep @norbix.ai/ts in package.json at the version the manifest was made
from (a test checks every curated tool is in the manifest).
Tests
npm testVitest, no network: the server runs over the MCP SDK's in-memory transport
with a fake Norbix client (or the real @norbix.ai/ts client with a fake
fetch).
Versioning and releases
Every merge to main is released to npm by
semantic-release from the
conventional-commit messages: feat: → minor, fix: / perf: /
refactor: → patch; ci:, build:, test:, chore: do not release.
The major version is frozen until the public launch: a breaking change
is written as feat(...) with a Breaking: <what> line in the body (a
!: title or a BREAKING CHANGE: footer fails the PR check). The git tag
is the source of truth for the version; release notes are on the GitHub
Releases page.
The commit analyzer reads only the start of each subject, so a step
number goes at the end (feat(database): expand references — step 2),
never in front of the type: [2] feat(database): … is read as "no
release". Pull request 10 (the schema-content contract) shipped that way
and needed this follow-up commit to publish 0.3.0.
Security notes
- The server can do exactly what the API key can do — nothing more. Scope the service user's role to what you need (e.g. read-only roles for analysis).
- Never commit API keys. Use env vars in the MCP client config.
- In
--httpmode, put the server behind TLS and network controls; theAuthorizationheader carries the Norbix API key.
