Metadata-Version: 2.4
Name: gcontext-mcp
Version: 0.2.0
Summary: gcontext connector — local MCP bridge: cloud structure, local secret values
Project-URL: Homepage, https://gcontext.ai
License-Expression: MIT
Requires-Python: >=3.11
Requires-Dist: keyring>=25
Requires-Dist: mcp<2,>=1
Requires-Dist: python-dotenv>=1
Description-Content-Type: text/markdown

# mcp-minimal

A single local Python MCP server for a workspace of **integrations** (third-party
services the AI can use: docs, dependencies, secret names) and **tasks** (units of
work with goals, steps and progress). Both are typed folders in a virtual file tree,
backed by a secret-name registry and on-the-fly Python script execution with the
local `.env` injected. Secret VALUES never leave this machine and never enter the
database.

> **Self-hosting?** See [SELF_HOSTING.md](./SELF_HOSTING.md): one `docker compose up`, plus how to pull future updates.

## Setup

```bash
cd apps/mcp-minimal
cp .env.example .env   # fill in your secret values
```

Get a token first by running `uvx gcontext-mcp login` (browser sign-in at
https://app.gcontext.ai mints it).

### Add to Claude Code

Published connector (hosted cloud):

```bash
claude mcp add-json gcontext '{
  "type": "stdio",
  "command": "uvx",
  "args": ["gcontext-mcp"],
  "env": { "GCONTEXT_TOKEN": "<your token>" }
}'
```

Pure-local (no cloud, own SQLite):

```bash
claude mcp add mcp-minimal -- uv run --directory /ABS/PATH/TO/apps/mcp-minimal python server.py
```

### Add to Claude Desktop

The CLI commands above only work in Claude Code. For the Desktop app, edit the
config file directly (Settings → Developer → Edit Config, or open it from):

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

Add your server under `mcpServers`, then fully quit and reopen Claude Desktop.

Published connector (hosted cloud):

```json
{
  "mcpServers": {
    "gcontext": {
      "command": "uvx",
      "args": ["gcontext-mcp"],
      "env": { "GCONTEXT_TOKEN": "<your token>" }
    }
  }
}
```

Pure-local (no cloud, own SQLite):

```json
{
  "mcpServers": {
    "mcp-minimal": {
      "command": "uv",
      "args": ["run", "--directory", "/ABS/PATH/TO/apps/mcp-minimal", "python", "server.py"]
    }
  }
}
```

Note: Desktop has no slash-command prompts (`/use-integration`, etc.) — you drive
the same tools by plain chat. Both modes need `uv`/`uvx` on your PATH.

## Tools

- `tool_list_dir(path="/")`, `tool_read_file(path)`, `tool_write_file(path, content)`,
  `tool_delete(path)` — `tool_write_file` auto-creates missing parent folders
- `tool_secrets()`, `tool_register_secret(name, description)`, `tool_unregister_secret(name)`,
  `tool_setup_secrets(form=True)`
- `tool_run_script(code)` - runs `uv run --env-file .env python -c "<code>"`

## The secret registry

The registry holds secret NAMES + descriptions only — it is for **setup and
verification**, not runtime. It does NOT gate `tool_run_script`, which injects the
whole `.env` regardless of what's registered.

1. `tool_register_secret(name, description)` - declare a required secret.
2. `tool_setup_secrets(form=False)` - append blank `NAME=` lines to `.env` for any registered
   secret not yet present, so the user just fills in the values (`form=True` opens a browser form).
3. `tool_secrets()` - shows `present` per name so you can confirm setup.

## How it works

1. Write a file describing a 3rd-party operation and which secret NAMES it needs;
   declare those names with `tool_register_secret`.
2. To act, read the file, generate Python, and call `tool_run_script`.
3. Secret values resolve from the local `.env` at run time - never stored in the DB.

## Security / trust model

`tool_run_script` runs **arbitrary Python locally with your real `.env` injected** —
there is no sandbox. It is exactly as trusted as whatever drives the server. Run it
on your own machine only; never expose this server remotely.

## Script contract

- Read secrets via `os.environ["VAR"]` - never hardcode, never `load_dotenv`.
- Use only registered names that show `present_locally: true`.
- Exit codes: `0` OK, `2` missing secret (`KeyError`), `1` any other failure.

## Config (env vars)

- `MCP_MINIMAL_DB` - SQLite path (default `db.sqlite` next to `server.py`).
- `MCP_MINIMAL_ENV_FILE` - secret-values file (default `.env` next to `server.py`).
