YouGile Secure MCP
# YouGile Secure MCP
A local stdio [Model Context Protocol](https://modelcontextprotocol.io/) server for the [YouGile](https://yougile.com) API v2. Read-only by default; writes require an explicit, single-use approval issued after the user confirms the exact payload in chat.
## Tools (v0.2.0)
### Read-only
| Tool | Purpose |
| --- | --- |
| `get_current_user` | Profile that owns the API key |
| `list_projects`, `get_project` | Projects |
| `list_boards`, `get_board` | Boards |
| `list_columns` | Columns |
| `list_tasks` | Compact task summaries with server-side filters (column, assignee, title, sticker) |
| `get_task` | Full task object by UUID |
| `find_task_by_short_id` | Look up a task by human-readable ID such as `ID-484` / `DEV-484` |
| `list_task_comments` | Task chat messages |
| `list_users` | Company users (filter by project or email) |
| `list_string_stickers` | Custom stickers and their states |
All list tools return `{"items": [...], "has_more": bool}`; `limit` is capped at 100, use `offset` for the next page.
### Staged writes (explicit approval required)
| Tool | Purpose |
| --- | --- |
| `propose_task_create` | Stage a new task, returns a preview + single-use approval token |
| `propose_task_update` | Stage changes to an existing task, same contract |
| `apply_approved_action` | Execute a staged action; the only tool that can mutate YouGile |
The flow is: agent stages an action → shows the preview to the user → the user approves in chat → agent calls `apply_approved_action` with the token. Tokens are bound to the exact payload, single-use, and expire after `YOUGILE_APPROVAL_TTL_SECONDS` (default 600). **Delete operations are not implemented at all.**
### Security model
- Uses only `YOUGILE_API_KEY`; never accepts, stores, or sends an account login/password.
- Never creates, lists, or deletes YouGile API keys, webhooks, or users.
- Never writes credentials to disk; API errors never include response bodies, so the key cannot leak through error messages.
- All object IDs interpolated into URL paths are validated as UUIDs (no path traversal).
- `YOUGILE_BASE_URL` must be `https` (plain `http` is allowed only for localhost).
- Handles the YouGile rate limit (50 requests/minute) with bounded retries on HTTP 429.
## Install
```bash
git clone https://github.com/ropuwz-dot/MCP-Yougile.git
cd MCP-Yougile
python3 -m venv .venv
.venv/bin/python -m pip install -e '.[dev]' # Linux/macOS
# .venv\Scripts\python -m pip install -e .[dev] # Windows
```
Run it with the API key in the environment:
```bash
export YOUGILE_API_KEY='your-api-key' # Windows: $env:YOUGILE_API_KEY='your-api-key'
.venv/bin/python run_server.py # Windows: .venv\Scripts\python run_server.py
```
## Configuration
| Variable | Default | Purpose |
| --- | --- | --- |
| `YOUGILE_API_KEY` | — (required) | YouGile API v2 key |
| `YOUGILE_BASE_URL` | `https://yougile.com` | Self-hosted deployments: the `mainPageUrl` from your `conf.json` |
| `YOUGILE_TIMEOUT_SECONDS` | `30` | HTTP timeout |
| `YOUGILE_APPROVAL_TTL_SECONDS` | `600` | Lifetime of a staged write approval |
| `YOUGILE_SSL_CA_CERT` | — | Path to a CA bundle for self-hosted servers with a self-signed certificate |
| `YOUGILE_ALLOW_INSECURE_HTTP` | `false` | Explicit opt-in for plain-http local self-hosted servers |
### Self-hosted (box) YouGile
The [self-hosted Linux Server edition](https://docs.yougile.com/docs/admin-guide-linux/api/) exposes the same API v2 on your own domain. Point `YOUGILE_BASE_URL` at the `mainPageUrl` value from your `conf.json`:
- **HTTPS with a self-signed certificate** — set `YOUGILE_SSL_CA_CERT` to the path of the certificate (or its CA) so TLS verification keeps working. Verification can never be turned off.
- **Plain HTTP on a trusted local network** — allowed by YouGile for local use, but here it requires `YOUGILE_ALLOW_INSECURE_HTTP=true` so the API key is never sent in clear text by accident. `http://localhost` works without the flag.
## Client configuration
### Claude Code
```bash
claude mcp add yougile -e YOUGILE_API_KEY=your-api-key -- /absolute/path/to/MCP-Yougile/.venv/bin/python /absolute/path/to/MCP-Yougile/run_server.py
```
### Claude Desktop (`claude_desktop_config.json`)
```json
{
"mcpServers": {
"yougile": {
"command": "/absolute/path/to/MCP-Yougile/.venv/bin/python",
"args": ["/absolute/path/to/MCP-Yougile/run_server.py"],
"env": { "YOUGILE_API_KEY": "your-api-key" }
}
}
}
```
### Hermes
Keep the secret in `~/.hermes/.env` with `0600` permissions:
```dotenv
YOUGILE_API_KEY=your-api-key
```
Then add this server under `mcp_servers` in `~/.hermes/config.yaml`:
```yaml
mcp_servers:
yougile:
command: /absolute/path/to/MCP-Yougile/.venv/bin/python
args: [/absolute/path/to/MCP-Yougile/run_server.py]
env:
YOUGILE_API_KEY: "${YOUGILE_API_KEY}"
timeout: 60
connect_timeout: 30
sampling:
enabled: false
```
Verify it before restarting Hermes: `hermes mcp test yougile`.
## Development
```bash
.venv/bin/python -m pytest -q
.venv/bin/python -m ruff check src tests
.venv/bin/python -m mypy
```
CI runs the same three checks on Python 3.11–3.13 for every push and pull request.
## License
[MIT](LICENSE)
TDQS
Scored across 15 tools
Each tool targets a distinct resource or action. Read tools (get_*, list_*) are separate from write tools (propose_*, apply_approved_action). The find_task_by_short_id is unique. No overlapping purposes.
All tool names use lower_snake_case and follow a verb_noun pattern. Verbs are consistently get_, list_, find_, propose_, apply_. No mixing of conventions.
15 tools is appropriate for a project management server. It covers listing and getting all major entities, plus a safe write pattern, without being excessive or too sparse.
Covers reading all entities and creating/updating tasks with a safe approval pattern. Missing delete for tasks and modifications for boards/columns/projects, but these are reasonable omissions given the secure nature.