Skip to main content
Glama

flori

Web research tools exposed over MCP: search, read, open, grep, corpus_search, corpus_list, cite. See spec.md for the design, DECISIONS.md for the open questions resolved during the build, and HANDOFF.md for what still needs a Kagi key.

Layout

  • src/flori/ tool server (types, ports, tools module, SQLite store, adapters, MCP wrapper)

  • fetcher/ isolated fetch process (OCI image; Crawl4AI, headless Chromium, PyMuPDF)

  • tests/ tool-server tests; tests/fetcher/ and tests/e2e/ need the container up

  • fetcher/tests/ fetcher unit tests, runnable on the host

Related MCP server: myscrape

Run

# 1. build and start the fetcher (Docker/OrbStack; Apple container works the same way)
cd fetcher && DOCKER_BUILDKIT=0 /usr/local/bin/docker build -f Containerfile -t flori-fetcher:dev . && cd ..
./scripts/fetcher-up.sh            # also starts the test fixture server

# 2. test
uv run pytest                      # container tests skip if the fetcher is down
(cd fetcher && uv run pytest)
KAGI_API_KEY=... uv run pytest -m live

# 3. serve over MCP (stdio)
KAGI_API_KEY=... FETCHER_URL=http://127.0.0.1:8765 uv run flori
FLORI_TRANSPORT=http FLORI_PORT=8000 uv run flori     # streamable HTTP instead

MCP client config (stdio):

{
  "mcpServers": {
    "flori": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/flori", "flori"],
      "env": {"KAGI_API_KEY": "...", "FETCHER_URL": "http://127.0.0.1:8765"}
    }
  }
}

Configuration: [tool.flori] in pyproject.toml for non-secrets (search_engine, db_path, fetcher_url, search_limit); env vars KAGI_API_KEY, FETCHER_URL, FLORI_DB_PATH, FLORI_SESSION_ID, FLORI_TRANSPORT.

Acceptance

./scripts/fetcher-up.sh
KAGI_API_KEY=... uv run python tests/e2e/acceptance.py

Available Tools

7 tools
citeA

Convert an inspected span of a stored page into a citation. Validates that the page is stored and 0 <= start < end <= len(text) within the length cap, records the verbatim span as an EvidenceEntry, and returns it.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
spanYesCharacter offsets into page.text.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses validation rules (0 <= start < end <= len(text)), a length cap, and the side effect of recording an EvidenceEntry. It does not cover failure/error behavior or any permission requirements, which keeps it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense sentence that front-loads the core action, followed by validation and side-effect details. No filler, though the validation clause is packed tightly enough that it reads a little heavy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return format need not be explained, and the description still notes it returns an EvidenceEntry. For a two-parameter nested-object tool with no annotations, the validation and side-effect disclosure makes it nearly complete; only error handling is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50% (the span object is documented, url is not), and the description compensates by spelling out the valid offset range and the constraint that the page must be stored. That adds real meaning beyond the schema's terse 'Character offsets into page.text.'

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Convert...into a citation') and a specific resource ('an inspected span of a stored page'), which is far more than a restatement of the name. It is clearly distinct from siblings like search/read/grep, though it never explicitly names a sibling it is not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'an inspected span of a stored page' implies a precondition (the page must first be inspected/read), which hints at when the tool applies. However, there is no explicit when-to-use, when-not-to-use, or routing against siblings such as read or corpus_search.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

corpus_listC

Retrieve across the accumulated corpus by metadata: URL, domain, length, fetch time, how many searches surfaced the page, how many evidence entries cite it, and its CSL-JSON record.

ParametersJSON Schema
NameRequiredDescriptionDefault
filterNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It does not say the operation is read-only, whether results are paginated or capped, how they are ordered, or what happens with an empty corpus. It only states that retrieval happens.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense sentence with no filler, and the resource is front-loaded. It is appropriately sized for the amount of genuine information conveyed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so enumerating returned fields (URL, domain, length, CSL-JSON) is redundant, while the actual gap, how the filter argument behaves, is left unaddressed. With no annotations and 0% schema coverage on the only parameter, the definition is not complete enough to invoke the tool confidently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for a nested 'filter' object (domain, min_len, cited_only) with defaults, so the description must compensate. Listing 'domain' and 'length' hints at two filter fields, but the filter semantics, default behavior, and the meaning of cited_only are never explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The tool retrieves corpus entries and the description names the resource (accumulated corpus) and the available metadata axes. However, 'Retrieve ... by metadata' is ambiguous about whether metadata is the filter or the payload, and it does not distinguish itself from the sibling corpus_search, which an agent would plausibly confuse it with.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to use this tool versus corpus_search, grep, or read. Usage is only weakly implied by the word 'list' in the name. No exclusions, prerequisites, or alternatives are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

grepA

Query a stored source, or the whole corpus when url is omitted, with a regular expression. Returns matches with character offsets; results are capped.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNo
patternYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It usefully discloses that matches include character offsets and that results are capped, which is real behavioral detail. It is silent on error behavior for invalid regexes, permissions, and how the cap is applied or what happens when it is hit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action and scoping rule, no filler. Every clause adds information the schema does not carry.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be re-explained beyond the offsets and cap note. For a 2-parameter read tool, the description covers the search target, scoping default, input type, and result shape – enough for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must supply meaning, and it does: it explains that `url` selects a single stored source and that omitting it targets the whole corpus, and that `pattern` is a regular expression. It stops short of clarifying the expected format of `url` (URL vs. identifier) and does not describe the default semantics more deeply.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: querying a stored source or the whole corpus via regular expression, plus the url-omission scoping rule. It does not explicitly differentiate itself from regex-adjacent siblings like search or corpus_search, so an agent must infer the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives one implied usage rule – omit `url` to search the whole corpus – which is genuinely useful context. However, it never says when to prefer grep over `search` or `corpus_search`, nor when-not to use it, leaving alternative selection to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openB

Inspect a stored source in full: returns a window of the stored page text starting at offset with up to length characters (capped).

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
lengthYes
offsetYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It does disclose useful non-obvious behavior: the result is a window, `offset` sets the start, and `length` is capped. However, it omits access/permission requirements, what happens on out-of-range offsets, and error behavior, so transparency is only partial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence that front-loads the purpose and packs the windowing semantics into the same line, with no padding. The only slack is the mildly misleading 'in full'.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and the windowing parameters are covered. Still, for a tool sitting in a six-sibling family with ambiguous names, the definition is not complete enough: it lacks routing guidance and provenance for `url`, and there are no annotations to fill the gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and all three parameters are required, so the description must compensate. It meaningfully explains `offset` (start position), `length` (character count, capped), and implies `url` selects the stored source, but it never clarifies what form `url` takes or where it is obtained, leaving one parameter under-specified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a concrete resource (a stored source's page text) and the exact mechanics of retrieval (a window starting at `offset` of up to `length` characters). It is clear what the tool returns, but it does not distinguish itself from closely named siblings like `read` or `grep`, and the phrase 'in full' sits awkwardly against 'returns a window'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to use `open` rather than `read`, `grep`, `search`, or `corpus_search`, and no prerequisites (e.g. that the url must come from a prior search) are given. The agent is left to infer the routing decision entirely.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

readA

Read a discovered source against a goal and capture citable evidence. Fetches and stores the page on first access (no fetch if already stored), selects the heading sections around the passages most relevant to goal, records each as an EvidenceEntry (with the scoring chunk offsets in hits), and returns them. max_chars bounds the total text returned (500 to 20000). Refuses any URL not returned by a prior search in this session.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
goalYes
max_charsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden, and it does disclose meaningful behavior: fetch-and-store idempotency ('no fetch if already stored'), section-selection around the goal, EvidenceEntry production with hit offsets, the max_chars range, and a hard refusal for unsearched URLs. It stops short of stating storage/auth details or error behavior beyond the refusal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences, front-loaded with the core action before the mechanics, and every clause carries operational information (fetch caching, section selection, hit offsets, max_chars bounds, URL gate). It is slightly packed but not padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't describe return shapes, and it appropriately focuses on the preconditions and side effects of the read. Given three parameters and a gated workflow, it covers the essential context an agent needs to invoke this correctly, with only minor gaps around URL/goal formatting.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate and does: max_chars gets a stated purpose and bounds (500–20000), goal gets its role as the relevance axis for section selection, and url gets the implicit constraint that it must originate from a prior search. This adds real meaning beyond bare types, though it doesn't specify url/goal formats.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read a discovered source against a goal and capture citable evidence') and distinguishes itself from siblings by naming the gate ('Refuses any URL not returned by a prior search') and by hinting at the search/read pipeline. An agent can tell this apart from search, grep, and open.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the workflow constraint (must follow a prior search in this session) which is effectively a precondition and an exclusion, and the goal parameter indicates the usage mode. However it never names an explicit alternative for cases where the URL wasn't from search, so it's clear context but not a full when/when-not/alternatives rubric.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 7 tool updatesv0.1.0
    • First observedcite
    • First observedcorpus_list
    • First observedcorpus_search
    • First observedgrep
    • First observedopen
    • First observedread
    • First observedsearch

TDQS

B3.4/5.0

Scored across 7 tools

Disambiguation4/5

Each tool has a fairly distinct role: search discovers URLs, read extracts goal-relevant evidence, open inspects raw windows, grep is regex retrieval, corpus_search/corpus_list retrieve across the accumulated corpus, and cite builds citations. The main soft spot is that read, open, and grep all surface text from stored pages, so an agent must read carefully to pick the right one, but the descriptions differentiate them well.

Naming Consistency3/5

Most names are bare verbs (search, read, open, grep, cite) while the corpus family uses a prefix (corpus_search, corpus_list), so conventions are mixed. It is still readable and the corpus_ prefix sensibly groups related tools, but there is no single predictable pattern.

Tool Count5/5

Seven tools is well-scoped for a search-read-cite research workflow, with each tool earning a clear place in the pipeline (discovery, reading, inspection, corpus retrieval, citation). No redundancy or padding.

Completeness4/5

The core research lifecycle is covered: discover sources, read them against a goal, inspect/grep stored text, search the corpus, and create citations. Minor gaps exist, such as no explicit bibliography export, no tool to list/prioritize collected evidence, and no way to unregister a source, but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Provides local-first web intelligence over MCP with tools for search, fetch, crawl, extract, cache, find-similar, research, and autonomous agent loops, requiring no API keys.
    10
    839 npm
    5,245
    AGPL 3.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    A self-contained web-research MCP server that lets local LLM agents search, fetch, and synthesize web content using tools like web_search, web_fetch, and web_research.
    2
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to perform web research in one tool call by searching, fetching and cleaning full pages, and ranking cited passages. Provides web_research, web_fetch, web_search, and status tools for MCP clients.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to perform unified web research through a single MCP server, including search, page fetching, recursive crawling, document parsing, YouTube transcript extraction, and deep multi-query research.
    2
    -