{
	"openapi": "3.1.0",
	"info": {
		"title": "Eigen Mesh MCP API",
		"summary": "Eigen Mesh public API: MCP (Model Context Protocol) over HTTP",
		"description": "Eigen Mesh does not expose a REST API. Its public programmatic surface is an MCP (Model Context Protocol) endpoint that speaks JSON-RPC 2.0 over a single HTTP POST path. AI assistants and other MCP clients connect with Bearer auth and call four memory tools: capture_thought, retrieve_thoughts, edit_thought, and delete_thought.\n\nProtocol: JSON-RPC 2.0. Supported methods are `tools/list` (enumerate tools) and `tools/call` (invoke a tool with `params.name` and `params.arguments`). See the MCP specification at https://modelcontextprotocol.io and the human-readable docs at https://eigenmesh.xyz/developers/mcp-tools.\n\nInternal/admin endpoints (campaigns, admin stats, etc.) are intentionally not part of this public surface and are not documented here.",
		"version": "1.0.0"
	},
	"servers": [
		{
			"url": "https://app.eigenmesh.xyz/api/mcp",
			"description": "Managed Eigen Mesh MCP endpoint"
		}
	],
	"security": [
		{
			"bearerAuth": []
		}
	],
	"tags": [
		{
			"name": "MCP",
			"description": "JSON-RPC 2.0 calls against the single MCP endpoint"
		}
	],
	"paths": {
		"/api/mcp": {
			"post": {
				"tags": ["MCP"],
				"operationId": "mcpJsonRpc",
				"summary": "MCP JSON-RPC 2.0 endpoint",
				"description": "Single MCP endpoint. Send JSON-RPC 2.0 requests with `method` set to `tools/list` or `tools/call`. For `tools/call`, `params.name` must be one of the four public tools (see the `ToolName` enum) and `params.arguments` must match that tool's input schema. Clients should send `Accept: application/json, text/event-stream`.",
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"$ref": "#/components/schemas/JsonRpcRequest"
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "JSON-RPC response (result or error). Responses may be delivered as `application/json` or `text/event-stream` depending on the request Accept header.",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/JsonRpcResponse"
								}
							}
						}
					},
					"401": {
						"description": "Missing or invalid Bearer token."
					},
					"406": {
						"description": "Request is not acceptable: the Accept header must include `application/json` (and/or `text/event-stream`)."
					}
				}
			}
		}
	},
	"components": {
		"securitySchemes": {
			"bearerAuth": {
				"type": "http",
				"scheme": "bearer",
				"description": "MCP API key issued in the Eigen Mesh app. Default auth attributes captures to the agent (the API key's name); pass `as_user: true` to capture_thought to store the human user's memory."
			}
		},
		"schemas": {
			"JsonRpcRequest": {
				"type": "object",
				"required": ["jsonrpc", "id", "method"],
				"properties": {
					"jsonrpc": {
						"type": "string",
						"const": "2.0"
					},
					"id": {
						"description": "Request identifier, echoed back in the response.",
						"type": ["integer", "string"]
					},
					"method": {
						"type": "string",
						"enum": ["tools/list", "tools/call"]
					},
					"params": {
						"type": "object",
						"description": "For tools/list: empty object. For tools/call: the tool name and its arguments.",
						"properties": {
							"name": {
								"$ref": "#/components/schemas/ToolName"
							},
							"arguments": {
								"description": "Arguments for the tool selected via `params.name`. Must match that tool's input schema (see CaptureThoughtArguments, RetrieveThoughtsArguments, EditThoughtArguments, DeleteThoughtArguments).",
								"type": "object"
							}
						}
					}
				}
			},
			"JsonRpcResponse": {
				"type": "object",
				"required": ["jsonrpc", "id"],
				"properties": {
					"jsonrpc": {
						"type": "string",
						"const": "2.0"
					},
					"id": {
						"type": ["integer", "string"]
					},
					"result": {
						"type": "object",
						"description": "For tools/call, result.content[0].text carries the tool output.",
						"properties": {
							"content": {
								"type": "array",
								"items": {
									"$ref": "#/components/schemas/ContentBlock"
								}
							}
						}
					},
					"error": {
						"type": "object",
						"properties": {
							"code": {
								"type": "integer",
								"description": "JSON-RPC error code, e.g. -32000 for auth/acceptance issues."
							},
							"message": {
								"type": "string"
							}
						}
					}
				}
			},
			"ContentBlock": {
				"type": "object",
				"properties": {
					"type": {
						"type": "string",
						"enum": ["text"]
					},
					"text": {
						"type": "string"
					}
				}
			},
			"ToolName": {
				"type": "string",
				"enum": ["capture_thought", "retrieve_thoughts", "edit_thought", "delete_thought"],
				"description": "The four tools exposed over HTTP MCP. Notes tools (create_text_file, search_text_files, etc.) are available in the in-app chat agent only."
			},
			"CaptureThoughtArguments": {
				"type": "object",
				"description": "Capture and store a raw thought. Tier 1: returns immediately after text persist; keyword recall on lexical_text is ready. Tier 2 (background): embedding, entities, graph links. Use retrieve_thoughts for recall. MCP Bearer auth: default labels the thought as agent-authored (your API key name). Pass as_user true when the user asked you to remember something for them (their memory, not yours). Omit as_user when storing the agent's own observation or note.",
				"properties": {
					"raw": {
						"type": "string"
					},
					"captured_at": {
						"type": "string",
						"description": "Optional ISO-8601 capture time for backdated memories (temporal anchoring)."
					},
					"as_user": {
						"type": "boolean",
						"description": "When true, store as the human user's memory (e.g. they asked you to remember this for them). When false or omitted on MCP API key auth, store as agent-authored with your API key name."
					},
					"author": {
						"type": "string",
						"description": "Optional override: first ~10 characters of a different API key prefix to attribute authorship. Usually omitted — MCP Bearer token identity is used automatically."
					}
				},
				"required": ["raw"]
			},
			"RetrieveThoughtsArguments": {
				"type": "object",
				"description": "Read stored thoughts. Defaults to user-authored open memories (excludes agent captures and completed/archived). For the latest open thoughts (newest first): omit query or set order=created_at — use top_k and optional cursor_created_at + cursor_id to paginate. With query and order=relevance (default): hybrid semantic, lexical, and graph search over open thoughts plus lexical search over attached text notes. Pass author=all or include_agent=true to include agent/API-key captures.",
				"properties": {
					"query": {
						"type": "string",
						"description": "Optional search text. Omit (or set order=created_at) to browse recent open thoughts newest-first instead of searching."
					},
					"order": {
						"type": "string",
						"enum": ["created_at", "relevance"],
						"description": "created_at: newest open thoughts first (ignores query). relevance: rank by search match (default; requires query)."
					},
					"top_k": {
						"type": "number",
						"description": "Max results (default 10). When browsing recent thoughts, acts as the page size."
					},
					"threshold": {
						"type": "number"
					},
					"mode": {
						"type": "string",
						"enum": ["fast", "full"]
					},
					"detail": {
						"type": "string",
						"enum": ["snippet", "full"]
					},
					"author": {
						"type": "string",
						"enum": ["user", "agent", "all"],
						"description": "Whose memories to retrieve. Default user (human captures). agent = API-key captures only. all = no author filter."
					},
					"include_agent": {
						"type": "boolean",
						"description": "When true, same as author=all (ignored if author is set)."
					},
					"cursor_created_at": {
						"type": "string",
						"description": "Pagination cursor (ISO created_at) when browsing recent thoughts without query."
					},
					"cursor_id": {
						"type": "string",
						"description": "Pagination cursor (thought UUID) when browsing recent thoughts without query."
					}
				}
			},
			"EditThoughtArguments": {
				"type": "object",
				"description": "Edit an existing thought by ID with a natural-language request. Covers text changes (reword, fix typo) and lifecycle/status changes (mark complete, mark done, reopen, archive, dismiss as irrelevant/outdated). Works for ANY category — task, idea, observation, fact, etc. are interchangeable; never refuse because something is \"not a todo\". Done/complete sets completed; archive/irrelevant/outdated soft-removes like delete_thought. There is no separate set_status tool.",
				"properties": {
					"thought_id": {
						"type": "string"
					},
					"edit_request": {
						"type": "string",
						"description": "Natural-language instruction, e.g. \"mark as done\", \"mark complete\", \"archive\", \"not relevant\", \"outdated\", \"fix typo in second sentence\". Category does not matter."
					},
					"raw_text": {
						"type": "string",
						"description": "Optional direct text replacement. When provided, replaces the thought text directly without LLM processing."
					}
				},
				"required": ["thought_id"]
			},
			"DeleteThoughtArguments": {
				"type": "object",
				"description": "Archive (soft-remove) one stored thought by ID — reversible, not a permanent delete. Same soft-remove family as edit_thought \"archive\" / \"not relevant\" / \"outdated\"; use for delete/remove. Works for any category.",
				"properties": {
					"thought_id": {
						"type": "string"
					}
				},
				"required": ["thought_id"]
			}
		}
	}
}
