{
  "markdown": "# Aha MCP Server\n\n![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)\n![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6)\n![MCP](https://img.shields.io/badge/MCP-1.7+-green)\n\nA Model Context Protocol (MCP) server that provides seamless integration with Aha.io's product management platform. Features offline database synchronization, vector embeddings for semantic search, and comprehensive workflow automation.\n\n## 🔧 Client Configuration\n\n### MCP Registry\n\nThis server is published to the [official MCP Registry](https://registry.modelcontextprotocol.io)\nas `io.github.cedricziel/aha-mcp`, so a client that browses the registry can install it\nwithout any of the configuration below:\n\n```bash\ncurl \"https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.cedricziel/aha-mcp\"\n```\n\nThe registry holds metadata only. Its entry points at the three artifacts described below —\nthe npm package, the `ghcr.io` image and the `.mcpb` desktop extension — and a client picks\nwhichever it can run. Either way the server needs `AHA_COMPANY` and `AHA_TOKEN`.\n\n### Claude Desktop Extension (easiest)\n\nDownload `aha-mcp-v<version>.mcpb` from the [latest release](https://github.com/cedricziel/aha-mcp/releases/latest)\nand open it with Claude Desktop, which will prompt you for your Aha.io subdomain and API\ntoken. No Node.js or Docker setup and no manual JSON editing required.\n\nThe extension exposes 50 tools that query Aha.io directly, so results are always current and\nnothing is stored locally. Cross-record search is served by Aha.io's own index — see\n[Search](#-search).\n\n### Claude Desktop Configuration\n\nTo use this MCP server with Claude Desktop, add the following to your `claude_desktop_config.json`:\n\n**Using npx:**\n```json\n{\n  \"mcpServers\": {\n    \"aha\": {\n      \"command\": \"npx\",\n      \"args\": [\"@cedricziel/aha-mcp\"],\n      \"env\": {\n        \"AHA_COMPANY\": \"your-company\",\n        \"AHA_TOKEN\": \"your-api-token\"\n      }\n    }\n  }\n}\n```\n\n**Using Docker:**\n```json\n{\n  \"mcpServers\": {\n    \"aha\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"--rm\", \"-i\",\n        \"-e\", \"AHA_COMPANY=your-company\",\n        \"-e\", \"AHA_TOKEN=your-api-token\",\n        \"ghcr.io/cedricziel/aha-mcp\"\n      ]\n    }\n  }\n}\n```\n\n> **Note:** Replace `your-company` and `your-api-token` with your actual Aha.io subdomain and API token.\n\n## 🚀 Getting Started\n\n### Quick Start with npx\n\nYou can run the MCP server directly using npx without installing it globally:\n\n```bash\n# Set environment variables\nexport AHA_COMPANY=\"your-company\"  # Your Aha.io subdomain\nexport AHA_TOKEN=\"your-api-token\"   # Your Aha.io API token\n\n# Run the server\nnpx @cedricziel/aha-mcp\n```\n\n### Quick Start with Docker\n\nYou can also run the MCP server using Docker:\n\n```bash\n# Set environment variables\nexport AHA_COMPANY=\"your-company\"  # Your Aha.io subdomain\nexport AHA_TOKEN=\"your-api-token\"   # Your Aha.io API token\n\n# Run in stdio mode (default)\ndocker run --rm -e AHA_COMPANY=\"$AHA_COMPANY\" -e AHA_TOKEN=\"$AHA_TOKEN\" ghcr.io/cedricziel/aha-mcp\n\n# Run in Streamable HTTP mode (recommended for remote access)\ndocker run --rm -p 3001:3001 -e AHA_COMPANY=\"$AHA_COMPANY\" -e AHA_TOKEN=\"$AHA_TOKEN\" ghcr.io/cedricziel/aha-mcp --mode streamable-http\n\n```\n\n### Development Setup\n\n1. Install [Bun](https://bun.sh/) if you haven't already:\n   ```bash\n   curl -fsSL https://bun.sh/install | bash\n   ```\n\n2. Install dependencies:\n   ```bash\n   bun install\n   ```\n\n3. Configure environment variables:\n   ```bash\n   export AHA_COMPANY=\"your-company\"  # Your Aha.io subdomain\n   export AHA_TOKEN=\"your-api-token\"   # Your Aha.io API token\n   ```\n\n4. Start the server:\n   ```bash\n   # Start the stdio server (for MCP clients - default)\n   bun start\n\n   # Or start with Streamable HTTP (recommended for remote access)\n   bun start -- --mode streamable-http\n\n   # Or start the HTTP server (legacy entry point)\n   bun run start:http\n   ```\n\n5. For development with auto-reload:\n   ```bash\n   # Development mode with stdio\n   bun run dev\n\n   # Development mode with Streamable HTTP\n   bun run dev -- --mode streamable-http\n\n   # Development mode with HTTP (legacy)\n   bun run dev:http\n   ```\n\n## 🔌 Aha.io Integration\n\nThis MCP server provides hybrid integration with Aha.io through both live API access and offline database synchronization. The server automatically maintains a local SQLite database with your Aha.io data, enabling faster queries, offline access, and advanced semantic search capabilities.\n\n### Architecture Overview\n\n- **Hybrid Data Access**: Live API calls for real-time data + offline SQLite database for performance\n- **Background Sync**: Automatic synchronization of Aha.io entities to local database\n- **Vector Embeddings**: Semantic search using sentence transformers and SQLite vector extensions\n- **Real-time Progress**: Background job monitoring with detailed progress tracking\n- **Configuration Management**: Runtime configuration without server restarts\n\n### Configuration\n\nThe Aha.io integration can be configured using multiple methods, with the following priority order:\n\n1. **Environment Variables** (highest priority)\n2. **Configuration File** (`~/.aha-mcp-config.json`)\n3. **Default Values** (lowest priority)\n\n#### Environment Variables\n\n- `AHA_COMPANY`: Your Aha.io subdomain (e.g., `mycompany` for `mycompany.aha.io`)\n- `AHA_TOKEN`: Your Aha.io API token (for API token authentication)\n- `AHA_ACCESS_TOKEN`: Your OAuth 2.0 access token (for OAuth authentication)\n- `MCP_TRANSPORT_MODE`: Transport mode (`stdio` or `streamable-http`)\n- `MCP_PORT`: Port number for HTTP-based modes (default: 3001)\n- `MCP_HOST`: Host address for HTTP-based modes (default: 0.0.0.0)\n- `MCP_AUTH_TOKEN`: Authentication token for HTTP-based modes (optional)\n- `MCP_TOOL_RATE_LIMIT_PER_MINUTE`: Tool calls allowed per minute (default: 120, `0` disables)\n\n#### Transport Modes\n\nThe server supports two transport modes:\n\n1. **stdio**: Standard input/output mode for MCP client integration (default)\n2. **streamable-http**: HTTP transport (MCP protocol 2025-06-18), for remote and web clients\n\nExample usage:\n```bash\n# Stdio mode (default)\naha-mcp\n\n# Streamable HTTP mode\naha-mcp --mode streamable-http --port 3001\n```\n\n> **Removed:** the `sse` transport was deprecated in MCP spec 2025-03-26 and has been\n> removed. `MCP_TRANSPORT_MODE=sse` and `--mode sse` now fall back to `streamable-http`\n> with a warning, so existing configurations keep starting.\n\n#### Authentication (HTTP transport)\n\nThe `streamable-http` transport supports optional Bearer token authentication:\n\n##### Environment Variable Configuration\n\n```bash\n# Set authentication token\nexport MCP_AUTH_TOKEN=\"your-secure-token-here\"\n\n# Start server with authentication\naha-mcp --mode streamable-http --port 3001\n```\n\n##### Client Authentication\n\nWhen authentication is enabled, clients must include a Bearer token in the Authorization\nheader. All MCP traffic goes to the single `/mcp` endpoint:\n\n```bash\ncurl -X POST \\\n     -H \"Authorization: Bearer your-secure-token-here\" \\\n     -H \"Content-Type: application/json\" \\\n     -H \"MCP-Protocol-Version: 2025-06-18\" \\\n     -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/list\", \"params\": {}}' \\\n     http://localhost:3001/mcp\n```\n\nMost callers should use an MCP client library rather than raw HTTP; pass the token as an\n`Authorization` header when constructing the transport.\n\n##### Security Notes\n\n- **Opt-in**: Authentication is optional. If `MCP_AUTH_TOKEN` is not set, all requests are allowed.\n- **Token Security**: Use strong, randomly generated tokens (minimum 8 characters).\n- **HTTPS**: In production, always use HTTPS to protect tokens in transit.\n- **Token Storage**: Tokens are obfuscated (base64 encoded) in the configuration file but should be treated as sensitive data.\n\n##### Checking Authentication Status\n\n```bash\ncurl http://localhost:3001/\n\n# Response includes:\n# {\n#   \"authentication\": {\n#     \"enabled\": true,\n#     \"type\": \"Bearer token\"\n#   }\n# }\n```\n\n#### Configuration Management Tools\n\nThe server provides three MCP tools for configuration management:\n\n1. **configure_server**: Update server settings at runtime\n2. **get_server_config**: View current configuration and validation status\n3. **test_configuration**: Test API connectivity with current settings\n\nThese tools allow you to manage configuration without restarting the server, making it easy to switch between different Aha.io accounts or update credentials.\n\n### Database Synchronization\n\nThe server maintains a local SQLite database with your Aha.io data for improved performance and offline access.\n\n#### Sync Management Tools\n\n- `aha_sync_start`: Start background synchronization of specified entity types\n- `aha_sync_status`: Check the status and progress of sync jobs\n- `aha_sync_stop`: Stop a running sync job\n- `aha_sync_pause`: Pause a sync job (can be resumed later)\n- `aha_sync_resume`: Resume a paused sync job\n- `aha_sync_history`: View detailed history of sync operations\n- `aha_sync_health`: Get overall sync service health status\n- `aha_database_health`: Check database connectivity and statistics\n- `aha_database_cleanup`: Clean up old sync jobs and optimize database\n\n#### Sync Features\n\n- **Entity Types**: Sync features, products, ideas, epics, initiatives, releases, goals, users, comments\n- **Progress Tracking**: Real-time progress updates with detailed statistics\n- **Error Handling**: Comprehensive error logging and recovery mechanisms\n- **Batch Processing**: Configurable batch sizes for optimal performance\n- **Incremental Updates**: Support for `updatedSince` filtering to sync only recent changes\n- **Concurrent Operations**: Multiple sync jobs can run simultaneously\n\n#### Example Sync Workflow\n\n```bash\n# Start syncing features and products\naha_sync_start --entities features,products --batchSize 50\n\n# Check progress\naha_sync_status --jobId sync-abc123\n\n# View sync history\naha_sync_history --jobId sync-abc123 --limit 20\n\n# Check overall health\naha_sync_health\n```\n\n### Semantic Search & Embeddings\n\nThe server includes advanced semantic search capabilities using vector embeddings.\n\n#### Embedding Management Tools\n\n- `aha_generate_embeddings`: Generate vector embeddings for entity text content\n- `aha_embedding_status`: Check the status of embedding generation jobs\n- `aha_semantic_search`: Search entities using natural language queries\n- `aha_generate_entity_embedding`: Generate embedding for a specific entity\n- `aha_find_similar`: Find entities similar to a given entity\n- `aha_pause_embeddings`: Pause embedding generation jobs\n- `aha_stop_embeddings`: Stop embedding generation jobs\n\n#### Semantic Search Features\n\n- **Vector Storage**: Embeddings stored in SQLite with sqlite-vec extension\n- **Multiple Models**: Support for different embedding models (default: all-MiniLM-L6-v2)\n- **Similarity Search**: Cosine similarity search with configurable thresholds\n- **Cross-Entity Search**: Find similar content across different entity types\n- **Real-time Generation**: Background embedding generation with progress tracking\n\n#### Example Embedding Workflow\n\n```bash\n# Generate embeddings for features and ideas\naha_generate_embeddings --entities features,ideas --batchSize 25\n\n# Search for similar content\naha_semantic_search --query \"user authentication security\" --threshold 0.7\n\n# Find similar features to a specific feature\naha_find_similar --entityType features --entityId FEAT-123 --limit 5\n\n# Check embedding job progress\naha_embedding_status --jobId embed-xyz789\n```\n\n### Available Resources\n\n**Breaking change:** many collection resources (slim index lists like `aha_features`, and a\nfew with a handful of scalar columns like `aha_ideas`) now return `text/markdown` - a link\nlist or a table, depending on the record type - instead of a JSON array. Anything that used\nto parse those collections' contents as JSON needs to change. Collections with richer nested\ndata (`aha_goals`, `aha_initiatives`, comment resources, and similar) are unaffected and, like\nevery single-record resource (`aha://feature/{id}` and the like), still return\n`application/json`.\n\n#### Individual Entity Resources\n- `aha_idea`: Access individual ideas using `aha://idea/{id}`\n- `aha_feature`: Access individual features using `aha://feature/{id}`\n- `aha_user`: Access individual users using `aha://user/{id}`\n- `aha_epic`: Access individual epics using `aha://epic/{id}`\n- `aha_product`: Access individual products using `aha://product/{id}`\n- `aha_initiative`: Access individual initiatives using `aha://initiative/{id}`\n- `aha_requirement`: Access individual requirements using `aha://requirement/{id}`\n- `aha_competitor`: Access individual competitors using `aha://competitor/{id}`\n- `aha_todo`: Access individual todos using `aha://todo/{id}`\n\n#### Collection Resources\n- `aha_features`: List features with optional filtering using `aha://features?query=...&tag=...`\n- `aha_users`: List all users using `aha://users`\n- `aha_epics`: List epics for a product using `aha://epics/{product_id}`\n- `aha_products`: List all products using `aha://products?updatedSince=...`\n- `aha_initiatives`: List all initiatives using `aha://initiatives?query=...&onlyActive=true`\n- `aha_ideas`: List all ideas globally using `aha://ideas?query=...&status=...&category=...`\n- `aha_ideas_by_product`: List ideas for a product using `aha://ideas/{product_id}?query=...&spam=false&sort=recent`\n- `aha_competitors`: List competitors for a product using `aha://competitors/{product_id}`\n- `aha_product_releases`: List releases for a product using `aha://releases/{product_id}?query=...&status=...`\n- `aha_initiative_epics`: List epics for an initiative using `aha://initiative/{initiative_id}/epics`\n\n#### Comment Resources\n- `aha_feature_comments`: Access comments for a feature using `aha://comments/feature/{feature_id}`\n- `aha_epic_comments`: Access comments for an epic using `aha://comments/epic/{epic_id}`\n- `aha_idea_comments`: Access an idea's **internal** comments using `aha://comments/idea/{idea_id}`\n- `aha_idea_portal_comments`: Access an idea's **ideas-portal** comments using `aha://idea-comments/{idea_id}` — different records from the above, including anything a customer wrote\n- `aha_initiative_comments`: Access comments for an initiative using `aha://comments/initiative/{initiative_id}`\n- `aha_product_comments`: Access comments for a product using `aha://comments/product/{product_id}`\n- `aha_goal_comments`: Access comments for a goal using `aha://comments/goal/{goal_id}`\n- `aha_release_comments`: Access comments for a release using `aha://comments/release/{release_id}`\n- `aha_release_phase_comments`: Access comments for a release phase using `aha://comments/release-phase/{release_phase_id}`\n- `aha_requirement_comments`: Access comments for a requirement using `aha://comments/requirement/{requirement_id}`\n- `aha_todo_comments`: Access comments for a todo using `aha://comments/todo/{todo_id}`\n\n#### Goal Resources\n- `aha_goal`: Access individual goals using `aha://goal/{goal_id}`\n- `aha_goals`: List all goals using `aha://goals`\n- `aha_goal_epics`: Access epics associated with a goal using `aha://goal/{goal_id}/epics`\n- `aha_goal_key_results`: Access key results for a goal using `aha://goal/{goal_id}/key_results`\n- `aha_key_result`: Access individual key results using `aha://key_result/{id}`\n\n#### Release Resources\n- `aha_release`: Access individual releases using `aha://release/{release_id}`\n- `aha_releases`: List all releases using `aha://releases`\n- `aha_release_features`: Access features associated with a release using `aha://release/{release_id}/features`\n- `aha_release_epics`: Access epics associated with a release using `aha://release/{release_id}/epics`\n- `aha_release_phase`: Access individual release phases using `aha://release-phase/{release_phase_id}`\n- `aha_release_phases`: List all release phases using `aha://release-phases`\n\n#### Custom Fields Resources\n- `aha_custom_fields`: List all custom field definitions using `aha://custom-fields`\n- `aha_custom_field_options`: Access options for a custom field using `aha://custom-field/{custom_field_id}/options`\n\n#### Resource URI Examples\n```\n# Individual Entity Resources\naha://idea/IDEA-123               # Get specific idea\naha://feature/PROJ-456            # Get specific feature\naha://user/USER-789               # Get specific user\naha://epic/EPIC-101               # Get specific epic\naha://product/PROD-001            # Get specific product\naha://initiative/INIT-202         # Get specific initiative\naha://requirement/REQ-666         # Get specific requirement\naha://competitor/COMP-444         # Get specific competitor\naha://todo/TODO-777               # Get specific todo\n\n# Collection Resources (enhanced with filtering)\naha://features?query=auth&tag=api&assignedToUser=user@example.com # Search features\naha://users                       # List all users\naha://epics/PROJ-001              # List epics for product\naha://products?updatedSince=2024-01-01T00:00:00Z # List products with filter\naha://initiatives?query=mobile&onlyActive=true&assignedToUser=user@example.com # Search initiatives\naha://ideas?query=nodejs&status=new&category=enhancement # List ideas globally with filters\naha://ideas/PROJ-001?query=search&spam=false&sort=recent&tag=enhancement # List ideas with filters\naha://competitors/PROJ-001        # List competitors for product\naha://releases/PROJ-001?query=mobile&status=shipped # List releases for product\naha://initiative/INIT-123/epics   # List epics for initiative\n\n# Comment Resources\naha://comments/feature/PRJ1-123   # Get comments for feature\naha://comments/epic/EPIC-123      # Get comments for epic\naha://comments/idea/IDEA-456      # Get an idea's internal comments\naha://idea-comments/IDEA-456      # Get an idea's ideas-portal comments\naha://comments/initiative/INIT-789 # Get comments for initiative\naha://comments/product/PROD-001   # Get comments for product\naha://comments/goal/GOAL-555      # Get comments for goal\naha://comments/release/REL-333    # Get comments for release\naha://comments/release-phase/RP-444 # Get comments for release phase\naha://comments/requirement/REQ-666 # Get comments for requirement\naha://comments/todo/TODO-777      # Get comments for todo\n\n# Goal Resources\naha://goal/GOAL-123               # Get specific goal\naha://goals                       # List all goals\naha://goal/GOAL-456/epics         # Get epics for goal\naha://goal/GOAL-456/key_results   # Get key results for goal\naha://key_result/PRJ1-G-3-KR-1    # Get specific key result\n\n# Release Resources\naha://release/REL-123             # Get specific release\naha://releases                    # List all releases\naha://release/REL-456/features    # Get features for release\naha://release/REL-456/epics       # Get epics for release\naha://release-phase/RP-123        # Get specific release phase\naha://release-phases              # List all release phases\n\n# Custom Fields Resources\naha://custom-fields               # List all custom field definitions\naha://custom-field/CF-123/options # Get options for custom field\n```\n\n### Available Tools\n\n**Note**: List operations are handled through MCP resources. Tools cover search, single-record\nreads, write operations and relationship management.\n\n#### Record Read Tools\n- `aha_get_feature`: Read one feature, including workflow status, release, assignee, tags, score and custom field values\n- `aha_get_epic`: Read one epic\n- `aha_get_idea`: Read one idea\n- `aha_get_initiative`: Read one initiative\n- `aha_get_release`: Read one release\n- `aha_get_goal`: Read one goal, including its time frame, progress source, success metric and key result summary\n- `aha_get_key_result`: Read one key result, including its status and starting, current and target metrics\n\nThese return the full record as `structuredContent`. They duplicate what\n`aha://feature/{id}` and friends already serve, deliberately: a client is free to surface\nresources to its model or not, and several do not — on those, every read here was\nunreachable, leaving write tools with no way to see what they were about to replace.\n`aha_search` is not a substitute, as it cannot return per-record fields.\n\n#### Collection Read Tools\n- `aha_list_release_features`: List the features assigned to a release, with a link per feature and Aha's total for the release\n- `aha_list_release_epics`: List the epics assigned to a release, with a link per epic and Aha's total for the release\n- `aha_list_key_results`: List a goal's key results, with status, progress and metrics\n- `aha_list_comments`: List the comments on a record, both streams for an idea\n\nThe two release tools are the only way to enumerate a release. `aha_search` is\nrelevance-ranked, returns no release membership on a hit and cannot be asked for every record\nin a scope, so a release list assembled from search results is partial — and nothing in it says\nso. Both types are listed because a release is not organised the same way in every workspace: a\nrelease planned in epics is invisible to the features tool. Each asks for 200 records per page\n(Aha's own default is 30 for features; on the epics route it is unmeasured, which is why the\ntool never relies on it) and always returns Aha's pagination block, so a caller can tell a\ncomplete list from the front of a longer one. Aha\nreturns identity fields only on these endpoints, so use `aha_get_feature` or `aha_get_epic` for\nthe state of any one record.\n\n#### Write Operation Tools\n- `aha_create_feature_comment`: Create a comment on a feature\n- `aha_create_initiative_in_product`: Create an initiative within a specific product\n\n#### Feature CRUD Tools\n- `aha_create_feature`: Create a feature within a specific release\n- `aha_update_feature`: Update a feature\n- `aha_delete_feature`: Delete a feature\n- `aha_update_feature_progress`: Update a feature's progress\n- `aha_update_feature_score`: Update a feature's score\n- `aha_update_feature_custom_fields`: Update a feature's custom fields\n\n#### Epic CRUD Tools\n- `aha_update_epic`: Update an epic\n- `aha_delete_epic`: Delete an epic\n- `aha_create_epic_in_product`: Create an epic within a specific product\n- `aha_create_epic_in_release`: Create an epic within a specific release\n\n#### Idea CRUD Tools\n- `aha_create_idea`: Create an idea in a product\n- `aha_create_idea_with_category`: Create an idea with a category\n- `aha_create_idea_with_score`: Create an idea with a score\n- `aha_delete_idea`: Delete an idea\n\n#### Goal and Key Result Tools (OKRs)\n- `aha_create_goal`: Create a goal (objective) in a workspace\n- `aha_update_goal`: Update a goal's name, description, success metric, status, time frame or progress\n- `aha_delete_goal`: Delete a goal, and with it the key results it owns\n- `aha_list_key_results`: List a goal's key results, with status, progress and metrics\n- `aha_create_key_result`: Create a key result under a goal\n- `aha_update_key_result`: Update a key result — its status and starting, current or target metric\n- `aha_delete_key_result`: Delete a key result\n\nThree things about these differ from the rest of the API, all measured against a live account:\n\n- **Goal creation and deletion are workspace-scoped.** `POST /products/{id}/goals` and\n  `DELETE /products/{id}/goals/{id}` are the only routes Aha offers, so both tools require a\n  workspace id — `aha_get_goal` returns it as `product_id`. Updates do not need one.\n- **A key result has no `url`.** Unlike every other record type, the standalone record carries\n  neither `url` nor `resource`, so the `aha://key_result/{id}` resource link each tool returns\n  is the only pointer a client can follow.\n- **A goal has no top-level workflow status.** It lives under `success_metric.workflow_status`,\n  which is what the Aha UI shows as the goal's status.\n\n#### Competitor Management Tools\n- `aha_create_competitor`: Create a competitor in a product\n- `aha_update_competitor`: Update a competitor\n- `aha_delete_competitor`: Delete a competitor\n\n#### Portal Integration Tools\n- `aha_create_idea_by_portal_user`: Create an idea by a portal user\n- `aha_create_idea_with_portal_settings`: Create an idea with enhanced portal settings\n\n#### Relationship Management Tools\n- `aha_associate_feature_with_epic`: Associate a feature with an epic\n- `aha_move_feature_to_release`: Move a feature to a different release\n- `aha_associate_feature_with_goals`: Associate a feature with multiple goals\n- `aha_update_feature_tags`: Update tags for a feature\n\n**Note**: reads are offered through both interfaces, by design:\n- **Resources** cover the full read surface — every entity type, with filtering through URI parameters, and lists as well as single records\n- **Tools** cover writes (create/update/delete), relationship management (associate/move), search, and single-record reads for the five most-written types\n\nThe overlap is deliberate. Resources are the richer read surface, but the MCP spec leaves it\nto each client whether to expose them to its model, and tool-only clients are common. Keeping\nreads tool-accessible for the types that have write tools is what stops an agent from changing\na field it cannot see.\n\n### 🚀 Phase 8 - Complete CRUD Operations & Advanced Features\n\nThe MCP server now provides comprehensive lifecycle management for Aha.io entities with complete CRUD operations, portal integration, and advanced workflow features:\n\n#### Phase 8A - Core CRUD Operations (18 Tools)\n**Feature Management (6 Tools)**\n- `aha_create_feature`: Create features within releases\n- `aha_update_feature`: Update existing features\n- `aha_delete_feature`: Delete features\n- `aha_update_feature_progress`: Update feature progress (0-100%)\n- `aha_update_feature_score`: Update feature scores\n- `aha_update_feature_custom_fields`: Update feature custom fields\n\n**Epic Management (2 Tools)**\n- `aha_update_epic`: Update existing epics\n- `aha_delete_epic`: Delete epics\n\n**Idea Management (4 Tools)**\n- `aha_create_idea`: Create ideas in products\n- `aha_create_idea_with_category`: Create ideas with categories\n- `aha_create_idea_with_score`: Create ideas with scores\n- `aha_delete_idea`: Delete ideas\n\n#### Phase 8B - Competitor Management (3 Tools)\n**Competitor Management (3 Tools)**\n- `aha_create_competitor`: Create competitors in products\n- `aha_update_competitor`: Update existing competitors\n- `aha_delete_competitor`: Delete competitors\n\n**Note**: Initiative data access is now handled through MCP resources (`aha_initiative`, `aha_initiatives`, `aha_initiative_comments`, `aha_initiative_epics`) for a cleaner separation between read and write operations.\n\n#### Phase 8C - Portal Integration & Advanced Features (2 Tools)\n**Portal Integration**\n- `aha_create_idea_by_portal_user`: Create ideas by portal users\n- `aha_create_idea_with_portal_settings`: Create ideas with portal settings\n\n#### Enhanced Filtering & Resources\n- **Initiative Filtering**: Enhanced with `query`, `updatedSince`, `assignedToUser`, `onlyActive` parameters\n- **Portal Configuration**: Support for `skip_portal` and `submitted_idea_portal_id` settings\n- **Comprehensive Entity Coverage**: Full CRUD operations for features, epics, ideas, and competitors\n\n#### Technical Achievements\n- **50 MCP tools**, all querying Aha.io directly — no local state\n- **17 listed MCP resources** covering the entity set, plus templated resource URIs\n- **17 domain-specific prompts** (workflow automation)\n- **32 core CRUD and write operation tools** for complete lifecycle management, including OKRs (goals and key results)\n- **Cross-record search** over Aha's own index, covering 20 record types\n- **7 single-record read tools**, so a write can be checked against the record's current state on clients that do not surface resources\n- **Comment reads and writes** on every record type Aha supports, with an idea's ideas-portal conversation handled as its own stream\n- **Goal and key result CRUD**, so a quarterly OKR loop can run through the server rather than the Aha UI\n- **5 server configuration tools** for runtime configuration\n- **534 tests passing** with comprehensive service coverage\n- **No native dependencies**, so the server runs anywhere Node does\n- **Comprehensive error handling** with proper Zod schema validation\n\n## 🔍 Search\n\n`aha_search` queries Aha.io's own search index through the GraphQL API\n(`POST /api/v2/graphql`, `searchDocuments`). Nothing is cached locally, so results are\nalways current and no native dependencies or writable storage are required.\n\n```jsonc\n// Everything matching \"alerting\", any record type\n{ \"query\": \"alerting\" }\n\n// Ideas only, within one workspace\n{ \"query\": \"alerting\", \"recordTypes\": [\"Idea\"], \"workspaceId\": \"7387509120724661690\" }\n\n// Sweep a workspace broadly: alternatives, because there is no match-all\n{ \"query\": \"a* OR e* OR i* OR o* OR u*\", \"recordTypes\": [\"Idea\"], \"workspaceId\": \"7387509120724661690\" }\n```\n\n**What it matches:** record names and descriptions. Comment bodies match too, surfacing as\n`Comment` hits that link to their parent record.\n\n**Query syntax:** `term*` for prefix matching, `AND` / `OR` / `NOT`, and `\"quoted phrases\"`.\n\n**There is no match-all query.** A bare `*` is rejected: on its own Aha returns an arbitrary\nsubset for it, and combined with `workspaceId` it returns nothing at all — an empty result\nthat reads like an empty workspace. Search for a term, or enumerate a workspace through the\nlist resources (`aha://features`, `aha://ideas/{product_id}`) instead of searching it.\n\n**What a hit carries:** name, type, `reference_num`, internal id, workspace, absolute URL and\n`updated_at`. Idea hits also carry portal `votes` and `endorsements`, and scorable types their\nAha.io `score`, so ideas can be ranked by demand without a second call. Hits whose type is\nreadable as a resource — feature, epic, idea, initiative, goal, key result, release,\nrequirement, competitor — come with a `resource_link`; the rest are reachable by URL.\n\n**Quote a reference number in full.** The workspace prefix is part of it: `IDEASVOC-I-9930`\nidentifies an idea, `I-9930` identifies nothing, and Aha answers the truncated form with a 404\nthat reads like a missing record rather than a mistyped one.\n\n**What it does not return:** workflow status, release membership, assignee or custom field\nvalues. Read the record itself for those:\n\n```jsonc\n{ \"featureId\": \"PRJ1-123\" }   // aha_get_feature — full record, including custom fields\n```\n\n**Record types** (`recordTypes`, omit to search all):\n\n```\nBusinessModel · Comment · Competitor · Epic · Feature · Goal · Idea · IdeaOrganization\nIdeaTheme · IdeaUser · Initiative · KeyResult · Page · Persona · Project · Release\nReleasePhase · Requirement · StrategicPositioning · Task\n```\n\n**Paging:** `perPage` accepts 10–200 and defaults to 20 — Aha raises anything below 10.\n`total_count` stops counting at 10,000, reported as `total_count_is_capped: true`.\n\nUse `scripts/check-graphql.ts` to confirm what your own account and token can reach:\n\n```bash\nAHA_COMPANY=mycompany AHA_TOKEN=... bun run scripts/check-graphql.ts\n```\n\n### Why not local embeddings?\n\nEarlier versions synced Aha into SQLite and ranked results with a local \"semantic search\".\nThat has been removed. The embedding function hashed character codes through `Math.sin()`,\nso it carried no semantic signal and its similarity scores were not interpretable. It also\nrequired the native `sqlite3` module and a writable data directory, which is what broke it\nin packaged installs. Aha's server-side index is keyword-based but real, always current, and\nfree of all that machinery.\n\nAha also hosts its own MCP server at `https://<yourcompany>.aha.io/api/v1/mcp`.\n\n## 🛠️ Adding Custom Tools and Resources\n\nWhen adding custom tools, resources, or prompts to your MCP server:\n\n1. Use underscores (`_`) instead of hyphens (`-`) in all resource, tool, and prompt names\n   ```typescript\n   // Good: Uses underscores\n   server.tool(\n     \"my_custom_tool\",\n     \"Description of my custom tool\",\n     {\n       param_name: z.string().describe(\"Parameter description\")\n     },\n     async (params) => {\n       // Tool implementation\n     }\n   );\n\n   // Bad: Uses hyphens, may cause issues with Cursor\n   server.tool(\n     \"my-custom-tool\",\n     \"Description of my custom tool\",\n     {\n       param-name: z.string().describe(\"Parameter description\")\n     },\n     async (params) => {\n       // Tool implementation\n     }\n   );\n   ```\n\n2. This naming convention ensures compatibility with Cursor and other AI tools that interact with your MCP server\n\n## 🐳 Docker Usage\n\n### Docker Images\n\nThe Aha MCP server is available as Docker images on GitHub Container Registry:\n\n- **GitHub Container Registry**: `ghcr.io/cedricziel/aha-mcp`\n\n### Running with Docker\n\n#### Basic Usage\n\n```bash\n# Run in stdio mode (default)\ndocker run --rm \\\n  -e AHA_COMPANY=\"your-company\" \\\n  -e AHA_TOKEN=\"your-api-token\" \\\n  ghcr.io/cedricziel/aha-mcp\n\n# Run in Streamable HTTP mode\ndocker run --rm \\\n  -p 3001:3001 \\\n  -e AHA_COMPANY=\"your-company\" \\\n  -e AHA_TOKEN=\"your-api-token\" \\\n  ghcr.io/cedricziel/aha-mcp --mode streamable-http\n\n# Run in Streamable HTTP mode with authentication\ndocker run --rm \\\n  -p 3001:3001 \\\n  -e AHA_COMPANY=\"your-company\" \\\n  -e AHA_TOKEN=\"your-api-token\" \\\n  -e MCP_AUTH_TOKEN=\"your-secure-token\" \\\n  ghcr.io/cedricziel/aha-mcp --mode streamable-http\n```\n\n#### Persistent Configuration\n\nTo persist configuration between runs:\n\n```bash\n# Create a named volume for configuration\ndocker volume create aha-mcp-config\n\n# Run with persistent configuration\ndocker run --rm \\\n  -v aha-mcp-config:/home/mcp/.config \\\n  -e AHA_COMPANY=\"your-company\" \\\n  -e AHA_TOKEN=\"your-api-token\" \\\n  ghcr.io/cedricziel/aha-mcp\n```\n\n#### Using Docker Compose\n\nThe repository includes a `docker-compose.yml` file for easy setup:\n\n```bash\n# Copy the example environment file\ncp .env.example .env\n\n# Edit .env with your credentials\nAHA_COMPANY=your-company\nAHA_TOKEN=your-api-token\n\n# Run in stdio mode\ndocker-compose --profile stdio up\n\n# Run in Streamable HTTP mode\ndocker-compose --profile http up\n\n# Run in detached mode\ndocker-compose --profile http up -d\n```\n\nExample `.env` file:\n```env\nAHA_COMPANY=mycompany\nAHA_TOKEN=your-api-token-here\nMCP_AUTH_TOKEN=your-secure-token-here\n```\n\n### Docker Environment Variables\n\nThe Docker image supports all the same environment variables as the npm package:\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `AHA_COMPANY` | Aha.io company subdomain | - |\n| `AHA_TOKEN` | Aha.io API token | - |\n| `MCP_TRANSPORT_MODE` | Transport mode (`stdio` or `streamable-http`) | `stdio` |\n| `MCP_PORT` | Port for streamable-http mode | `3001` |\n| `MCP_HOST` | Host for streamable-http mode | `0.0.0.0` |\n| `MCP_AUTH_TOKEN` | Bearer token for the streamable-http transport | - |\n| `MCP_TOOL_RATE_LIMIT_PER_MINUTE` | Tool calls allowed per minute (`0` disables) | `120` |\n| `MCP_CONFIG_DIR` | Configuration directory | `/home/mcp/.config` |\n\n### Health Checks\n\nThe Docker image includes health checks for streamable-http mode:\n\n```bash\n# Check if the HTTP server is healthy\ncurl http://localhost:3001/health\n\n# Get detailed server status\ncurl http://localhost:3001/status\n```\n\n### Building from Source\n\nTo build the Docker image locally:\n\n```bash\n# Build the image\nnpm run docker:build\n\n# Test the image\nnpm run docker:test\n\n# Run the image\nnpm run docker:run\n\n# Run in Streamable HTTP mode\nnpm run docker:run:http\n```\n\n### Multi-Architecture Support\n\nThe Docker images are built for multiple architectures:\n\n- `linux/amd64` (x86_64)\n- `linux/arm64` (Apple Silicon, ARM64)\n\nDocker will automatically pull the correct image for your platform.\n\n### Docker Security\n\nThe Docker image follows security best practices:\n\n- Runs as non-root user (`mcp`)\n- Uses minimal Alpine Linux base image\n- Includes tini for proper signal handling\n- Configuration directory has proper permissions\n- Uses multi-stage builds to reduce attack surface\n\n## 🏗️ Development\n\n### Commit Guidelines\n\nThis project uses [Conventional Commits](https://www.conventionalcommits.org/) to ensure consistent commit messages and enable automated versioning.\n\n**Commit Message Format:**\n```\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n```\n\n**Types:**\n- `feat`: A new feature\n- `fix`: A bug fix\n- `docs`: Documentation only changes\n- `style`: Changes that do not affect the meaning of the code\n- `refactor`: A code change that neither fixes a bug nor adds a feature\n- `perf`: A code change that improves performance\n- `test`: Adding missing tests or correcting existing tests\n- `build`: Changes that affect the build system or external dependencies\n- `ci`: Changes to CI configuration files and scripts\n- `chore`: Other changes that don't modify src or test files\n\n**Examples:**\n```bash\nfeat: add new MCP tool for listing projects\nfix: resolve authentication issue with API tokens\ndocs: update README with installation instructions\nfeat!: change API response format (breaking change)\n```\n\nCommit messages are validated using commitlint on every commit and in CI.\n\n### Testing\n\n#### Local Testing\n\nRun the test suite:\n\n```bash\n# Run all tests\nbun test\n\n# Run tests in watch mode\nbun run test:watch\n\n# Run tests with coverage\nbun test --coverage\n```\n\n#### Docker Testing\n\nThe Docker environment includes all necessary dependencies for testing:\n\n```bash\n# Test the Docker build\ndocker build -t aha-mcp-test .\n\n# Run tests inside Docker container\ndocker run --rm aha-mcp-test bun test\n\n# Test with environment variables\ndocker run --rm \\\n  -e AHA_COMPANY=\"test-company\" \\\n  -e AHA_TOKEN=\"test-token\" \\\n  aha-mcp-test bun test\n\n# Verify all dependencies are available\ndocker run --rm aha-mcp-test bun install --dry-run\n\n# Test database functionality (SQLite)\ndocker run --rm aha-mcp-test node -e \"\n  const sqlite3 = require('sqlite3');\n  const db = new sqlite3.Database(':memory:');\n  console.log('SQLite available:', !!db);\n  db.close();\n\"\n\n# Test if sqlite-vec extension loads (graceful fallback if not available)\ndocker run --rm aha-mcp-test bun run start --help\n```\n\n#### Testing Database Features\n\nThe Docker environment includes:\n- **SQLite3**: Core database functionality\n- **Node.js sqlite packages**: Database drivers and utilities\n- **Graceful fallback**: sqlite-vec extension warnings are suppressed in test environments\n- **Temporary databases**: Each test uses isolated temporary database files\n- **Proper cleanup**: Database connections and files are cleaned up after tests\n\n#### Verifying Docker Environment\n\n```bash\n# Check all key components are available\ndocker run --rm aha-mcp-test sh -c \"\n  echo 'Checking Bun...'; bun --version\n  echo 'Checking Node.js...'; node --version  \n  echo 'Checking SQLite...'; node -e 'console.log(require(\\\"sqlite3\\\"))'\n  echo 'Checking dependencies...'; bun install --dry-run\n  echo 'Running basic tests...'; bun test --reporter=dot\n\"\n\n# Test MCP server startup\ndocker run --rm -d --name aha-test \\\n  -e AHA_COMPANY=\"test\" \\\n  -e AHA_TOKEN=\"test\" \\\n  aha-mcp-test\n\n# Check if server started successfully\ndocker logs aha-test\n\n# Cleanup\ndocker stop aha-test\n```\n\nThe Docker environment supports the full test suite including:\n- **194+ test cases** across all services\n- **Database service tests** (25 test cases)\n- **Background sync service tests** (16 test cases)  \n- **MCP accessibility tests** (172 test cases)\n- **SQLite extension warnings** are automatically suppressed in test mode\n\n### Building\n\nTo build for production:\n\n```bash\n# Build stdio server\nbun run build\n\n# Build HTTP server\nbun run build:http\n```\n\n### Publishing\n\n#### Automated Release Process (Recommended)\n\nThis project uses [release-please](https://github.com/googleapis/release-please-action) for automated versioning and publishing:\n\n1. **Make changes** using [Conventional Commits](https://www.conventionalcommits.org/) format:\n   - `feat:` for new features (minor version bump)\n   - `fix:` for bug fixes (patch version bump)\n   - `feat!:` or `fix!:` for breaking changes (major version bump)\n\n2. **Push to main** - release-please will automatically:\n   - Create a release PR with updated version and changelog\n   - Once the release PR is merged, it will create a GitHub release\n   - The release will trigger automatic publication to npm, `ghcr.io` and the\n     [MCP Registry](https://registry.modelcontextprotocol.io)\n\n   The registry job runs last, because the registry verifies ownership by reading the\n   already-published artifacts: `mcpName` in the npm package, the\n   `io.modelcontextprotocol.server.name` label on the image, and the SHA-256 of the `.mcpb`\n   asset attached to the release. It authenticates with GitHub OIDC, so no registry\n   credential is stored anywhere.\n\n#### Manual Publishing\n\nTo publish the package manually:\n\n```bash\n# 1. Ensure you're logged in to npm\nnpm login\n\n# 2. Build the package\nbun run build\n\n# 3. Publish to npm\nnpm publish --access public\n```\n\n**Note**: Make sure to set the `NPM_TOKEN` secret in your repository settings for automated publishing.\n\n## 📚 Documentation\n\n- [CLAUDE.md](CLAUDE.md) - Development guidance for Claude Code when working with this repository\n- [MCP Documentation](https://modelcontextprotocol.io/introduction) - Official Model Context Protocol documentation\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n",
  "bytes": 41264,
  "sha": "4e92b8a818b23c8f87f57b4e967ab330ff0bd949091c4b5d35906cd2dfb58c3a",
  "repo_slug": "cedricziel/aha-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_cedricziel_aha_mcp_14cbfae2/readme"
}