{
  "_schema_version": "v0.5",
  "_generated": "2026-06-29",
  "_transport": "stdio (ADR-0010 entry point: python -m app.mcp.server) + HTTP Streamable at /mcp/server when MCP_AUTH_TOKEN is set (ADR-0029). Distinct surfaces: stdio used by CliAgentProvider (F17); HTTP used by remote clients (claude.ai). See docs/api/openapi.json GET /mcp/info for live transport/http_enabled state.",
  "_server": "backend/app/mcp/server.py (FastMCP synapse). Mounted into FastAPI app at /mcp/server for HTTP (ADR-0029). Introspected by GET /mcp/info (ADR-0027).",
  "_contract_ref": "ADR-0010 (transport + write path), ADR-0027 (introspection), ADR-0029 (HTTP mount + auth + remote_write_enabled)",
  "tools": [
    {
      "name": "search_wiki",
      "description": "Search the Synapse wiki. Routes through the same retrieve() pipeline as /search (ADR-0022 + ADR-0030): dense bge-m3/Qdrant Phase 1 when EMBEDDINGS_ENABLED=true (default), or lexical Postgres ILIKE Phase 1 when EMBEDDINGS_ENABLED=false (ADR-0030 §2.3). Graph-expansion Phase 2, token-budget Phase 3, and context-assembly Phase 4 run in both modes. Returns up to k results sorted by relevance score. When exposed over the HTTP surface (ADR-0029, MCP_REMOTE_WRITE_ENABLED irrelevant for reads), this tool is always available to remote clients.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "description": "Natural-language search query."
          },
          "k": {
            "type": "integer",
            "default": 5,
            "minimum": 1,
            "maximum": 50,
            "description": "Maximum number of results to return. Clamped to [1, 50]."
          }
        },
        "required": ["query"]
      },
      "outputSchema": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": { "type": "string", "format": "uuid" },
            "title": { "type": ["string", "null"] },
            "type": { "type": ["string", "null"], "enum": ["entity", "concept", "source", "synthesis", "comparison", null] },
            "relevance_score": { "type": "number", "minimum": 0.0, "maximum": 1.0 }
          },
          "required": ["id", "relevance_score"]
        },
        "description": "Empty list on Qdrant/embedding error (no exception propagated)."
      },
      "invariants": ["I9 — reuses retrieve() + Qdrant/bge-m3 or Postgres (no new search engine); I7 — single bounded pass; degrade when EMBEDDINGS_ENABLED=false (ADR-0030)"]
    },
    {
      "name": "write_page",
      "description": "Create or update a wiki page through the Synapse ingest seam (I1, I5, ADR-0010 §2). Validates frontmatter (type, title, sources[], lang) before writing. Returns a structured error dict (not an exception) on missing/invalid fields so the CLI agent can retry. The write goes through write_wiki_page() — the SAME primitive the orchestrated loop uses — so K5 wikilink parsing, K3 index update, Qdrant upsert, and log.md append all run identically (single write path).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "description": "Page title (non-empty). Must match frontmatter.title."
          },
          "content": {
            "type": "string",
            "minLength": 1,
            "description": "Markdown body WITHOUT a frontmatter block."
          },
          "frontmatter": {
            "type": "object",
            "description": "Dict with at least {type, title, sources, lang}.",
            "properties": {
              "type": {
                "type": "string",
                "enum": ["entity", "concept", "source", "synthesis", "comparison"],
                "description": "Page type (PageType enum). Required."
              },
              "title": {
                "type": "string",
                "minLength": 1,
                "description": "Page title. Required."
              },
              "sources": {
                "type": "array",
                "items": { "type": "string" },
                "minItems": 1,
                "description": "Non-empty list of source paths for F3 traceability. Required."
              },
              "lang": {
                "type": "string",
                "minLength": 2,
                "description": "ISO-639-1 language code (e.g. 'en', 'it'). Required."
              }
            },
            "required": ["type", "title", "sources", "lang"],
            "additionalProperties": true
          },
          "origin_source": {
            "type": "string",
            "default": "",
            "description": "Optional origin path injected into sources[] for F3 traceability."
          }
        },
        "required": ["title", "content", "frontmatter"]
      },
      "outputSchema": {
        "oneOf": [
          {
            "type": "object",
            "description": "Success: PageRef",
            "properties": {
              "id": { "type": "string", "format": "uuid" },
              "title": { "type": ["string", "null"] },
              "type": { "type": ["string", "null"] },
              "relevance_score": { "type": "number", "const": 0.0 }
            },
            "required": ["id"]
          },
          {
            "type": "object",
            "description": "Validation failure: structured error dict (not an exception — AC-MCP-3)",
            "properties": {
              "error": { "type": "string" }
            },
            "required": ["error"]
          }
        ]
      },
      "invariants": ["I1 — reuses write_wiki_page primitive (no direct file write)", "I5 — WikiFrontmatter enforced before write"]
    },
    {
      "name": "get_page",
      "description": "Retrieve a live wiki page by title. Returns full content and frontmatter on success, or a structured error dict if the page is not found or has been soft-deleted.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Exact page title (case-sensitive)."
          }
        },
        "required": ["title"]
      },
      "outputSchema": {
        "oneOf": [
          {
            "type": "object",
            "description": "Success",
            "properties": {
              "title": { "type": "string" },
              "type": { "type": ["string", "null"] },
              "content": { "type": "string", "description": "Markdown body without frontmatter block." },
              "frontmatter": { "type": "object", "description": "Parsed YAML frontmatter as dict." }
            },
            "required": ["title", "content", "frontmatter"]
          },
          {
            "type": "object",
            "description": "Not found or soft-deleted",
            "properties": {
              "error": { "type": "string" }
            },
            "required": ["error"]
          }
        ]
      },
      "invariants": []
    },
    {
      "name": "list_pages",
      "description": "List live wiki pages, optionally filtered by page type. Excludes soft-deleted pages (deleted_at IS NOT NULL). Results sorted by title.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "type": {
            "type": ["string", "null"],
            "default": null,
            "enum": ["entity", "concept", "source", "synthesis", "comparison", null],
            "description": "Optional page type filter. null returns all live pages."
          }
        },
        "required": []
      },
      "outputSchema": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": { "type": "string", "format": "uuid" },
            "title": { "type": ["string", "null"] },
            "type": { "type": ["string", "null"] },
            "relevance_score": { "type": "number", "const": 0.0 }
          },
          "required": ["id", "relevance_score"]
        }
      },
      "invariants": []
    }
  ]
}
