Content
# Freedcamp MCP Server (multi-project fork)
[](./LICENSE)
[](https://nodejs.org/)
A Model Context Protocol (MCP) server for Freedcamp that works across **all** your projects. Discover projects, task lists, and users; create, update, list, and delete tasks (bulk and cross-project); create and edit projects; and comment on items - with credentials optionally sourced from AWS SSM so nothing secret lives in your client config.
> **Fork of [gabeosx/freedmcpcamp](https://github.com/gabeosx/freedmcpcamp).** What this fork adds:
> - Removes the single-project lock - `FREEDCAMP_PROJECT_ID` is now an **optional default**, a per-call `project_id` always wins.
> - New discovery tools: `freedcamp_list_projects`, `freedcamp_list_task_groups`, `freedcamp_list_users`.
> - Project write tools: `freedcamp_add_project`, `freedcamp_update_project` (the API treats name/color/group as mandatory on every edit, so partial edits auto-backfill from the live project).
> - Comment tools: `freedcamp_add_comment`, `freedcamp_update_comment`, `freedcamp_delete_comment` (comment on tasks and other items).
> - Pagination-aware listing (no silent 200-item truncation).
> - Per-task error isolation in bulk operations (one bad item doesn't fail the batch).
> - An AWS SSM credential launcher (`dist/ssm-launch.js`) + a one-command `scripts/setup.sh`.
>
> **Not published to npm** - install from source (see below). `npx freedcamp-mcp` would fetch the upstream package, which does NOT have these changes.
**Transports:** STDIO (default; for Claude Code, Cursor, Claude Desktop) and HTTP (for web/cloud).
## Features
- Discover and work across ALL your Freedcamp projects (not locked to a single project)
- List projects, task lists (groups), and project users for discovery
- Create multiple tasks in a single operation with title, description, priority, due date, assignee, target project, and task list
- Update existing tasks including status, task-list moves, and other changes
- List tasks for a specific project or across all accessible projects
- Delete tasks permanently
- Create and update projects (the API's mandatory edit fields are backfilled automatically, so a partial edit never wipes the others)
- Add, edit, and delete comments on tasks (and other Freedcamp items)
- Bulk operations support for all task, project, and comment operations (including across projects)
- Pagination-aware listing (no silent 200-item truncation)
- Optional default project via `FREEDCAMP_PROJECT_ID` (a per-call `project_id` always wins)
- Credentials via environment variables or AWS SSM Parameter Store
- Comprehensive error handling and validation
## Prerequisites
- Node.js 17 or higher
- Freedcamp account with API access - API Key and Secret (Freedcamp → avatar → Settings → API)
- (Optional) AWS CLI v2 + a profile, if you want SSM-backed credentials
## Installation
This fork is installed from source (not published to npm).
```bash
git clone https://github.com/justadityaraj/freedcamp-mcp.git
cd freedcamp-mcp
npm install
npm run build
```
**Fast path (Claude Code + AWS SSM):** if you keep credentials in SSM, just run `./scripts/setup.sh` - it builds, verifies AWS/SSM access, and registers the server with Claude Code (idempotent). See [Credentials via AWS SSM](#credentials-via-aws-ssm-keep-secrets-out-of-config).
**Credentials via `.env`** (for local runs / HTTP): create a `.env` in the repo root:
```bash
FREEDCAMP_API_KEY=your_api_key
FREEDCAMP_API_SECRET=your_api_secret
# Optional. If set, used as the DEFAULT project when a call omits project_id.
# A per-call project_id always overrides this. Leave unset to work across all projects.
FREEDCAMP_PROJECT_ID=your_project_id
```
## Usage
### Running the Server
Build first:
```bash
npm run build
```
#### STDIO Transport (Default)
The transport used by IDEs and MCP clients:
```bash
npm start # node dist/server.js
# or, with SSM-backed credentials:
npm run start:ssm # node dist/ssm-launch.js
```
#### HTTP Transport
For containerized deployments and HTTP-based integrations:
**Development (with .env file):**
```bash
npm run start:http:test
```
**Production (with environment variables):**
```bash
npm run start:http
```
**Direct execution:**
```bash
FREEDCAMP_API_KEY=your_key FREEDCAMP_API_SECRET=your_secret node dist/http-server.js
```
The HTTP server starts on port 3000 (or `PORT`) and provides:
- **MCP endpoint**: `http://localhost:3000/mcp`
- **Health check**: `http://localhost:3000/health`
> **⚠️ Security — the HTTP transport has no authentication by default.** Anyone who can reach the port can drive your Freedcamp account with your credentials. Set `MCP_AUTH_TOKEN` to require an `Authorization: Bearer <token>` header on every `/mcp` request, and only expose the server on a trusted network (or behind an authenticating proxy / tunnel). The STDIO transport is unaffected — it has no network surface.
>
> ```bash
> MCP_AUTH_TOKEN=$(openssl rand -hex 32) npm run start:http
> # then call it with: Authorization: Bearer <that token>
> ```
**HTTP Transport Features:**
- Stateless operation - each request is independent
- JSON responses with proper error handling
- Optional bearer-token auth via `MCP_AUTH_TOKEN` (off by default; see the warning above)
- Built-in health monitoring (`/health` reports version and whether auth is required)
- Suitable for load balancing and clustering
### Docker Deployment
For production deployments, you can use Docker to run the HTTP transport:
#### Using Docker Compose (Recommended)
1. Create a `.env` file with your Freedcamp credentials (`FREEDCAMP_API_KEY`, `FREEDCAMP_API_SECRET`, optional `FREEDCAMP_PROJECT_ID`).
2. Start the service:
```bash
docker-compose up -d
```
#### Using Docker directly
```bash
# Build the image
docker build -t freedcamp-mcp .
# Run the container
docker run -d \
--name freedcamp-mcp \
-p 3000:3000 \
-e FREEDCAMP_API_KEY=your_api_key \
-e FREEDCAMP_API_SECRET=your_api_secret \
-e MCP_AUTH_TOKEN=your_long_random_token \
freedcamp-mcp
```
The containerized server provides the same MCP functionality via HTTP transport, suitable for cloud, Kubernetes, and load-balanced setups. Because a container typically publishes the port beyond localhost, set `MCP_AUTH_TOKEN` (as shown) so `/mcp` requires `Authorization: Bearer <token>`.
### Running the Test Harness
```bash
npm test # STDIO: offline unit tests + (if creds present) a live integration scenario
npm run test:http # HTTP transport (requires the HTTP server running)
```
The STDIO harness runs offline `resolveProjectId` unit tests with no credentials, and - when `FREEDCAMP_API_KEY` / `FREEDCAMP_API_SECRET` are set - a live scenario: list_projects → list_task_groups + list_users → add → list → update → delete. It skips the live part (exit 0) when credentials are absent, so it is CI-safe.
### Multi-Project Workflow (Discover, Then Act)
This server is not locked to a single project. The recommended flow:
1. **`freedcamp_list_projects`** - discover the project IDs you have access to.
2. **`freedcamp_list_task_groups`** (optional) - find the `list_id` of a specific task list within a project.
3. **`freedcamp_list_users`** (optional) - find the `user_id` to use as `assigned_to_id`.
4. **`freedcamp_add_task` / `freedcamp_update_task` / `freedcamp_list_tasks`** - act on any project by passing `project_id`.
If you set `FREEDCAMP_PROJECT_ID`, it becomes the default project used whenever a call omits `project_id`. A per-call `project_id` always wins over the default. If neither is set, project-required tools return a clear error pointing you to `freedcamp_list_projects`, and `freedcamp_list_tasks` lists tasks across all accessible projects.
## Credentials via AWS SSM (keep secrets out of config)
Instead of putting `FREEDCAMP_API_KEY` / `FREEDCAMP_API_SECRET` in plaintext in your MCP client config, you can store them in AWS SSM Parameter Store and let the bundled launcher (`dist/ssm-launch.js`) fetch them at startup. The config then references only the parameter **names**, never the secret values.
**Fastest path on a new machine:** once the SSM parameters exist (step 1 below), run `./scripts/setup.sh` from the repo root. It builds the server, verifies AWS profile + SSM access, and registers the `freedcamp` MCP server with Claude Code (idempotent). Override defaults via `AWS_PROFILE`, `AWS_REGION`, `SSM_KEY_PARAM`, `SSM_SECRET_PARAM` env vars. The rest of this section explains what it does under the hood.
**1. Store the secrets once** (run in your own terminal so they never touch the config):
```bash
aws ssm put-parameter --name "/freedcamp-mcp/api-key" \
--type SecureString --value "YOUR_API_KEY" --region ap-south-1 --profile your-profile
aws ssm put-parameter --name "/freedcamp-mcp/api-secret" \
--type SecureString --value "YOUR_API_SECRET" --region ap-south-1 --profile your-profile
```
**2. Point the MCP client at the launcher** (`dist/ssm-launch.js`). It reads the params, injects them as env vars, then runs the server over the same stdio channel:
```json
{
"mcpServers": {
"freedcamp": {
"command": "node",
"args": ["/absolute/path/to/freedcamp-mcp/dist/ssm-launch.js"],
"env": {
"AWS_PROFILE": "your-profile",
"AWS_REGION": "ap-south-1"
}
}
}
}
```
Launcher environment variables (all optional, with the defaults shown):
| Variable | Default | Purpose |
|----------|---------|---------|
| `FREEDCAMP_SSM_KEY_PARAM` | `/freedcamp-mcp/api-key` | SSM param holding the API key |
| `FREEDCAMP_SSM_SECRET_PARAM` | `/freedcamp-mcp/api-secret` | SSM param holding the API secret |
| `FREEDCAMP_SSM_PROJECT_PARAM` | (unset) | SSM param holding a default project id |
| `AWS_PROFILE` | (CLI default) | AWS profile to use |
| `AWS_REGION` | `ap-south-1` | AWS region |
Requires AWS CLI v2 installed and a profile with `ssm:GetParameter` (and `kms:Decrypt` for SecureString) on the parameters. Diagnostics are written to stderr so they never corrupt the MCP protocol.
> **Git Bash note (Windows):** MSYS rewrites leading-slash arguments into Windows paths, which corrupts SSM param names when you call `aws ssm get-parameter --name /freedcamp-mcp/...` from Git Bash (you get a misleading `ParameterNotFound`). Prefix the command with `MSYS_NO_PATHCONV=1`. This does NOT affect the launcher (Node's `execFileSync` bypasses the shell) or the MCP client.
### Available Tools
1. **`freedcamp_list_projects`** (discovery)
- Lists all Freedcamp projects you have access to (active AND archived)
- No parameters
- Returns: `project_id`, `project_name`, `f_active` (`true` = active, `false` = archived), and (when available) `project_description`, `role_name`, `group_id`
- Pagination-aware (returns all projects, not just the first 200)
2. **`freedcamp_list_task_groups`** (discovery)
- Lists the task lists (groups) for a project
- Input: `project_id` (optional - falls back to the default project)
- Returns: `id` (this is the `list_id` you pass on a task), `title`, `project_id`
3. **`freedcamp_list_users`** (discovery)
- Lists the users in a project
- Input: `project_id` (optional - falls back to the default project)
- Returns: `user_id` (this is the `assigned_to_id` you pass on a task), `full_name`, `email`
4. **`freedcamp_add_task`**
- Creates one or more new tasks in Freedcamp (supports bulk, including across projects)
- Input: Object with `tasks` array containing task details
- Task Parameters:
- `title` (required): Task title - should be clear and descriptive
- `project_id` (optional): Project to create the task in. Falls back to the default project; a value here overrides the default.
- `description` (optional): Detailed description of what the task involves
- `list_id` (optional): Task list (group) ID to place the task in. Defaults to the project's first task list.
- `priority` (optional): Task priority level (0=None, 1=Low, 2=Medium, 3=High)
- `due_date` (optional): Due date as a `YYYY-MM-DD` string (e.g., `2026-01-26`). NOT a Unix timestamp - the API rejects timestamps for due dates.
- `assigned_to_id` (optional): User ID to assign the task to (must be valid Freedcamp user ID)
5. **`freedcamp_update_task`**
- Updates one or more existing tasks in Freedcamp
- Input: Object with `tasks` array containing task updates
- Task Parameters:
- `task_id` (required): ID of the task to update (must be valid existing Freedcamp task ID)
- `title` (optional): New task title
- `description` (optional): New task description
- `list_id` (optional): Task list (group) ID to move the task into
- `priority` (optional): New task priority (0=None, 1=Low, 2=Medium, 3=High)
- `due_date` (optional): New due date as a `YYYY-MM-DD` string (e.g., `2026-01-26`). NOT a Unix timestamp.
- `assigned_to_id` (optional): User ID to reassign the task to
- `status` (optional): New task status (0=Not started, 1=Completed, 2=In progress)
6. **`freedcamp_list_tasks`**
- Retrieves tasks from Freedcamp (pagination-aware)
- Input: `project_id` (optional). If provided, scopes to that project; otherwise uses the default project. If neither is set, lists tasks across ALL accessible projects.
- Returns task details including ID, title, status, and other metadata
7. **`freedcamp_delete_task`**
- Permanently deletes one or more tasks from Freedcamp
- Input: Object with `tasks` array containing task IDs to delete
- Task Parameters:
- `task_id` (required): ID of the task to delete (WARNING: This action cannot be undone)
8. **`freedcamp_add_project`**
- Creates one or more new projects (supports bulk)
- Input: Object with `projects` array
- Project Parameters:
- `project_name` (required): Project name (max 255 characters)
- `project_description` (optional)
- `project_color` (optional): HEX color WITHOUT the `#`, e.g. `34ad22` (defaults to `34ad22`)
- `group_id` / `group_name` (optional): place the project in a group (folder); if neither is given the project is created without a group
- `todo_view_type` (optional): `default` (list) or `kanban`
- Returns the new `project_id`
9. **`freedcamp_update_project`**
- Updates one or more existing projects: rename, change description/color, move between groups, archive/unarchive (supports bulk)
- Input: Object with `projects` array
- Project Parameters:
- `project_id` (required)
- `project_name`, `project_description`, `project_color`, `group_id` / `group_name` (optional)
- `f_active` (optional): `true` = unarchive, `false` = archive
- The Freedcamp API treats name + color + group as MANDATORY on every edit. Any you omit are auto-filled from the project's current values, so a partial edit (e.g. rename-only) won't wipe the others. If the current project can't be loaded, the edit is refused rather than risk a destructive partial write.
10. **`freedcamp_add_comment`**
- Adds one or more comments to items - tasks by default (supports bulk)
- Input: Object with `comments` array
- Comment Parameters:
- `item_id` (required): the item to comment on (e.g. a `task_id`)
- `description` (required): comment text (HTML supported)
- `app_id` (optional): the item's application id, defaults to `2` (Tasks). Others: 3=Files/Discussions, 13=Bug Tracker, 14=Wiki, 19=Calendar
- Returns the new `comment_id`
11. **`freedcamp_update_comment`**
- Edits one or more existing comments (supports bulk)
- Input: Object with `comments` array
- Comment Parameters:
- `comment_id` (required)
- `description` (required): the new comment text
12. **`freedcamp_delete_comment`**
- Permanently deletes one or more comments (supports bulk)
- Input: Object with `comments` array
- Comment Parameters:
- `comment_id` (required): ID of the comment to delete (WARNING: This action cannot be undone)
### Example Usage
**Creating multiple tasks (uses the default project):**
```json
{
"tasks": [
{
"title": "Setup project structure",
"description": "Initialize the basic project folder structure",
"priority": 2,
"due_date": "2026-01-26"
},
{
"title": "Implement authentication",
"description": "Add user login and registration functionality",
"priority": 3,
"assigned_to_id": "12345"
}
]
}
```
**Creating tasks across multiple projects:**
First discover project IDs with `freedcamp_list_projects`, then target them per task. A single bulk call can write to different projects at once. One task failing (e.g. an unresolved project) does not fail the rest of the batch.
```json
{
"tasks": [
{
"project_id": "111111",
"title": "Draft Q3 roadmap",
"list_id": "555555",
"priority": 3
},
{
"project_id": "222222",
"title": "Review marketing copy",
"assigned_to_id": "98765"
}
]
}
```
**Listing tasks for a specific project:**
```json
{
"project_id": "111111"
}
```
Omit `project_id` (and leave `FREEDCAMP_PROJECT_ID` unset) to list tasks across all accessible projects.
**Updating multiple tasks:**
```json
{
"tasks": [
{ "task_id": "67890", "status": 1, "description": "Updated: Added OAuth integration" },
{ "task_id": "67891", "priority": 3, "due_date": "2026-01-27" }
]
}
```
**Deleting multiple tasks:**
```json
{
"tasks": [
{ "task_id": "67892" },
{ "task_id": "67893" }
]
}
```
## IDE / Client Integration
Because this fork is installed from source, MCP clients point at the built files in `dist/` (run `npm install && npm run build` first). Supply credentials either via **AWS SSM** (recommended - point at `dist/ssm-launch.js`) or **environment variables** (point at `dist/server.js`).
### Claude Code
Easiest is the bundled script (builds, verifies AWS/SSM, registers at user scope):
```bash
./scripts/setup.sh
```
Or register manually:
```bash
# Option A - SSM launcher (no secrets in config)
claude mcp add freedcamp -s user -e AWS_PROFILE=your-profile -e AWS_REGION=ap-south-1 \
-- node /absolute/path/to/freedcamp-mcp/dist/ssm-launch.js
# Option B - credentials in env
claude mcp add freedcamp -s user \
-e FREEDCAMP_API_KEY=your_key -e FREEDCAMP_API_SECRET=your_secret \
-- node /absolute/path/to/freedcamp-mcp/dist/server.js
```
### Cursor / Claude Desktop (JSON config)
Add to `.cursor/mcp.json` (Cursor) or `claude_desktop_config.json` (Claude Desktop - `~/Library/Application Support/Claude/` on macOS, `%APPDATA%/Claude/` on Windows):
```json
{
"mcpServers": {
"freedcamp": {
"command": "node",
"args": ["/absolute/path/to/freedcamp-mcp/dist/ssm-launch.js"],
"env": {
"AWS_PROFILE": "your-profile",
"AWS_REGION": "ap-south-1"
}
}
}
}
```
For env-based credentials instead of SSM, point `args` at `dist/server.js` and set `FREEDCAMP_API_KEY` / `FREEDCAMP_API_SECRET` (and an optional `FREEDCAMP_PROJECT_ID` default) in `env`. Restart/reload the client after editing.
### HTTP transport
For a hosted setup, run `npm run start:http` (or `node dist/http-server.js`) and point the client at `http://localhost:3000/mcp`.
## API Reference
For detailed information about Freedcamp's API, visit: https://freedcamp.com/api-docs
## License
MIT License - see the [LICENSE](./LICENSE) file for details. Forked from [gabeosx/freedmcpcamp](https://github.com/gabeosx/freedmcpcamp).
<!-- by [Aditya Raj Singh](https://adityarajsingh.com/) -->
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available