← work / mcp-server

liveSolo: tool design, implementation and the search performance fix behind it

Plus234Feed MCP Server

Grounded Nigerian data for Claude Desktop, Claude Code and other MCP clients

// the problem

Assistants answer questions about Nigerian rates, markets and politics confidently and wrongly, because that data changes faster than training and is thin online. This server gives them the current numbers and the archive instead.

// context

The newest surface on the Plus234Feed data platform, added in September 2026. It reads live data on every call and caches only query embeddings, so new articles and rates reach the assistant without a redeploy.

// what I built

  1. An MCP server in TypeScript exposing 13 tools in four groups: the news archive (170,000+ articles), NGX markets and 2,482 corporate filings, money and prices (naira official vs parallel, commodities, NBS series), and civic data (National Assembly members, trending topics).
  2. Two search tools on purpose: semantic search over pgvector embeddings for meaning, and exact keyword search with Postgres ts_rank for names and tickers, because each fails where the other works.
  3. Responses lead with the period they are quoting, and tools report their own coverage gaps rather than implying a fact is absent from the world.
  4. FX returns both the CBN official and parallel rates with the spread, since quoting either alone misleads.
  5. It reads the same Postgres functions that rank the website, so a ranking change reaches the site and the assistant together.

// key decisions

  1. stdio first, behind a transport-agnostic factory

    The client launches the process, so there is no listener or port. createServer() is kept apart from the entrypoint so an HTTP transport can be added without duplicating tools. Given up for now: the database key sits on the user's machine, which is the main argument for a remote deployment later.

  2. Wrap the website's Postgres functions instead of reimplementing retrieval

    Archive tools call the same ranking and matching functions the site uses, so a ranking change reaches both together. The cost is that a slow site function is slow here too, which is how a storage problem in keyword search surfaced and got fixed.

  3. Fix the storage, not the query

    Keyword search timed out for 17 of the 20 most common terms. The cause was the tsvector stored out of line in TOAST beside wide article rows, not the window count first blamed. Copying it into a narrow, trigger-synced table cut "Dangote Refinery" from up to 35.9 s to 29 ms.

  4. Tools state their own gaps

    The legislator tool reports "X of Y seats on file", measured at query time, so a missing state is never read as a vacant seat. NBS answers lead with the period quoted because NBS publishes in arrears. An empty result would otherwise teach the model that the thing does not exist.

// results

  1. Keyword search for "Lagos" (15,001 matches) went from never completing to 125 ms.
  2. About $0.20 per million semantic searches in embedding cost; every other tool is a plain database read.
  3. An end-to-end smoke test makes 24 calls covering all 13 tools over real stdio MCP.