Minolith Context API
The Context service is a structured knowledge base for AI coding agents. It stores categorised knowledge entries that persist across sessions — giving every agent that connects to a project the full picture of how that project works.
Writing context is not extra work on top of development — it is part of development. When you make a decision, record it. When you discover a gotcha, store it. When you establish a pattern, write it down. This is how you keep your future self (and every other agent on the project) from repeating mistakes or re-litigating settled choices. Treat these tools the way a developer treats their notes: write in the moment, not as an afterthought.
Base URL: https://api.minolith.io/v1/context
Authentication: All endpoints require an API key via the Authorization header:
Authorization: Bearer mlth_your_api_key_here
Pricing: All Context operations are free. Context is included with every Minolith account. No credit metering is applied. This is deliberate — there should be zero friction to reading and writing context.
Limits
Each project has two hard limits on context storage:
| Limit | Value |
|---|---|
| Maximum entries | 500 per project |
| Maximum storage | 100 MB per project |
Whichever limit is reached first will block new entry creation. Storage is calculated from the actual data stored in each entry (type, scope, title, body, priority, created_by) plus all tag values.
When a limit is reached, store_context (MCP) and POST /v1/context/entries (REST) return an error. Existing entries can still be read, updated, and deleted.
Error response (403):
{
"error": {
"code": "quota_exceeded",
"message": "Entry limit reached. Maximum 500 context entries per project. Delete unused entries to free up space.",
"docs": "https://docs.minolith.io/api/context#limits",
"suggestion": "Delete unused entries to free up space.",
"entry_count": 500,
"entry_limit": 500
}
}
{
"error": {
"code": "quota_exceeded",
"message": "Storage limit reached. Using 100.0 MB of 100 MB. Delete unused entries to free up space.",
"docs": "https://docs.minolith.io/api/context#limits",
"suggestion": "Delete unused entries to free up space.",
"storage_bytes": 104857600,
"storage_limit": 104857600
}
}
Getting Back Under Limits
If you hit a quota limit, use these steps to free up space:
-
Identify low-value entries. Query by type to find candidates for removal:
get_contextwithtype: ["event"]— old deployment/incident events are often no longer useful. Note: event entries are immutable and cannot be deleted via the API. They can only be deleted from the dashboard.get_contextwithtype: ["todo"]— completed todos that were never cleaned up.get_contextwithtype: ["workaround"]— workarounds whose removal criteria have been met.get_contextwithtype: ["bug"]— bugs that have been fixed.get_contextwithpriority: "low"— low-priority entries are the first to consider removing.
-
Consolidate duplicate or overlapping entries. If multiple entries cover the same topic, merge them into one comprehensive entry and delete the others.
-
Trim verbose bodies. Update entries with unnecessarily long body text to be more concise. Storage is calculated from actual field lengths — shorter text means less storage used.
-
Remove stale entries. Query by date range (
created_before) to find old entries that may no longer be relevant. -
Delete entries. Use
delete_context(MCP) orDELETE /v1/context/entries/:id(REST) to remove entries. Tags are deleted automatically with the entry.
Current usage is visible on the project's Context page in the dashboard at https://app.minolith.io.
Entry Types
Every entry has a type that categorises what kind of knowledge it represents. Types are universal — they work across any language, framework, or domain. Use tags and scope for language-specific, framework-specific, or domain-specific scoping.
| Type | Purpose | Mutable | Example |
|---|---|---|---|
rule |
Must/must-not constraints. Hard rules the agent must follow without exception. | Yes | "All CSS must be in external files — never inline styles or style blocks in templates." |
pattern |
Code and implementation patterns. The established way to do things in this project. | Yes | "When adding a new API endpoint, follow the controller → service → model pattern." |
snippet |
Reusable code. Templates, boilerplate, and reference implementations to copy and adapt. | Yes | A standard controller method template, a database query pattern, test file boilerplate. |
decision |
Why something was chosen. Architectural and design decisions with rationale. | Yes | "We use cursor-based pagination, not offset-based. Rationale: offset breaks on large datasets." |
fact |
Objective truths about the project or environment. | Yes | "The production database is MySQL 8.0.35." |
warning |
Gotchas and pitfalls. Known landmines that cause problems if the agent isn't aware of them. | Yes | "CI4 4.7 changed rawData default — this breaks encryption of existing data." |
event |
Immutable timeline entries. Deployments, migrations, incidents, significant occurrences. | No | "Deployed v1.2.0 to production at 14:32 on March 15." |
brief |
Specs and requirements. Feature specifications, acceptance criteria, project requirements. | Yes | "The changelog widget must be under 15KB gzipped, render in shadow DOM." |
bug |
Known defects and issues. Documented bugs including reproduction steps and impact. | Yes | "Dashboard session expires silently after 2FA — user sees a blank page." |
todo |
Tasks, action items, and planned work. Things that need to be done, persisting across sessions. | Yes | "Add spending cap alerts — email notification when account reaches 80% of cap." |
dependency |
External services, integrations, and version constraints. | Yes | "Stripe API version 2023-10-16 pinned. Do not upgrade without testing webhooks." |
config |
Environment configuration, feature flags, and settings. | Yes | "Redis database 0 for caching, database 1 for sessions." |
workaround |
Temporary fixes with explicit removal criteria. | Yes | "Bypassing email verification due to missing email service. Remove when /v1/email/ is built." |
workflow |
Multi-step procedures and processes. How to do things that involve multiple ordered steps. | Yes | "To add a new service: 1. Generate migration 2. Create models 3. Create controllers..." |
persona |
Voice, tone, and communication style for this project's context. | Yes | "Error messages use first person plural: 'We couldn't process your request'." |
reference |
Links to external documentation, specifications, or resources. | Yes | "Stripe webhook event types: https://stripe.com/docs/api/events/types" |
preference |
Soft conventions and style choices. Defaults to follow but can deviate from with reason. | Yes | "Prefer early returns over nested conditionals. Prefer single quotes for PHP strings." |
test |
Test strategies, test data conventions, and expected behaviours. | Yes | "Integration tests require Redis. Test database uses prefix test_." |
glossary |
Project-specific terminology and definitions. Prevents misinterpreting domain language. | Yes | "'Entry' means a changelog item, not a database row. 'Published' means visible on the public page." |
Event entries are immutable. Once created, an entry with type: event cannot be updated or deleted. This ensures the event log is a reliable historical record.
Choosing a Type
- Hard constraint that must never be violated →
rule - Soft preference that should usually be followed →
preference - How to implement something →
pattern - Reusable code to copy →
snippet - Why a choice was made →
decision - Objective truth about the environment →
fact - Environment-specific configuration →
config - Danger that causes bugs →
warning - Temporary hack →
workaround - Happened at a point in time, shouldn't be edited →
event - Feature spec or requirement →
brief - Known bug →
bug - Work to be done →
todo - External service or version constraint →
dependency - Multi-step procedure →
workflow - How to write or communicate →
persona - Link to external docs →
reference - How to test →
test - Defines a term →
glossary
Scoping with Tags and Scope
Types are universal. Use tags and scope for language/framework-specific categorisation:
- A PHP pattern → type:
pattern, tags:[php] - A CI4 convention → type:
rule, tags:[codeigniter, ci4] - A frontend warning → type:
warning, scope:css, tags:[frontend, styling] - A React snippet → type:
snippet, tags:[react, javascript, frontend]
Endpoints
Create Entry
POST /v1/context/entries
Creates a new context entry.
Request body:
{
"type": "rule",
"scope": "css",
"title": "Never inline styles or create per-page CSS",
"body": "All styles must use the shared stylesheet at assets/css/app.css. Never use inline style attributes. Never create <style> blocks in templates.",
"tags": ["css", "styling", "templates", "html", "frontend"],
"priority": "high"
}
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | See Entry Types for the full list of 19 types |
title |
string | yes | Short description, max 500 characters |
body |
string | yes | Full content, max 100,000 characters |
scope |
string | no | Category or area this applies to (e.g. "css", "auth", "api"). Max 100 chars, lowercase alphanumeric + hyphens |
tags |
array | no | Up to 20 string tags for filtering. Each tag: max 100 chars, lowercase alphanumeric + hyphens |
priority |
string | no | One of: high, normal, low. Defaults to normal |
Response (201 Created):
{
"data": {
"id": "ctx_a1b2c3d4e5f6",
"type": "rule",
"scope": "css",
"title": "Never inline styles or create per-page CSS",
"body": "All styles must use the shared stylesheet at assets/css/app.css...",
"tags": ["css", "styling", "templates", "html", "frontend"],
"priority": "high",
"is_immutable": false,
"created_by": "api",
"created_at": "2026-03-15 10:00:00",
"updated_at": "2026-03-15 10:00:00"
}
}
Error responses:
403— Quota exceeded. The project has reached its entry or storage limit. See Limits for remediation steps.422— Validation error. The response includes the field name and a description of the problem.
{
"error": {
"code": "validation_error",
"message": "Invalid type. See docs for the full list of valid types.",
"field": "type",
"docs": "https://docs.minolith.io/api/context#validation-rules",
"suggestion": "Did you mean 'rule'?"
}
}
List Entries
GET /v1/context/entries
Returns a paginated list of entries for the authenticated project. Supports filtering by type, scope, priority, tags, date range, and full-text search.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
type |
string | Filter by type. Supports comma-separated values: type=rule,pattern |
scope |
string | Filter by exact scope: scope=css |
priority |
string | Filter by priority: priority=high |
tags |
string | Filter by tags (comma-separated, matches ANY): tags=css,html |
search |
string | Full-text search across title and body fields. Returns entries where the search term appears as a substring in either field. Max 500 characters. |
created_after |
string | ISO date/datetime: created_after=2026-03-14 |
created_before |
string | ISO date/datetime: created_before=2026-03-15 |
limit |
integer | Number of results (1-100, default 20) |
cursor |
string | Cursor from a previous response's pagination.next_cursor |
Example requests:
GET /v1/context/entries?tags=css,html&type=rule,pattern&priority=high&limit=20
GET /v1/context/entries?type=warning&scope=admin
GET /v1/context/entries?type=event&created_after=2026-03-14
GET /v1/context/entries?search=inline+styles
GET /v1/context/entries?limit=50
Response (200 OK):
{
"data": [
{
"id": "ctx_a1b2c3d4e5f6",
"type": "rule",
"scope": "css",
"title": "Never inline styles",
"body": "...",
"tags": ["css", "styling"],
"priority": "high",
"is_immutable": false,
"created_by": "api",
"created_at": "2026-03-15 10:00:00",
"updated_at": "2026-03-15 10:00:00"
}
],
"pagination": {
"has_more": true,
"next_cursor": "ctx_xyz789abc123",
"limit": 20
}
}
Pagination: Results are ordered by created_at descending (newest first). To get the next page, pass the next_cursor value from the response as the cursor parameter in the next request. When has_more is false, there are no more results.
Get Entry
GET /v1/context/entries/:id
Returns a single entry by its ID.
Response (200 OK):
{
"data": {
"id": "ctx_a1b2c3d4e5f6",
"type": "rule",
"scope": "css",
"title": "Never inline styles",
"body": "All styles must use the shared stylesheet...",
"tags": ["css", "styling"],
"priority": "high",
"is_immutable": false,
"created_by": "api",
"created_at": "2026-03-15 10:00:00",
"updated_at": "2026-03-15 10:00:00"
}
}
Error responses:
404— Entry not found.
{
"error": {
"code": "not_found",
"message": "Entry 'ctx_nonexistent' not found.",
"docs": "https://docs.minolith.io/api/context#get-entry"
}
}
Update Entry
PUT /v1/context/entries/:id
Updates an existing entry. Only include the fields you want to change. Omitted fields are left unchanged.
Cannot update immutable entries. Entries with type: event return 403 Forbidden.
Cannot change type to or from event. The immutability rules for events would make this inconsistent.
Request body (partial update):
{
"title": "Updated title",
"tags": ["new-tag", "another-tag"],
"priority": "high"
}
All fields from the create endpoint are accepted. All are optional for updates.
Response (200 OK):
Returns the full updated entry in the same format as the create response.
Error responses:
403— Entry is immutable.
{
"error": {
"code": "forbidden",
"message": "This entry is immutable and cannot be updated. Event entries are permanently locked after creation.",
"docs": "https://docs.minolith.io/api/context#immutable-entries"
}
}
404— Entry not found.422— Validation error.
Delete Entry
DELETE /v1/context/entries/:id
Permanently deletes an entry and its tags. This is a hard delete — the entry cannot be recovered.
Cannot delete immutable entries. Entries with type: event return 403 Forbidden.
Response (204 No Content):
Empty response body.
Error responses:
403— Entry is immutable.404— Entry not found.
Bulk Create Entries
POST /v1/context/entries/bulk-create
Create multiple entries in a single request. Maximum 50 entries per call. All entries are validated first — if ANY entry fails validation, the entire batch is rejected with no partial creates.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
entries |
array of objects | yes | Entry objects to create (max 50) |
Each entry object has the same fields as the Create Entry endpoint:
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | See Entry Types |
title |
string | yes | Short description, max 500 characters |
body |
string | yes | Full content, max 100,000 characters |
scope |
string | no | Category or area |
tags |
array of strings | no | Up to 20 tags per entry |
priority |
string | no | high, normal, or low. Defaults to normal |
Example request:
{
"entries": [
{
"type": "rule",
"title": "Never inline CSS",
"body": "All styles must be in external stylesheet files.",
"tags": ["css", "frontend"],
"priority": "high"
},
{
"type": "pattern",
"title": "Controller naming convention",
"body": "Controllers are named {Resource}Controller and placed in app/Controllers/.",
"tags": ["php", "codeigniter"],
"scope": "api"
},
{
"type": "fact",
"title": "Database engine",
"body": "Production database is MySQL 8.0.",
"tags": ["database", "infrastructure"]
}
]
}
Response (201 Created):
{
"data": {
"created": 3,
"entries": [
{"id": "ctx_a1b2c3d4e5f6", "type": "rule", "title": "Never inline CSS"},
{"id": "ctx_b2c3d4e5f6a7", "type": "pattern", "title": "Controller naming convention"},
{"id": "ctx_c3d4e5f6a7b8", "type": "fact", "title": "Database engine"}
]
}
}
Error responses:
403— Quota exceeded. The batch would push the project over its entry or storage limit.422— Validation error. The error message indicates which entry (by position) failed and why. No entries are created.
{
"error": {
"code": "validation_error",
"message": "Entry 2: Invalid type. See docs for the full list of valid types.",
"field": "type",
"docs": "https://docs.minolith.io/api/context#validation-rules",
"suggestion": "Did you mean 'pattern'?"
}
}
Bulk Delete Entries
POST /v1/context/entries/bulk-delete
Delete multiple entries in a single request. Provide either entry IDs, tags, or both. When tags are provided, all entries matching ANY of the tags are deleted. Immutable entries (events) are silently skipped and reported in the response.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
ids |
array of strings | no* | Entry IDs to delete |
tags |
array of strings | no* | Delete entries matching ANY of these tags |
*At least one of ids or tags is required. Both can be provided — the union of matched entries will be deleted.
Example request:
{
"ids": ["ctx_a1b2c3d4e5f6", "ctx_b2c3d4e5f6a7"]
}
{
"tags": ["deprecated", "old-feature"]
}
Response (200 OK):
{
"data": {
"deleted": 5,
"skipped_immutable": 2
}
}
skipped_immutable counts entries that matched but were not deleted because they are immutable (events).
Bulk Update Entries
POST /v1/context/entries/bulk-update
Update multiple entries in a single request. Only priority, scope, and tags can be bulk-updated — title, body, and type are per-entry fields that require individual updates. Immutable entries (events) are silently skipped.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
ids |
array of strings | yes | Entry IDs to update |
updates |
object | yes | Fields to update (see below) |
updates object:
| Field | Type | Description |
|---|---|---|
priority |
string | high, normal, or low |
scope |
string | New scope for all entries |
tags |
array of strings | Replace tags on all entries |
At least one field in updates is required.
Example request:
{
"ids": ["ctx_a1b2c3d4e5f6", "ctx_b2c3d4e5f6a7", "ctx_c3d4e5f6a7b8"],
"updates": {
"priority": "high",
"tags": ["reviewed", "production"]
}
}
Response (200 OK):
{
"data": {
"updated": 3,
"skipped_immutable": 0
}
}
Recent Events
GET /v1/context/events/recent
Convenience endpoint that returns recent event entries. Equivalent to GET /v1/context/entries?type=event but exists as a dedicated endpoint because "get recent events" is the most common query at session start.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
limit |
integer | Number of results (1-100, default 20) |
cursor |
string | Cursor for pagination |
Response (200 OK):
Same format as the list entries response, but only contains entries with type: event.
List Tags
GET /v1/context/tags
Returns all distinct tags used across entries in this project. Use this to discover available tags before filtering with the list entries endpoint.
Response (200 OK):
{
"tags": ["api", "auth", "css", "database", "deployment", "security"]
}
List Scopes
GET /v1/context/scopes
Returns all distinct scopes used across entries in this project. Use this to discover available scopes before filtering.
Response (200 OK):
{
"scopes": ["api", "auth", "css", "dashboard", "deployment", "security"]
}
Validation Rules
| Field | Type | Required | Constraints |
|---|---|---|---|
type |
enum | yes | rule, pattern, snippet, decision, fact, warning, event, brief, bug, todo, dependency, config, workaround, workflow, persona, reference, preference, test, glossary |
scope |
string | no | Max 100 chars. Lowercase alphanumeric and hyphens only (/^[a-z0-9\-]*$/) |
title |
string | yes | Max 500 chars |
body |
string | yes | Max 100,000 chars |
tags |
array of strings | no | Max 20 tags. Each tag: max 100 chars, lowercase alphanumeric and hyphens only (/^[a-z0-9\-]+$/) |
priority |
enum | no | high, normal, low. Defaults to normal |
Immutable Entries
Entries with type: event are automatically marked as immutable when created (is_immutable: true). Immutable entries:
- Cannot be updated (returns
403) - Cannot be deleted (returns
403) - Cannot have their type changed to or from
event
This ensures the event log is a reliable, tamper-proof historical record.
Error Format
All errors follow the standard Minolith error format:
{
"error": {
"code": "validation_error",
"message": "Human-readable description of the problem.",
"field": "type",
"docs": "https://docs.minolith.io/api/context#relevant-section",
"suggestion": "Did you mean 'rule'?"
}
}
| Field | Always Present | Description |
|---|---|---|
code |
yes | Machine-readable error code (snake_case) |
message |
yes | Human/agent-readable explanation |
field |
no | Which request field caused the error |
docs |
yes | URL to relevant documentation |
suggestion |
no | Suggested fix, when available |
The suggestion field uses fuzzy matching. If you send an invalid type like "rules", the error will suggest "Did you mean 'rule'?".
ID Format
Entry IDs use the prefix ctx_ followed by 12 random hex characters:
ctx_a1b2c3d4e5f6
Always use the full ID (including prefix) when referencing entries in API calls.
Rate Limiting
All API endpoints are rate-limited to 100 requests per minute per API key. Rate limit headers are included in every response (see Platform API — Rate Limiting for full details):
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1710504060
If you exceed the limit, you'll receive a 429 Too Many Requests response with a retry_after field indicating how many seconds to wait.
Authentication
See Platform API — Authentication for full details. Include your API key in every request:
Authorization: Bearer mlth_your_api_key_here
API keys are created in the Minolith dashboard at https://app.minolith.io. Each key is scoped to a single project. Entries created with one key are only visible to other keys in the same project.
If the key is missing, invalid, or revoked, you'll receive a 401 Unauthorized response.
MCP Tools
The Context service is available via MCP (Model Context Protocol) for direct integration with AI coding tools like Claude Code, Cursor, Windsurf, and Cline.
Connection
claude mcp add --transport http minolith https://mcp.minolith.io \
--header "Authorization: Bearer mlth_your_api_key_here" \
--header "X-Minolith-Agent: your-agent-name"
The MCP server uses the same API key as the REST API. All data access is scoped to the key's project.
store_context
Store an entry in the project knowledge base. Writing context is part of development, not extra work — record decisions as you make them, gotchas as you hit them, and patterns as you establish them. See Entry Types for the full list of 19 types.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
type |
string | yes | See Entry Types for the full list |
title |
string | yes | Short, descriptive title |
body |
string | yes | Full content. For snippets, include the code. For rules, state the rule clearly. |
scope |
string | no | Category: css, admin, api, auth, database, etc. |
tags |
array of strings | no | Tags for retrieval. Be comprehensive — these are how you'll find this entry later. |
priority |
string | no | high, normal, or low |
Example:
{
"name": "store_context",
"arguments": {
"type": "rule",
"title": "Never inline CSS styles",
"body": "All styles must use external stylesheet at assets/css/app.css. No inline style attributes. No <style> blocks in templates.",
"scope": "css",
"tags": ["css", "styling", "templates"],
"priority": "high"
}
}
get_context
Retrieve entries from the project knowledge base filtered by type, tags, scope, priority, and/or search. Supports full-text search across title and body fields. Do not fetch everything at once — use targeted queries to load only what's relevant. See Session Start below for the recommended retrieval pattern. The knowledge base is only as useful as what you put into it — if it is empty or stale, that is your responsibility.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
tags |
array of strings | no | Filter by tags. Returns entries matching ANY of the provided tags. |
type |
array of strings | no | Filter by entry type. See Entry Types for the full list. |
scope |
string | no | Filter by scope |
priority |
string | no | high, normal, or low |
search |
string | no | Full-text search across title and body. Returns entries where the search term appears as a substring in either field. |
limit |
integer | no | Max entries to return (default 20, max 100) |
Example:
{
"name": "get_context",
"arguments": {
"tags": ["css", "frontend"],
"type": ["rule", "pattern"],
"search": "inline styles",
"priority": "high",
"limit": 50
}
}
update_context
Update an existing knowledge base entry. Cannot update event entries (immutable).
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Entry ID (ctx_xxxxxxxx) |
title |
string | no | New title |
body |
string | no | New body |
scope |
string | no | New scope |
tags |
array of strings | no | Replace all tags |
priority |
string | no | high, normal, or low |
delete_context
Delete a knowledge base entry. Cannot delete event entries (immutable).
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Entry ID (ctx_xxxxxxxx) |
bulk_store_context
Create multiple knowledge base entries in a single call. Maximum 50 entries per call. All entries are validated first — if ANY entry fails validation, the entire batch is rejected (no partial creates). Use this when you need to store several related pieces of knowledge at once, such as after a thorough codebase review or during initial project setup.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
entries |
array of objects | yes | Entry objects to create (max 50) |
Each entry object has the same fields as store_context:
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | See Entry Types |
title |
string | yes | Short, descriptive title |
body |
string | yes | Full content |
scope |
string | no | Category: css, admin, api, auth, database, etc. |
tags |
array of strings | no | Tags for retrieval |
priority |
string | no | high, normal, or low |
Example:
{
"name": "bulk_store_context",
"arguments": {
"entries": [
{
"type": "rule",
"title": "Never inline CSS",
"body": "All styles must be in external stylesheet files.",
"tags": ["css", "frontend"],
"priority": "high"
},
{
"type": "pattern",
"title": "Controller naming convention",
"body": "Controllers are named {Resource}Controller.",
"tags": ["php", "codeigniter"],
"scope": "api"
}
]
}
}
Returns:
{
"created": 2,
"entries": [
{"id": "ctx_a1b2c3d4e5f6", "type": "rule", "title": "Never inline CSS"},
{"id": "ctx_b2c3d4e5f6a7", "type": "pattern", "title": "Controller naming convention"}
]
}
bulk_update_context
Update multiple knowledge base entries at once. Only priority, scope, and tags can be bulk-updated — title, body, and type are per-entry fields that require individual updates via update_context. Immutable entries (events) are silently skipped.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ids |
array of strings | yes | Entry IDs (ctx_xxxxxxxx) to update |
priority |
string | no | New priority for all entries: high, normal, or low |
scope |
string | no | New scope for all entries |
tags |
array of strings | no | Replace tags on all entries |
At least one of priority, scope, or tags must be provided.
Example:
{
"name": "bulk_update_context",
"arguments": {
"ids": ["ctx_a1b2c3d4e5f6", "ctx_b2c3d4e5f6a7"],
"priority": "high",
"tags": ["reviewed", "production"]
}
}
Returns: { "updated": 2, "skipped_immutable": 0 }
bulk_delete_context
Delete multiple knowledge base entries at once. Provide either entry IDs or tags (entries matching ANY of the tags will be deleted), or both. Immutable entries (events) are silently skipped.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ids |
array of strings | no* | Entry IDs (ctx_xxxxxxxx) to delete |
tags |
array of strings | no* | Delete entries matching ANY of these tags |
*At least one of ids or tags is required.
Example:
{
"name": "bulk_delete_context",
"arguments": {
"tags": ["deprecated", "old-feature"]
}
}
Returns: { "deleted": 5, "skipped_immutable": 2 }
log_event
Log an immutable event to the project timeline. Use for deployments, migrations, incidents, and other significant occurrences. Log events as they happen, not after — this is part of the development workflow.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
title |
string | yes | Short event description |
body |
string | yes | Event details |
scope |
string | no | Category |
tags |
array of strings | no | Tags for retrieval |
Example:
{
"name": "log_event",
"arguments": {
"title": "Deployed v2.3.1 to production",
"body": "Deployed commit abc123. Includes new user search feature and bug fix for pagination.",
"tags": ["deployment", "production"]
}
}
get_recent_events
Get the most recent events from the project timeline. Use at session start to understand what has happened since last session.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
integer | no | Number of events to return (default 20, max 50) |
list_tags
List all distinct tags used across context entries in this project. Use to discover available tags before querying with get_context.
Parameters: None.
Returns: { "tags": ["api", "auth", ...], "count": 12 }
list_scopes
List all distinct scopes used across context entries in this project. Use to discover available scopes before querying with get_context.
Parameters: None.
Returns: { "scopes": ["api", "auth", ...], "count": 8 }
Session Tracking and Warnings
The server tracks which context tools each API key has called within a rolling 30-minute session window. When an agent skips recommended workflow steps, responses include a _warnings array with advisory guidance. These warnings are informational — the tool still executes successfully.
Warning triggers:
| Situation | Warning |
|---|---|
Calling store_context, update_context, delete_context, or log_event without having called get_context in the last 30 minutes |
"You haven't loaded existing context this session. Run get_context with priority=high first to avoid overwriting or duplicating existing entries." |
Calling get_context without having called list_tags or list_scopes first |
"Use list_tags and list_scopes to discover available filters before querying. This ensures you don't miss relevant entries." |
Example response with warnings:
{
"data": {
"id": "ctx_a1b2c3d4e5f6",
"type": "rule",
"title": "...",
"body": "..."
},
"_warnings": [
"You haven't loaded existing context this session. Run get_context with priority=high first to avoid overwriting or duplicating existing entries."
]
}
MCP responses include _warnings in the tool result JSON. REST responses include _warnings as a top-level field alongside data and pagination.
Warnings disappear once the recommended workflow steps are followed. The 30-minute window resets on each tool call, so an active session never expires.
Following the recommended session-start protocol (list_tags/list_scopes, then get_context with priority=high, then get_recent_events) eliminates all warnings for the remainder of the session.
Example Workflows
Session Start
At the beginning of a coding session, load project knowledge before making changes. Do not fetch everything at once — a single unfiltered get_context call with a high limit will miss important entries once the knowledge base grows beyond that limit. Instead, use multiple targeted queries:
- Discover available filters: Call
list_tagsandlist_scopesto see what tags and scopes exist. This informs your subsequent queries and eliminates the_warningsonget_context. - Load critical rules: Call
get_contextwithpriority: "high"— these are the non-negotiable rules, warnings, and decisions that every session needs regardless of task. This set stays small and focused. - Check recent activity: Call
get_recent_eventswithlimit: 10to see what happened since last session (deployments, incidents, migrations). - Load task-specific context: Call
get_contextwithtagsand/orscoperelevant to your current task. Working on CSS? Usetags: ["css", "design-system"]. Touching auth? Usescope: "auth".
# Step 1: Discover filters (always)
list_tags
list_scopes
# Step 2: Critical rules (always)
get_context → priority: "high"
# Step 3: Recent activity (always)
get_recent_events → limit: 10
# Step 4: Task-specific (varies per session)
get_context → tags: ["css", "frontend"], type: ["rule", "pattern"]
This approach scales as the knowledge base grows, ensures critical context is never lost below a limit cutoff, and avoids session warnings.
During Development
Writing context entries is part of the development workflow, not something you do after. As you work:
- Made a decision? Store it as a
decisionwith the rationale, so the next session doesn't revisit it. - Hit a gotcha? Store it as a
warningimmediately, while the details are fresh. - Established a pattern? Store it as a
patternso it gets followed consistently. - Discovered a fact? Store it as a
factso nobody has to rediscover it. - Found a bug? Store it as a
bugwith reproduction steps. - Need to do something later? Store it as a
todoso it persists across sessions. - Applied a temporary hack? Store it as a
workaroundwith removal criteria. - Found an external dependency constraint? Store it as a
dependency. - Finished a deployment or migration? Log it as an
event.
The quality of this knowledge base is your responsibility. If it contains crummy information, that's on you. If it's empty, that's on you too.
Storing a New Rule
When you discover a project convention or constraint:
{
"name": "store_context",
"arguments": {
"type": "rule",
"title": "Always use UUIDs for URL parameters",
"body": "Never expose database primary keys in URLs. All URL parameters must use prefixed UUIDs (ctx_, prj_, acc_, etc.).",
"scope": "api",
"tags": ["security", "api", "routing", "urls"],
"priority": "high"
}
}
Logging a Deployment
After completing a deployment:
{
"name": "log_event",
"arguments": {
"title": "Added user search to admin dashboard",
"body": "Implemented search by email and status filtering on the accounts list page. Files changed: AccountController.php, admin/accounts/index.php.",
"tags": ["feature", "admin", "accounts"]
}
}