Skip to main content
AI tutorials

Build and Use a Local File Knowledge Base with FastAPI, SQLite, and MCP

Learn how to install the FastAPI knowledge base, initialize its SQLite database, authenticate users, upload and organize documents, preview supported files, and connect AI agents through the included read-only MCP service.

Build and Use a Local File Knowledge Base with FastAPI, SQLite, and MCP

Overview

Knowledge Base Phase 1 is a minimum viable file knowledge base built with FastAPI, SQLite, and local filesystem storage. It supports authenticated document management, nested folders, browser-local previews, metadata and tags, administrator tools, audit information, and read-only access for AI agents through the Model Context Protocol, or MCP.

This phase is deliberately lightweight. It does not require Docker, PostgreSQL, MinIO, LibreOffice, ONLYOFFICE, or another running database service. PostgreSQL and object storage are reserved for a later migration.

What the project provides

  • Administrator-created users, login, and JWT authentication.
  • Public knowledge bases with nested folders and breadcrumb navigation.
  • Folder-scoped document listing, single-file upload, and batch upload.
  • Support for PDF, text, Markdown, HTML, images, PowerPoint, Word, and Excel files.
  • Document metadata, tags, owner and uploader information.
  • Original-file preview and download.
  • In-app reading for text, Markdown, PDF, DOCX, XLSX, PPTX, and images.
  • Best-effort text extraction for legacy DOC, XLS, and PPT files.
  • Owner-only document editing, soft deletion, restoration, folder renaming, and empty-folder deletion.
  • A recycle bin for deleted documents.
  • Cross-scope document and folder copying, including recursive folder copies and physical storage duplication.
  • Administrator-only user management, audit logs, and MCP invocation logs.
  • A read-only REST API, generated OpenAPI documentation, and MCP integration.

How storage works

The application creates runtime files under backend/data/. The SQLite database is stored as backend/data/knowledge_base.db, while uploaded files and generated Markdown files are placed under backend/data/storage/.

Local storage includes path traversal protection. The existing Docker Compose configuration is intended for the later PostgreSQL and object-storage migration and is not needed for this phase.

Install the backend

1. Create the environment file

Open PowerShell, enter the repository's backend directory, and copy the root environment template to backend/.env.

cd backend
Copy-Item ..\.env.example .env

Operational settings are defined through .env.example, backend/app/core/config.py, and the PowerShell control files under scripts/.

2. Create a Python virtual environment

python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt

Run these commands from the backend directory. Activating the virtual environment keeps the project's packages separate from your global Python installation.

3. Initialize SQLite

python -m app.db.init_db

This command initializes or recreates the required SQLite tables. Because recreating tables may affect existing data, treat it carefully after you begin storing documents.

4. Start FastAPI

uvicorn app.main:app --reload

The development server is then available at http://127.0.0.1:8000. The --reload option automatically reloads the application when source files change.

5. Open the API documentation

Visit http://127.0.0.1:8000/docs to inspect and try the generated OpenAPI endpoints.

Verify the installation

Tests require the backend directory on PYTHONPATH. In Windows Command Prompt, run:

set PYTHONPATH=.
python -m pytest

In PowerShell, use:

$env:PYTHONPATH = "."
python -m pytest

The repository also provides separate PowerShell control files under scripts/ for service start, restart, stop, and status operations.

Authenticate with the REST API

Users are created by an administrator. Once you have an account, submit its username and password to the login endpoint. The response contains the token needed for authenticated requests.

$body = @{
  username = "demo"
  password = "password-123"
} | ConvertTo-Json

$response = Invoke-RestMethod `
  -Method Post `
  -Uri http://127.0.0.1:8000/api/v1/auth/login `
  -ContentType "application/json" `
  -Body $body

$response

Copy the returned access token and use it as a Bearer credential. Token permissions follow the identity and role of the authenticated user.

Upload a document

The upload endpoint accepts multipart form data. Supply a knowledge base ID, optional tags, the file, and the Bearer token:

$token = "<access_token>"
$knowledgeBaseId = 1

curl.exe `
  -X POST `
  "http://127.0.0.1:8000/api/v1/documents/upload" `
  -H "Authorization: Bearer $token" `
  -F "knowledge_base_id=$knowledgeBaseId" `
  -F "tags=制度,测试" `
  -F "file=@D:\path\to\guide.txt"

The project supports both individual and batch uploads. Uploaded originals remain in local storage, while supported content can be opened in the in-app reader.

Create and use folders

Create a folder by posting its knowledge base ID and name to the folder endpoint:

$body = @{
  knowledge_base_id = 1
  name = "实验方案"
} | ConvertTo-Json

Invoke-RestMethod `
  -Method Post `
  -Uri http://127.0.0.1:8000/api/v1/folders `
  -Headers @{ Authorization = "Bearer $token" } `
  -ContentType "application/json" `
  -Body $body

To upload into a particular folder, add folder_id to the multipart upload form. The web interface adds it automatically when a folder is selected.

The knowledge base selector defaults to 全部, meaning “all.” This view displays root documents and folders across all public knowledge bases. When creating a folder, select its destination knowledge base in the dialog. An upload made from the all-knowledge-bases view uses the first available knowledge base unless a folder is selected.

Understand browser-local previews

The frontend fetches files through the authenticated API, holds them in browser memory, and renders them locally. It uses vue3-office-preview for DOCX, PPTX, XLS, and XLSX, @vue3-office/vue-pdf for PDF, and @deot/docs-markdown for Markdown. PPTX rendering uses the bundled pptx-renderer.

This path does not need LibreOffice, ONLYOFFICE, Docker, or a Python document-preview SDK. The original file stays in local storage. Markdown extraction and fallback processing for legacy .doc, .xls, and .ppt files remain backend responsibilities.

Connect an AI agent through MCP

The repository includes a separate read-only MCP service. It shares the FastAPI application's SQLite database, local storage, JWT secret, and document reader. The available Phase 1 tools are:

  • list_knowledge_bases
  • list_documents
  • search_knowledge
  • get_document
  • get_document_metadata

The MCP process cannot upload, move, delete, or manage folders. Its document access is restricted to what the associated user is allowed to read.

Install MCP dependencies

Create a dedicated MCP virtual environment from the backend directory:

cd backend
python -m venv .mcp-venv
.\.mcp-venv\Scripts\python.exe -m pip install -r requirements-mcp.txt

Run MCP over standard input and output

Configure the MCP process with the same database and storage settings as the API. Place a login access token in KB_MCP_TOKEN, then start the server:

$env:PYTHONPATH = "."
$env:KB_MCP_TOKEN = "<access_token>"
.\.mcp-venv\Scripts\python.exe -m app.mcp_server

For local stdio clients, KB_MCP_TOKEN may be omitted. In that case, the agent must call the authenticate tool once with the user's username and password. The resulting short-lived session exists only in MCP process memory.

Do not add ordinary print() calls to the stdio MCP service. Standard output carries protocol messages, so diagnostics must be written to standard error.

Run the MCP smoke test

$env:PYTHONPATH = "."
.\.mcp-venv\Scripts\python.exe scripts\mcp_stdio_smoke.py

Expose MCP through Streamable HTTP

Set the transport, listening address, port, path, and stateless mode before starting the same MCP module:

$env:PYTHONPATH = "."
$env:MCP_TRANSPORT = "streamable-http"
$env:MCP_HOST = "0.0.0.0"
$env:MCP_PORT = "8020"
$env:MCP_PATH = "/mcp"
$env:MCP_STATELESS_HTTP = "true"
.\.mcp-venv\Scripts\python.exe -m app.mcp_server

After configuring an HTTPS reverse proxy, the public endpoint can be https://your-domain/mcp. Remote clients must send Authorization: Bearer <access_token> and should use the same protected Bearer credential as the API connection.

The browser page /mcp-token.html can request an MCP Token for the logged-in account without reading or storing its password. Administrators can use /admin.html to manage user status, roles, passwords, and per-user MCP Token expiration policies, including persistent long-lived Tokens.

Advanced operational tips

  • Keep API and MCP settings aligned. Both services must point to the same SQLite database and storage paths and use the same JWT secret.
  • Use least-privilege identities. An MCP agent inherits the readable document scope of its token's user.
  • Protect Bearer tokens. Do not place API or MCP credentials in source control, logs, or ordinary console output.
  • Preserve the stdio protocol. Send MCP diagnostics to standard error rather than standard output.
  • Use HTTPS remotely. Put the Streamable HTTP endpoint behind an HTTPS reverse proxy before exposing it outside the local machine.
  • Remember Phase 1 boundaries. Docker Compose, PostgreSQL, and object storage are migration targets rather than current runtime requirements.
  • Review ownership restrictions. Document editing, soft deletion, restoration, folder renaming, and empty-folder deletion are owner-only operations.
  • Use the generated API documentation. The /docs page is the most direct way to inspect available request fields and responses beyond the examples shown here.

Conclusion

Knowledge Base Phase 1 provides a practical local foundation for authenticated file organization, preview, retrieval, and agent access. With only Python, SQLite, and local storage, you can initialize the service, upload structured document collections, manage folders and metadata, and safely expose read-only knowledge tools through either local stdio or remote Streamable HTTP MCP transport.