Run your whole workspace by asking.
Freedcamp MCP exposes tasks, lists, milestones, time tracking, the Issue Tracker, discussions, wikis, files, the calendar and CRM as 102 tools any MCP client can call. Point Claude, Cursor or Codex CLI at it and ask for what you want in plain language.
https://mcp.freedcamp.com/mcp
fc_“Create a Fix login race condition task in the API Platform project, due Friday, assigned to me, In Progress.”
“Show every task assigned to me that is overdue, grouped by project.”
“Log 45 minutes on the Acme refactor for today and mark it billed.”
Quickstart
One way in, and nothing to install: the hosted OAuth endpoint. Add it to your client as a remote MCP server, authorize once in the browser with your own Freedcamp API key, and all 102 tools are live. Pick your client below.
Open Settings → Connectors, choose Add ▾ → Add custom connector, and paste the endpoint below. Claude walks you through authorization in the browser.
https://mcp.freedcamp.com/mcp
One command adds the connector. Then run /mcp inside the session and pick Authenticate to finish in the browser.
claude mcp add --transport http freedcamp https://mcp.freedcamp.com/mcp
Create .cursor/mcp.json in your project, or add the same block to your global Cursor MCP settings. Cursor opens the authorization page on first use.
{
"mcpServers": {
"freedcamp": { "url": "https://mcp.freedcamp.com/mcp" }
}
}Add the server to ~/.codex/config.toml. Remote MCP servers need Codex’s streamable-HTTP client enabled, so keep both lines.
experimental_use_rmcp_client = true [mcp_servers.freedcamp] url = "https://mcp.freedcamp.com/mcp"
Both read the standard mcpServers shape — Cline from its MCP Servers panel, Continue from config.json.
{
"mcpServers": {
"freedcamp": {
"type": "streamableHttp",
"url": "https://mcp.freedcamp.com/mcp"
}
}
}Add this to .vscode/mcp.json or your User Settings (JSON). VS Code prompts you to sign in the first time the server is used.
{
"servers": {
"freedcamp": {
"type": "http",
"url": "https://mcp.freedcamp.com/mcp"
}
}
}Whichever client you use, the first request opens a Freedcamp authorization page in your browser. Paste your API key and secret there once — they are never stored in a config file. Then ask “list my Freedcamp projects” to confirm the connection.
Claude Desktop, click by click
No config file, no terminal — six clicks from the menu bar to a working connection. Step through the screens below.

In the macOS menu bar click Claude, then Settings… — or just press ⌘, from anywhere in the app. On Windows it is the same panel, reached from the app menu.

Scroll the settings sidebar down to Customize and pick Connectors. This is the list of everything Claude can reach — MCP servers show up here as connectors.

Top right of the Connectors panel, open Add ▾ and choose Add custom connector. Freedcamp MCP is not in the browse list — it is your own hosted endpoint.

Call it Freedcamp-MCP (this is only the label you will see in the list), paste https://mcp.freedcamp.com/mcp as the address, and click Continue.

Claude probes the server and pre-selects the right options — Always required authentication and No client ID — register one automatically, both marked Detected. Leave them alone, skip the headers, and click Add.

A browser page opens. Paste the API Key and API Secret from Freedcamp → Settings → API and hit Authorize. Your credentials go to Freedcamp, never to Claude. Back in the app, ask “list my Freedcamp projects” to confirm all 102 tools are live.
Authentication
Freedcamp MCP supports OAuth only. Every call is made as you, with your own Freedcamp API key and secret — handed over on a Freedcamp authorization page, never pasted into a config file. The server signs upstream requests with HMAC, so your secret is never sent as a credential.
In Freedcamp, go to Settings → API and create an API key. You get a key and a secret. The secret is shown once.
Your client redirects to the Freedcamp authorization page on first use. Paste the key and secret there and press Authorize — the page talks to Freedcamp, not to your AI client.
Your credentials are verified against the Freedcamp API, then encrypted into a bearer token with AES-256-GCM. A bad key fails immediately, at authorization time, rather than on your first request.
OAuth over the hosted HTTPS endpoint is the only supported transport today — there is no npx install, no environment variables and no config file to keep secrets in. If you need a self-hosted or stdio option, say so on the GitHub repository.
How the AI should work
The server ships instructions that MCP clients read on connect. Worth knowing, because it explains why your assistant behaves the way it does.
Call fc_get_groups_projects once at the start of a conversation to get groups, projects and their apps by human-readable name — then reuse that result instead of re-fetching. Only refresh if the user asks, or after creating or deleting a project.
Prefer the project and app names from that first call when talking to the user. fc_add_item_by_names and fc_add_comment_by_names accept names directly.
Every fc_fetch_* tool is marked read-only, every fc_delete_* destructive. Clients use those hints to decide what to confirm with you.
Silent no-ops are treated as failures. Starting an already-running timer returns isError: true with the entry state, not a cheerful “done”.
Comments, links and files are addressed by app: 2 Tasks, 3 Discussions, 4 Milestones, 5 Time, 6 Files, 13 Issue Tracker, 14 Wikis, 16 CRM, 19 Calendar, 37 Overview.
Tool reference
All 102 tools, grouped by the Freedcamp app they drive. Every tool takes a flat JSON object; anything not marked required can be left out. Search filters by tool name, description and parameter name.
Values below are illustrative — IDs come from your own workspace via fc_get_groups_projects.
Helpers & discovery
5 toolsStart here. These resolve your workspace by human-readable name so nothing downstream has to guess an ID.
fc_get_groups_projectsRead-onlyGroups, projects and their apps keyed by readable name. The preferred first call in any conversation — call once, reuse the result.
{
"name": "fc_get_groups_projects",
"arguments": {}
}fc_fetch_current_sessionRead-onlyThe current user and session, including raw groups and projects. Call once at the start rather than repeatedly.
{
"name": "fc_fetch_current_session",
"arguments": {}
}fc_add_item_by_namesWritesAdd an item to an app inside a project by name instead of ID. Tasks are supported today.
project_namestring · requiredA project name from fc_get_groups_projects.app_namestring · requiredApp name, e.g. Tasks, Discussions, Issue Tracker.titlestring · requiredTitle of the item to add.{
"name": "fc_add_item_by_names",
"arguments": {
"project_name": "API Platform",
"app_name": "Tasks",
"title": "Fix login race condition"
}
}fc_add_comment_by_namesWritesComment on any item, naming the app instead of passing a numeric app_id.
item_idstring · requiredID of the task, issue or discussion to comment on.app_namestring · requiredApp name that owns the item.descriptionstring · requiredComment body — wrap in <p> tags.{
"name": "fc_add_comment_by_names",
"arguments": {
"item_id": "18432901",
"app_name": "Tasks",
"description": "<p>Two tabs, one session — reproduces on staging.</p>"
}
}fc_update_statusWritesUpdate a task's status with a single call.
item_idstring · requiredID of the task to update.statusstring | int · required0 not started, 1 completed, 2 in progress, 3 invalid, 4 review.{
"name": "fc_update_status",
"arguments": {
"item_id": "18432901",
"status": 2
}
}Projects
10 toolsCreate, edit, favourite and leave projects. Overview returns the project's dashboard summary.
fc_fetch_projectsRead-onlyEvery project, flat — no group or app context. Prefer fc_get_groups_projects.
{
"name": "fc_fetch_projects",
"arguments": {}
}fc_fetch_projectRead-onlyA single project by ID.
project_idstring · requiredID of the project to fetch.{
"name": "fc_fetch_project",
"arguments": {
"project_id": "7451190"
}
}fc_fetch_recent_project_idsRead-onlyIDs of the projects you touched most recently.
{
"name": "fc_fetch_recent_project_ids",
"arguments": {}
}fc_add_projectWritesCreate a project, optionally inside a new or existing group.
project_namestring · requiredName of the new project.project_descriptionstringDescription of the project.project_colorstringHex colour without the leading #, e.g. 1C7160.todo_view_typestringDefault task view — list or board.usage_typeintFreedcamp usage-type ID for the project template.group_idstringExisting group to create the project under.group_namestringName for a new group to create for it.{
"name": "fc_add_project",
"arguments": {
"project_name": "API Platform"
}
}fc_edit_projectWritesRename a project, recolour it, or move it between groups.
project_idstring · requiredID of the project to edit.project_namestringNew project name.project_colorstringNew hex colour, no leading #.group_idstringMove the project to this group.cs_tpl_idstringCustom-field template to apply.{
"name": "fc_edit_project",
"arguments": {
"project_id": "7451190"
}
}fc_leave_projectDestructiveLeave a project you are a member of.
membership_idstring · requiredYour membership ID — not the project ID.{
"name": "fc_leave_project",
"arguments": {
"membership_id": "6640012"
}
}fc_delete_projectDestructivePermanently delete a project.
project_idstring · requiredID of the project to delete.{
"name": "fc_delete_project",
"arguments": {
"project_id": "7451190"
}
}fc_fetch_overviewRead-onlyThe project's overview payload — progress, activity and app summaries.
project_idstring · requiredID of the project.{
"name": "fc_fetch_overview",
"arguments": {
"project_id": "7451190"
}
}fc_add_favorite_projectWritesPin a project to your favourites.
project_idstring · requiredID of the project.{
"name": "fc_add_favorite_project",
"arguments": {
"project_id": "7451190"
}
}fc_delete_favorite_projectDestructiveRemove a project from your favourites.
project_idstring · requiredID of the project.{
"name": "fc_delete_favorite_project",
"arguments": {
"project_id": "7451190"
}
}Tasks
6 toolsThe busiest group. Tasks carry status, priority, assignee, dates, recurrence, subtasks, tags and custom fields — and can be edited 500 at a time.
fc_fetch_taskRead-onlyA single task by ID.
task_idstring · requiredID of the task to fetch.{
"name": "fc_fetch_task",
"arguments": {
"task_id": "18432901"
}
}fc_fetch_tasksRead-onlyList tasks with filters and sorting. Omit project_id to search across every project you can see.
limitintMaximum results per page.offsetintResults to skip, for paging.project_idstringRestrict to one project. Omit for all accessible projects.filters.statusstring[]STATUS_NOT_STARTED, STATUS_COMPLETED, STATUS_IN_PROGRESS, STATUS_INVALID, STATUS_REVIEW.filters.assigned_to_idstring[]Only tasks assigned to these user IDs.filters.created_by_idstringOnly tasks created by this user.filters.due_date_fromstringDue on or after YYYY-MM-DD.filters.due_date_tostringDue on or before YYYY-MM-DD.filters.created_date_fromstringCreated on or after YYYY-MM-DD.filters.created_date_tostringCreated on or before YYYY-MM-DD.filters.f_with_archivedint1 includes tasks from archived lists; 0 is the default.filters.list_statusstringFilter by parent list status — active or archived.filters.f_include_tagsint1 returns each task's tags.filters.order_priorityasc | descSort by priority.filters.order_due_dateasc | descSort by due date.{
"name": "fc_fetch_tasks",
"arguments": {
"project_id": "7451190",
"limit": 25,
"filters": {
"status": ["STATUS_NOT_STARTED", "STATUS_IN_PROGRESS"],
"assigned_to_id": ["4410021"],
"due_date_to": "2026-09-11",
"order_due_date": "asc"
}
}
}fc_add_taskWritesCreate a task, with scheduling, recurrence, assignment, attachments, subtasks and custom fields.
titlestring · requiredTask title.project_idstring · requiredProject the task belongs to.descriptionstringBody text — plain text or HTML.list_idstringTask list to place it in. Omit for the project default.task_group_idstringLegacy alias for list_id. Send one or the other.priorityint0 none, 1 low, 2 medium, 3 high.assigned_to_idstringUser to assign it to.start_datestringYYYY-MM-DD or YYYY-MM-DD HH:mm:ss. Surfaces in the calendar.due_datestringYYYY-MM-DD or YYYY-MM-DD HH:mm:ss.r_rulestringRecurrence, e.g. FREQ=WEEKLY;BYDAY=MO,WE.statusint0 not started, 1 completed, 2 in progress, 3 invalid, 4 review.completed_datestringSet alongside status 1.attached_idsstring[]IDs of files already uploaded.h_parent_idstringParent task, making this a subtask. Same list, and the parent cannot itself be a subtask.cf_tpl_idintCustom-fields template ID. Usually inferred.custom_fieldsobject[]{ cf_id, value, dd_actual_value } from fc_fetch_cf_templates.{
"name": "fc_add_task",
"arguments": {
"title": "Fix login race condition",
"project_id": "7451190",
"description": "<p>Two tabs, one session — reproduces on staging.</p>",
"list_id": "9012345",
"priority": 3,
"status": 2,
"assigned_to_id": "4410021",
"due_date": "2026-09-11"
}
}fc_update_taskWritesUpdate any field on a task, move it between lists, or make it a subtask.
task_idstring · requiredID of the task to update.titlestringNew title.descriptionstringNew body text.list_idstringMove the task to this list.task_group_idstringLegacy alias for list_id.statusint0 not started, 1 completed, 2 in progress, 3 invalid, 4 review.priorityint0 none, 1 low, 2 medium, 3 high.assigned_to_idstringReassign to this user.start_datestringNew start date. Empty string clears it.due_datestringNew due date.r_rulestringNew recurrence. Empty string stops recurrence.attached_idsstring[]Replaces the current attachment set.h_parent_idstringNew parent. Empty string promotes a subtask back to top level.cf_tpl_idintCustom-fields template ID.custom_fieldsobject[]Custom field values to set.{
"name": "fc_update_task",
"arguments": {
"task_id": "18432901"
}
}fc_batch_edit_tasksWritesApply the same change to up to 500 tasks in one request. Only the fields you send change.
batch_idsstring[] · required1–500 task IDs to edit.statusintStatus to set on every listed task.priorityintPriority to set on every listed task.assigned_to_idstringSingle assignee for all of them.assigned_idsstring[]Multiple assignees, replacing the current set.titlestringNew title for every listed task.descriptionstringNew description for every listed task.start_datestringStart date to set.due_datestringDue date to set.ms_idstringMilestone to link them to.h_parent_idstringParent task to nest them under.tagsstring[]Tag names to set.custom_fieldsobject[]Custom field values to set.follower_idsstring[]Followers to add or remove.followers_operationstringappend or remove, controlling follower_ids.{
"name": "fc_batch_edit_tasks",
"arguments": {
"batch_ids": ["18432901", "18432902", "18432903"],
"status": 1,
"assigned_to_id": "4410021"
}
}fc_delete_taskDestructiveDelete a task.
task_idstring · requiredID of the task to delete.{
"name": "fc_delete_task",
"arguments": {
"task_id": "18432901"
}
}Lists
4 toolsLists are the containers inside an app — task lists, discussion folders, wiki folders. app_id defaults to 2 (Tasks).
fc_fetch_listsRead-onlyLists for a project, for one app.
project_idstring · requiredProject whose lists to fetch.app_idintApp the lists belong to. Default 2 (Tasks).{
"name": "fc_fetch_lists",
"arguments": {
"project_id": "7451190"
}
}fc_add_listWritesCreate a list.
project_idstring · requiredProject the list belongs to.titlestring · requiredList title.app_idintApp to create it under. Default 2 (Tasks).descriptionstringList description.{
"name": "fc_add_list",
"arguments": {
"project_id": "7451190",
"title": "Fix login race condition"
}
}fc_edit_listWritesRename or re-describe a list.
list_idstring · requiredID of the list to edit.titlestring · requiredNew list title.app_idintApp the list belongs to. Default 2.descriptionstringNew description.{
"name": "fc_edit_list",
"arguments": {
"list_id": "9012345",
"title": "Fix login race condition"
}
}fc_delete_listDestructiveDelete a list.
list_idstring · requiredID of the list to delete.app_idintApp the list belongs to. Default 2.{
"name": "fc_delete_list",
"arguments": {
"list_id": "9012345"
}
}Comments
3 toolsOne comment surface for every app. Pass the app_id that owns the item, or use fc_add_comment_by_names.
fc_add_commentWritesComment on a task, issue, discussion or any other item.
item_idstring · requiredID of the item to comment on.app_idint · requiredApp that owns the item — 2 Tasks, 3 Discussions, 13 Issue Tracker.descriptionstring · requiredComment body.attached_idsstring[]IDs of files already uploaded.{
"name": "fc_add_comment",
"arguments": {
"item_id": "18432901",
"app_id": 2,
"description": "<p>Two tabs, one session — reproduces on staging.</p>"
}
}fc_edit_commentWritesRewrite a comment body.
comment_idstring · requiredID of the comment to edit.descriptionstring · requiredNew comment body.{
"name": "fc_edit_comment",
"arguments": {
"comment_id": "9987120",
"description": "<p>Two tabs, one session — reproduces on staging.</p>"
}
}fc_delete_commentDestructiveDelete a comment.
comment_idstring · requiredID of the comment to delete.{
"name": "fc_delete_comment",
"arguments": {
"comment_id": "9987120"
}
}Calendar
6 toolsEvents with times, all-day flags, recurrence and invitees. fc_fetch_calendar_items also picks up dated tasks and milestones.
fc_fetch_eventsRead-onlyList calendar events.
project_idstringRestrict to one project. Omit for all.{
"name": "fc_fetch_events",
"arguments": {}
}fc_fetch_eventRead-onlyA single event.
event_idstring · requiredID of the event.{
"name": "fc_fetch_event",
"arguments": {
"event_id": "6620481"
}
}fc_add_eventWritesCreate an event, optionally recurring, with invitees.
project_idstring · requiredProject the event belongs to.titlestring · requiredEvent title.start_datestring · requiredStart date, YYYY-MM-DD.descriptionstringEvent description.f_all_dayint1 for an all-day event, 0 for a timed one.start_timestringHH:mm. Omit for all-day events.end_datestringEnd date, YYYY-MM-DD.end_timestringHH:mm. Omit for all-day events.r_rulestringiCalendar RRULE, e.g. FREQ=WEEKLY;COUNT=10.f_response_notifyint1 notifies the organizer when invitees respond.mixed_usersstring[]User IDs to invite.attached_idsstring[]IDs of files already uploaded.{
"name": "fc_add_event",
"arguments": {
"project_id": "7451190",
"title": "Fix login race condition",
"start_date": "2026-09-08"
}
}fc_edit_eventWritesEdit an event's title, timing, recurrence or attachments.
event_idstring · requiredID of the event to edit.titlestringNew title.descriptionstringNew description.f_all_dayint1 all-day, 0 timed.start_datestringNew start date.start_timestringNew start time.end_datestringNew end date.end_timestringNew end time.r_rulestringNew recurrence rule.attached_idsstring[]Attachment IDs.{
"name": "fc_edit_event",
"arguments": {
"event_id": "6620481"
}
}fc_delete_eventDestructiveDelete an event.
event_idstring · requiredID of the event to delete.{
"name": "fc_delete_event",
"arguments": {
"event_id": "6620481"
}
}fc_fetch_calendar_itemsRead-onlyEverything dated in a project — events plus tasks and milestones with dates.
project_idstringRestrict to one project. Omit for all.{
"name": "fc_fetch_calendar_items",
"arguments": {}
}Discussions
5 toolsThreaded conversations, optionally sticky or private to named users.
fc_fetch_discussionsRead-onlyList discussions in a project.
limitintMaximum results per page.offsetintResults to skip, for paging.project_idstring · requiredProject whose discussions to fetch.{
"name": "fc_fetch_discussions",
"arguments": {
"project_id": "7451190"
}
}fc_fetch_discussionRead-onlyA single discussion.
discussion_idstring · requiredID of the discussion.{
"name": "fc_fetch_discussion",
"arguments": {
"discussion_id": "2231560"
}
}fc_add_discussionWritesStart a discussion, filed under an existing or brand-new list.
titlestring · requiredDiscussion title.project_idstring · requiredProject it belongs to.descriptionstringOpening post body.list_idstringExisting list to file it under.list_titlestringTitle for a new list to create for it.list_descrstringDescription for that new list.f_stickyint1 pins it to the top.f_privateint1 limits it to private_users.private_usersstring[]User IDs allowed to see it when private.notificationsstring[]User IDs to notify.attached_idsstring[]IDs of files already uploaded.{
"name": "fc_add_discussion",
"arguments": {
"title": "Fix login race condition",
"project_id": "7451190"
}
}fc_edit_discussionWritesRename, re-file or pin a discussion.
discussion_idstring · requiredID of the discussion to edit.titlestringNew title.list_idstringMove it to this list.list_titlestringTitle for a new list to move it into.list_descrstringDescription for that new list.f_stickyint1 pins, 0 unpins.{
"name": "fc_edit_discussion",
"arguments": {
"discussion_id": "2231560"
}
}fc_delete_discussionDestructiveDelete a discussion.
discussion_idstring · requiredID of the discussion to delete.{
"name": "fc_delete_discussion",
"arguments": {
"discussion_id": "2231560"
}
}Issue Tracker
5 toolsBug and request tracking. Status and type are project-defined workflow IDs, so read them off an existing issue first.
fc_fetch_issuesRead-onlyList issues in a project.
limitintMaximum results per page.offsetintResults to skip, for paging.project_idstring · requiredProject whose issues to fetch.{
"name": "fc_fetch_issues",
"arguments": {
"project_id": "7451190"
}
}fc_fetch_issueRead-onlyA single issue.
issue_idstring · requiredID of the issue.{
"name": "fc_fetch_issue",
"arguments": {
"issue_id": "5511207"
}
}fc_add_issueWritesFile an issue.
titlestring · requiredIssue title.project_idstring · requiredProject it belongs to.descriptionstringIssue description.priorityint0 none, 1 low, 2 medium, 3 high.statusintProject-defined workflow status ID.typeintProject-defined type ID, e.g. bug or feature.assigned_to_idstringUser to assign it to.due_datestringYYYY-MM-DD.closer_idstringUser who resolved it.attached_idsstring[]IDs of files already uploaded.{
"name": "fc_add_issue",
"arguments": {
"title": "Fix login race condition",
"project_id": "7451190"
}
}fc_edit_issueWritesUpdate an issue's fields, status or assignee.
issue_idstring · requiredID of the issue to edit.titlestringNew title.descriptionstringNew description.priorityint0 none, 1 low, 2 medium, 3 high.statusintProject-defined workflow status ID.typeintProject-defined type ID.assigned_to_idstringReassign to this user.due_datestringNew due date.closer_idstringUser who resolved it.attached_idsstring[]Attachment IDs.{
"name": "fc_edit_issue",
"arguments": {
"issue_id": "5511207"
}
}fc_delete_issueDestructiveDelete an issue.
issue_idstring · requiredID of the issue to delete.{
"name": "fc_delete_issue",
"arguments": {
"issue_id": "5511207"
}
}Milestones
5 toolsDated goalposts you can hang tasks off via fc_batch_edit_tasks and its ms_id field.
fc_fetch_milestonesRead-onlyList milestones in a project.
limitintMaximum results per page.offsetintResults to skip, for paging.project_idstring · requiredProject whose milestones to fetch.{
"name": "fc_fetch_milestones",
"arguments": {
"project_id": "7451190"
}
}fc_fetch_milestoneRead-onlyA single milestone.
milestone_idstring · requiredID of the milestone.{
"name": "fc_fetch_milestone",
"arguments": {
"milestone_id": "3308115"
}
}fc_add_milestoneWritesCreate a milestone.
titlestring · requiredMilestone title.project_idstring · requiredProject it belongs to.descriptionstringMilestone description.priorityint0 none, 1 low, 2 medium, 3 high.statusint0 not started, 1 completed, 2 in progress, 3 invalid, 4 review.assigned_to_idstringUser to assign it to.start_datestringYYYY-MM-DD.due_datestringYYYY-MM-DD.{
"name": "fc_add_milestone",
"arguments": {
"title": "Fix login race condition",
"project_id": "7451190"
}
}fc_edit_milestoneWritesUpdate a milestone.
milestone_idstring · requiredID of the milestone to edit.titlestringNew title.descriptionstringNew description.priorityint0 none, 1 low, 2 medium, 3 high.statusintNew status.assigned_to_idstringReassign to this user.start_datestringNew start date.due_datestringNew due date.{
"name": "fc_edit_milestone",
"arguments": {
"milestone_id": "3308115"
}
}fc_delete_milestoneDestructiveDelete a milestone.
milestone_idstring · requiredID of the milestone to delete.{
"name": "fc_delete_milestone",
"arguments": {
"milestone_id": "3308115"
}
}Time tracking
6 toolsLog minutes, run timers and mark work billed. Timer actions verify the entry actually changed state.
fc_fetch_timesRead-onlyList time entries in a project.
limitintMaximum results per page.offsetintResults to skip, for paging.project_idstring · requiredProject whose entries to fetch.{
"name": "fc_fetch_times",
"arguments": {
"project_id": "7451190"
}
}fc_fetch_timeRead-onlyA single time entry.
time_idstring · requiredID of the entry.{
"name": "fc_fetch_time",
"arguments": {
"time_id": "7723004"
}
}fc_add_timeWritesLog time, or start a running timer.
project_idstring · requiredProject the entry belongs to.datestring · requiredDate logged, YYYY-MM-DD.minutes_countint · requiredDuration in minutes.descriptionstringWhat the work was.assigned_to_idstringWhose time this is. Defaults to you; the call fails if it cannot be determined.f_startedint | boolean1 or true creates it as a running timer.f_billedint | boolean1 or true marks it billed.{
"name": "fc_add_time",
"arguments": {
"project_id": "7451190",
"date": "2026-09-04",
"minutes_count": 45,
"description": "Acme refactor",
"f_billed": 1
}
}fc_edit_timeWritesAdjust an entry's duration, date, note or owner.
time_idstring · requiredID of the entry to edit.descriptionstringNew description.assigned_to_idstringReassign the entry.datestringNew date.minutes_countintNew duration in minutes.{
"name": "fc_edit_time",
"arguments": {
"time_id": "7723004"
}
}fc_delete_timeDestructiveDelete a time entry.
time_idstring · requiredID of the entry to delete.{
"name": "fc_delete_time",
"arguments": {
"time_id": "7723004"
}
}fc_time_actionWritesStart, stop, bill or unbill an entry. If nothing actually changed, the call fails rather than reporting success.
time_idstring · requiredID of the entry to act on.actionstart | stop | bill | unbill · requiredThe action to perform.{
"name": "fc_time_action",
"arguments": {
"time_id": "7723004",
"action": "start"
}
}Wikis
6 toolsVersioned pages with private and public visibility. Edits can overwrite or save as a new version.
fc_fetch_wikisRead-onlyList wiki pages in a project.
limitintMaximum results per page.offsetintResults to skip, for paging.project_idstring · requiredProject whose pages to fetch.order_titlestringasc or desc by title. Default asc.{
"name": "fc_fetch_wikis",
"arguments": {
"project_id": "7451190"
}
}fc_fetch_wikiRead-onlyA single wiki page.
wiki_idstring · requiredID of the page.{
"name": "fc_fetch_wiki",
"arguments": {
"wiki_id": "4419902"
}
}fc_add_wikiWritesCreate a wiki page.
titlestring · requiredPage title.project_idstring · requiredProject it belongs to.descriptionstringPage content — HTML or plain text.list_idstringExisting wiki folder to file it under.list_titlestringTitle for a new folder to create.list_descrstringDescription for that new folder.f_privateint1 limits it to private_users.f_publicint1 makes it viewable without login.private_usersstring[]User IDs allowed to view it when private.attached_idsstring[]IDs of files already uploaded.{
"name": "fc_add_wiki",
"arguments": {
"title": "Fix login race condition",
"project_id": "7451190"
}
}fc_edit_wikiWritesEdit a page — overwrite it, or save the edit as a new version.
wiki_idstring · requiredID of the page to edit.titlestringNew title.descriptionstringNew content.list_idstringMove it to this folder.list_titlestringTitle for a new folder to move it into.list_descrstringDescription for that new folder.f_privateint1 limits it to private_users.f_publicint1 makes it publicly viewable.private_usersstring[]User IDs allowed to view it.attached_idsstring[]Attachment IDs.f_new_versionbooleantrue saves the edit as a new version instead of overwriting.{
"name": "fc_edit_wiki",
"arguments": {
"wiki_id": "4419902"
}
}fc_delete_wikiDestructiveDelete a wiki page.
wiki_idstring · requiredID of the page to delete.{
"name": "fc_delete_wiki",
"arguments": {
"wiki_id": "4419902"
}
}fc_add_wiki_versionWritesAdd a new version to an existing page.
wiki_idstring · requiredID of the page.titlestringTitle for the new version.descriptionstringContent for the new version.attached_idsstring[]Attachment IDs.{
"name": "fc_add_wiki_version",
"arguments": {
"wiki_id": "4419902"
}
}CRM
10 toolsCRM tasks and call logs. These live on a group (the CRM workspace), not a project — pass group_id.
fc_fetch_crm_tasksRead-onlyList CRM tasks in a group.
limitintMaximum results per page.offsetintResults to skip, for paging.group_idstring · requiredGroup whose CRM tasks to fetch.{
"name": "fc_fetch_crm_tasks",
"arguments": {
"group_id": "1120034"
}
}fc_fetch_crm_taskRead-onlyA single CRM task.
crm_task_idstring · requiredID of the CRM task.{
"name": "fc_fetch_crm_task",
"arguments": {
"crm_task_id": "1150223"
}
}fc_add_crm_taskWritesCreate a CRM task against a contact.
titlestring · requiredCRM task title.group_idstring · requiredGroup the task belongs to.descriptionstringTask description.typeintCRM task type ID — call, meeting, to-do.contact_titlestringName of the related contact.f_privateint1 makes it private.assigned_to_idstringUser to assign it to.due_datestringYYYY-MM-DD.{
"name": "fc_add_crm_task",
"arguments": {
"title": "Fix login race condition",
"group_id": "1120034"
}
}fc_edit_crm_taskWritesUpdate a CRM task.
crm_task_idstring · requiredID of the CRM task to edit.titlestringNew title.descriptionstringNew description.statusintCRM task status ID.typeintCRM task type ID.contact_titlestringRelated contact name.f_privateint1 makes it private.assigned_to_idstringReassign to this user.due_datestringNew due date.{
"name": "fc_edit_crm_task",
"arguments": {
"crm_task_id": "1150223"
}
}fc_delete_crm_taskDestructiveDelete a CRM task.
crm_task_idstring · requiredID of the CRM task to delete.{
"name": "fc_delete_crm_task",
"arguments": {
"crm_task_id": "1150223"
}
}fc_fetch_crm_callsRead-onlyList CRM calls in a group.
limitintMaximum results per page.offsetintResults to skip, for paging.group_idstring · requiredGroup whose calls to fetch.{
"name": "fc_fetch_crm_calls",
"arguments": {
"group_id": "1120034"
}
}fc_fetch_crm_callRead-onlyA single CRM call.
crm_call_idstring · requiredID of the call.{
"name": "fc_fetch_crm_call",
"arguments": {
"crm_call_id": "1150887"
}
}fc_add_crm_callWritesLog a call, inbound or outbound.
titlestring · requiredCall title or subject.group_idstring · requiredGroup the call belongs to.descriptionstringNotes about the call.f_inboundint1 inbound, 0 outbound.contact_titlestringWho the call was with.assigned_to_idstringUser who owns the call.due_datestringWhen it happened or is scheduled.durationintCall length in minutes.{
"name": "fc_add_crm_call",
"arguments": {
"title": "Fix login race condition",
"group_id": "1120034"
}
}fc_edit_crm_callWritesUpdate a logged call.
crm_call_idstring · requiredID of the call to edit.titlestringNew title.descriptionstringNew notes.f_inboundint1 inbound, 0 outbound.contact_titlestringContact name.assigned_to_idstringOwner.due_datestringNew call date.durationintNew duration in minutes.{
"name": "fc_edit_crm_call",
"arguments": {
"crm_call_id": "1150887"
}
}fc_delete_crm_callDestructiveDelete a logged call.
crm_call_idstring · requiredID of the call to delete.{
"name": "fc_delete_crm_call",
"arguments": {
"crm_call_id": "1150887"
}
}Users & account
11 toolsWho is who, plus account-level operations. Several of these are irreversible — check the badges.
fc_fetch_usersRead-onlyEvery user you share a workspace with. Use it to resolve assigned_to_id.
{
"name": "fc_fetch_users",
"arguments": {}
}fc_fetch_current_userRead-onlyThe authenticated user.
{
"name": "fc_fetch_current_user",
"arguments": {}
}fc_fetch_userRead-onlyA user by ID.
user_idstring · requiredID of the user.{
"name": "fc_fetch_user",
"arguments": {
"user_id": "4410021"
}
}fc_fetch_groupsRead-onlyAll groups, without their projects or apps. Prefer fc_get_groups_projects.
{
"name": "fc_fetch_groups",
"arguments": {}
}fc_update_current_userWritesUpdate your own profile. Changing email or password needs current_password.
first_namestringNew first name.last_namestringNew last name.emailstringNew email address.timezonestringIANA timezone, e.g. America/Los_Angeles.passwordstringNew password. Requires current_password.current_passwordstringRequired when changing password or email.{
"name": "fc_update_current_user",
"arguments": {}
}fc_register_userWritesRegister a new Freedcamp account.
emailstring · requiredEmail for the new account.passwordstring · requiredPassword for the new account.first_namestring · requiredFirst name.last_namestring · requiredLast name.timezonestringIANA timezone name.{
"name": "fc_register_user",
"arguments": {
"email": "you@example.com",
"password": "••••••••",
"first_name": "Ada",
"last_name": "Lovelace"
}
}fc_validate_emailRead-onlyCheck whether an email address is valid and available.
emailstring · requiredAddress to check.{
"name": "fc_validate_email",
"arguments": {
"email": "you@example.com"
}
}fc_request_password_resetWritesSend a password reset email.
emailstring · requiredAddress to send the link to.{
"name": "fc_request_password_reset",
"arguments": {
"email": "you@example.com"
}
}fc_apply_password_resetWritesComplete a password reset with the key from the email.
reset_keystring · requiredToken from the reset email.passwordstring · requiredNew password to set.{
"name": "fc_apply_password_reset",
"arguments": {
"reset_key": "b91f…",
"password": "••••••••"
}
}fc_delete_avatarDestructiveRemove your current avatar image.
{
"name": "fc_delete_avatar",
"arguments": {}
}fc_delete_accountDestructiveDelete the whole account. Requires your password and is not reversible.
passwordstring · requiredYour current password.confirmstringConfirmation value required by the API.{
"name": "fc_delete_account",
"arguments": {
"password": "••••••••"
}
}Notifications
5 toolsRead your activity feed and mark things read, one at a time or in bulk.
fc_fetch_notificationsRead-onlyRecent notifications — last 60 days, things you follow.
{
"name": "fc_fetch_notifications",
"arguments": {}
}fc_fetch_all_notificationsRead-onlyEvery notification, with no date or following filter.
{
"name": "fc_fetch_all_notifications",
"arguments": {}
}fc_fetch_notifications_by_projectRead-onlyNotifications for one project.
project_idstring · requiredProject whose notifications to fetch.{
"name": "fc_fetch_notifications_by_project",
"arguments": {
"project_id": "7451190"
}
}fc_update_notification_readWritesMark a single notification read.
uidstringThe notification's item_u_key.{
"name": "fc_update_notification_read",
"arguments": {}
}fc_edit_notificationsWritesBulk update notification state.
itemsobject[] · requiredNotifications to update, each carrying an item_u_key.new_statestringread or unread. Default read.{
"name": "fc_edit_notifications",
"arguments": {
"items": [
{
"item_u_key": "t_18432901"
}
]
}
}Files
5 toolsUpload from a path or base64, attach to any item or comment, or stage a temporary record and attach it later via attached_ids.
fc_fetch_fileRead-onlyFile metadata by ID.
file_idstring · requiredID of the file.{
"name": "fc_fetch_file",
"arguments": {
"file_id": "8834110"
}
}fc_upload_fileWritesUpload a file and attach it to a project, item or comment. Send file_path or content_base64.
file_pathstringAbsolute path to a local file. This or content_base64.content_base64stringBase64 file contents. This or file_path.filenamestringName to give the upload.mime_typestringMIME type. Defaults to application/octet-stream.project_idstringProject the file belongs to.group_idstringGroup the file belongs to.application_idintApp to attach it to, e.g. 2 Tasks.item_idstringItem to attach it to.comment_idstringComment to attach it to.temporaryint1 uploads it as temporary; attach later via attached_ids.{
"name": "fc_upload_file",
"arguments": {}
}fc_add_file_metaWritesCreate a metadata record for a file uploaded elsewhere.
project_idstringProject the file belongs to.group_idstringGroup the file belongs to.application_idintApp the file is attached to.item_idstringItem to attach it to.comment_idstringComment to attach it to.temporaryint1 creates a temporary record.{
"name": "fc_add_file_meta",
"arguments": {}
}fc_upload_avatarWritesUpload a new avatar for the current user.
file_pathstringAbsolute path to the image. This or content_base64.content_base64stringBase64 image contents. This or file_path.filenamestringName to give the upload.mime_typestringMIME type, e.g. image/png.{
"name": "fc_upload_avatar",
"arguments": {}
}fc_delete_fileDestructiveDelete a file.
file_idstring · requiredID of the file to delete.{
"name": "fc_delete_file",
"arguments": {
"file_id": "8834110"
}
}Custom fields & links
5 toolsDefine custom field templates for Tasks, the Issue Tracker or CRM, and cross-link items between apps.
fc_fetch_cf_templatesRead-onlyList custom field templates, with each field's cf_id.
module_idintApp to list templates for. Default 2 (Tasks).{
"name": "fc_fetch_cf_templates",
"arguments": {}
}fc_add_cf_templateWritesCreate a custom field template — a named set of fields.
titlestring · requiredName of the template.module_idint · required2 Tasks, 13 Issue Tracker, 37 CRM.fieldsobject[] · requiredFields to create: { title, type, f_required, cf_order, currency_code, dd_options }.owner_idstringOwner user ID. Defaults to you.{
"name": "fc_add_cf_template",
"arguments": {
"title": "Engineering fields",
"module_id": 2,
"fields": [
{ "title": "Team", "type": "dd", "f_required": true,
"dd_options": [{ "title": "Backend", "f_default": true }, { "title": "Frontend" }] },
{ "title": "Est. cost", "type": "currency", "currency_code": "USD" }
]
}
}fc_edit_cf_templateWritesRename a template, replace its fields, remove fields, or archive it.
cft_idstring · requiredID of the template to edit.titlestring · requiredNew template name.module_idint · required2 Tasks, 13 Issue Tracker, 37 CRM.fieldsobject[] · requiredFull replacement set of fields.owner_idstringOwner user ID.deleted_field_idsint[]Existing field IDs to remove.f_archivedbooleanWhether the template is archived.{
"name": "fc_edit_cf_template",
"arguments": {
"cft_id": "220145",
"title": "Fix login race condition",
"module_id": 2,
"fields": [
{
"title": "Team",
"type": "dd",
"dd_options": [
{
"title": "Backend"
},
{
"title": "Frontend"
}
]
}
]
}
}fc_fetch_linked_itemsRead-onlyItems linked to a given item.
app_idint · requiredApp that owns the item, e.g. 2 Tasks.item_idstring · requiredItem whose links to fetch.{
"name": "fc_fetch_linked_items",
"arguments": {
"app_id": 2,
"item_id": "18432901"
}
}fc_add_linked_itemsWritesLink an item to items in any app.
app_idint · requiredApp that owns the source item.item_idstring · requiredSource item to link from.linksobject · requiredMap of target app ID (string key) to an array of item IDs.{
"name": "fc_add_linked_items",
"arguments": {
"app_id": 2,
"item_id": "18432901",
"links": { "13": ["5511207"], "4": ["3308115"] }
}
}Account & misc
5 toolsInvitations, timezones, backups and account state. Small tools, occasionally exactly what you need.
fc_fetch_invitationsRead-onlyPending invitations addressed to you.
{
"name": "fc_fetch_invitations",
"arguments": {}
}fc_respond_invitationWritesAccept or decline an invitation.
invitation_idstring · requiredID of the invitation.actionstringaccept or decline.responsestringExtra response value some invitation types need.project_idstringProject the invitation is for, if applicable.{
"name": "fc_respond_invitation",
"arguments": {
"invitation_id": "7710033"
}
}fc_fetch_timezonesRead-onlyEvery timezone the API accepts — useful before setting one on a profile.
{
"name": "fc_fetch_timezones",
"arguments": {}
}fc_fetch_backupsRead-onlyAccount backups available for download.
{
"name": "fc_fetch_backups",
"arguments": {}
}fc_fetch_wipe_currentRead-onlyCurrent account-wipe state.
{
"name": "fc_fetch_wipe_current",
"arguments": {}
}Prompt recipes
Things worth asking for, and the tools your assistant will reach for. Copy a line, change the names.
What is overdue across all my projects, grouped by project, with who it is assigned to?
fc_get_groups_projects → fc_fetch_tasks → fc_fetch_usersTurn these meeting notes into tasks in the API Platform project, due next Friday, assigned to me.
fc_get_groups_projects → fc_fetch_lists → fc_add_taskMark every task in the Release 4.1 list completed and move the leftovers to Release 4.2.
fc_fetch_tasks → fc_batch_edit_tasksLog 45 minutes against today on the Acme refactor and mark it billed.
fc_add_time or fc_time_actionSummarise what changed in the API Platform project since Monday and post it as a discussion.
fc_fetch_notifications_by_project → fc_add_discussionCreate a Q4 Launch milestone and link the six auth tasks to it.
fc_add_milestone → fc_batch_edit_tasks (ms_id)Draft a wiki page from this thread and file it under Engineering Notes.
fc_fetch_discussion → fc_add_wikiLog a 20-minute inbound call with Acme Corp and schedule a follow-up for Thursday.
fc_add_crm_call → fc_add_crm_taskSecurity & limits
The server holds no data of its own. It is a typed, annotated surface over the Freedcamp REST API, running as whoever authorized it.
Each bearer token carries one user’s own encrypted API credentials, and each token gets its own handler. Two people on the same endpoint never see each other’s workspace.
Credentials live only inside the encrypted bearer token your client holds. Nothing is written to disk, and there is no config file on your machine holding an API secret in plain text.
Requests to Freedcamp are signed per call. Your API secret is used to compute the signature, not transmitted as a credential.
There is no separate quota — you inherit the Freedcamp API's own rate limiting and your plan's permissions. A tool can never do more than you can.
fc_delete_project, fc_delete_account and the other fc_delete_* tools act immediately and are not undoable from here. They are annotated destructive so your client can ask first — leave those confirmations on.
Errors & troubleshooting
Failures come back as a tool result with isError: true and a plain-text message, so your assistant can read and explain them. Here is what the common ones mean.
Invalid input for fc_add_task: project_id: Required
Zod rejected the arguments before any request was made. The message names the exact field path and what was wrong — usually a missing required ID. Fetch it with fc_get_groups_projects and retry.
HTTP 401 — invalid_token
Your bearer token expired or was rejected. Re-run the authorization flow: in Claude Desktop reconnect the connector under Settings → Connectors, in Claude Code run /mcp and choose Authenticate.
Invalid Freedcamp API credentials
The authorization page checked your key and secret against the Freedcamp API and they did not match. Generate a fresh pair under Settings → API — the secret is only shown once, so a half-copied secret is the usual cause.
No project found named "API platform"
A name-based helper could not match that project. Names are matched exactly, including case — call fc_get_groups_projects and use the name it returns.
fc_add_item_by_names does not yet support the "Discussions" app
The by-name shortcut currently creates Tasks only. Use the app's own tool — fc_add_discussion, fc_add_issue, fc_add_wiki — with the project_id from fc_get_groups_projects.
isError: true — timer state unchanged
fc_time_action compares the entry before and after. Starting an already-running timer, or billing an already-billed entry, is reported as a failure with the entry state attached instead of a false success.
Unknown tool: fc_list_tasks
That name does not exist. Listing is fc_fetch_tasks — every read tool is fc_fetch_*. If your client shows stale tools, reconnect the server.
FAQ
No. Point your client at https://mcp.freedcamp.com/mcp and authorize with your own Freedcamp API key and secret in the browser. There is nothing to download and nothing to keep running.
Yes — everyone points at the same endpoint and completes their own OAuth authorization with their own Freedcamp credentials. Each bearer token gets its own isolated handler, so sessions never mix.
No. Every call is signed with your own API credentials, so the server can only ever see and change what you can see and change in Freedcamp.
Because almost every other tool needs a project_id, list_id or user_id, and that one call returns all of them keyed by readable name. The server's own instructions tell clients to fetch it once and reuse it.
Call fc_add_task with h_parent_id set to the parent task. The parent must live in the same list and cannot itself be a subtask.
They are the same field. list_id is the current name, task_group_id is the legacy alias — send one, not both.
fc_batch_edit_tasks takes up to 500 task IDs and applies the same status, priority, assignees, dates, tags, custom fields, milestone or parent to all of them in one request.
Not at the moment — OAuth over the hosted HTTPS endpoint is the only supported transport, which is why there are no environment variables or npx commands anywhere in this guide.