Giới Thiệu
Mô hình Giao thức Ngữ cảnh Mô hình (MCP) đã trở thành một tiêu chuẩn đột phá trong việc kết nối các mô hình AI với các công cụ và dịch vụ bên ngoài, nhằm nâng cao khả năng của chúng. Bài viết này sẽ hướng dẫn bạn qua một cái nhìn tổng quan về hành trình phát triển máy chủ xử lý PDF toàn diện bằng FastMCP, với kiến trúc hợp lý, xử lý lỗi, và các tính năng đạt tiêu chuẩn sản xuất.
Danh Sách Công Cụ Sẵn Có
Máy Chủ & Tiện Ích Tập Tin
server_info(): Lấy cấu hình và trạng thái của máy chủ.list_temp_resources(): Liệt kê các tập tin hiện có trong thư mục tạm thời của máy chủ.upload_file(),upload_file_base64(),upload_file_url(): Tải lên các tập tin từ máy tính của bạn hoặc từ một URL.get_resource_base64(): Tải xuống một tập tin từ thư mục tạm thời của máy chủ.
Văn Bản & Siêu Dữ Liệu
get_pdf_info(): Nhanh chóng lấy số trang, kích thước tập tin và trạng thái mã hóa.extract_text(): Trích xuất toàn bộ nội dung văn bản từ một PDF.extract_text_by_page(): Trích xuất văn bản từ các trang cụ thể hoặc dãy trang.extract_metadata(): Đọc siêu dữ liệu của PDF (tác giả, tiêu đề, ngày tạo, v.v.).
Xử Lý PDF
merge_pdfs(): Kết hợp nhiều tập tin PDF thành một tài liệu duy nhất.split_pdf(): Chia một PDF thành nhiều tập tin nhỏ hơn dựa trên dãy trang.rotate_pages(): Xoay các trang cụ thể trong một PDF.
Chuyển Đổi
pdf_to_images(): Chuyển đổi các trang PDF đã chỉ định thành các tập tin hình ảnh (PNG, JPEG).images_to_pdf(): Tạo một PDF mới từ danh sách các tập tin hình ảnh.
Bạn có thể tìm thấy mã nguồn trong GitHub Repo 📁 MCP PDF Server.
Nghiên Cứu Tình Huống: Theo Dõi Công Cụ "extract_text"
Chúng ta sẽ khám phá công cụ 'extract_text'; tất cả các công cụ khác đều chia sẻ một quy trình nhất quán và dễ dàng truy cập trong repo, nếu bạn muốn kiểm tra.
Mô Hình
Bằng cách tách logic thành "Dịch vụ" -> "Công cụ" -> "Đăng ký", chúng ta giữ cho mã nguồn sạch sẽ, có thể kiểm tra và dễ dàng mở rộng. Bạn có thể thêm công cụ của riêng mình bằng cách làm theo mô hình này.
Bước 1: Logic Cốt Lõi - "Dịch Vụ"
Trước khi nghĩ về máy chủ, công cụ hay giao thức, chúng ta cần một hàm Python đơn giản và đáng tin cậy có thể thực hiện nhiệm vụ cốt lõi của chúng ta. Đây là "Lớp Dịch Vụ" - động cơ.
Tập tin: src/fastmcp_pdf_server/services/pdf_processor.py
Bước đầu tiên là viết một hàm nhận một đường dẫn tệp và trả về văn bản, chúng ta sử dụng thư viện "pdfplumber" cho việc này. Lưu ý rằng hàm trả về một lớp TextExtractionResult, giúp đảm bảo cấu trúc dữ liệu nhất quán.
python
from __future__ import annotations
from dataclasses import dataclass
from typing import List
import pdfplumber
from ..utils.validators import validate_pdf
@dataclass
class TextExtractionResult:
text: str
page_count: int
char_count: int
def extract_text(file_path: str, encoding: str = "utf-8") -> TextExtractionResult:
pdf_path = validate_pdf(file_path)
with pdfplumber.open(str(pdf_path)) as pdf:
texts: List[str] = []
for page in pdf.pages:
texts.append(page.extract_text() or "")
text = "\n".join(texts)
return TextExtractionResult(text=text, page_count=len(texts), char_count=len(text))
Hàm này hoàn toàn bằng Python. Nó không biết gì về FastMCP. Nó có thể được kiểm tra đơn vị bằng "pytest" hoặc được sử dụng trong một ứng dụng hoàn toàn khác. Sự tách biệt này là nền tảng của một hệ thống có thể bảo trì. Khi chúng ta đã thực hiện logic dịch vụ của mình, chúng ta tiếp tục với "Công cụ" MCP.
Bước 2: Cây Cầu - "Công Cụ"
Bây giờ chúng ta cần phơi bày hàm dịch vụ của mình cho thế giới bên ngoài như một Công cụ MCP. "Lớp Công cụ" này đóng vai trò như một cây cầu. Nó xử lý thực tế rối rắm của cuộc gọi công cụ và chuyển đổi nó thành một cuộc gọi sạch sẽ đến dịch vụ của chúng ta.
Tập tin: src/fastmcp_pdf_server/tools/text_extraction.py
Đây là phần quan trọng nhất của câu đố. Nó sẽ xử lý cuộc gọi công cụ, giải quyết tệp, gọi dịch vụ và định dạng phản hồi.
python
from __future__ import annotations
import time
import uuid
from typing import Any
from fastmcp import FastMCP # type: ignore
from ..services import pdf_processor
from ..services.file_manager import resolve_to_path
from ..utils.logger import get_logger
logger = get_logger(__name__)
def register(app: FastMCP) -> None:
@app.tool()
async def extract_text(file: Any, encoding: str | None = "utf-8") -> dict:
op_id = uuid.uuid4().hex
start = time.perf_counter()
try:
resolved = resolve_to_path(file, filename_hint="uploaded.pdf")
res = pdf_processor.extract_text(str(resolved), encoding or "utf-8")
duration_ms = int((time.perf_counter() - start) * 1000)
return {
"text": res.text,
"page_count": res.page_count,
"char_count": res.char_count,
"meta": {
"operation_id": op_id,
"execution_ms": duration_ms,
"resolved_path": str(resolved),
},
}
except Exception as e:
logger.error("extract_text error: %s", e)
hint = (
"Cung cấp một đường dẫn đầy đủ, tải lên tệp trước qua 'upload_file', "
"hoặc truyền bytes/base64. Ví dụ payload:\n"
"{\n"
" \"name\": \"upload_file\",\n"
" \"arguments\": {\n"
" \"file\": { \"base64\": \"<...>\", \"filename\": \"my.pdf\" }\n"
" }\n"
"}"
)
raise ValueError(f"extract_text failed: {e}. {hint}")
Công cụ chỉ là một lớp bọc. Nó là một trình quản lý điều phối các phần khác của mã. Nó xử lý các đầu vào rối rắm, gọi logic dịch vụ sạch sẽ và đóng gói phản hồi cuối cùng. Mô hình 'try...except ValueError' là một thực tiễn tốt nhất quan trọng.
Bước 3: Kết Nối Cuối Cùng - "Đăng Ký"
Hàm công cụ của chúng ta đã được định nghĩa, nhưng ứng dụng máy chủ vẫn chưa biết nó tồn tại. Bước cuối cùng là kết nối, hoặc đăng ký, mô-đun công cụ của chúng ta với phiên bản ứng dụng "FastMCP" chính.
Tập tin: src/fastmcp_pdf_server/main.py
Tập tin này là điểm vào của toàn bộ máy chủ. Nhiệm vụ của nó là xây dựng đối tượng ứng dụng và đăng ký tất cả các bộ công cụ.
python
from __future__ import annotations
from typing import Any
from .config import settings
from .utils.logger import get_logger
logger = get_logger(__name__)
def build_app() -> Any:
try:
from fastmcp import FastMCP # type: ignore
except Exception as exc:
raise SystemExit(
"fastmcp chưa được cài đặt. Vui lòng cài đặt các phụ thuộc trước."
) from exc
app = FastMCP(settings.server_name, version=settings.server_version)
from .tools import utilities, text_extraction, pdf_manipulation, conversion, uploads
from .services.file_manager import cleanup_expired
utilities.register(app)
text_extraction.register(app)
pdf_manipulation.register(app)
conversion.register(app)
uploads.register(app)
try:
cleanup_expired()
except Exception as exc:
logger.error("cleanup_expired at startup failed: %s", exc)
return app
Bằng cách nhập các mô-đun và gọi hàm "register" từ mỗi mô-đun. Tập tin chính vẫn sạch sẽ và hoạt động như một tóm tắt cấp cao về khả năng của máy chủ. Thêm hoặc xóa một loại công cụ hoàn toàn đơn giản như thêm hoặc xóa một dòng ở đây.
Bức Tranh Hoàn Chỉnh
Bây giờ, hãy theo dõi một yêu cầu từ đầu đến cuối:
- Một LLM gọi công cụ
extract_text. - Ứng dụng
FastMCP, được xây dựng trongmain.py, chuyển hướng cuộc gọi đến hàm bất đồng bộextract_textbên trongtext_tools.py. - Hàm công cụ gọi
resolve_to_pathđể có đường dẫn tệp sạch. - Hàm công cụ sau đó gọi dịch vụ
pdf_processor.extract_textvới đường dẫn sạch đó. - Dịch vụ thực hiện công việc nặng nhọc và trả về một từ điển đơn giản:
{'text': ..., 'page_count': ...}. - Hàm công cụ nhận từ điển này, thêm
char_countvà khốimeta, và trả về từ điển cuối cùng và đã được làm giàu. FastMCPgửi từ điển cuối cùng này trở lại LLM dưới dạng phản hồi JSON.
Kết Quả Cuối Cùng
Sử dụng Claude Desktop như là khách hàng MCP, chúng ta có thể kiểm tra công cụ "extract_text" từ máy chủ của chúng ta, đơn giản bằng cách đăng ký MCP, thêm nó vào tệp cấu hình "claude_desktop_config.json"
json
{
"mcpServers": {
"pdf-processor-server": {
"command": "D:\\Github Projects\\mcp_pdf_server\\.venv\\Scripts\\python.exe",
"args": [
"-m",
"fastmcp_pdf_server"
],
"env": {
"TEMP_DIR": "D:\\Github Projects\\mcp_pdf_server\\temp_files"
}
}
}
}
Khi bạn đã thêm MCP, nó sẽ trông như thế này.
Thông thường, đối với loại khách hàng MCP này, bạn nên thêm vào prompt của mình việc sử dụng Máy chủ MCP, trong trường hợp này là "Máy chủ xử lý PDF" của chúng ta; đôi khi, bạn cũng phải chỉ định đường dẫn đầy đủ của tệp.
Hướng Đi Tiếp Theo
Bạn đã hoàn thành! Bạn đã thiết lập một máy chủ, học cách kết nối với nó, yêu cầu nó trích xuất văn bản, và thậm chí đã nhìn thấy cách mọi thứ hoạt động.
Tiếp theo là gì?
- Khám Phá Các Công Cụ Khác: Xem tệp
README.md. Bạn sẽ tìm thấy danh sách các công cụ khác mà bạn có thể gọi, nhưmerge_pdfs,split_pdf, vàpdf_to_images. - Mở Rộng Máy Chủ: Cố gắng thêm công cụ của riêng bạn! Làm theo mô hình.
- Tự Động Hóa Cuộc Sống Của Bạn: Nghĩ về các quy trình làm việc của bạn. Bạn có thể sử dụng máy chủ này để tự động trích xuất văn bản từ hóa đơn? Hoặc để kết hợp các báo cáo hàng tuần của bạn thành một PDF duy nhất? Quyền lực nằm trong tay bạn.
Chúc bạn lập trình vui vẻ! 🤖