otama
by Ronith2906
README.md
# otama
An [MCP](https://modelcontextprotocol.io) server that gives AI assistants — Cursor, Claude
Desktop, or your own voice agent — access to your local git repositories.
Read operations run freely. Anything that writes returns a confirmation token and a
plain-English summary first, and only acts when called a second time with that token. The
assistant asks before it commits.
```
You: commit my changes in api-service with message "fix auth timeout"
LLM: Commit 3 changed files in api-service with message 'fix auth timeout'. Confirm?
You: yes
LLM: Committed — a4f21c9 fix auth timeout
```
## Why
Most filesystem MCP servers give a model unrestricted read and write access to a directory
tree. That is fine when you are watching every tool call. It is not fine when the model is
driving a voice assistant, running unattended, or has just misheard you.
`otama` assumes the model will occasionally be wrong and makes the consequences small:
- **A path sandbox.** Every path is resolved *before* it is checked against your configured
roots. `..`, symlinks and absolute paths cannot escape.
- **Two-phase confirmation.** Write and execute tools called without a token do nothing but
describe what they would do. Tokens are single-use, expire after two minutes, and are
bound to the tool that issued them.
- **A command allowlist.** `run_command` refuses anything outside the list outright rather
than offering it for confirmation. A mishearing should never be one "yes" away from
`rm -rf`.
## Install
Requires Python 3.11+ and git on PATH.
```bash
git clone https://github.com/Ronith2906/otama.git
cd otama
python -m venv .venv
.venv/bin/pip install -r requirements.txt # Windows: .venv\Scripts\pip.exe
cp otama.example.toml otama.toml
```
Edit `otama.toml` and set `project_roots` to the folder or folders containing your repos.
Use forward slashes on Windows.
```toml
[projects]
project_roots = ["C:/Users/you/code"]
```
Verify:
```bash
.venv/bin/python -c "import asyncio; from projects_server import otama; print([t.name for t in asyncio.run(otama.list_tools())])"
```
Ten tool names means you are running.
## Connect it
**Cursor** — `~/.cursor/mcp.json`. **Claude Desktop** — `claude_desktop_config.json`
(Settings → Developer → Edit Config). Same shape either way:
```json
{
"mcpServers": {
"otama-projects": {
"command": "/absolute/path/to/otama/.venv/bin/python",
"args": ["/absolute/path/to/otama/projects_server.py"]
}
}
}
```
On Windows use `\\` in JSON paths — `C:\\Users\\you\\otama\\.venv\\Scripts\\python.exe`.
Restart the app fully. A reload is not enough; MCP servers load at startup.
## Tools
**Read — run immediately**
| Tool | Returns |
|---|---|
| `list_projects` | Every repo or folder under your roots, with a `is_git_repo` flag |
| `project_tree` | Two-level tree, skipping `node_modules`, `.venv`, `dist` and friends |
| `read_file` | One text file, size-capped |
| `search_code` | Regex across a project, with file and line numbers |
| `git_status` | Branch, uncommitted files, last five commits |
| `git_diff` | Working-tree diff, truncated |
| `daily_brief` | What moved across every repo in the last N days |
**Write and execute — confirmation required**
| Tool | Does |
|---|---|
| `git_commit` | Stage all and commit |
| `write_file` | Create or overwrite a file |
| `run_command` | Run an allowlisted development command |
## Configuration
```toml
[projects]
project_roots = ["C:/Users/you/code"]
max_file_bytes = 200000 # refuse to read anything larger
command_timeout_seconds = 120
confirmation_ttl_seconds = 120 # how long a token stays valid
# run_command refuses anything not on this list. This is not something a
# confirmation can override — add what you actually use.
allowed_commands = ["git","npm","npx","pnpm","yarn","node",
"python","py","pip","pytest","ruff","uv",
"dotnet","cargo","go"]
```
## Notes for contributors
The two-phase pattern lives in `stage()`, `redeem()` and `_expire()`. If you add a tool with
side effects, use it.
One subtlety worth preserving: `redeem()` does **not** consume the token when the tool kind
does not match. A model calling the wrong tool by mistake must not burn the user's approval
and force them to confirm all over again. This was a real bug, caught in testing.
New capability servers should follow the same shape — one file, one domain, read tools free,
write tools gated, refuse rather than confirm when the action is outside the envelope.
## Status
Early. The projects server is tested and in daily use; more capability servers (media, mail,
browser) are planned as part of a larger voice-assistant project. Issues and PRs welcome.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues