@atolis-hq/corum
v0.1.46
Published
Corum is a Git-native design graph for service architecture. It models components (APIs, domain models, schemas, fields) as nodes with typed edges, and exposes the graph through MCP tools so AI assistants can reason about your architecture.
Readme
Corum
Corum is a Git-native design graph for service architecture. It models components (APIs, domain models, schemas, fields) as nodes with typed edges, and exposes the graph through MCP tools so AI assistants can reason about your architecture.
Install
npm install -g @atolis-hq/corumOr run without installing:
npx @atolis-hq/corum <command>Windows: If you see an "execution policy" error in PowerShell, run this once:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUserThis is a standard one-time setup step for Node.js development on Windows. Alternatively, npx @atolis-hq/corum <command> works without any setup on all platforms.
Update
npm update -g @atolis-hq/corumQuick Start
Scaffold a new project in the current directory:
corum initThis creates .corum/config.yaml, scaffolds a graph at .corum/graph/, and downloads the official template packs (core, domain, rest, messaging). Then start the MCP server:
corum mcpIf you only want the web UI:
corum webCommands
corum mcp
Start the MCP stdio server. Also starts a web UI by default.
corum mcp [options]
Options:
--no-web Suppress the web UI
--watch Reload file-backed graphs on local file changes
--graph <path> Override the graph directoryNotes:
corum mcpstarts the web UI unless you pass--no-web.--watchapplies to filesystem graphs. Git-backed graphs reload through polling instead.
corum web
Start the web UI only.
corum web [options]
Options:
--port <n> Port to listen on (default: 3000)
--graph <path> Override the graph directoryNotes:
- Filesystem graphs can be watched for local YAML changes with
CORUM_FILE_WATCHER=trueorCORUM_WATCH=true. - Git-backed graphs reload through polling when
git_poll_seconds/CORUM_GIT_POLL_SECONDSis set.
corum lint
Lint the graph and report diagnostics.
corum lint [options]
Options:
--graph <path> Override the graph directorycorum init
Scaffold a .corum/ project structure and install the four default template packs (core, domain, rest, messaging). Skips any step where the target already exists.
corum initCreates:
.corum/config.yaml- project configuration.corum/graph/graph.yaml- graph definition.corum/graph/components/and.corum/graph/edges/- empty directories ready for nodes.corum/packs/- downloaded template packs.corum/packs.yaml- local manifest of installed packs
corum pack install
Install a template pack from the registry into .corum/packs/. Appends the pack to .corum/graph/graph.yaml and records it in .corum/packs.yaml.
corum pack install <name> # install latest tag
corum pack install <name>@<ref> # install a specific tagExamples:
corum pack install domain
corum pack install [email protected]
corum pack install extract # required for corum-extract import adaptercorum pack list
List installed packs with their resolved version and install date.
corum pack listcorum import
Import specifications into the graph.
corum import --config <path> Import using a config YAML fileImport config file
The --config flag accepts a YAML file that can combine multiple imports in a single run and configure cross-adapter options:
# Optional: remap extracted component names before node IDs are built.
# Useful when the same component appears under different names in different specs
# (e.g. "order-shipping" from a URI segment vs "ordershipping" from a topic name).
componentNameReplacements:
- from: ordershipping
to: order-shipping
# Optional: deduplicate nodes emitted by different adapters after all imports
# complete. For each rule, keep nodes from the primary adapter and merge/drop
# matching nodes from the secondary adapter.
deduplication:
- primary: openapi
secondary: corum
imports:
- adapter: openapi
spec: ./specs/order-shipping.openapi.yaml
componentMapping:
strategy: uri-segment
segment: 0
- adapter: asyncapi
spec: ./specs/order-shipping.asyncapi.yaml
componentMapping:
strategy: channel-segment
separator: "."
segment: 0
messageNaming:
strategy: name-segment
separator: "."
segment: -1Replacements are applied in order; the first matching from wins. Unmatched names are passed through unchanged.
Deduplication rules are applied after all adapters finish. They are intended for
cross-adapter reconciliation, for example keeping OpenAPI endpoints as canonical
while merging matching extractor-emitted Corum nodes into them.
corum import openapi <spec>
Import an OpenAPI spec directly.
corum import openapi <spec> [options]
Options:
--component-strategy <strategy> Component mapping: uri-segment (default), tag, hardcoded
--segment <n> URI segment index (uri-segment strategy)
--pattern <regex> Regex pattern (uri-segment strategy)
--component <name> Component name (hardcoded strategy)
--graph <path> Override the graph directorycorum import asyncapi <spec>
Import an AsyncAPI spec directly.
corum import asyncapi <spec> [options]
Options:
--component-strategy <strategy> Component mapping: channel-segment (default), channel-pattern,
name-segment, name-pattern, tag, hardcoded
--separator <char> Separator for segment strategies (default: .)
--segment <n> Segment index (negative counts from end)
--pattern <regex> Regex pattern for pattern strategies
--component <name> Component name (hardcoded strategy)
--event-classification <mode> always-integration (default) or always-domain
--include-consumed Also import receive (consumed) operations
--graph <path> Override the graph directorycorum import corum <spec>
Import a corum interchange file (*.corum.yaml) produced by corum-extract or compatible extraction tooling.
corum import corum <spec> [options]
Options:
--graph <path> Override the graph directoryThe interchange format is self-describing - no component mapping strategy is needed. Node IDs, template names, and field references are already corum-native. Gaps reported by the extractor (unresolved types, name collisions) are surfaced as warnings.
Requires the extract pack to be active in your graph:
corum pack install extractYou can also configure corum imports in a config file:
# .corum/imports.yaml
imports:
- adapter: corum
spec: path/to/output.corum.yamlConfiguration
Run corum init to generate a .corum/config.yaml with all available options. Corum walks up from the current directory to find it, so you can place it at your project root.
Precedence (highest to lowest): CLI flags -> environment variables -> .corum/config.yaml
| Config key | Environment variable | Description |
|---|---|---|
| pack_registry | - | URL of the pack registry YAML (set by corum init) |
| source | CORUM_SOURCE | Source mode: file / filesystem / fs (default) or git |
| graph | CORUM_GRAPH_PATH | Path to the graph directory |
| git_local_path | CORUM_GIT_LOCAL_PATH | Local git repo path |
| git_remote_url | CORUM_GIT_REMOTE_URL | Remote git repo URL |
| git_branch | CORUM_GIT_BRANCH | Default branch ref used when loading a git-backed graph |
| git_poll_seconds | CORUM_GIT_POLL_SECONDS | Poll interval, in seconds, for git-backed web reloads |
| git_token | CORUM_GIT_TOKEN | Auth token for private repos |
| git_username | CORUM_GIT_USERNAME | Auth username (default: x-access-token) |
Additional environment-only runtime settings:
| Environment variable | Description |
|---|---|
| CORUM_WEB_PORT | Default port for corum web |
| CORUM_FILE_WATCHER | Enable local file watching for filesystem graphs when running the web UI |
| CORUM_WATCH | Alias for CORUM_FILE_WATCHER |
File source (default)
# .corum/config.yaml
source: file
graph: .corum/graphUse this when the graph lives directly on the local filesystem with no git source abstraction.
Git source
# .corum/config.yaml
source: git
git_remote_url: https://github.com/org/design-repo
git_branch: main
git_poll_seconds: 30Or for a local git repository:
# .corum/config.yaml
source: git
git_local_path: /path/to/repo
git_branch: mainRules:
- Set exactly one of
git_local_pathorgit_remote_url. git_branchselects the default branch Corum loads for read operations and the web UI.git_poll_secondsis only used for git-backed web reloads.
For private repositories, set CORUM_GIT_TOKEN as an environment variable rather than storing it in the config file.
MCP Client Configuration
Configure your MCP client to run Corum. For Claude Code or Claude Desktop:
{
"mcpServers": {
"corum": {
"command": "npx",
"args": ["@atolis-hq/corum", "mcp", "--no-web"],
"env": {
"CORUM_GRAPH_PATH": "/path/to/your/graph"
}
}
}
}Or if installed globally:
{
"mcpServers": {
"corum": {
"command": "corum",
"args": ["mcp", "--no-web"],
"env": {
"CORUM_GRAPH_PATH": "/path/to/your/graph"
}
}
}
}MCP Tools
| Tool | Description |
|---|---|
| list_nodes | List graph nodes using a filter object with templates, exclude_templates, component, state, and stability |
| list_templates | List loaded templates with summary metadata |
| get_template | Return full details for a template |
| get_cluster | Return a node's structural contents. By default, schema and enum child nodes are collapsed into compact schemas and enums blocks on the root. Pass collapse_schemas: false to restore the full node-per-field representation |
| get_graph | Return the semantic graph as { nodes, edges }, excluding structural templates and structural edges by default |
| get_graph_metadata | Return discoverable metadata: template names, node templates in use, edge types, and valid enum values |
| get_lineage | Traverse lineage from one or more start nodes. Lean nodes and no edges by default; opt in to fuller payloads when needed |
| get_graph_summary | Return high-level graph statistics: node count, component count, orphan breakdown, edge counts, diagnostics |
| search_nodes | Fuzzy-search root-level nodes by ID, with optional template filters and property search |
| get_linked_fields | Return maps-to edges touching fields owned by a root node |
| list_branches | List available branches and their load status from the configured source |
| diff_branch | Diff a branch against the default branch |
| start_changes | Open a working mutation session |
| apply_cluster | Upsert a cluster-style document in merge or replace mode |
| create_node | Create a root cluster or owned child node |
| update_node | Patch node properties, state, or stability |
| rename_node | Rename a node while preserving identity trail metadata |
| delete_node | Soft-delete or hard-delete a node subtree |
| create_edges | Batch-create explicit edges as one atomic operation |
| update_edge | Patch an explicit edge |
| delete_edge | Delete an explicit edge |
| create_fields | Batch-create fields across schemas (grouped and applied per parent) |
| pending_changes | Show the open session's journal and summary diff |
| discard_changes | Abort the working session |
| commit_changes | Lint, serialize, and persist the session's changes |
All tools accept an optional format argument: toon (default; leanest for the LLM), yaml, or json. All tools also accept compact_keys: true to shorten common keys before serialization, reducing token usage further.
All node-returning MCP tools accept include_provenance: true to include extractedFrom, lastModifiedAt, derivation, and derivedBy. These fields are omitted by default. schemaVersion is never returned by MCP.
Common notes:
branchis supported on graph-query tools when Corum is running against a source-backed graph.list_nodesis a breaking-change surface from older builds: usefilter.templatesinstead of top-leveltemplate.search_nodesacceptsqueries: string[].get_graph_metadatashould usually be your first call. Useedge_types_in_useto avoid traversing edge types that do not exist in the current graph.get_graph_metadatareturnsvalid_edge_types,states,stabilities,lineage_directions, andoutput_formatswhen you passinclude_static_enums: true.- Prefer
search_nodesoverlist_nodesfor discovery. Uselist_nodeswhen you need a full inventory under explicit filters. get_lineageacceptsnode_ids: string[],depth,direction,edge_types,node_types,exclude_node_types,include_dangling_edges,reads_outbound_only,lean, andinclude_edges.get_lineagedefaults tolean: trueandinclude_edges: false. Lean lineage nodes contain onlyid,origin_id,depth,via_edge_type, andvia_node_id.- Pass multiple
node_idstoget_lineagein one call instead of making separate traversal calls. - Use
get_clusteronly when you need full structural contents for one node. By default it returns compactschemasandenumsblocks on the root rather than individual field nodes, which keeps response size manageable for large aggregates. Useget_lineagefor relationship traversal. - Read tools reflect the open working session while one exists. Unbranched reads, and branch-scoped reads for that same session branch, show uncommitted changes.
- The graph reflects modeled relationships, not guaranteed complete truth. Missing edges do not prove no relationship exists; agents should treat naming and schema similarity as hypotheses and then verify via cluster inspection or source material.
MCP Write Workflow
Corum's write tools are session-based:
- Call
start_changes. - Make one or more mutations with
apply_cluster,create_node,update_node,rename_node,delete_node,create_edges,update_edge,delete_edge, orcreate_fields. - Inspect the session with
pending_changes. - Finish with
commit_changesor abort withdiscard_changes.
Important behavior:
- No write tool works without an open session.
rename_nodeis the only rename path.apply_clusterand imports never infer renames.apply_clusterreplacemode is authoritative for the root's owned sections: absent children are deleted, and an absent owned section means "empty section".delete_nodedefaults to soft delete for nodes that already exist on the default branch, and hard delete for branch-local design work.discard_changescloses the session. On file-backed autosave sessions it does not roll back mutations already written through to disk.
Source-mode defaults:
- Filesystem source:
start_changesdefaultsautosaveon. Each mutation writes through immediately;commit_changesmainly lint-gates and closes the session. - Git source:
start_changesdefaultsautosaveoff. Changes stay in memory untilcommit_changes. - Git source with
autosave: true: each mutation creates acorum-wip:checkpoint commit;commit_changessquashes that run when no external commit interleaved.
Typical sequence:
start_changes:
branch: feat/order-design
create: true
rename_node:
id: orders.Schema.invoice
new_name: bill
pending_changes: {}
commit_changes:
message: rename invoice schema to billMCP Prompts
The server also exposes a discoverable MCP prompt:
| Prompt | Description |
|---|---|
| usage-guide | Orientation guide covering graph structure, read and write workflow, output-format choices, graph-completeness caveats, and inference guidance |
Contributing
See DEVELOPMENT.md for build, test, and local development instructions.
