1. guides
prorm
  • prorm documentation
  • Known test gaps
  • Architecture
  • Core concepts
  • Database types & coverage
  • Getting started
  • Going further
  • compliance
    • Compliance
    • The security toolkit: `prorm audit`
    • Checklists by regulation
    • Declaring personal data
    • Evidence bundles
    • Evidence
    • Frameworks: `@Security`
    • Jurisdictions
    • Platform policies
    • Protecting data
    • The regulation dataset
    • Residency and cross-border transfers
    • Retention & integrity
    • Status
    • Subject rights
  • decorators
    • prorm with decorators
    • Models with decorators
    • Querying a decorated model
    • Relations with decorators
  • diagrams
    • Diagram generators
    • Chen diagram
    • Class diagram
    • Dependency diagram
    • ER diagram
    • Flow diagram
    • From your models to a diagram
    • Gantt diagram
    • Index diagram
    • Migration diagram
    • Model diagram
    • Package diagram
    • Crow’s-foot diagram
    • Schema documentation
    • Sequence diagram
    • State diagram
    • Tree diagram
  • dialects
    • SQL dialects
    • AlloyDB Dialect
    • AlloyDB Omni Dialect
    • Amazon Athena Dialect
    • Aurora DSQL Dialect
    • Amazon Aurora MySQL Dialect
    • Amazon Aurora PostgreSQL Dialect
    • Azure Database for MySQL Dialect
    • Azure Database for PostgreSQL Dialect
    • Azure SQL Database Dialect
    • Azure SQL Managed Instance Dialect
    • Google BigQuery Dialect
    • Citus Dialect
    • ClickHouse dialect
    • Cloud Authentication (`cloud-auth`)
    • Cloud SQL for SQL Server Dialect
    • Cloud SQL for MySQL Dialect
    • Cloud SQL for PostgreSQL Dialect
    • CockroachDB Dialect
    • Azure Cosmos DB for PostgreSQL Dialect
    • CrateDB Dialect
    • Cloudflare D1 Dialect
    • Databricks dialect
    • IBM Db2 Dialect
    • Dolt Dialect
    • Apache Doris Dialect
    • Druid Dialect
    • DuckDB Dialect
    • Exasol dialect
    • Microsoft Fabric Data Warehouse Dialect
    • Firebird Dialect
    • Greenplum Dialect
    • SAP HANA Dialect
    • MySQL HeatWave Dialect
    • Azure Data Explorer (Kusto) Dialect — T-SQL
    • MariaDB Dialect
    • Materialize Dialect
    • MonetDB Dialect
    • MotherDuck Dialect
    • Microsoft SQL Server Dialect
    • MySQL Dialect
    • Neon Dialect
    • OceanBase Dialect
    • openGauss Dialect
    • Oracle Dialect
    • Oracle Autonomous Database Dialect
    • ParadeDB Dialect
    • PolarDB Dialect
    • PostgreSQL Dialect
    • Presto Dialect
    • QuestDB Dialect
    • Aurora RDS Data API Dialect (`rdsdata`)
    • Amazon RDS for Db2 Dialect
    • Amazon RDS for MariaDB Dialect
    • Amazon RDS for SQL Server Dialect
    • Amazon RDS for MySQL Dialect
    • Amazon RDS for Oracle Dialect
    • Amazon RDS for PostgreSQL Dialect
    • Amazon Redshift
    • Amazon Redshift Data API Dialect
    • RisingWave Dialect
    • rqlite Dialect
    • SingleStore Dialect
    • Snowflake Dialect
    • Google Cloud Spanner Dialect
    • Spanner (PostgreSQL interface) Dialect
    • SQLite Dialect
    • StarRocks Dialect
    • Supabase Dialect
    • Azure Synapse Analytics (dedicated SQL pool)
    • Teradata Dialect
    • TiDB Dialect
    • TimescaleDB Dialect
    • Trino Dialect
    • Turso / libSQL Dialect
    • Vertica dialect
    • Vitess Dialect
    • Yellowbrick Dialect
    • YugabyteDB Dialect
  • guides
    • Access rules and behaviour profiles
    • ArangoDB (AQL)
    • Associations
    • Audit levels and escalation
    • Audit logging
    • In the browser
    • Bulk operations
    • Caching
    • Capabilities, tiers and team roles
    • CLI
    • Cloudflare
    • Compliance & data protection
    • Connection Pooling & Performance
    • Security in the console
    • Couchbase: structured N1QL queries
    • Data types
    • Decorators
    • Eager loading
    • Enums and constants
    • Error handling & error types
    • Extensions
    • External fields
    • Foreign data wrappers
    • Graph databases
    • Hooks & lifecycle events
    • Indexes & constraints
    • InfluxDB: structured Flux pipelines
    • klock-errors
    • klock — the `.klock` file
    • Local databases (`prorm db up`)
    • Structured log search — Splunk, Graylog, Papertrail, Sumo Logic
    • Logging
    • Grafana Loki: structured LogQL queries
    • MCP server
    • Migrate — the data transfer subsystem
    • Migrations & Schema Sync
    • Models from an existing database
    • Defining models
    • Multiple databases
    • OrientDB, Neptune and TigerGraph
    • Passwords
    • Importing a Prisma schema
    • Structured PromQL and MetricsQL
    • Query firewall
    • QueryInterface
    • Query operators reference
    • Query optimization
    • Composing find options with `pipe()` and `Q`
    • Query safety: the fail-closed WHERE guard
    • Querying
    • Raw Queries & Query Building
    • Read replicas
    • Schema diffing & migration generation
    • Views, triggers & other schema objects
    • Scopes & default scopes
    • Seeders
    • SPARQL / RDF triplestores
    • SQL constants
    • SQL features
    • SQL function builders
    • SQLite advanced features
    • StoreKey — a prod-orm database as the storage
    • Streaming results
    • Terraform
    • Transactions & Isolation Levels
    • Type mapping: legacy and modern
    • TypeScript types
    • Database users, roles & privileges
    • Validation & constraints
    • Virtual & Computed Fields
    • Writing docs
  • javascript
    • prorm in JavaScript
    • Models in JavaScript
    • Querying in JavaScript
    • Relations in JavaScript
  • runbooks
    • Operational runbooks
    • Connection failures
    • Credential rotation
    • Failover
    • Incident checklist
    • Deploying klock v2
    • Migration rollback
  • running-databases
    • Running databases in Docker
    • Running prorm under Bun in Docker
    • Running Cassandra in Docker with prorm
    • Running ClickHouse in Docker with prorm
    • Running CockroachDB in Docker with prorm
    • Running prorm under Deno in Docker
    • Running Elasticsearch in Docker with prorm
    • Running MariaDB in Docker with prorm
    • Running MongoDB in Docker with prorm
  • prorm control plane
    • Introduction
    • Authentication
    • Errors
    • Getting started
      • Service
        • Is it up
        • This description
    • Account
      • Sign-up and verification
        • Create an account
        • Exchange credentials for a token
        • Verify with the emailed code
        • Verify by clicking the emailed link
        • Name the parent or guardian
        • What a consent link is about
        • Give consent for a child's account
        • Ask the parent or guardian again
        • Send a new code and link
      • Family
        • Everyone this account is responsible for
        • One child, in detail
        • Turn a limit on or off
      • Profile
        • Who am I
        • Change the account
        • Every address on the account
        • Add an address
        • Confirm an address with the code mailed to it
        • Mail a fresh code to an unconfirmed address
        • Make an address primary
        • Remove an address
        • What this caller may do
    • Security
      • Sessions
        • Everywhere this account is signed in
        • Sign out everywhere else
        • Sign one out
        • A token for the CLI on a named machine
        • A token for the customer console, from the staff one
        • Park a sign-in for the CLI to collect
        • The CLI collecting its sign-in
        • The team's members' live sessions
        • Sign a member's session out
        • Sign an account out everywhere
        • Everywhere the account is signed in
        • Sign an account's session out
      • Single sign-on
        • Begin a single sign-on
        • The provider's return
        • Link the signed-in account to a team's provider
        • Which team an address signs in to
        • The team's single sign-on, as a member sees it
        • Set the team's OpenID Connect provider up, or change it
        • Remove the provider
        • The team's domain claims and the DNS record each needs
        • Prove a claimed domain
      • MFA and passwords
        • Start enrolling a second factor
        • Prove the app has it
        • Remove the second factor
        • Ask for a reset link
        • Set a new password with the emailed token
      • Klock
        • Open a device-bound klock session
        • Check in, for the next grant
        • Step up the session asking
        • Rotate the device key
        • Freeze a session
        • Unfreeze a session
        • A guest grant
        • The revocation feed
        • The published keyset
        • What this control plane supports
      • Devices
        • Your devices, or a team's
        • Approve a new device's pairing code
        • One device
        • Rename a device
        • Revoke a device
        • Suspend a device
        • Reinstate a suspended device
        • Wipe a device
        • Ask a device to rotate its key
        • The team's members' devices
        • Revoke a member's device
        • An account's devices
        • Revoke an account's device
        • Wipe an account's device
        • The device fleet
      • Access rules and behaviour
        • The access rules that bear on you
        • Add an access rule
        • This request, as the rules see it
        • One access rule
        • Remove an access rule
        • The behaviour profiles that bear on you
        • Add or change a behaviour profile
        • The profile presets
        • Your behaviour findings
        • Acknowledge a finding
        • One behaviour profile
        • Remove a behaviour profile
        • The team's access rules
        • Add a team access rule
        • Remove a team access rule
        • The team's behaviour profiles
        • Add or change a team behaviour profile
        • Remove a team behaviour profile
        • What the team's profiles caught
        • Acknowledge a team finding
      • Recovery and lockdown
        • Ask for a recovery link
        • Recover access with the emailed code
        • Is the account locked down
        • Lock the account down
        • Release a lockdown
        • Lock a member down
        • Release a member's lockdown
      • MCP tokens
        • Make a delegated token for one MCP client
        • The account's delegated tokens
        • Revoke a delegated token
        • What a delegated token may do now
        • Run one MCP tool with a delegated token
        • Run a device-signed MCP tool call relayed by the MCP Worker
      • Kerberos
        • Give the team its own Kerberos realm
        • The team's realm
        • Remove the team's realm
    • Logging and monitoring
      • Audit log
        • What has been done to the account
        • What has happened to this account
        • The account's audit trail
      • Operations
        • Everything that has been asked of this database
        • One, with its steps
        • Stop it
        • Put a failed one back in the queue
        • Every operation, across all accounts
      • Metrics and events
        • Every measurement, for a graph
        • Who did what to it
    • Billing
      • Plans and pricing
        • What the plans allow
        • The rate card
        • What one database would cost
        • What this account is paying for, itemised
      • Subscriptions and invoices
        • What this month's invoice will say
        • What this account is on
        • What it has been charged
        • Start a Stripe Checkout session
        • Open the customer portal
        • Stripe's events
        • Buy more connection pools
      • Team billing
        • The team's billing account
        • What the team has been charged
        • What this month's invoice will say
        • The team's cards
        • Add a card, through a Stripe-hosted setup session
        • Make a card the team's default
        • Remove a card
        • Start the team paying
        • Open the Stripe portal on the team's customer
        • Change the team's plan
        • Who receives the team's bills
        • How the team pays for transfers
    • Support
      • Support chat
        • My conversations
        • Start a conversation
        • Every support conversation, open first
        • A ticket for the socket
        • One conversation, with who is in it and who is connected
        • Rename a group; open or close a support conversation
        • The lines, oldest first
        • Say something
        • Add somebody
        • Mark read
    • Administration
      • Users
        • Every account
        • One account, with everything hanging off it
        • Grant or revoke admin
        • Verify an account by hand
        • Lock or unlock sign-in
        • Allow or hold provisioning
        • Send the verification mail again
        • Set the plan by hand
      • Platform
        • Every database and store, across all accounts
        • The counts worth putting on a dashboard
      • Staff and permissions
        • What kind of admin the caller is, and which scopes they hold
        • The admin presets
        • Every admin, and the scopes each resolves to
        • Make an account an admin of a kind
        • Change an admin's kind, or a custom admin's scopes
        • Revoke admin
      • Team administration
        • Every team, with its owner and size
        • One team in full — members with their accounts, and projects
        • Hand the team to another member
        • Put an account in the team, active at once
        • Change a member's role
        • Remove a member
      • Assumed identities
        • Assume an identity — act as a customer account
        • The identities the caller holds open
        • End an assumed identity
      • Support inbox
        • The platform's addresses
        • Add a platform address
        • One address, with its counts
        • Change an address's label, routing, or whether it accepts mail
        • Remove an address that holds no mail
        • Make, adopt or repair the address's routing rule
        • Every admin's personal address, made where missing
        • File a raw message, as if it had arrived
        • The inbox
        • One message, whole
        • Mark a message
        • Hand a message to an admin, or take it back
        • Leave an internal note
        • Reply, from the address the message came to
        • What is waiting
    • Databases
      • Databases
        • Data stores
          • Every data store on the account
          • Provision a data store
          • Change a data store that is already running
          • One data store
          • Deprovision it
          • Report what it is using
          • How to reach a data store
        • Connections and credentials
          • The api keys on a database
          • Issue a key
          • Revoke a key
          • The engine users we created
          • Create a user inside the database
          • Give a user a new password
          • Drop a user
          • How the database is reached
          • Set how it is reached
          • Revoke every api key on it
          • How to connect to it
          • The ssh keys that open its bastion
          • Add a key, or have one made
          • The private half of a generated key, once
          • Revoke an ssh key
        • Schema and objects
          • The SQL objects we put in it
          • Create one, and apply it
          • What is in the database, as the engine reports it
          • One table
          • What it would run, without running it
          • Redefine an object in place
          • Drop it
          • The extensions installed in it
        • Migrations
          • A plan compiled to statements, recording nothing
          • The migrations recorded for it
          • Record one
          • Apply everything recorded and not yet run
          • Apply everything pending, oldest version first
        • Lifecycle
          • Grow or shrink it
          • Stop it accepting connections
          • Start it again
          • Move it to another region
        • Backups and replicas
          • Take a backup
          • The backups it has
          • Restore one into it
          • What has been restored into it, and from where
          • Its read copies
          • Add one
        • Policies
          • The catalog
          • One policy
          • What this database is held to
          • Switch a policy on, or change its knobs
          • Switch it off
          • Mark the policies reviewed
          • Evaluate the periodic policies now
          • Who is behind a credential
        • Passwordless
          • The database's passwordless sessions
          • Issue a passwordless session (v1)
          • Revoke a passwordless session
          • Bind a session to a device key
          • Issue a v2 session for a host to bind
          • Redeem an enrolment ticket on the host
          • Check a passwordless credential
          • Run one described query under a passwordless credential
        • Database roles
          • The database's roles
          • Define a role
          • One role
          • Change what a role permits
          • Delete a role, and revoke every key granted it
          • Grant a role, which mints a key
          • Who holds a role
          • The api keys bound to a role
        • Pools
          • A database's connection pools, and how busy each is
          • Open another pool
          • Rename a pool or change its size
          • Close a pool
        • Data plane
          • Run a query against a database
          • Several statements, in order, over one connection
          • Is this database answering
          • What the proxy itself is holding
        • Transfers
          • The strategies this account's tier may use
          • Price a transfer without creating it
          • The account's transfer jobs, newest first
          • Create a transfer job
          • One job, and whether its certificate holds
          • Cancel an unfinished job
          • Start a created job, confirming its price
          • Report a job's status (the runner, or the owner's side of a local run)
        • Every database on the account
        • Provision a database
        • Change a database that is already running
        • One database
        • Deprovision it
        • Read or write it
        • Report what it is using
        • The engines this API will provision
        • Where a managed database can be put
    • Teams
      • Teams
        • Members
          • Who is on it
          • Invite somebody
          • Accept an invitation
          • Change somebody's role
          • Remove somebody
        • Projects
          • The projects a team runs
          • Start one
          • Rename a project, or move its environment
          • Delete a project
          • One project, and what is in it
          • Put a database or store in it
          • What is in a project
          • Take one out
        • The teams this account is on
        • Start one
        • The twelve roles, and what each may do
        • Rename a team
        • Close a team
        • One team
        • Hand the team to somebody else
        • Leave a team
    • Schemas
      • Error
      • ValidationErrors
      • Token
      • PolicyCategory
      • PolicySeverity
      • PolicyAction
      • PolicyTrigger
      • PolicyParam
      • Policy
      • PolicyCatalog
      • PolicyAssignment
      • PolicyOutcome
      • PolicyFiring
      • CredentialTrace
      • Relation
      • Restrictions
      • ChildSummary
      • SignupRequest
      • SigninRequest
      • UpdateMeRequest
      • User
      • Address
      • GeoPoint
      • D1Region
      • Usage
      • UsageReport
      • Resource
      • Database
      • DataStore
      • NewDatabase
      • NewDataStore
      • QueryRequest
      • DatabasePrivilege
      • ApiKey
      • DbUser
      • Access
      • AccessRequest
      • DatabaseObject
      • NewDatabaseObject
      • NewMigration
      • SchemaOperation
      • Migration
      • Operation
      • Session
      • AdminPowers
      • Admin
      • AuditEntry
      • TeamRole
      • Conversation
      • ChatMessage
      • TeamSso
      • Team
      • TeamMember
      • SshKey
      • ConnectionInfo
      • InboxAddress
      • InboxMailbox
      • InboxMessageSummary
      • InboxMessage
      • InboxNote
      • Page
      • Quote
      • Plan
      • ApiError
      • CapabilityRefusal
      • KlockErrorCode
      • PageWindow
      • SessionView
      • KlockStepUpRequest
      • KlockOpenRequest
      • KlockOpenedSession
      • UpdateMeResult
      • CapabilitiesView
      • SessionLimits
      • Device
      • DeviceListed
      • DeviceTeamRef
      • DeviceCommand
      • DeviceAuditLine
      • DeviceActionRequest
      • StaffActionRequest
      • ManagedSession
      • SessionRevoked
      • AccessRule
      • AccessRuleRequest
      • BehaviourProfile
      • BehaviourProfileRequest
      • BehaviourProfileSaved
      • BehaviourFinding
      • BehaviourFindingAck
      • StepUpProof
      • Removed
      • MemberLockdownRequest
      • McpClient
      • McpDelegatedView
      • McpToolCall
      • McpForwardRequest
      • PasswordlessScope
      • RoleScope
      • PasswordlessSession
      • PasswordlessTlsMaterial
      • PasswordlessKerberosMaterial
      • ServiceDeviceKeys
      • ServiceSession
      • DatabaseRole
      • TransferEndpoint
      • TransferJobRequest
      • TransferQuote
      • TransferStrategy
      • TransferJob
      • TransferJobAccess
      • Pool
      • PoolAllowance
      • BillingSubscription
      • Invoice
      • BillingContact
      • PaymentMethod
      • UpcomingCharges
      • TeamBilling
      • TeamKerberosRealm
      • TeamSsoDomain
      • TeamSsoResponse
      • StoreConnection
      • BatchFailure
      • ProxyStatus
  1. guides

MCP server

prorm is available to AI agents over the
Model Context Protocol. Connect a client and
the model can search the documentation, read a page, query the vector index,
look up any of the library's own lists, generate a model, a migration or a
query in whichever of the three styles your project uses — and, with your
token, operate your account: databases, keys, queries, the bill. Grounded in
what is published and what the control plane says, rather than recalled from
training data.

Connect#

One server, one address:
$ claude mcp add --transport http prorm https://mcp.prod-orm.io/mcp \
    --header "Authorization: Bearer <your prorm token>"
Leave the header off and you still get the documentation tools; the account
tools are then not listed at all. The console issues a delegated token under
Security → MCP clients (see the console's security pages),
and prorm mcp clients create does the same from a terminal.
For a client with a config file:
{
  "mcpServers": {
    "prorm": {
      "command": "npx",
      "args": ["-y", "mcp-remote@latest", "https://mcp.prod-orm.io/mcp",
               "--header", "Authorization: Bearer <your prorm token>"]
    }
  }
}
Two narrower endpoints exist for a client that wants a shorter tool list:
https://mcp.prod-orm.io/mcp/docs (the documentation tools, public) and
https://mcp.prod-orm.io/mcp/account (the account tools).
Which token goes in that header matters. A CLI or console token acts as you,
with everything you can do. For a third-party client, prefer a delegated
token
that holds only the capabilities the client needs and expires on its
own; see Delegated tokens for MCP clients.

Tools#

Seventy-eight, in four kinds. The first three answer anyone; the fourth acts as
you.
Retrieval — right for "how do I …".
ToolDoes
prorm_search(query, limit?)The passages matching a query, each with its page.
prorm_ask(question)A written answer, with the pages it used.
prorm_vector_search(query, topK?, minScore?)The vector index directly: nearest chunks and their scores.
prorm_pages(filter?)Every documentation page, with a one-line summary.
prorm_page(slug)One page in full.
Reference — the library's own lists, read out of the build.
ToolDoes
prorm_dialects()Every SQL dialect, grouped by compatibility.
prorm_operators(filter?)Every where operator, its SQL and an example.
prorm_decorators(filter?, group?)Every decorator and what it does.
prorm_datatypes(filter?)Every member of DataTypes.
prorm_validators(filter?)The validation rules and what each takes.
prorm_hooks()The lifecycle hooks and their handlers.
prorm_errors(code?)The error classes, for a catch block that names one, and the klock error codes; with code, the full entry of one klock error (see the klock error reference).
prorm_cli(filter?, group?, detail?)Every CLI command, by group, with flags.
prorm_stores(filter?)The non-SQL stores.
prorm_diagrams()The diagram kinds.
prorm_vocabulary(name?)Any of the library's enums and its members.
prorm_version()The current version and the install line.
prorm_changelog(version?)The release notes for one version.
prorm_upgrade_notes(from)Everything that changed since a given version.
prorm_secure_methods()How to declare a hashed column, and with what.
Scaffolding — code, generated the same way in every style.
ToolDoes
prorm_write_model(model, fields, track?)A model from a field list.
prorm_write_model_styles(model, fields)The same model in all three styles.
prorm_write_connection(dialect, url?)The Prorm construction for a dialect.
prorm_write_association(kind, source, target, …)Both sides of a relationship.
prorm_write_query(model, where?, order?, …)A read as findAll options.
prorm_write_migration(name, operation, table, …)A migration whose down undoes its up.
prorm_write_seeder(name, table, environments?)A seeder safe to run twice.
prorm_write_transaction(isolation?, retry?)A managed transaction, with the retry.
prorm_write_docker_compose(dialect)A local database with a health check.
prorm_review(code)Findings on a snippet: raw SQL, deprecated calls, N+1.
Account — your databases, keys, teams, sessions, devices and bill, as you.
Every tool is one call to the control plane as the caller, so it can do only
what that caller already can. Queries are described JSON, never raw SQL — the same rule as
everywhere else. Each account tool names the capability it needs; the
per-principal filtering section lists them.
ToolDoes
prorm_list_databases(), prorm_get_database(id)Your databases; one in full.
prorm_create_database(name, engine, …), prorm_update_database(id, …), prorm_delete_database(id)Provision, change, remove.
prorm_list_stores(), prorm_get_store(id), prorm_create_store(…), prorm_delete_store(id)The same for data stores.
prorm_list_engines(), prorm_list_regions()What can be provisioned, and where.
prorm_connect_database(id), prorm_connect_store(id)How to reach one from code.
prorm_run_query(id, query)Run a described query against a database.
prorm_list_keys(id), prorm_issue_key(id, …), prorm_revoke_key(id, keyId)API keys.
prorm_list_logins(id), prorm_create_login(id, …), prorm_get_access(id)Engine logins and access settings.
prorm_backup_database(id), prorm_resize_database(id, …), prorm_pause_database(id), prorm_resume_database(id)Maintenance; each returns an operation.
prorm_list_operations(), prorm_get_operation(id)Follow those operations.
prorm_billing_estimate(), prorm_billing_upcoming()What this month costs, and the next invoice.
prorm_whoami()Who the caller is, and what it may do.
prorm_list_teams(), prorm_team_members(team), prorm_invite_member(team, …), prorm_team_projects(team), prorm_attach_resource(…)Teams, their members and projects.
prorm_list_sessions(), prorm_revoke_session(id), prorm_list_devices(), prorm_revoke_device(id), prorm_lockdown()Your sessions and devices, and the emergency lockdown.
prorm_list_access_rules(), prorm_add_access_rule(…)Access rules; a new one always starts in report mode.
prorm_list_passwordless_sessions(id), prorm_issue_passwordless_binding(id, …), prorm_revoke_passwordless(id, sessionId)Passwordless database sessions; a binding returns an enrolment ticket, never a secret.
prorm_admin_stats(), prorm_admin_find_user(…), prorm_admin_user_sessions(…), prorm_admin_operations()Staff only, read-only, klock sessions with a step-up.
The reference tools answer from the library rather than from retrieval.
Retrieval is right for "how do I …" and wrong for "list every …", where it
returns a passage mentioning some of the list and the model fills in the rest —
which is exactly how an agent ends up confidently naming a dialect that does not
exist. Those lists are generated from the build and checked by the repository's
own tests, so one that goes stale fails there rather than in your editor.

Who is calling, and what they see#

An MCP request is made by one of four kinds of principal, and
tools/list and prompts/list show only what that principal may use. The
capabilities are the ones in the capabilities guide. The
remote Worker decides who is calling from the Authorization header
(workers/mcp/src/auth.ts):
PrincipalHow it is recognisedWhat it is listedWhere its calls go
Klock sessionAuthorization: Klock <grant> plus an RFC 9421 signature by the device key (a v2 prorm login; prorm mcp sends these)The grant's capabilities; a stepUp tool also when its capability is only dormant. Past the grant's checkInBy, only the public set.Relayed to the API's forward
Delegated tokenAuthorization: Bearer prorm_dt_…What GET /security/mcp/capabilities returns for the token: never a staff tool or a stepUp toolPOST /security/mcp/call
BearerAny other Authorization: Bearer …: a legacy CLI or console tokenYour capabilities from GET /me/capabilities: never a staff toolForwarded to the API with your own token, as before
GuestNo Authorization headerThe documentation, reference and scaffolding tools and every prompt; no account tools–
The Worker verifies a Klock principal offline: the grant against the
root-pinned keyset (its audience must include mcp), the request signature
against the device key the grant carries, and the grant's session and device
against the API-signed revocation feed. It does not claim the nonce; the API
does, when a signed tool call is forwarded. A klock-signed tools/call must
be sent on its own, not inside a JSON-RPC batch.
A credential the Worker or the API rejects gets HTTP 401 with
WWW-Authenticate: Klock error="<code>" (or Bearer error="<code>"). The
Worker does not quietly fall back to the guest list. The codes are the
catalogue's: grant_invalid,
grant_expired,
signature_invalid,
clock_skew,
session_revoked, device_revoked,
unauthenticated; and, as 503, capabilities_unavailable,
no_keyset, keyset_invalid and
feed_invalid.

The endpoints#

RouteServes
POST /mcpEverything this caller may use
POST /mcp/docsThe documentation, reference and scaffold tools only. Always public: a credential sent here is never looked at, so even a bad token does not cause a 401.
POST /mcp/accountThe account tools only, filtered as /mcp is
GET /, GET /healthA description, and readiness. Both list every account tool with the capability it needs, and whether it confirms first or needs a step-up.

How the registry drives the filter#

Every account tool in src/mcp/registry.ts carries three fields beside its
build(args):
needs: the capability the call needs. An array means any of them.
prorm_run_query needs data:read or data:write, and the API then checks
the intent: a query with select needs data:read, anything else needs
data:write.
destructive: the call cannot be undone. The first call returns
confirmation required: call again with confirm "<token>" instead of
acting. The token is an HMAC over the session, the tool and the arguments,
and it is good for the current two-minute window and the one before it.
The client must repeat the same call with confirm set, so a person sees
the action before it happens.
stepUp: the call needs a fresh step-up. A capability that is only
dormant (an admin capability before prorm step-up) is not enough: the
tool is listed to a Klock session, but a call answers
Run `prorm step-up`, then retry. Delegated tokens never see stepUp
tools.
For a destructive tool the confirmation token comes from the API for Klock
and delegated callers (HTTP 428 confirmation_required), and from the Worker
for a legacy bearer (keyed by the optional MCP_CONFIRM_KEY secret). Either
way it is good for about two minutes, for exactly those arguments and that
caller, and the tool's schema declares a confirm string argument.
needs decides visibility, not authority. The API re-checks every call,
and the route it lands on still runs its own ownership, team-role and
capability checks.
NeedsTools
catalog:read (public)prorm_list_engines, prorm_list_regions
account:readprorm_whoami
resource:readprorm_list_databases, prorm_get_database, prorm_list_stores, prorm_get_store, prorm_list_operations, prorm_get_operation
resource:provisionprorm_create_database, prorm_create_store
resource:operateprorm_update_database, prorm_backup_database, prorm_resize_database, prorm_pause_database, prorm_resume_database
resource:delete (destructive)prorm_delete_database, prorm_delete_store
key:readprorm_connect_database, prorm_connect_store, prorm_list_keys
key:writeprorm_issue_key, prorm_revoke_key (destructive)
data:read or data:writeprorm_run_query
access:readprorm_list_logins, prorm_get_access, prorm_list_passwordless_sessions
access:writeprorm_create_login, prorm_issue_passwordless_binding, prorm_revoke_passwordless (destructive)
billing:readprorm_billing_estimate, prorm_billing_upcoming
team:readprorm_list_teams, prorm_team_members
team:manage-membersprorm_invite_member
project:readprorm_team_projects
project:writeprorm_attach_resource
session:readprorm_list_sessions
session:manageprorm_revoke_session (destructive), prorm_lockdown (destructive, step-up)
device:readprorm_list_devices
device:manage (destructive, step-up)prorm_revoke_device
access-rule:readprorm_list_access_rules
access-rule:write (step-up)prorm_add_access_rule
admin:dashboard (step-up)prorm_admin_stats
admin:users (step-up)prorm_admin_find_user, prorm_admin_user_sessions
admin:operations (step-up)prorm_admin_operations
Three tools are narrowed further:
prorm_add_access_rule always creates the rule in report mode. An agent can
never pass force or enforceNow.
prorm_issue_passwordless_binding calls
POST /provision/databases/:id/passwordless/enrol and returns an enrolment
ticket, never a secret
; the Worker also strips any secret field. A host
redeems the ticket with its own device key (see klock).
The staff tools (prorm_admin_*) are read-only, need a step-up, and are
listed only to a Klock session. Bearer and delegated tokens never see them,
and there is no mutating admin tool over MCP.
The API applies the same rules to every principal (dispatchTool in
api/security/controllers/mcpForward.ts):
An unknown tool and a forbidden tool get the same answer. The API
answers 404 tool_not_found, and both the Worker and the local server turn
that into the JSON-RPC error -32602 "No such tool: <name>", so a client
cannot probe for tools it may not use.
No admin tool runs for a delegated token, and no mutating admin tool
runs over MCP at all
.
A derived call may only reach /provision/…, /billing/…, /teams…,
/security/{sessions,devices,access-rules,behaviour,lockdown}… and
/me/capabilities. /admin/… is reachable only by an admin tool, with
GET, and an admin tool can reach nothing else.

Guests#

With no header, a client of the remote server gets the documentation,
reference and scaffolding tools and every prompt, and no account tools. A call
to an account tool is answered as an unknown tool. Nothing is needed to use
the documentation. (The local prorm mcp, not signed in, also lists the two
public catalogue tools, prorm_list_engines and prorm_list_regions.)

Delegated tokens for MCP clients#

A delegated token is what a third-party MCP client (Claude Desktop, a
hosted assistant) should hold instead of your CLI token. It is:
narrow: it holds only the capabilities you list, and the API
intersects them with your own live capabilities on every call, so a
capability you lose (a team role that changes) is lost by the token at once;
expiring: at most 30 days (the default), and it is revoked after 7
days without use;
per client: it carries the client's name, and you can list and revoke
each one;
never admin: admin capabilities are never delegated.
The same token can be made three ways:
$ prorm mcp clients create --name "Claude Desktop" --caps resource:read,data:read,billing:read --days 30
✓ Token for Claude Desktop (id 0b9f3c52-6d1e-4a7b-8c20-5e4f1a9d7c36): resource:read, data:read, billing:read, 30 days.
! Shown this once — put it in the client’s config now:
  prorm_dt_…
$ curl -s https://api.prod-orm.io/security/mcp/clients \
    -H "Authorization: Bearer $PRORM_SESSION_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"clientName":"Claude Desktop","caps":["resource:read","data:read","billing:read"],"expiresInDays":30,"label":"laptop"}'
The answer is 201 { token, client }; client has id, clientId,
clientName, label, caps, resource, teamId, createdAt,
expiresAt, lastSeenAt, revokedAt and revokedReason. The API route
also takes resource and teamUuid, which the CLI does not.
Security → MCP clients → Create. Pick the capabilities (only delegable
ones you hold; the quick picks are "Docs only", "Read my data" and "Read and
write data"), 1, 7 or 30 days, and optionally one database to lock the token
to. The token is shown once, with the MCP settings JSON ready to paste.
Manage them from the CLI (src/cli/basic/commands/mcp.ts):
$ prorm mcp clients create --name "Nightly agent" --caps resource:read --days 7
$ prorm mcp clients list            # add --all to include revoked and expired tokens
$ prorm mcp clients revoke 0b9f3c52-6d1e-4a7b-8c20-5e4f1a9d7c36
create takes --name (1–80 printable characters), --caps
(comma-separated ids, or ns:*) and --days (1–30, default 30). The token
(prorm_dt_…) is printed once. The API stores only its SHA-256 hash.
list (alias mcp clients) shows the id, name, capabilities, expiry, last
use and state. It never shows a token.
revoke takes the id list shows (the token row's uuid), asks for
confirmation (--yes skips it), takes effect on the next call, and the
token goes onto the revocation feed.
Managing tokens needs the mcp:clients capability, which a delegated token
never holds, so one token cannot mint another. An assumed identity (support
acting as you) cannot manage them either.
What a delegated token can never hold. The session kind delegated masks
out session:manage, device:manage, access-rule:*, behaviour:*,
billing:manage, team:manage-members, mcp:clients,
device:manage-members, session:manage-members and every admin:*
capability (KIND_MASK.delegated in src/capabilities.ts). The CLI refuses
these locally with a usage error; the API refuses them with 400 not_delegable
(or admin_not_delegable), and an id it does not know with 400 unknown_capability. You also cannot delegate a capability you do not hold
yourself (403 capability_missing).
Limits. At most 5 live delegated tokens per account. Creating a sixth
revokes the least recently used one.
Locking a token to one resource. The API also accepts
resource: { kind: 'database' | 'store', id } and a teamUuid when a token is
created (POST /security/mcp/clients). A locked token sees only the tools that
act on one resource of that kind, plus the catalogue, and a call on any other
resource is answered as an unknown tool. The CLI does not expose these options
yet; use the API directly.

Claude Desktop with a delegated token#

Create the token#

$ prorm mcp clients create --name "Claude Desktop" --caps resource:read,data:read,billing:read
Copy the prorm_dt_… line; it is not shown again.

Check what it can do#

$ curl -s https://api.prod-orm.io/security/mcp/capabilities \
    -H "Authorization: Bearer prorm_dt_…"
The answer
{
  "tier": "user",
  "caps": ["billing:read", "data:read", "resource:read"],
  "dormant": [],
  "session": { "kind": "delegated", "binding": "bearer", "expiresAt": "2026-10-26T09:14:02.000Z" },
  "client": { "id": "5d0c2b8e-3f41-4a6c-9e7d-2b1a8f6c4e90", "name": "Claude Desktop" },
  "resource": null,
  "tools": [
    "prorm_list_databases", "prorm_get_database", "prorm_list_stores", "prorm_get_store",
    "prorm_run_query", "prorm_list_operations", "prorm_get_operation",
    "prorm_billing_estimate", "prorm_billing_upcoming"
  ],
  "capabilitiesVersion": 1
}
tools is exactly what the client will be listed: prorm_run_query is
there because data:read satisfies it, but a write query through it is
refused with 403 capability_missing. client.id here is the client's own
id (clientId), not the token id list and revoke use.

Put it in the client's config#

{
  "mcpServers": {
    "prorm": {
      "command": "prorm",
      "args": ["mcp"],
      "env": { "PRORM_TOKEN": "prorm_dt_…" }
    }
  }
}
With PRORM_TOKEN set to a delegated token, the local server lists what
/security/mcp/capabilities returns and sends every call through
/security/mcp/call. Nothing else is called with the token.
{
  "mcpServers": {
    "prorm": {
      "command": "npx",
      "args": ["-y", "mcp-remote@latest", "https://mcp.prod-orm.io/mcp",
               "--header", "Authorization: Bearer prorm_dt_…"]
    }
  }
}
Use this where prorm is not installed. The Worker recognises the
prorm_dt_ prefix and filters and relays exactly as the local server does.
On macOS the file is
~/Library/Application Support/Claude/claude_desktop_config.json. Restart
the client after editing it.

Revoke it when you are done#

$ prorm mcp clients list
$ prorm mcp clients revoke <id>
[!CAUTION]
Never put a CLI or console token (prorm login's) in a third-party
client's config: it acts as you, with every capability you hold,
including destructive ones. A delegated token holds only what you listed,
can never hold session:manage, mcp:clients or any admin:*
capability, and dies on its own.

A call, by hand#

What the client does for each tools/call, done with curl:
$ curl -s https://api.prod-orm.io/security/mcp/call \
    -H "Authorization: Bearer prorm_dt_…" -H "Content-Type: application/json" \
    -d '{"tool":"prorm_run_query","arguments":{"id":"shop","query":{"select":{"from":"orders","where":{"status":"paid"},"limit":5}}}}'
A destructive tool answers the first call with 428, and runs only when the
same call is repeated with confirm:
{
  "error": "confirmation_required",
  "message": "confirmation required: call again with confirm \"q3VhZ0l5Yk5mTjB6d1lQeEpKbmVtcTRr\"",
  "tool": "prorm_revoke_key",
  "confirm": "q3VhZ0l5Yk5mTjB6d1lQeEpKbmVtcTRr",
  "expiresIn": 120
}

The API routes#

RouteCredentialDoes
POST /security/mcp/clientsyour session (mcp:clients){ clientName, caps[], expiresInDays?, resource?, teamUuid?, label? } → 201 { token, client }. The token is shown once.
GET /security/mcp/clientsyour session (mcp:clients){ clients }, never the tokens
DELETE /security/mcp/clients/:idyour session (mcp:clients)Revoke one token
GET /security/mcp/capabilitiesBearer prorm_dt_…What the token may do now: { caps, session, client, resource, tools, capabilitiesVersion }
POST /security/mcp/callBearer prorm_dt_…{ tool, arguments } → the tool's answer
A delegated token is not a JWT, so every other API route refuses it. It is good
only for /security/mcp/capabilities and /security/mcp/call, where each call
is re-derived from the shared registry and checked as described above.
A call that fails a rule gets one of these answers:
StatuserrorMeaning
401token_invalid, token_revoked, token_expiredThe token is unknown, revoked, past its expiry, or idle for more than 7 days
423session_frozenThe token was frozen
404tool_not_foundNo such tool, or one this token may not use
403capability_missingA visible tool used beyond its intent (a write query on a read-only token)
428confirmation_requiredA destructive tool; call again with the returned confirm
401step_up_requiredA stepUp tool; not available to a delegated token

Klock-signed MCP requests: the forward#

A v2 CLI session signs every request with its device key. The MCP Worker
cannot sign as your device, so it does not try: for a Klock principal it
relays the signed request unchanged to the API, and the API decides.
What this gives you:
The Worker cannot invent a call. The tool and its arguments are read
from the bytes the device signed. When the Worker also sends its own copy,
it must match, or the call is refused with 400 intent_mismatch and an
audit event at level warning.
The Worker cannot replay a call. The request is a signed POST, so its
nonce is claimed once. A second use is 401 nonce_replayed.
The request must have been signed for the MCP endpoint. The signed URL
must be /mcp or /mcp/account on an origin in MCP_ORIGINS (default
https://mcp.prod-orm.io), with no query string.
The call is re-derived, not trusted. The API builds the HTTP request with
the shared registry's build(args) and runs it through the app from the top:
maintenance mode, access rules, rate limits and the route's own ownership and
capability checks all apply. The principal it runs as is narrowed to the
capabilities this call was checked against, with no admin capability.
Forwarded calls are recorded under one bearer row per Klock session
(subjectKind: mcp-client, client name mcp (klock forward), linked to its
parent session), so they are attributed to that session and can be revoked
on their own.
The grant and signature are the credential, so POST /internal/mcp/forward
takes no other authentication.

Caching and freshness#

The Worker keeps what it verified, never a token:
The keyset is cached for an hour, per isolate and in the Cache API. A
grant naming an unknown kid triggers a refetch, at most once a minute. A
keyset with a lower seq is refused as a rollback.
The revocation feed is re-read at most every 30 seconds, from the last
seq seen. A Klock caller is refused (503 feed_invalid) if there has been
no good read in 10 minutes, rather than trusted on stale data.
Bearer and delegated views are cached for 60 seconds, keyed by
sha256(token). A delegated token revoked on the feed is dropped at the next
feed read. In the worst case, a revoked token keeps its tool list for up to
30 seconds; its calls fail at once, because the API re-checks them.

Configuration#

In workers/mcp/wrangler.toml and the Worker's secrets:
NameWhat it does
API (service binding to prorm-control-plane)How the Worker reaches the API. Without it, or with API_TRANSPORT=url, it uses plain fetch to API_URL. For wrangler dev without the API running: wrangler dev --var API_TRANSPORT:url.
MCP_CONFIRM_KEY (optional secret)The HMAC key for the confirmation tokens the Worker issues to legacy bearers
PRORM_KLOCK_ROOTSReplaces the pinned roots, for development and staging only. Never set it in production.
KLOCK_ISSUER (optional)The grant issuer to expect. Defaults to the origin of API_URL.
CORS allows the klock signature headers (signature, signature-input,
content-digest, klock-client, idempotency-key, x-prorm-team) and
exposes www-authenticate.

Prompts#

Twenty-three, which a client offers as slash commands. Three are the
project-structure prompts — one each for TypeScript, JavaScript and decorators —
and prorm_upgrade(from) takes the version you are on and expands to the
release notes between it and now, with what to search for and the replacement
for each deprecated call. The rest are a subject each: passwords, security,
validation, associations, querying, migrations, seeders, transactions, hooks,
indexes, logging, docker, testing, performance, NoSQL, diagrams, the CLI,
compliance, and porting a schema between dialects.

The vector index#

prorm_vector_search queries a vector index built from the same pages the
documentation search crawls, and answers a different question: not what the
documentation says, but what is near a phrase and how near. That is what you
want when the name of the concept is the thing you are missing — and a low score
is an answer too: it says the documentation may not cover it.

What it is built on#

A Cloudflare Worker implementing the Streamable HTTP transport, over the same
AutoRAG index that answers the documentation site's own search. prorm_ask's
generation step runs on Workers AI routed through Cloudflare's AI Gateway,
so answers are cached, rate limited and logged in one place.
Nothing is stateful: every tool answers from an index, from the generated
catalogue of the library's own lists, from its own arguments, or from one call
to the control plane made with your token — so there is no session to keep,
and the server holds no secret of its own.

The same tools, locally#

prorm mcp runs the account tools as a local stdio server on your
prorm login, so no token goes into any agent's config:
{ "mcpServers": { "prorm": { "command": "prorm", "args": ["mcp"] } } }
prorm mcp --tools lists what it exposes without starting the server. This is
the right choice for Claude Desktop, Claude Code, and any agent that can spawn
a local process; the remote server is for a hosted assistant that cannot. Both
read one tool registry, so a tool behaves identically on your machine and at
the edge.

What plain prorm mcp runs on#

Plain prorm mcp does not run on your whole session. When you are signed
in (and not already on an MCP client token), it mints a child delegated
token
holding your session's non-destructive capabilities, and runs the
server on that token exactly as --caps does: the listing comes from
/security/mcp/capabilities, every call goes through POST /security/mcp/call,
and nothing is sent with your own credential.
"Non-destructive" is your capabilities, intersected with the delegated kind
mask, minus every admin capability and minus DESTRUCTIVE_CAPS
(src/mcp/stdio.ts). That set is every capability a destructive registry tool
needs, plus the ones whose ordinary use overwrites:
Left outWhy
resource:delete, key:write, session:manage, device:manage, access:writeA destructive tool needs it
data:writeWrites rows
migration:applyChanges a schema
billing:manageChanges what you pay
So listing, provisioning, operating (backup, resize, pause), read-only
queries, reading keys and reading the bill all work. Deleting, revoking,
issuing keys or logins, and writing rows do not; restart the server with
--caps … or --full for those.
The child is created with client name prorm mcp (<host>), label
prorm mcp (default: non-destructive) and a one-day lifetime. It is
renewed every 20 hours while the server runs (a new child from your
session, then the old one revoked; a failed renewal keeps the old one until it
expires, never your session) and revoked when the server stops. It shows
in prorm mcp clients list while it lives and counts toward the live
delegated-token limit. On start, stderr says:
prorm mcp: running on a narrowed session (non-destructive: <N> capabilities). --full for everything.
{ "mcpServers": { "prorm": { "command": "prorm", "args": ["mcp"] } } }
Non-destructive capabilities, enforced by the API.
{ "mcpServers": { "prorm": { "command": "prorm", "args": ["mcp", "--caps", "resource:read,data:read"] } } }
Exactly these, enforced by the API. Refuses to start without a child token.
{ "mcpServers": { "prorm": { "command": "prorm", "args": ["mcp", "--full"] } } }
Your whole session. Destructive tools ask for a confirmation token first.
--full is the old behaviour: the server runs on your whole session, and
stderr warns you so. Destructive tools then need a confirmation
(below). --full with --caps is a usage
error (exit 2).
The fallback. When the API cannot mint a child (an older API with no
/security/mcp/clients, a 403 because the session may not create MCP
clients, any other failure, or an answer with no prorm_dt_ token), or when
it has no /me/capabilities to say what the session holds, the server still
starts. It narrows your session locally to the same non-destructive set,
and says so on stderr:
prorm mcp: this API has no narrowed MCP sessions (/security/mcp/clients). Running on your session narrowed here to its non-destructive capabilities (enforced by this process, not the API; destructive tools are not offered). Use --caps for a server-enforced session when the API supports it, or --full for everything.
In that mode destructive tools are not listed and answer No such tool, and a
prorm_run_query whose described query writes (insert, update, delete
or upsert) is refused locally with "This session reads data only…".
[!NOTE] Why fall back instead of refusing to start
An MCP host spawns prorm mcp from a fixed config, so refusing to start
would lose every tool. Local narrowing gives the same ceiling against what
narrowing is for, a model steered into a destructive call. It is not
enforced by the server against the host process itself, but a host that can
run code as you can already read your credential from the same config and
keychain. It never silently runs with everything: that takes --full.
--caps is stricter and still refuses to start without a server-side child.
An MCP client token in PRORM_TOKEN (prorm_dt_…) runs as it is, since it is
already narrowed. The child token is handed to the stdio server directly,
never through process.env.PRORM_TOKEN; your session stays configured only to
mint, renew and revoke it.

Confirming destructive tools#

On a klock or legacy session (that is, with --full), a destructive tool's
first call sends nothing to the API. It answers with a tool error that names
the action and carries a token:
This will delete a database (prorm_delete_database {"id":"1"}). confirmation required: call again with confirm "<32 chars>" — only once the user has agreed to this action. It is good for about 2 minutes, for exactly these arguments.
The token is an HMAC over the tool, its arguments without confirm, and a
2-minute window, under a random key made for this process (the Worker's
shape for bearers).
It is accepted in the current window and the one before, so it lasts 2 to 4
minutes, for exactly that tool and those arguments.
confirm is stripped before the call is built.
Every destructive tool's inputSchema declares confirm, in every mode, so
a strict client lets the model send it.
On a delegated child (the default, or --caps), the confirmation is the
API's own 428 confirmation_required, passed on in the same words.

How the local server works#

What the local server does (src/mcp/stdio.ts):
It speaks newline-delimited JSON-RPC on stdin and stdout, and writes
everything human to stderr.
It filters tools/list by the local session, as the CLI's guard does:
SessionWhat is listedHow calls are made
Default (signed in)Your non-destructive capabilities, from GET /security/mcp/capabilities on the childEvery call through POST /security/mcp/call on the child token
klock v2, --fullThe verified grant's capabilitiesSigned by the device key
Legacy token, --fullYour capabilities from /me/capabilities (cached an hour). If the API has no such route, every non-admin tool is listed and the API decides.With the token
Delegated token (PRORM_TOKEN=prorm_dt_…)What GET /security/mcp/capabilities returnsEvery call through POST /security/mcp/call; nothing else is called with it
Not signed inThe public catalogue tools plus the documentation set–
The view is re-read every 60 seconds, so a revoked token or a changed grant
shows without a restart.
The documentation, reference and scaffold tools, and every prompt, are
proxied
to the public https://mcp.prod-orm.io/mcp/docs
(src/mcp/docs-proxy.ts) rather than bundled. The listing is cached for 24
hours in ~/.prorm/cache/mcp-docs.json, and no credential is ever sent to
the docs endpoint. Offline, a cached listing is still shown, but calls need
the network. PRORM_MCP_DOCS_URL points it elsewhere (staging, tests).
An unknown tool and a forbidden one both get -32602 "No such tool: <name>",
and destructive tools carry annotations.destructiveHint: true.
A narrowed session: prorm mcp --caps a,b [--hours N]. Use this when the
host application should get less than you hold:
{
  "mcpServers": {
    "prorm": {
      "command": "prorm",
      "args": ["mcp", "--caps", "resource:read,data:read", "--hours", "8"]
    }
  }
}
1.
The CLI mints a child delegated token with your session
(POST /security/mcp/clients, one day, client name prorm mcp (<host>)).
The capabilities are checked locally against the delegated mask first.
2.
It runs the server on that token only: listing from
/security/mcp/capabilities, every call through /security/mcp/call. It
never falls back to your own session. If no token comes back, it does not
start (exit 1).
3.
--hours (default 12, 1–24) is enforced locally: after it, account tools
answer that the narrowed session has ended. The token itself lives at most
a day.
4.
When the server stops, the token is revoked. If that fails, stderr prints
the prorm mcp clients revoke <id> command to run.
The child counts toward the five live delegated tokens per account and shows
in prorm mcp clients list while it lives. --caps needs your own session:
with PRORM_TOKEN=prorm_dt_… it refuses to start. The documentation set stays
listed even when --caps leaves out docs:read, since it is public anyway.

Source#

workers/mcp/ in the repository — the documentation tools in src/tools*.ts,
the account transport in src/tools-account.ts — with the shared tool registry
in src/mcp/registry.ts and the local stdio server in src/mcp/stdio.ts. The
hostname is in src/hosts.ts, with every other prorm address.
On the API side, delegated tokens, the forward and the MCP rules are in
api/security/controllers/mcpForward.ts, with the routes in
api/basic/routes/mcpClients.js (mounted at /security/mcp and
/internal/mcp).

Related reading#

CLI — the same documentation, from a terminal
Capabilities — the capability ids the tools need, and the session kinds
klock — v2 sessions, grants and request signing
Console security pages — MCP clients, sessions and devices in the console
Browser — the ORM itself, in a page
Modified at 2026-10-04 00:40:16
Previous
Grafana Loki: structured LogQL queries
Next
Migrate — the data transfer subsystem
Built with