Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
reviews:
auto_review:
enabled: false
189 changes: 183 additions & 6 deletions README.md

Large diffs are not rendered by default.

17 changes: 15 additions & 2 deletions docs/appcircle_access_token.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,23 @@ Then start the server as usual (e.g. `appcircle-mcp` or with your chosen transpo

---

## Renewing an Expired Token

Access tokens are valid for **about 24 hours** (see [Troubleshooting](#401-unauthorized-after-some-time)). Once a token expires, exchange your Personal Access Key or API key for a **new** access token, the same way you got the first one. The key/secret itself does not expire on this schedule: Personal Access Keys are valid for 1 year, and API Keys expire on their own configured expiry date (up to 1 year). You can repeat the exchange as many times as needed until the key itself expires.

1. **Get a new access token:**
- If you used a **Personal Access Key**, repeat [Step 2: Exchange the Key for an Access Token](#step-2-exchange-the-key-for-an-access-token) with the same key.
- If you used an **API Key**, repeat [Step 2: Retrieve an Access Token Using the API Key](#step-2-retrieve-an-access-token-using-the-api-key) with the same key name/secret.
2. **Copy the new `access_token`** from the response.
3. **Update `APPCIRCLE_ACCESS_TOKEN`** with the new value, in whichever place you set it for your setup (shell environment, `.env`, or your MCP client's configuration; see the client-specific [installation guides](installation_guides/claude_applications.md) for exact config locations).
4. **Restart the MCP server** (and/or reconnect your MCP client) so it picks up the new token. The server reads `APPCIRCLE_ACCESS_TOKEN` at startup and won't see an updated value until it's restarted.

---

## Troubleshooting

### 401 Unauthorized after some time

Access tokens obtained via **Personal Access Key** or **API Keys** are valid for **about 10 hours**. After that, they expire and API calls will return **401 Unauthorized**.
Access tokens obtained via **Personal Access Key** or **API Keys** are valid for **about 24 hours**. After that, they expire and API calls will return **401 Unauthorized**.

**What to do:** Generate a new access token using the same steps above (exchange your Personal Access Key or API key for a new token), then update `APPCIRCLE_ACCESS_TOKEN` in your environment or client configuration and restart the MCP server if needed.
**What to do:** See [Renewing an Expired Token](#renewing-an-expired-token) above.
2 changes: 1 addition & 1 deletion docs/installation_guides/antigravity.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ docker run -d --name appcircle-mcp -p 8000:8000 -e APPCIRCLE_EXCLUDED_TOOLSETS=r

- **Server not showing in Antigravity:** Ensure the JSON is valid (no missing commas or braces), the config file is in the correct location (`~/.gemini/antigravity/mcp_config.json` on macOS/Linux), and you saved the file. Toggle the server off and on in **Manage MCP Servers**, or restart Antigravity.
- **"Error Calling Initialize: EOF":** This often happens when the `command` for a local server (Section 2) uses a **relative path**. Use the full absolute path from `which appcircle-mcp` (e.g. `/Users/you/appcircle-mcp/venv/bin/appcircle-mcp`).
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **Streamable-http / Docker:** Confirm the server is running (`http://localhost:8000/health`) and that your config sends `Authorization: Bearer <your_token>` in the `--header` argument.
- **Manage MCP Servers:** You can add or edit servers via **Agent Panel** → **"..."** → **Manage MCP Servers** → **View raw config**; save and toggle or restart after changes.
- **Server-side logging (LOG_LEVEL):** To get more verbose logs from the Appcircle MCP server, set the `LOG_LEVEL` environment variable to `DEBUG`. In your config (stdio), add it to the `env` block:
Expand Down
4 changes: 2 additions & 2 deletions docs/installation_guides/claude_applications.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ docker run -d --name appcircle-mcp -p 8000:8000 -e APPCIRCLE_EXCLUDED_TOOLSETS=r
## Troubleshooting

- **Server not showing in Claude:** Ensure the JSON is valid and you fully restarted Claude Desktop.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Generate a new one and update your config or auth. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Generate a new one and update your config or auth. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **Streamable-http / Docker:** Confirm the server is running (`http://localhost:8000/health`) and that the client is sending `Authorization: Bearer <your_token>`.
- **Debug mode and logs:** To see more detail from MCP and Claude Desktop, enable debug logging: **Claude Desktop → Settings → Developer** and turn on **Debug mode**. To open the log file: **Claude Desktop → Developer → View logs** (or **Open log file**). Check the logs for connection errors, missing tokens, or server startup failures.
- **Server-side logging (LOG_LEVEL):**
Expand Down Expand Up @@ -393,7 +393,7 @@ claude mcp add appcircle \
### Troubleshooting (Claude Code)

- **Check server status:** Run `/mcp` inside Claude Code to see connected servers and their status.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Remove and re-add the server with a new token, or update the token in `~/.claude.json`. See [Obtaining a token](../appcircle_access_token.md#troubleshooting).
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Remove and re-add the server with a new token, or update the token in `~/.claude.json`. See [Obtaining a token](../appcircle_access_token.md#troubleshooting).
- **Debug logging:** Set `LOG_LEVEL=DEBUG` when adding the server to get verbose MCP server logs:

```bash
Expand Down
4 changes: 2 additions & 2 deletions docs/installation_guides/codex.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ Authorization = "Bearer your_access_token_here"
## Troubleshooting

- **Server not showing in Codex:** Ensure the TOML is valid, the config file is in the right place (`~/.codex/config.toml` or `.codex/config.toml`), and you fully restarted Codex.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Generate a new one and update your config or environment. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Generate a new one and update your config or environment. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **Streamable-http / Docker:** Confirm the server is running (`http://localhost:8000/health`) and that your config includes the `Authorization` header in `[mcp_servers.appcircle.http_headers]` with a valid token.
- **MCP settings:** You can also open the config via **Codex → Settings → Configuration → Open config.toml**; restart Codex after changes.
- **Server-side logging (LOG_LEVEL):** To get more verbose logs from the Appcircle MCP server, set the `LOG_LEVEL` environment variable to `DEBUG`. In your config (stdio), add it to the env table:
Expand Down Expand Up @@ -330,7 +330,7 @@ In the Codex TUI, use `/mcp` to see active MCP servers and their status.
### Troubleshooting (Codex CLI)

- **Check server status:** Run `codex mcp list` or `/mcp` in the Codex TUI to see configured servers and their status.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Remove and re-add the server with a new token: `codex mcp remove appcircle` then `codex mcp add appcircle ...` with the new token. See [Obtaining a token](../appcircle_access_token.md#troubleshooting).
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Remove and re-add the server with a new token: `codex mcp remove appcircle` then `codex mcp add appcircle ...` with the new token. See [Obtaining a token](../appcircle_access_token.md#troubleshooting).
- **Debug logging:** Set `LOG_LEVEL=DEBUG` when adding the server to get verbose MCP server logs (stdio only):

```bash
Expand Down
2 changes: 1 addition & 1 deletion docs/installation_guides/cursor.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ Or using npx mcp-remote:
## Troubleshooting

- **Server not showing in Cursor:** Ensure the JSON is valid, the config file is in the right place (`.cursor/mcp.json` or `~/.cursor/mcp.json`), and you fully restarted Cursor.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **Streamable-http / Docker:** Confirm the server is running (`http://localhost:8000/health`) and that the client is sending `Authorization: Bearer <your_token>`.
- **Settings UI:** You can also add or edit MCP servers via **Cursor → Settings → Tools & MCP**; restart Cursor after changes.
- **Server-side logging (LOG_LEVEL):** To get more verbose logs from the Appcircle MCP server, set the `LOG_LEVEL` environment variable to `DEBUG`. In your config (stdio), add it to the `env` block:
Expand Down
2 changes: 1 addition & 1 deletion docs/installation_guides/gemini_cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ docker run -d --name appcircle-mcp -p 8000:8000 -e APPCIRCLE_EXCLUDED_TOOLSETS=r
## Troubleshooting

- **Server not showing in Gemini CLI:** Ensure the JSON is valid, the config file is in the right place (`~/.gemini/settings.json` or `.gemini/settings.json`), and you restarted Gemini CLI. Use `/mcp list` to see connected servers.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **Streamable-http / Docker:** Confirm the server is running (`http://localhost:8000/health`) and that your config includes the `Authorization` header with a valid token. Use **`httpUrl`** (not `url`) for HTTP in Gemini CLI.
- **Settings:** You can view and edit settings via the `/settings` command in the CLI; restart after changes.
- **Server-side logging (LOG_LEVEL):** To get more verbose logs from the Appcircle MCP server, set the `LOG_LEVEL` environment variable to `DEBUG`. In your config (stdio), add it to the `env` object:
Expand Down
2 changes: 1 addition & 1 deletion docs/installation_guides/vscode.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ docker run -d --name appcircle-mcp -p 8000:8000 -e APPCIRCLE_EXCLUDED_TOOLSETS=r
## Troubleshooting

- **Server not showing in VS Code:** Ensure the JSON is valid, the config file is in the right place (user `mcp.json` or `.vscode/mcp.json`), and each server has the correct `"type"` (`"stdio"` or `"http"`). Use **MCP: List Servers** to start or restart the server.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **Streamable-http / Docker:** Confirm the server is running (`http://localhost:8000/health`) and that your config includes the `Authorization` header with a valid token.
- **View logs:** Run **MCP: List Servers**, select the Appcircle server, and choose **Show Output** to view server logs.
- **Trust:** If you need to re-confirm trust, run **MCP: Reset Trust** from the Command Palette.
Expand Down
2 changes: 1 addition & 1 deletion docs/installation_guides/windsurf.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ docker run -d --name appcircle-mcp -p 8000:8000 -e APPCIRCLE_EXCLUDED_TOOLSETS=r

- **Server not showing in Windsurf:** Ensure the JSON is valid (no missing commas or braces), the config file is in the correct location (`~/.codeium/windsurf/mcp_config.json` on macOS/Linux), and you saved the file. Restart the server via **Manage MCPs** or restart Windsurf.
- **Startup / init errors:** When using a local binary (Section 2), use the full **absolute path** from `which appcircle-mcp` for the `command`; relative paths often cause initialization failures.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 10 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **401 Unauthorized:** Your access token may have expired (tokens are valid about 24 hours). Generate a new one and update your config. See [Obtaining a token](../appcircle_access_token.md) and the [Troubleshooting section](../appcircle_access_token.md#troubleshooting) there.
- **Streamable-http / Docker:** Confirm the server is running (`http://localhost:8000/health`) and that your config includes the `Authorization` header with a valid token. Use the latest version of Windsurf for native HTTP support.
- **Manage MCPs:** You can add or edit servers via **Windsurf: Configure MCP Servers** or **Windsurf Settings → Manage MCPs → View raw config**; save and restart the server or Windsurf after changes.
- **Server-side logging (LOG_LEVEL):** To get more verbose logs from the Appcircle MCP server, set the `LOG_LEVEL` environment variable to `DEBUG`. In your config (stdio), add it to the `env` block:
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "appcircle-mcp-server"
version = "0.1.0"
version = "1.2.0"
description = "MCP server for Appcircle: build, distribution, enterprise app store, publish, and reporting tools."
readme = "README.md"
requires-python = ">=3.10"
Expand All @@ -24,7 +24,7 @@ classifiers = [
"Topic :: Software Development",
]
dependencies = [
"mcp==1.26.0",
"mcp==1.28.1",
"fastmcp==3.2.0",
"httpx==0.28.1",
"pydantic==2.12.5",
Expand Down Expand Up @@ -73,6 +73,7 @@ addopts = "-v --tb=short"
norecursedirs = ".git .hg __pycache__ .tox .env venv ENV dist"
markers = [
"integration: integration tests (require APPCIRCLE_ACCESS_TOKEN and real API); run with pytest test/integration/ -v",
"integration_write: write/action integration tests (mutate real data against a real org); require APPCIRCLE_ACCESS_TOKEN AND APPCIRCLE_RUN_WRITE_INTEGRATION_TESTS=true, skipped otherwise even when running the full integration suite",
]
filterwarnings = [
"ignore::DeprecationWarning",
Expand Down
6 changes: 6 additions & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from importlib.metadata import PackageNotFoundError, version

try:
__version__ = version("appcircle-mcp-server")
except PackageNotFoundError:
__version__ = "0.0.0-dev"
9 changes: 9 additions & 0 deletions src/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class Settings:
# Toolsets to exclude from registration (set via set_excluded_toolsets)
EXCLUDED_TOOLSETS: set = set()

# Whether write/action tools register at all (set via set_write_tools_enabled).
# Default true: write tools are opt-out (set AC_MCP_ENABLE_WRITE_TOOLS=false to disable).
ENABLE_WRITE_TOOLS: bool = True

@classmethod
def set_access_token(cls, token: str) -> None:
"""Set the access token from MCP configuration."""
Expand Down Expand Up @@ -72,4 +76,9 @@ def set_excluded_toolsets(cls, names: Iterable[str]) -> None:
)
cls.EXCLUDED_TOOLSETS = normalized

@classmethod
def set_write_tools_enabled(cls, enabled: bool) -> None:
"""Enable or disable registration of write/action tools."""
cls.ENABLE_WRITE_TOOLS = bool(enabled)

settings = Settings()
Loading
Loading