ASK KNOX
beta
LESSON 404

Building a Knowledge-OS Bridge — A Real MCP Server

12 tools, namespaces, query/remember/recall — the exact architecture of Semantic Memory Layer, 414 tests, 92% coverage, running 24/7 on a persistent server.

10 min read·Building Production MCP Servers

What You Are Building

The previous lessons taught the principles. This lesson is the build. You are constructing a knowledge-OS MCP server modeled exactly on Semantic Memory Layer: 12 tools, 6 namespaces, ChromaDB backend, HTTP/SSE transport, bearer token auth, read-after-write verification, and the query-first habit wired into the tool descriptions.

Semantic Memory Layer is not a toy example. It indexes 2,968 chunks across 43 repos. It has 414 tests at 92% coverage. It has been in production on a persistent server since early 2025. It survived the split-brain incident (the next lesson), the native+Docker dual-bind incident, and a ChromaDB volume migration. Everything in this lesson is drawn from production experience, not theory.

The 12-Tool Surface

The 12 tools divide into four groups. Understanding the group structure helps you decide where to add new tools as your knowledge-OS evolves.

Query & Retrieval (memory_query, memory_recall, memory_search): The read surface. These tools are called frequently by Claude Code sessions. They must be fast — memory_query should return in under 200ms for most queries. memory_search is cheaper than memory_query (lower token cost, less precision) and is appropriate for session orientation when you want to understand what's in the index before committing to a specific query.

Write & Maintain (memory_remember, memory_forget, memory_update): The write surface. memory_remember is the primary intake. memory_update supersedes stale memories without losing the memory_id. memory_forget soft-deletes with a confirmation gate. These tools change state — they need the idempotency patterns from the previous lesson.

Context Assembly (memory_context, memory_gaps, memory_namespaces): The meta tools. memory_context builds an assembled context string from the top-N relevant memories — optimized for injection at session start. memory_gaps surfaces what is missing. memory_namespaces shows the distribution of indexed content.

Operations (memory_events, memory_status, memory_reindex): The admin tools. memory_events is the audit trail. memory_status is the L3 health check. memory_reindex rebuilds the index — expensive, used rarely.

The Namespace Architecture

Six namespaces, one ChromaDB collection, metadata-based isolation. This is the design decision that makes Semantic Memory Layer scale: you do not need separate vector databases for different content types. You need a filter.

When a Claude Code session calls memory_query("trading bot architecture"), the query searches across all namespaces and returns results from trading-kb, project-docs, and lessons — ranked by semantic relevance. The session does not need to know which namespace the relevant content is in.

When the agent gateway stores a new session correction, it calls memory_remember(content, namespace="claude-code-memory"). The namespace scopes the write to the right partition.

When Knox wants to find what academy lessons cover context engineering, he calls memory_query("context engineering", namespace="lessons"). The namespace filter limits the search to the ~1,100 lesson chunks.

The distribution bar at the top of the diagram tells the story: lessons (37%) is the largest namespace because the academy MDX is ingested by the ingest-corpus cron on every merge to main. project-docs (28%) is second because Knox's 43 repos all have architecture documents. The other four namespaces are smaller but critical for their use cases.

Building the Tool: memory_query Implementation Sketch

server.setRequestHandler(CallToolRequestSchema, async (req) => {
  const { name, arguments: args } = req.params

  if (name === 'memory_query') {
    const start = Date.now()
    const { query, namespace, limit = 10 } = args as {
      query: string
      namespace?: string
      limit?: number
    }

    const where = namespace ? { namespace: { $eq: namespace } } : undefined
    const results = await collection.query({
      queryTexts: [query],
      nResults: limit,
      where,
    })

    return {
      content: [{
        type: 'text',
        text: JSON.stringify({
          results: results.documents[0].map((doc, i) => ({
            memory_id: results.ids[0][i],
            content: doc,
            namespace: results.metadatas[0][i]?.namespace,
            relevance: 1 - (results.distances?.[0][i] ?? 0),
          })),
          total_found: results.ids[0].length,
          query_time_ms: Date.now() - start,
        }),
      }],
    }
  }
})

This sketch shows the essential pattern: extract args, construct the ChromaDB query with optional namespace filter, map results to the stable output contract, and return the structured JSON. The key is the output contract — the same shape every time, regardless of how ChromaDB internally represents the results.

That was the read surface. Now you build the write surface. memory_remember is the primary intake tool, and it has a requirement memory_query does not: it must be safe to call twice. A flaky network retry should not double-write the same memory. The idempotency pattern from the previous lesson — a content-hash key — is how you get there.

The Query-First Habit Wired into Tool Descriptions

The most important operational pattern for a knowledge-OS server is the query-first habit: call memory_query at the start of every session before reading any file. The habit only works if the tool description explicitly instructs the model to call it at session start.

The current Semantic Memory Layer memory_query description includes: "Call at session start with the project name or task description to load architectural context, known failure modes, and recent corrections before reading any files." That bolded instruction is the difference between a knowledge-OS that gets used and one that accumulates memories nobody reads.

The agent gateway's memory_remember call after corrections includes the description: "Call after any correction from Knox to record the pattern, what went wrong, and the prevention rule." Both instructions drive the two-way discipline: query before you act, remember when you learn.

What's Next

The next lesson covers observability and failure modes — structured logging, the split-brain incident that happens when two processes share a port via SO_REUSEPORT, and the health check standard that proves downstream artifact growth rather than just process liveness.