Sanctum Letta MCP (SMCP)
Plugin-based Model Context Protocol server for Letta and MCP clients
Sanctum Letta MCP — SMCP — is the tool layer of SanctumOS. It discovers CLI plugins, exposes their commands as MCP tools, and speaks the protocol over SSE/HTTP (remote clients like Letta) or STDIO (local clients like Cursor).
Latest release: SMCP 3.1.0: The Tool Layer Ships — production merge on master, critical HTTP auth hardening, governor profiles, and structured tool errors. Repository: sanctumos/smcp · tag v3.1.0.
What SMCP does
- Plugin architecture — drop a plugin directory under
plugins/; its commands become MCP tools at startup. - Auto-discovery — preferred path is each plugin's
--describeJSON contract; help-text scraping is the fallback. - Session attach governor — expose a curated subset of tools per session via
sanctum__toolsand config-driven profiles (SMCP_PROFILES). - Two transports —
smcp.py(SSE/HTTP) andsmcp_stdio.py(STDIO). - Optional API-key auth on HTTP — fail-closed when binding externally (
--allow-externalrequiresMCP_API_KEYunless explicitly disabled).
Quick installation
Prerequisites
- Python 3.10+ (required by the
mcpdependency) - pip and a virtual environment
Install and run (SSE)
git clone https://github.com/sanctumos/smcp.git
cd smcp
git checkout master # production branch; v3.1.0+
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install .
# Localhost-only SSE server (default — no API key required)
smcp
# or: python smcp.py
git clone https://github.com/sanctumos/smcp.git cd smcp git checkout master # production branch; v3.1.0+ python3 -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install .
Localhost-only SSE server (default — no API key required)
smcp
or: python smcp.py
The server listens on http://127.0.0.1:8000 by default.
### STDIO transport (Cursor, local MCP)
bash
smcp-stdio
# or: python smcp_stdio.py
The server listens on http://127.0.0.1:8000 by default.
STDIO transport (Cursor, local MCP)
git clone https://github.com/sanctumos/smcp.git
cd smcp
git checkout master # production branch; v3.1.0+
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install .
# Localhost-only SSE server (default — no API key required)
smcp
# or: python smcp.py
smcp-stdio
or: python smcp_stdio.py
The server listens onhttp://127.0.0.1:8000by default. ### STDIO transport (Cursor, local MCP)bash smcp-stdio # or: python smcp_stdio.py
Verify
Connect your MCP client to http://127.0.0.1:8000/sse (Letta) or run STDIO per your IDE's MCP config. On startup you should see discovered plugins (bundled demo_math and demo_text in a fresh clone).
Security and external binding
Default is safe: bind to localhost only.
If you must listen on all interfaces:
git clone https://github.com/sanctumos/smcp.git
cd smcp
git checkout master # production branch; v3.1.0+
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install .
# Localhost-only SSE server (default — no API key required)
smcp
# or: python smcp.py
export MCP_API_KEY="$(openssl rand -hex 32)" smcp --allow-external --port 8000
The server listens on http://127.0.0.1:8000 by default.
### STDIO transport (Cursor, local MCP)
bash
smcp-stdio
# or: python smcp_stdio.py
Rules:
- --allow-external
withoutMCP_API_KEY→ process exits with code 2 (fail closed). - Clients must send Authorization: Bearer
or X-API-Key: . - Loopback clients skip auth by default; use --require-auth
to require keys locally too. - MCP_AUTH_DISABLED=1
is an explicit escape hatch (not recommended).
STDIO has no network auth surface.
Configuration
Environment variables (common)
| Variable | Default | Description |
|---|---|---|
MCP_PORT |
8000 |
HTTP port |
MCP_HOST |
127.0.0.1 |
Bind address |
MCP_PLUGINS_DIR |
plugins/ |
Plugin search path |
MCP_API_KEY |
— | Shared secret for HTTP/SSE auth |
MCP_API_KEYS |
— | Comma-separated keys (rotation) |
MCP_PLUGIN_TIMEOUT |
— | Subprocess timeout in seconds (0 = none) |
MCP_LOG_DIR |
logs/ |
Log directory (created at server start, not import) |
SMCP_PROFILES |
— | Governor profile JSON file or directory |
SMCP_ATTACH_PROFILE |
full |
Active attach profile name |
SMCP_ADMIN_PREFIX |
— | Optional admin profile tool prefix (e.g. tasks__) |
Full tables: upstream API reference.
Command-line flags
| Flag | Purpose |
|---|---|
--allow-external |
Bind 0.0.0.0 (requires API key) |
--require-auth |
Require API key even on loopback |
--host / --port |
Override bind |
--plugin-timeout |
Kill slow plugin subprocesses |
Directory layout
The server listens onhttp://127.0.0.1:8000by default. ### STDIO transport (Cursor, local MCP)bash smcp-stdio # or: python smcp_stdio.py
smcp/ ├── smcp.py # SSE/HTTP entrypoint ├── smcp_stdio.py # STDIO entrypoint ├── governor.py # Session attach governor ├── plugins/ │ ├── demo_math/ # Bundled demo plugin │ └── demo_text/ # Bundled demo plugin │ └── gmail/ # Example: clone smcp-gmail here └── docs/ # Operator + plugin author guides
The server listens on http://127.0.0.1:8000 by default.
### STDIO transport (Cursor, local MCP)
bash
smcp-stdio
# or: python smcp_stdio.py
Product plugins (Tasks, Gmail, GitHub, etc.) are separate repositories cloned into plugins/. See SMCP Plugins.
Session attach governor
SMCP separates catalog (everything discovered) from attachment (what this session may call).
- Configure profiles in JSON via SMCP_PROFILES
— example: governor-profiles.json. - Agents use sanctum__tools
(attach,detach,list-attached,help, …) to manage exposure at runtime. - Architecture write-up: SMCP Tool Governance blog post.
Plugin development
- Create plugins/your_plugin/cli.py
with argparse commands. - Implement --describe
returning JSON per docs/plugin-contract/v1.json. - Restart SMCP — valid plugins register; invalid describe payloads are skipped with a clear error.
Guide: Plugin Development.
Connecting Letta
Point your Letta MCP server URL at http://
Step-by-step: Letta MCP Connection Guide.
Branches
- master
— production-stable (3.1.0+). - dev
— day-to-day integration; merge to master` for releases.
Troubleshooting
| Symptom | Likely fix |
|---|---|
Exit code 2 on --allow-external |
Set MCP_API_KEY or drop --allow-external |
| 401 from client | Send Bearer / X-API-Key header |
| Plugin missing from catalog | Check --describe validates; read startup stderr |
| Tool timeout | Set MCP_PLUGIN_TIMEOUT or --plugin-timeout |
More: upstream troubleshooting and site troubleshooting guide.
License
- Code: AGPLv3
- Documentation: CC BY-SA 4.0
Sanctum Letta MCP — the MCP tool layer of SanctumOS.