Architecture
This page covers the internal architecture of MCP Task Server including storage, shared context, and workspace detection.
MCP Task Server series
- MCP Task Server
- Architecture - You are here
- Tools
- Multi-agent coordination
- Project scaffolding
Overview
Storage architecture
The server uses a scalable storage model with three layers.
1. JSON registry
Location: memory_bank/tasks/tasks.json
Machine-readable source of truth containing task IDs, status, dependencies, and subtasks.
{
"version": "2.0.0",
"tasks": [
{
"id": "1",
"title": "Project Setup",
"status": "done",
"priority": "high",
"subtasks": [
{ "id": 1, "title": "Init project", "status": "done" }
]
}
]
}
2. Task files
Location: memory_bank/tasks/task_XXX.txt
Human-readable detailed task files for each top-level task:
# Task ID: 1
# Title: Project Setup and Configuration
# Status: done
# Dependencies: None
# Priority: high
# Description: Initialise the project with required tooling.
# Details:
Full implementation details here...
# Subtasks:
## 1. Init project [done]
### Dependencies: None
### Description: Create initial project structure
3. Progress summary
Location: memory_bank/execution/progress.md
High-level overview auto-generated from tasks.json:
# Implementation Progress
## Task Completion Summary
### Completed Tasks (3/5)
- Task 1: Project Setup
- Task 2: Database Schema
This architecture scales well for complex projects with many tasks and subtasks.
Multi-project support
The server supports managing tasks across multiple projects with automatic filtering.
Dedicated project workspaces
When working in a project's own folder, bind it once:
# First time in this workspace - bind project to folder
call set_project({ project: "coach-platform", workspace: "/Users/yourname/Projects/coaching/platform" })
# Future sessions auto-detect via workspace binding
call get_project({ workspace: "/Users/yourname/Projects/coaching/platform" })
# Returns: { current_project: "coach-platform", source: "workspace" }
Hub workflow
When managing multiple projects from one workspace (like Obsidian):
Option A: Global context switching (one project at a time)
call set_project({ project: "coach-platform" })
call list_tasks # Shows coach-platform tasks
call set_project({ project: "mcp-task-server" })
call list_tasks # Now shows mcp-task-server tasks
Option B: Explicit project parameter (parallel work)
# Don't set context - pass project directly
call list_tasks({ project: "coach-platform" })
call list_tasks({ project: "mcp-task-server" })
call add_task({ title: "Fix bug", project: "coach-platform" })
Progress files
Progress files are generated per-project:
memory_bank/execution/
├── progress.md # Combined view (all projects)
├── progress-coach-platform.md # Coach platform tasks only
└── progress-mcp-task-server.md # MCP task server tasks only
Shared context and preferences
The server reads ~/.cursor/shared-context.json for user preferences and automatically injects them into tool responses and prompts.
How preferences flow
Memory storage
Where preferences are used
| Tool Type | How Preferences Are Applied |
|---|---|
list_tasks, get_task, add_task, update_task, next_task | Brief hint in response |
parse_prd, expand_task, research_task | Full context in generated prompt |
check_compliance | All preferences for validation |
| Wellness cursor rule | Session tracking and break reminders |
Managing memories
Memories use simple sequential IDs (1, 2, 3...) managed by the server. The sync action is recommended because it matches by title, avoiding duplicates:
| Action | What it does |
|---|---|
create | Add new memory with next available ID |
update | Update existing memory by ID |
delete | Remove memory by ID |
sync | Create or update by title match (recommended) |
migrate | One-time conversion of old IDs to sequential |
# Sync by title (recommended - avoids duplicates)
call update_memory({
action: "sync",
title: "Writing preferences",
content: "British English, ISO dates, no emojis..."
})
# Returns: { status: "synced_new", memory: { id: "1", ... } }
If you have memories with old-style IDs (like mem_1737900000_abc123), run update_memory({ action: "migrate" }) once to convert them to sequential IDs.
Content context
The content context file (~/.cursor/content-context.md) stores content inventory, themes, and locations for content creators.
# Content Context
## Current State
| Property | Value |
|----------|-------|
| Last update | 2026-02-01 |
## Published Content
- Post 1: Title (2026-01-15)
- Post 2: Title (2026-01-20)
## Themes Covered
- Theme A
- Theme B
## Content Locations
| Type | Location |
|------|----------|
| Draft posts | ~/drafts |
| Published | ~/published |
Use show_content_context to read and update_content_context to modify sections.
Workspace detection
The server automatically detects your project's root directory using multiple strategies.
process.cwd() is unreliable because when Cursor starts an MCP server, the working directory may be your home directory or another location rather than your project root. The server now walks up the directory tree looking for project markers (.git, package.json, memory_bank) and uses Cursor's undocumented WORKSPACE_FOLDER_PATHS environment variable when available.
Cursor does not register a workspace for empty folders. Create at least one file (e.g., touch README.md or npm init -y) before the MCP server can detect your project, then reload Cursor.
Detection order
| Priority | Method | When Used |
|---|---|---|
| 1 | TASK_WORKSPACE env | Explicit per-project override |
| 2 | WORKSPACE_FOLDER_PATHS env | Auto-set by Cursor (undocumented) |
| 3 | Project marker detection | Walks up from cwd looking for .git, package.json, memory_bank |
| 4 | process.cwd() | Final fallback |
Debugging workspace detection
Run call get_version to see how the workspace was detected:
call get_version
# Returns: { workspace: { root: "/path/to/project", source: "found .git" } }
Possible sources:
"TASK_WORKSPACE env"- Explicit override"WORKSPACE_FOLDER_PATHS env"- Detected from Cursor"found .git"/"found package.json"/"found memory_bank"- Project marker"process.cwd() fallback"- No detection, using current directory
Explicit override
If auto-detection is not working, set TASK_WORKSPACE in per-project config:
{
"mcpServers": {
"task-server": {
"command": "npx",
"args": ["-y", "mcp-task-server"],
"env": {
"TASK_WORKSPACE": "/absolute/path/to/project"
}
}
}
}
Project structure
After running init_project:
your-project/
├── agent-kit/
│ ├── AGENT_RULES.md # Role definitions and permissions
│ ├── KICKOFF.md # Session startup checklist
│ ├── TASKS.md # Task reference (points to memory_bank)
│ ├── HANDOFF.md # Handoff protocol reference
│ └── SHARED_CONTEXT.md # Shared context documentation
├── memory_bank/
│ ├── architecture/
│ │ ├── architecture.md # High-level architecture overview
│ │ ├── tech.md # Technical stack and context
│ │ ├── models.md # Data models
│ │ ├── services.md # System services
│ │ ├── deployment.md # Deployment guide
│ │ ├── kubernetes.md # Kubernetes deployment (if applicable)
│ │ └── webhooks.md # Webhooks implementation (if applicable)
│ ├── context/
│ │ ├── context.md # Context index
│ │ ├── brief.md # Project overview
│ │ ├── active.md # Current focus
│ │ ├── product.md # Product context
│ │ ├── canvas.md # Lean canvas
│ │ └── changelog.md # Change log
│ ├── execution/
│ │ ├── execution.md # Execution overview
│ │ ├── progress.md # Task summary (auto-synced)
│ │ ├── decisions.md # Decision log
│ │ ├── debug.md # Debug diary
│ │ └── git.md # Git setup and code quality
│ ├── reference/
│ │ └── README.md # Reference materials folder
│ └── tasks/
│ ├── tasks.json # Task registry (source of truth)
│ ├── task_001.txt # Detailed task file
│ └── ...
└── .cursor/
└── rules/
├── agent-workflow.mdc # Task management protocol
├── wellness-check.mdc # Break reminders
└── shared-context-sync.mdc # Memory sync guidance
The full structure includes 28 template files covering architecture, context, execution tracking, and cursor rules.
Configuration
Configure via environment variables:
| Variable | Default | Description |
|---|---|---|
TASK_MD_PATH | memory_bank/execution/progress.md | Path to markdown summary |
TASK_JSON_PATH | memory_bank/tasks/tasks.json | Path to JSON registry |
TASK_DIR | memory_bank/tasks | Directory for task files |
STATS_API_URL | https://stats-dev.reids.net.au | Work stats dashboard API URL |
SLACK_BOT_TOKEN | - | Slack bot OAuth token (xoxb-...) |
SLACK_CHANNEL_ID | - | Default Slack channel for notifications |
SLACK_TEAM_ID | - | Optional Slack workspace ID |