{
  "markdown": "# Soma\n\nRMCP runtime for provider-backed agents with CLI, REST, HTTP MCP, plugins, and scaffold support.\n\n[![Docs](https://github.com/dinglebear-ai/soma/actions/workflows/docs.yml/badge.svg)](https://github.com/dinglebear-ai/soma/actions/workflows/docs.yml)\n[**API docs**](https://dinglebear-ai.github.io/soma/) — rustdoc for every\nworkspace crate plus the Redoc-rendered OpenAPI reference, deployed to GitHub\nPages from `main`.\n\nSoma is a batteries-included server runtime and shipping binary for bringing\nnew agent capabilities online with as little custom Rust as possible. It locks\nin the production patterns that every server in the family keeps rediscovering:\none compact MCP tool, stdio and Streamable HTTP transports, CLI parity, direct\nREST routes, auth/OAuth, observability, plugin packaging, web fallback,\nDocker/runtime samples, generated contracts, and release automation.\n\nThe repository can still scaffold a renamed project, but Soma is now a shipped\nruntime first. The default product path is to run `soma` in an explicit mode,\ndrop provider files into `providers/` (or point `SOMA_PROVIDER_DIR`\nelsewhere), and let the provider registry project those capabilities across MCP,\nCLI, REST, OpenAPI, Palette summaries, generated docs, and plugin metadata.\nProvider manifests also carry MCP-native prompt, resource, task, and elicitation\nmetadata for the registry contract. Scaffolding is the path for creating a new\ndistributable repo with the same locked-in runtime.\n\n**30-second path:** install the `soma` binary -> `soma status` ->\n`npx -y @dinglebear/soma mcp` from an MCP client -> call the `soma` MCP tool through\n`tools/call` with `{\"action\":\"status\"}`.\n\n**Status:** production RMCP runtime. Write-capable provider actions are\nallowed only when the provider declares them and destructive actions are gated.\n\n**Not for:** an unauthenticated public gateway, a replacement for upstream\nservice authorization, arbitrary untrusted code execution, or a multi-tenant\nsecurity boundary by itself.\n\n## Contents\n\n- [Naming](#naming)\n- [Capabilities And Boundaries](#capabilities-and-boundaries)\n- [Install](#install)\n- [Quickstart](#quickstart)\n- [Client Configuration](#client-configuration)\n- [Runtime Surfaces](#runtime-surfaces)\n- [MCP Tool Reference](#mcp-tool-reference)\n- [CLI Reference](#cli-reference)\n- [Configuration](#configuration)\n- [Authentication](#authentication)\n- [Safety And Trust Model](#safety-and-trust-model)\n- [Architecture](#architecture)\n- [Distribution Contract](#distribution-contract)\n- [Development](#development)\n- [Verification](#verification)\n- [Deployment](#deployment)\n- [Troubleshooting](#troubleshooting)\n- [Related Servers](#related-servers)\n- [Documentation](#documentation)\n- [License](#license)\n\n## Naming\n\nSoma is the runtime product first and the template/export source second.\nGenerated projects replace these names during scaffold post-processing, but the\nshipped `soma` command is the source of truth for product behavior.\n\n| Surface | Soma value | Generated-project pattern |\n|---|---|---|\n| Repository | `dinglebear-ai/soma` (formerly `rmcp-template`, then `rtemplate-mcp` — both still redirect) | `dinglebear-ai/r<service>`, or the bare product name; older servers still carry `<service>-rmcp` names behind redirects |\n| Rust crate/package | `soma` | service-specific crate names |\n| Canonical binary | `soma` | usually `r<service>` or the product name |\n| npm package | `@dinglebear/soma` | `<service>-rmcp` |\n| MCP tool | `soma` | usually `<service>` |\n| Env prefix | `SOMA_*` | generated service prefix |\n\n## Capabilities And Boundaries\n\n| Path | Use when | You author | Runtime supplies |\n|---|---|---|---|\n| Drop-in provider | You can describe a capability as a manifest, script, WASM module, OpenAPI operation, or upstream MCP call. | Files under `providers/` with tools, prompts, resources, env needs, capability grants, and surface overlays. | MCP tool dispatch, dynamic CLI commands, direct REST routes, schema validation, auth policy, refresh, OpenAPI/Palette summaries, generated docs, and plugin metadata. |\n| Static Rust provider | The capability needs native Rust, tight integration, or reusable crates. | A Rust provider/action registered with the provider registry. | The same MCP/CLI/REST/docs/plugin projection without per-surface rewrites. |\n| Scaffolded product | You need a renamed repository, package identity, ports, plugins, Docker labels, and release metadata. | A `scaffold_intent` payload or `cargo xtask scaffold` options. | A compiling product repo, scaffold report, cargo-generate post-processing, and scaffold/export verification checks. |\n| Custom profile | You need a narrower binary or deployment shape. | Cargo feature selection. | The same runtime crates behind `local-adapter`, `server`, and `full` profiles. |\n\n## Batteries Included\n\n- One compact MCP service tool (`soma`) with `action` dispatch, so agent tool\n  lists stay small even as provider catalogs grow.\n- One canonical binary: `soma` with explicit `serve`, `mcp`, and CLI modes for\n  REST API, Streamable HTTP MCP, stdio MCP, optional web UI, and local actions.\n- Dynamic provider loading from `.json`, `.ts`, `.py`, `.wasm`, and `.md`\n  files, plus native Rust providers and upstream MCP/OpenAPI provider kinds.\n  A structured `providers/{tools,prompts,resources}/` layout is supported\n  alongside root-level files, including path-derived MCP resources (static\n  files and dynamic `.ts` readers) with a path-traversal trust boundary.\n- Provider manifest contracts for tools, prompts, resources, tasks,\n  elicitation forms, env requirements, capability grants, and surface overlays.\n- Shared validation, destructive-action confirmation, auth/scope enforcement,\n  response limits, redaction, logging, metrics, generated OpenAPI, generated\n  provider surface docs, plugin manifests, setup, doctor, and release tooling.\n\nSoma owns the runtime projection, validation, auth policy, packaging, generated\nmetadata, and scaffold automation. Provider code owns service-specific behavior\nand credentials. Upstream services own their own authorization and data model.\nSoma deliberately refuses to make credentials part of tool-call input and does\nnot turn provider manifests into an unrestricted remote execution boundary.\n\n## Install\n\nUse the npm launcher when an MCP client expects an `npx` command. During\n`postinstall`, the package downloads the matching Linux/x64 or Windows/x64\nrelease archive, verifies its `SHA256SUMS` entry and GitHub build attestation,\nand installs the native binary inside the package. GitHub CLI 2.68 or newer is\nrequired for provenance verification.\n\n```bash\nnpx -y @dinglebear/soma mcp\n```\n\nUse Cargo while developing the repo:\n\n```bash\ncargo run --bin soma -- mcp\ncargo run --bin soma -- serve\n```\n\nRelease builds publish GitHub Release binaries, Docker/OCI metadata, the\n`@dinglebear/soma` npm launcher, MCP registry metadata, and plugin package files from\nthe same release component.\n\n## Product Profiles\n\nChoose the amount of surface area you want without changing the provider authoring\nmodel.\n\n| Target | Best fit | Default profile | Includes |\n|---|---|---|---|\n| Local agent adapter | Thin wrapper over dropped providers or an upstream API | `local-adapter` | CLI + stdio MCP in one local binary. No REST/Web mirror by default. |\n| Shared API/MCP server | Service used by multiple clients or a gateway | `server` | CLI + REST API + Streamable HTTP MCP + stdio MCP + health/status routes + auth-capable runtime. |\n| Full application platform | App owns state, jobs, dashboards, workflows, or human UI | `full` | `server` plus embedded web UI, OAuth, observability, and plugin support. |\n| CLI-only or custom local tool | Scripts, operator utilities, one-machine tools | Custom feature set, usually starting from `cli` | CLI parser and shared service layer. The stock packaged local binary uses `local-adapter`, so CLI-only products may prune MCP or adjust binary feature gates. |\n\nLower-level Cargo features are available when you need a custom shape:\n\n| Feature | Purpose |\n|---|---|\n| `cli` | CLI shim and command parsing. |\n| `mcp` | MCP tool, schema, resource, prompt, and scope layers. |\n| `mcp-stdio` | Local stdio MCP transport. |\n| `api` | REST handlers and OpenAPI-backed business routes. |\n| `auth` | Shared auth policy and bearer-token enforcement. |\n| `oauth` | Google, Authelia, and GitHub OAuth/OIDC plus JWT issuance on top of `auth`. |\n| `mcp-http` | Streamable HTTP MCP mounted in Axum. |\n| `web` | Embedded static web UI fallback. |\n| `observability` | Metrics/tracing hooks. |\n| `plugin` | Plugin setup/support helpers. |\n| `local-adapter` | Lean local binary: `cli` + `mcp-stdio`. |\n| `server` | Deployable HTTP runtime profile: `cli` + `api` + HTTP MCP + stdio MCP. |\n| `full` | Complete platform profile: local adapter, server, web, OAuth, observability, and plugin support. |\n\n## Quickstart\n\nRun the product as-is:\n\n```bash\ngit clone https://github.com/dinglebear-ai/soma\ncd soma\n\n# Full platform mode: REST API + HTTP MCP + web fallback on :40060\ncargo run --bin soma -- serve\n\n# Local binary: stdio MCP\ncargo run --bin soma -- mcp\n\n# Local binary: CLI\ncargo run --bin soma -- greet --name Alice\n```\n\nUseful smoke checks:\n\n```bash\ncurl http://localhost:40060/health\ncargo run --bin soma -- status\ncargo run --bin soma -- doctor\n```\n\nCall the MCP endpoint directly:\n\n```bash\ncurl -s -X POST http://localhost:40060/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"soma\",\"arguments\":{\"action\":\"greet\",\"name\":\"Alice\"}}}'\n```\n\n## Drop In A Provider\n\nThe fastest path for a new server is provider-first. Add a provider manifest or\nmodule to `providers/`, then run the same binary. Use `SOMA_PROVIDER_DIR`\nwhen the provider catalog should live outside the working directory.\n\n```bash\nmkdir -p providers\ncat > providers/hello-local.json <<'JSON'\n{\n  \"schema_version\": 1,\n  \"provider\": {\n    \"name\": \"hello-local\",\n    \"kind\": \"static-rust\",\n    \"title\": \"Hello Local\"\n  },\n  \"tools\": [\n    {\n      \"name\": \"hello_local\",\n      \"description\": \"Return a deterministic hello payload from a dropped provider.\",\n      \"input_schema\": {\n        \"type\": \"object\",\n        \"additionalProperties\": false,\n        \"properties\": {\n          \"name\": { \"type\": \"string\" }\n        }\n      },\n      \"cli\": {\n        \"enabled\": true,\n        \"command\": \"hello-local\"\n      },\n      \"rest\": {\n        \"enabled\": true,\n        \"method\": \"POST\",\n        \"path\": \"/v1/hello-local\"\n      },\n      \"meta\": {\n        \"result\": {\n          \"message\": \"hello from a dropped provider\"\n        }\n      }\n    }\n  ]\n}\nJSON\n```\n\nCall it through the dynamic CLI surface:\n\n```bash\ncargo run --bin soma -- hello-local --name Alice\n```\n\nRun the server and call the same provider over REST and MCP:\n\n```bash\ncargo run --bin soma -- serve\n\ncurl -s -X POST http://localhost:40060/v1/hello-local \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"Alice\"}'\n\ncurl -s -X POST http://localhost:40060/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"soma\",\"arguments\":{\"action\":\"hello_local\",\"name\":\"Alice\"}}}'\n```\n\nPlain Python functions can also be dropped directly into `providers/`:\n\n```python\nPROVIDER = {\"name\": \"math-tools\", \"kind\": \"python\"}\n\ndef add(a: int, b: int) -> int:\n    \"\"\"Add two integers.\"\"\"\n    return a + b\n```\n\nWhen `TOOLS` is absent, public functions defined in the module become tools.\nSync and async functions are supported, and common Python type annotations are\nconverted into input schemas.\n\nPython provider files are trusted code. Soma imports them during provider\ncatalog refresh to discover tools, then executes tool calls in a sidecar with a\ncleared environment plus only declared provider/tool env values. Catalog import\ndoes not receive provider env; read secrets inside tool functions, not at module\nimport time.\n\nProvider manifests can declare:\n\n- tools/actions exposed through MCP by default and through CLI/REST when their\n  overlays opt in\n- MCP-native prompt, resource, task, and elicitation metadata for the provider\n  registry contract\n- required environment variables and redaction rules\n- filesystem, network, browser, terminal, GitHub, and env capability grants\n- limits, destructive-action metadata, examples, generated docs, plugin, and UI\n  metadata\n\nSupported provider kinds are `static-rust`, `openapi`, `ai-sdk`, `wasm`, `mcp`,\n`python`, `langchain`, and `llamaindex`. See\n[docs/specs/dynamic-provider-runtime.md](docs/specs/dynamic-provider-runtime.md),\n[docs/contracts/provider-manifest.schema.json](docs/contracts/provider-manifest.schema.json),\nand [docs/generated/provider-surfaces.md](docs/generated/provider-surfaces.md).\n\n## Scaffold A New Project\n\nUse `cargo xtask scaffold` when the provider-first path needs to become a new\nrepository with its own crate names, binary names, ports, plugin package,\nDocker metadata, release metadata, and docs. It can plan without touching files,\ngenerate with `cargo-generate` plus the Rust post-processor, write\n`docs/scaffold-report.md`, and verify the generated export shape.\n\nPlan from a short service name:\n\n```bash\ncargo xtask scaffold --name myservice --category upstream-client --port auto --plan\n```\n\nPlan from MCP `scaffold_intent` JSON:\n\n```bash\ncargo xtask scaffold --intent scaffold-intent.json --plan\n```\n\nGenerate into an output parent directory:\n\n```bash\ncargo xtask scaffold --intent scaffold-intent.json --apply ../generated\n```\n\nVerify an existing generated project:\n\n```bash\ncargo xtask scaffold --verify ../generated/myservice-mcp\n```\n\nPrint a path-aware follow-up plan for adapting the generated stub:\n\n```bash\ncargo xtask scaffold --adapt-plan ../generated/myservice-mcp\n```\n\nMaterialize starter artifacts from an action manifest:\n\n```bash\ncargo xtask scaffold \\\n  --write-action-starters ../generated/myservice-mcp \\\n  --actions actions.json\n```\n\nAdd starter action snippets:\n\n```bash\ncargo xtask scaffold \\\n  --intent scaffold-intent.json \\\n  --actions actions.json \\\n  --plan\n```\n\nExample action manifest:\n\n```json\n{\n  \"actions\": [\n    {\n      \"name\": \"list_things\",\n      \"description\": \"List visible things.\",\n      \"scope\": \"read\",\n      \"params\": [\n        { \"name\": \"kind\", \"type\": \"string\", \"required\": false }\n      ]\n    }\n  ]\n}\n```\n\nUse:\n\n- `--category upstream-client` for a lean local adapter around an existing API.\n- `--category application-platform` for API + CLI + MCP + web defaults.\n- `--no-cargo-check` only when you need fast static verification while iterating.\n\nSee [docs/SCAFFOLD.md](docs/SCAFFOLD.md), [docs/CARGO_GENERATE.md](docs/CARGO_GENERATE.md),\nand [docs/contracts/scaffold-intent.schema.json](docs/contracts/scaffold-intent.schema.json)\nfor the full scaffold contract.\n\n## Architecture\n\nThe runtime keeps product behavior behind the provider registry. Every external\nsurface is a thin parser/formatter around the same provider snapshot and service\nruntime, so dropping a provider does not require hand-editing MCP, CLI, REST,\nOpenAPI, plugin, or docs code.\n\n```text\nProviderRegistry\n  crates/soma/application/src/provider_registry.rs\n  Validates provider manifests, computes snapshots/fingerprints, indexes tools,\n  prompts, resources, CLI commands, REST routes, and MCP primitives.\n\nProvider sources\n  crates/soma/application/src/providers/\n  Static Rust, file-backed JSON manifests, TypeScript AI SDK sidecars, Python\n  LangChain/LlamaIndex sidecars, WASM, OpenAPI-backed providers, and upstream\n  MCP providers.\n\nSomaService\n  crates/soma/application/src/service.rs\n  Built-in product/service logic used by the static Rust provider.\n\nTransport shims\n  crates/soma/cli/src/lib.rs        CLI parser and output formatting.\n  crates/soma/mcp/src/tools.rs      MCP JSON args to service calls.\n  crates/soma/api/src/api.rs        REST extractors to service calls.\n  apps/soma/src/http.rs             Axum router, auth, MCP, API, web fallback.\n\nBuilt-in action metadata\n  crates/soma/domain/src/actions.rs\n  Native action metadata, validation, cached catalog/help, and native dispatch.\n```\n\nThe thin-shim rule is strict:\n\n1. Parse input at the surface.\n2. Call the provider registry or service runtime.\n3. Return or print the result.\n\nDo not put business rules in CLI, MCP, REST handlers, or the binary entrypoint\n(`apps/soma/src/bin/soma.rs` / `apps/soma/src/bootstrap.rs`).\n\n## Runtime Surfaces\n\nThe canonical binary can run the whole app from one executable:\n\n```bash\nsoma serve       # HTTP server: REST API + Streamable HTTP MCP + web fallback\nsoma mcp         # stdio MCP transport\nsoma status      # CLI command through the same binary\n```\n\nLocal adapter mode is optimized for plugin/local use:\n\n```bash\nsoma mcp                # stdio MCP transport\nsoma greet --name Alice # CLI command\nsoma doctor             # operator pre-flight checks\nsoma watch              # poll /health and emit state changes\nsoma setup check        # plugin/appdata setup checks\n```\n\nEvery explicit runtime mode loads the provider registry. File providers default\nto `./providers` and can be moved with `SOMA_PROVIDER_DIR`. CLI startup, MCP\ndispatch, and dynamic REST routes refresh file providers before execution, then\nenforce the active provider snapshot's schema, surface, scope, capability,\ndestructive-action, and response-limit rules.\n\nHTTP routes in the server profile:\n\n| Route | Purpose |\n|---|---|\n| `/mcp` | Streamable HTTP MCP transport. |\n| `/health` | Unauthenticated liveness. |\n| `/readyz` | Readiness check. |\n| `/status` | Public redacted runtime status. |\n| `/openapi.json` | Generated REST OpenAPI schema. |\n| `/metrics` | Prometheus metrics when built with `observability`. |\n| `/v1/capabilities` | REST route inventory. |\n| `/v1/greet`, `/v1/echo`, `/v1/status`, `/v1/help` | Direct REST business routes. |\n| `/v1/tools/{action}` | Generic REST execution route for dropped provider tools. |\n| `/v1/{provider-route}` | Optional provider-declared REST route when a tool supplies a custom REST overlay. |\n| `/mcp/.well-known/*` | OAuth metadata when OAuth is enabled. |\n| `/*` | Embedded web UI fallback when built with `web`. |\n\nREST is direct-route-only: there is no `/v1/soma` action envelope. MCP remains one `soma` tool with an `action` argument.\n\n## MCP Tool Reference\n\nThe runtime exposes one compact MCP tool, `soma`, with an `action` argument.\nBuilt-in actions and dropped provider tools share that same dispatch path. This\nkeeps MCP discovery small while allowing the provider catalog to grow behind the\nsingle tool.\n\n<!-- BEGIN GENERATED README_ACTION_TABLE -->\n<!-- Generated by scripts/generate-docs.py; do not edit by hand. -->\n| Action | Scope | Cost | Transport | REST route | CLI | Parameters | Description |\n|---|---|---|---|---|---|---|---|\n| `greet` | `soma:read` | `cheap` | MCP + CLI + REST | `POST /v1/greet` | `soma greet [--name NAME]` | `name` (optional string) | Return a greeting. |\n| `echo` | `soma:read` | `cheap` | MCP + CLI + REST | `POST /v1/echo` | `soma echo --message MSG` | `message` (required string) | Echo a message back unchanged. |\n| `status` | `soma:read` | `cheap` | MCP + CLI + REST | `GET /v1/status` | `soma status` | none | Return server status and configuration info. |\n| `python_environment_status` | `soma:write` | `cheap` | MCP + CLI + REST | `GET /v1/python/environments` | `soma python_environment_status` | none | Inspect immutable Python environment cache state without executing provider code. |\n| `python_environment_prune_plan` | `soma:write` | `moderate` | MCP + CLI + REST | `POST /v1/python/environments/prune-plan` | `soma python_environment_prune_plan --json '{\\` | `stale_before_unix_seconds` (required integer), `max_entries` (optional integer) | Plan a bounded prune of stale non-ready Python environment cache entries. |\n| `python_environment_prune` | `soma:write` | `write` | MCP + CLI + REST | `POST /v1/python/environments/prune` | `soma python_environment_prune --json '{\\` | `stale_before_unix_seconds` (required integer), `max_entries` (optional integer), `confirm` (required boolean) | Apply a bounded prune of stale non-ready Python environment cache entries. |\n| `python_environment_repair` | `soma:write` | `write` | MCP + CLI + REST | `POST /v1/python/environments/repair` | `soma python_environment_repair --json '{\\` | `provider_path` (required string), `confirm` (required boolean) | Repair the immutable environment for one managed Python provider. |\n| `python_environment_update` | `soma:write` | `write` | MCP + CLI + REST | `POST /v1/python/environments/update` | `soma python_environment_update --json '{\\` | `provider_path` (required string), `confirm` (required boolean) | Resolve, prepare, validate, and atomically activate an immutable update for one managed Python provider. |\n| `python_worker_status` | `soma:write` | `cheap` | MCP + CLI + REST | `GET /v1/python/workers` | `soma python_worker_status` | none | Inspect persistent Python worker health, quarantine, restart counts, and bounded redacted logs. |\n| `python_worker_cancel` | `soma:write` | `write` | MCP + CLI + REST | `POST /v1/python/workers/cancel` | `soma python_worker_cancel --json '{\\` | `provider` (required string), `confirm` (required boolean) | Cancel one active persistent Python invocation by terminating its process tree. |\n| `python_worker_reset` | `soma:write` | `write` | MCP + CLI + REST | `POST /v1/python/workers/reset` | `soma python_worker_reset --json '{\\` | `provider` (required string), `confirm` (required boolean) | Clear one persistent Python worker crash-loop quarantine. |\n| `python_generation_status` | `soma:read` | `cheap` | MCP + CLI + REST | `GET /v1/python/generations` | `soma python_generation_status` | none | Inspect the active Python provider generation and bounded rollback history. |\n| `python_generation_rollback` | `soma:write` | `write` | MCP + CLI + REST | `POST /v1/python/generations/rollback` | `soma python_generation_rollback --json '{\\` | `generation_id` (required integer), `confirm` (required boolean) | Atomically reactivate a retained Python provider generation. |\n| `python_graduation_status` | `soma:read` | `cheap` | MCP + CLI + REST | `POST /v1/python/graduation/status` | `soma python_graduation_status --json '{\\` | `workspace` (required string) | Inspect digest-bound Python graduation, conformance, activation, and rollback state. |\n| `python_graduation_apply` | `soma:write` | `write` | MCP + CLI + REST | `POST /v1/python/graduation/apply` | `soma python_graduation_apply --json '{\\` | `operation` (required string), `workspace` (required string), `source` (optional string), `component` (optional string), `fixtures` (optional string), `wheelhouse` (optional string), `confirm` (required boolean) | Scaffold, componentize, build, verify, compare, activate, or roll back a Python graduation workspace. |\n| `elicit_name` | `soma:read` | `cheap` | MCP-only | - | `_MCP-only_` | none | Ask the MCP client to collect a name, then return a personalised greeting. |\n| `scaffold_intent` | `soma:read` | `moderate` | MCP-only | - | `_MCP-only_` | none | Collect scaffold setup intent through MCP elicitation and return JSON for the scaffold-project skill. |\n| `help` | public | `cheap` | MCP + CLI + REST | `GET /v1/help` | `soma help` | none | Show the action reference. |\n<!-- END GENERATED README_ACTION_TABLE -->\n\nPython provider lifecycle administration is exposed through the same compact\ntool with these explicit actions:\n\n- environment cache: `python_environment_status`,\n  `python_environment_prune_plan`, `python_environment_prune`,\n  `python_environment_repair`, and `python_environment_update`;\n- persistent workers: `python_worker_status`, `python_worker_cancel`, and\n  `python_worker_reset`;\n- provider generations: `python_generation_status` and\n  `python_generation_rollback`;\n- Python-to-component graduation: `python_graduation_status` and confirmed\n  `python_graduation_apply`.\n\nBuilt-in business actions keep MCP + CLI + REST parity unless there is a\nprotocol reason they cannot. `elicit_name` and `scaffold_intent` are MCP-only\nbecause they rely on MCP elicitation. `serve`, `mcp`, `doctor`, `watch`, `setup`,\nand `package` are CLI operator commands, not business actions.\n\nDropped provider tools are MCP-enabled by default and REST-executable through\n`POST /v1/tools/{action}` unless the tool explicitly sets\n`rest.enabled=false`. A `rest` overlay can add a custom route, method, and\nOpenAPI metadata; the generic route remains the web/adapter-safe execution\nshape. CLI exposure is opt-in through each tool's `cli` overlay. Provider\nprompts, resources, tasks, and elicitation forms are part of the provider\nmanifest contract and registry index; they are not mirrored to CLI or REST by\ndefault.\n\n## CLI Reference\n\nThe `soma` binary exposes operator commands and provider-backed actions through\nthe same registry snapshot used by MCP:\n\n```bash\nsoma greet --name Alice\nsoma echo --message hello\nsoma status\nsoma help\nsoma providers validate\nsoma providers inspect\nsoma providers test status\nsoma providers list --dir ./examples/providers\nsoma providers lint --dir ./examples/providers\nsoma providers status --dir ./examples/providers\nsoma doctor\nsoma setup check\nsoma package generate --check\n```\n\nProvider tools opt in to CLI exposure with a `cli` overlay. Dynamic CLI flags\nare derived from the provider input schema, so the generated provider catalogs\nremain the source of truth for current action shapes.\n\n## Safety And Trust Model\n\nMCP callers never provide API keys, OAuth secrets, bearer tokens, passwords, or\nother credentials in tool arguments. Credentials live in environment variables,\nconfig files, appdata, or the upstream provider runtime.\n\nProvider manifests are validated before dispatch. The registry enforces surface\nopt-ins, JSON Schema input validation, auth scope, declared host capabilities,\ndestructive-action confirmation, response-size limits, and structured provider\nerrors. Python, LangChain, LlamaIndex, and TypeScript provider files are trusted\nlocal code; WASM providers run through the sandboxed WASM provider path; OpenAPI\nand MCP providers delegate trust to their configured upstream service.\n\n## Authentication\n\nThe HTTP server supports four auth policies:\n\n| Policy | When | Effect |\n|---|---|---|\n| Loopback development | Loopback bind, or `SOMA_MCP_NO_AUTH=true` on loopback | No auth middleware, no scope checks. |\n| Bearer token | `SOMA_MCP_TOKEN` set | `/mcp` and `/v1/*` require `Authorization: Bearer <token>`. |\n| OAuth | `SOMA_MCP_AUTH_MODE=oauth` with at least one configured provider | Browser-based Google, Authelia, or GitHub login issues JWT bearer tokens. |\n| Trusted gateway | `SOMA_NOAUTH=true` on non-loopback | Local auth and scope checks disabled because an upstream gateway is responsible. |\n\nThe startup guard refuses non-loopback unauthenticated binds unless bearer,\nOAuth, or trusted-gateway mode is configured. `/health`, `/readyz`, `/status`,\nand `/openapi.json` are public by design and return only safe runtime metadata.\n\nSee [docs/AUTH.md](docs/AUTH.md) for the detailed auth model.\n\n## Configuration\n\nValues load from `config.toml`, local appdata files, and environment variables;\nexplicit environment variables win. The built-in offline provider works without\nreal credentials, but generated projects should mark their real\nupstream/platform credentials as required.\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `SOMA_API_URL` | no | empty | Deployed platform API or upstream service URL. Empty selects stub/offline behavior. |\n| `SOMA_API_KEY` | no | empty | Bearer token or upstream service API key. |\n| `SOMA_PROVIDER_DIR` | no | `providers` | Directory scanned for drop-in provider files. Relative paths resolve from the current working directory. |\n| `SOMA_MCP_HOST` | no | `127.0.0.1` | HTTP server bind host. |\n| `SOMA_MCP_PORT` | no | `40060` | HTTP server bind port. |\n| `SOMA_MCP_SERVER_NAME` | no | `soma` | MCP server name advertised to clients. |\n| `SOMA_MCP_NO_AUTH` | no | `false` | Disable auth for loopback development. |\n| `SOMA_NOAUTH` | no | `false` | Trusted-gateway non-loopback no-auth mode. |\n| `SOMA_MCP_TOKEN` | bearer | empty | Static bearer token. |\n| `SOMA_MCP_ALLOWED_HOSTS` | no | empty | Extra comma-separated Host header values. |\n| `SOMA_MCP_ALLOWED_ORIGINS` | no | empty | Extra comma-separated CORS origins. |\n| `SOMA_MCP_TRACE_HEADERS` | no | `off` | Trusted inbound HTTP trace extraction: `off`, `trusted`, or `trusted-with-baggage`. |\n| `SOMA_MCP_AUTH_MODE` | no | `bearer` | `bearer` or `oauth`. |\n| `SOMA_MCP_PUBLIC_URL` | OAuth | empty | Public URL for OAuth metadata and callbacks. |\n| `SOMA_MCP_GOOGLE_CLIENT_ID` | OAuth | empty | Google OAuth client ID. |\n| `SOMA_MCP_GOOGLE_CLIENT_SECRET` | OAuth | empty | Google OAuth client secret. |\n| `SOMA_MCP_AUTHELIA_ISSUER_URL` | Authelia | empty | HTTPS Authelia OIDC issuer URL. |\n| `SOMA_MCP_AUTHELIA_CLIENT_ID` | Authelia | empty | Authelia OIDC client ID. |\n| `SOMA_MCP_AUTHELIA_CLIENT_SECRET` | Authelia | empty | Authelia OIDC client secret. |\n| `SOMA_MCP_GITHUB_CLIENT_ID` | GitHub | empty | GitHub OAuth App client ID. |\n| `SOMA_MCP_GITHUB_CLIENT_SECRET` | GitHub | empty | GitHub OAuth App client secret. |\n| `SOMA_MCP_AUTH_DEFAULT_PROVIDER` | no | first configured | Provider used when a request omits `provider`; automatic priority is Google, Authelia, GitHub. |\n| `SOMA_MCP_AUTH_ADMIN_EMAIL` | OAuth | empty | Initial/admin OAuth email. |\n| `RUST_LOG` | no | `info` | Log filter. Stdio mode suppresses noisy logs to avoid corrupting JSON-RPC. |\n\nKeep `SOMA_MCP_TRACE_HEADERS=off` unless the server is bound to loopback or a\ntrusted gateway strips or overwrites trace headers from untrusted clients.\nBearer/OAuth authentication alone is not that trust boundary. See\n[docs/TRACE_CONTEXT.md](docs/TRACE_CONTEXT.md) for the complete inbound-only\ntrace-header contract.\n\nSamples:\n\n- [.env.example](.env.example) for secrets, URLs, and runtime env.\n- [config.soma.toml](config.soma.toml) for non-secret defaults.\n\nProvider callback paths default to `/auth/google/callback`,\n`/auth/authelia/callback`, and `/auth/github/callback`; callback and scope\noverrides are listed in [docs/ENV.md](docs/ENV.md). GitHub OAuth Apps do not\nprovide an upstream refresh token, so GitHub-authenticated sessions do not\nreceive a local refresh token and must sign in again after their access token\nexpires. See [docs/AUTH.md](docs/AUTH.md) for provider selection and security\ndetails.\n\n## Development\n\n```bash\n# Build profiles\ncargo build --bin soma --no-default-features --features local-adapter\ncargo build --bin soma --no-default-features --features server\ncargo build --bin soma --features full\n\n# Run checks\ncargo fmt -- --check\ncargo clippy --all-targets -- -D warnings\ncargo nextest run\ncargo xtask contract-audit\ncargo xtask generate-provider-surfaces --check\n\n# Common just recipes\njust dev                 # loopback HTTP server with local no-auth\njust mcp                 # stdio MCP\njust greet               # CLI smoke test\njust doctor              # pre-flight check\njust build-local         # local adapter binary\njust build-full          # web assets + full platform binary\njust verify              # fmt, lint, check, test\njust check-docs          # generated docs/metadata current\njust scaffold-contract-check\njust validate-plugin\n```\n\n`cargo xtask ci` runs the main local CI sequence. Optional tools such as\n`cargo-nextest`, `taplo`, and `cargo-audit` are used when installed.\n\n### Workspace layout\n\n41 cargo members:\n\n| Path | Contents |\n|---|---|\n| `crates/soma/*` | Product code for this server — domain, application, config, client, api, cli, mcp, runtime, integrations, palette, web, test-support |\n| `crates/shared/*` | Reusable engine crates other servers consume — auth, mcp (client/server/proxy/gateway), provider-core, provider-adapters, http-api, http-server, observability, openapi, self-update, traces, codemode, cli-core, and namespaced reusable families such as `cortex/ingest-core` |\n| `crates/integrations/*` | Upstream service bridges — `gotify`, `unifi` |\n| `apps/soma` | The `soma` binary and its integration tests. **The only cargo member under `apps/`** — `apps/web` (Next.js) and `apps/palette` (assets) are not Rust crates. |\n| `packages/python` | pyo3 Python provider platform (`abi3-py311`) |\n| `xtask` | All repository automation; `scripts/*.py` are thin wrappers over it |\n\n`rmcp` is pinned exactly — `rmcp = { version = \"=3.1.0\", default-features = false }`\nin `[workspace.dependencies]`, duplicated on the `rmcp-client` alias entry\nbecause TOML cannot cross-reference. Bump both together.\n\n`[workspace.package]` is the source of truth for Rust edition and MSRV: new\nmembers inherit `edition = \"2024\"` and `rust-version = \"1.97.1\"` with\n`edition.workspace = true` and `rust-version.workspace = true`. Shared crates\nalso inherit workspace lints so architecture and module-layout policy stays\nconsistent across the fleet.\n\n## Client Configuration\n\nStreamable HTTP:\n\n```json\n{\n  \"mcpServers\": {\n    \"soma\": {\n      \"url\": \"http://localhost:40060/mcp\",\n      \"headers\": {\n        \"Authorization\": \"Bearer YOUR_TOKEN\"\n      }\n    }\n  }\n}\n```\n\nStdio:\n\n```json\n{\n  \"mcpServers\": {\n    \"soma\": {\n      \"command\": \"/path/to/soma\",\n      \"args\": [\"mcp\"],\n      \"env\": {\n        \"SOMA_API_URL\": \"https://api.example.com\",\n        \"SOMA_API_KEY\": \"YOUR_API_KEY\",\n        \"RUST_LOG\": \"warn\"\n      }\n    }\n  }\n}\n```\n\nFor generated projects, replace `soma`, `SOMA_*`, tool names, scopes,\nand paths with the generated service names.\n\n## Plugin Surfaces\n\nThe repo ships one shared Soma plugin package under [plugins/soma](plugins/soma)\nfor Claude Code, Codex, and Gemini surfaces. Plugin manifests are versionless;\nrelease tooling derives version identity from git state. The plugin package can\nuse the local stdio adapter and includes setup/doctor support for appdata and\nenvironment files.\n\nPrimary docs:\n\n- [docs/PLUGINS.md](docs/PLUGINS.md)\n- [plugins/soma/.codex-plugin/README.md](plugins/soma/.codex-plugin/README.md)\n- [plugins/soma/skills/soma/SKILL.md](plugins/soma/skills/soma/SKILL.md)\n- [plugins/soma/skills/scaffold-project/SKILL.md](plugins/soma/skills/scaffold-project/SKILL.md)\n\n## Distribution Contract\n\nThe `soma` release component is defined in\n[release/components.toml](release/components.toml). Version-bearing artifacts\nmust stay aligned across the Rust package, `Cargo.lock`, `server.json`, the npm\npackage, generated OpenAPI metadata, OCI image identifiers, and the changelog.\n\nPlugin manifests stay versionless. Marketplace and plugin release identity is\nderived from git/package metadata, while `server.json` and generated provider\nsurface docs describe the currently shipped runtime surface. Run\n`cargo xtask check-version-sync`, `cargo xtask generate-provider-surfaces --check`,\nand `cargo xtask check-docs` before publishing release metadata.\n\n## Web UI\n\nThe `web` feature serves the static export bundled by `soma-web`. Editable\nfrontend source lives in [apps/web](apps/web), and `cargo xtask sync-web-source`\ncopies that source into the Rust crate bundle.\n\nUseful commands:\n\n```bash\ncargo xtask build-web\ncargo xtask sync-web-source\ncargo xtask check-web-source-sync\npnpm -C apps/web validate\n```\n\nGenerated projects that do not need a human UI should use `local-adapter`,\n`server`, or a custom feature set without `web`.\n\n## Deployment\n\nThe full platform profile is designed for one deployable `soma` binary. The repository\nalso includes Docker and Compose samples:\n\n- [config/Dockerfile](config/Dockerfile)\n- [docker-compose.prod.yml](docker-compose.prod.yml)\n- [entrypoint.sh](entrypoint.sh)\n\nWhen adapting a generated project, verify the canonical binary name, exposed\nport, healthcheck port, image labels, service user/group, data volume, and\nrequired environment variables. The scaffold verifier catches several\nscaffold-only artifacts, but deployment files still need service-specific review\nbefore publishing an image.\n\n## When Drop-In Providers Are Not Enough\n\nMost new capabilities should start as provider files. Reach for native Rust or a\nscaffolded product when you need a reusable crate boundary, richer service state,\ncustom clients, background jobs, a dedicated package identity, or hand-tuned\ntransport behavior.\n\nFor a generated product, start by printing the profile-aware checklist:\n\n```bash\ncargo xtask scaffold --adapt-plan ../generated/myservice-mcp\n```\n\nThen generate reviewable starter artifacts for the repetitive action wiring:\n\n```bash\ncargo xtask scaffold \\\n  --write-action-starters ../generated/myservice-mcp \\\n  --actions actions.json\n```\n\nThis writes `docs/action-starters/` in the generated project with snippets for\naction metadata, MCP dispatch, CLI variants, service stubs, and test coverage.\n\n1. Replace the stub client in `crates/soma/client/src/client.rs` only when the provider file path is not enough.\n2. Put domain logic in `crates/soma/application/src/service.rs` or focused service modules.\n3. Register native provider/action metadata so MCP, CLI, REST, docs, and plugins stay registry-driven.\n4. Regenerate MCP schema docs, provider surface docs, and OpenAPI so generated surfaces reflect the provider registry.\n5. Add REST handlers only for infrastructure routes; business actions should stay registry-backed direct routes.\n6. Update config fields and env prefixes in `crates/soma/config/src/config.rs`.\n7. Update `.env.example`, `config.soma.toml`, plugin options, and setup mappings.\n8. Update `server.json`, plugin metadata, repository URLs, Docker labels, and release metadata.\n9. Add tests for MCP dispatch, CLI parsing, REST routes, provider loading, and service behavior.\n10. For generated/exported projects, run scaffold verification plus the\n    project's local quality gates.\n\nFor public repositories, also review tracked docs, generated metadata, CI runner\nconfiguration, and secret-scanning allowlists before publishing.\n\n## Troubleshooting\n\n- `soma doctor` checks local configuration, appdata, and connectivity.\n- `soma providers validate` confirms provider manifests and compiled schemas\n  against the *loaded, live* registry.\n- `soma providers inspect` shows provider surfaces, capability posture, and\n  generated action inventory.\n- `soma providers list|lint|status` inspect drop-in provider files on disk\n  without loading the registry or executing any handler — safe to run before\n  the runtime touches TS/WASM/MCP/OpenAPI providers. See\n  [`docs/PROVIDERS.md`](docs/PROVIDERS.md).\n- Stdio mode keeps logs quiet so JSON-RPC is not corrupted; use HTTP mode or\n  file logs when investigating noisy startup failures.\n- If generated docs drift, run `cargo xtask generate-provider-surfaces --write`\n  and then re-run the `--check` command.\n\n## Related Servers\n\n- [runifi](https://github.com/dinglebear-ai/runifi) - UniFi controller REST API bridge.\n- [rtailscale](https://github.com/dinglebear-ai/rtailscale) - Tailscale API bridge for devices, users, and tailnet operations.\n- [unraid](https://github.com/dinglebear-ai/unraid) - Unraid monorepo: Python and Rust GraphQL MCP servers plus Unraid plugins.\n- [rapprise](https://github.com/dinglebear-ai/rapprise) - Apprise notification fan-out bridge for many delivery backends.\n- [rgotify](https://github.com/dinglebear-ai/rgotify) - Gotify push notification bridge for sends, messages, apps, and clients.\n- [rarcane](https://github.com/dinglebear-ai/rarcane) - Arcane Docker management bridge for containers and related resources.\n- [yarr](https://github.com/dinglebear-ai/yarr) - Media-stack bridge for Sonarr, Radarr, Prowlarr, Plex, and related services.\n- [rytdl](https://github.com/dinglebear-ai/rytdl) - Media download and metadata workflow server.\n- [synapse](https://github.com/dinglebear-ai/synapse) - Local Synapse workflow server for scout and flux actions.\n- [cortex](https://github.com/dinglebear-ai/cortex) - Syslog and homelab log aggregation MCP server.\n- [axon](https://github.com/dinglebear-ai/axon) - RAG, crawl, scrape, extract, and semantic search project.\n- [labby](https://github.com/dinglebear-ai/labby) - Homelab control plane and MCP gateway project.\n- [lumen](https://github.com/jmagar/lumen) - Local semantic code search MCP server.\n\n## Documentation\n\n| Topic | Docs |\n|---|---|\n| Architecture and layering | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), [docs/PATTERNS.md](docs/PATTERNS.md) |\n| Cortex shared-crate extraction | [docs/cortex-extraction/README.md](docs/cortex-extraction/README.md), [ADR 0014](docs/adr/0014-extract-cortex-as-reusable-shared-crates.md) |\n| Dynamic provider runtime | [docs/specs/dynamic-provider-runtime.md](docs/specs/dynamic-provider-runtime.md), [docs/generated/provider-surfaces.md](docs/generated/provider-surfaces.md) |\n| Provider manifest contract | [docs/contracts/provider-manifest.schema.json](docs/contracts/provider-manifest.schema.json), [docs/contracts/examples/provider-manifests](docs/contracts/examples/provider-manifests) |\n| Scaffold workflow | [docs/SCAFFOLD.md](docs/SCAFFOLD.md), [docs/CARGO_GENERATE.md](docs/CARGO_GENERATE.md) |\n| Scaffold intent contract | [docs/specs/scaffold-intent-handoff.md](docs/specs/scaffold-intent-handoff.md), [docs/contracts/scaffold-intent.schema.json](docs/contracts/scaffold-intent.schema.json) |\n| MCP action schema | [docs/MCP_SCHEMA.md](docs/MCP_SCHEMA.md) |\n| REST OpenAPI | [docs/generated/openapi.json](docs/generated/openapi.json) |\n| Auth | [docs/AUTH.md](docs/AUTH.md) |\n| Plugins | [docs/PLUGINS.md](docs/PLUGINS.md) |\n| Release/versioning | [release/components.toml](release/components.toml), [docs/MCP-REGISTRY-PUBLISH-GUIDE.md](docs/MCP-REGISTRY-PUBLISH-GUIDE.md) |\n| Automation | [xtask/README.md](xtask/README.md), [scripts/README.md](scripts/README.md) |\n| Tests | [apps/soma/tests/README.md](apps/soma/tests/README.md) |\n\n## Verification\n\nProduct runtime gates:\n\n```bash\ncargo xtask check-docs\ncargo xtask generate-provider-surfaces --check\ncargo xtask check-schema-docs --check\ncargo xtask check-openapi --check\ncargo xtask validate-plugin-layout\ncargo xtask check-version-sync\njust verify\n```\n\nScaffold/template gates are a separate lane. Run them when a change touches the\nscaffold contract, cargo-generate post-processing, or generated-project output:\n\n```bash\ncargo xtask check-scaffold-intent-contract\ncargo xtask scaffold --verify ../generated/myservice-mcp\ncargo xtask check-cargo-generate\n```\n\nUse targeted checks while iterating, then run the broader product and affected\nscaffold gates before release.\n\n## License\n\nOriginal Dinglebear-authored portions of this project are licensed under [AGPL-3.0-only](LICENSE). Separate commercial licensing is available for organizations that need terms outside the AGPL. Third-party material remains under its original license. See [LICENSING.md](https://github.com/dinglebear-ai/soma/blob/main/LICENSING.md).\n",
  "bytes": 43019,
  "sha": "5639cc3bc79e4e29e5e87865bdebf3fed9cbbd5659196d64c82da598e83e93e7",
  "repo_slug": "dinglebear-ai/soma",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_ai_dinglebear_soma_98fdaf71/readme"
}