Phosphorus is a proof-of-concept for an agentic AI designed to fully manage an entire library, handling all tasks from backend organization to direct user requests. This AI operates on a robust Django/MySQL-based platform, leveraging a comprehensive API to autonomously manage books, borrowers, loans, and fine tracking, ensuring efficient staff operations and data integrity.
It is developer friendly with api endpoints available in JavaScript/TypeScript, Python, and HTTP.
All endpoints are under /api/ except for the Django admin interface.
POST /api/auth/login— Authenticate user and start session- Body:
{ "username": str, "password": str } - Response:
{ "message": str, "username": str, "id": int }or{ "error": str }
- Body:
POST /api/auth/logout— Log out current user and end session- Response:
{ "message": str }
- Response:
GET /api/auth/unauthorized— Always returns 401 unauthorized- Response:
{ "error": "Unauthorized" }
- Response:
GET /api/books/search— Search for books by title, ISBN, or author- Query:
?query=...&page=1&limit=10(pagination is required) - Response:
{ "books": [{ "isbn": str, "title": str, "authors": [str] }], "total": int, "page": int }
- Query:
GET /api/books/search_with_loan— Search for books with their current loan status- Query:
?query=...&page=1&limit=10(pagination is required) - Response:
{ "results": [[{ "isbn": str, "title": str, "authors": [str] }, {loan or null}]], "total": int, "page": int }
- Query:
GET /api/books/get— Get a single book by ISBN- Query:
?isbn=... - Response:
{ "isbn": str, "title": str, "authors": [str] }or{ "error": str }
- Query:
POST /api/borrower/create— Create a new borrower- Body:
{ "ssn": str, "bname": str, "address": str, "phone"?: str, "card_id"?: str } - Response:
{ "message": str, "card_id": str, "name": str }or{ "error": str }
- Body:
GET /api/borrower/search— Search for borrowers- Query:
?query=...&page=1&limit=10(pagination is required) - Response:
{ "borrowers": [{ "card_id": str, "ssn": str, "bname": str, "address": str, "phone": str }], "total": int, "page": int }
- Query:
GET /api/borrower/search_with_fine— Search for borrowers with their total fines- Query:
?query=...&page=1&limit=10(pagination is required) - Response:
{ "results": [[borrower, total_fines]], "total": int, "page": int }
- Query:
GET /api/borrower/search_with_info— Search for borrowers with their active loan count, total loan count, and total fines owed- Query:
?query=...&page=1&limit=10(pagination is required) - Response:
{ "results": [[borrower, active_loans, total_loans, fine_owed]], "total": int, "page": int }
- Query:
GET /api/borrower/fines— Get total fines for a borrower- Query:
?card_id=...&include_paid=true|false - Response:
{ "card_id": str, "total_fines": float }or{ "error": str }
- Query:
POST /api/librarian/create— Create a new librarian user- Body:
{ "username": str, "password": str } - Response:
{ "message": str, "username": str, "id": int }or{ "error": str }
- Body:
GET /api/loans/search— Search for loans- Query:
?query=...&page=1&limit=10(pagination is required) - Response:
{ "loans": [{ "loan_id": str, "isbn": str, "card_id": str, "date_out": str, "due_date": str, "date_in": str, "fine_amt": float, "paid": bool }], "total": int, "page": int }
- Query:
GET /api/loans/search_with_book— Search for loans with book details- Query:
?query=...&page=1&limit=10(pagination is required) - Response:
{ "results": [[loan, book]], "total": int, "page": int }
- Query:
POST /api/loans/checkout— Check out a book- Body:
{ "card_id": str, "isbn": str } - Response:
{ "message": str, "loan_id": str }or{ "error": str }
- Body:
POST /api/loans/checkin— Check in a book- Body:
{ "loan_id": str } - Response:
{ "message": str, "loan_id": str }or{ "error": str }
- Body:
/admin/— Django admin interface
All search endpoints require the following pagination parameters:
page: Page number (1-indexed)limit: Number of results per page
These parameters are required to ensure proper API behavior and prevent excessive data transfers.
root/
├── backend/ # Python backend folder
│ ├── api.py # Core API routing logic
│ ├── auth_views.py # Authentication-related view handlers
│ ├── query.py # Custom SQL queries or logic
│ ├── settings.py # App configuration (e.g., DB, middleware)
│ ├── urls.py # Maps URL paths to views
│ ├── views.py # Core request handling views
│ └── database/ # DB models and related logic
│ ├── models.py # SQL table definitions
│ └── views.py # Views specific to DB ops (if any)
│
├── src/ # Frontend app (React + Vite + TS)
│ ├── components/
│ │ ├── ui/ # Reusable UI elements (button, table, etc.)
│ │ ├── BorrowerModal.tsx # Modal for borrower actions
│ │ ├── DataTable.tsx # Generic data table component
│ │ ├── SearchArea.tsx # Search bar + filters
│ │ └── Sidebar.tsx # Main navigation sidebar
│ ├── pages/
│ │ ├── Borrowers.tsx # Page to view/search borrower data
│ │ ├── Checkout.tsx # Page to handle book checkouts
│ │ └── Loans.tsx # Page to view and manage loans
│ ├── lib/
│ │ └── api.ts # API client for frontend-backend requests
│ ├── App.tsx # Root component
│ └── main.tsx # Frontend entry point
│
├── manage.py # Django CLI entry point
├── main.py # Script to demonstrate backend usage
├── README.md # Project overview and instructions
├── package.json # Frontend dependencies and scripts
├── requirements.txt # Backend (Python) dependencies
└── vite.config.ts # Vite configuration for the frontend
search_books(query: Query) -> Results[Book]search_books_with_loan(query: Query) -> Results[Tuple[Book, Optional[Loan]]]get_book(isbn: str) -> Booksearch_loans(query: Query) -> Results[Loan]search_loans_with_book(query: Query) -> Results[Tuple[Loan, Book]]search_borrowers(query: Query) -> Results[Borrower]search_borrowers_with_fine(card_id: str, query: Query) -> Results[Tuple[Borrower, Decimal]]search_borrowers_with_info(card_id: str, query: Query) -> Results[Tuple[Borrower, int, Decimal]]checkout(card_id: str, isbn: str) -> Loancheckin(loan_id: str) -> Loanget_user_fines(card_id: str, include_paid: bool = False) -> Decimalget_fines(card_ids: list = [], include_paid: bool = False, sum: bool = False) -> List[Loan]get_fines_grouped(card_ids: list = [], include_paid: bool = False) -> Dict[str, Decimal]pay_loan_fine(loan_id: str) -> Loanpay_borrower_fines(card_id: str) -> List[Loan]update_fines(current_date: date = date.today()) -> Nonecreate_borrower(ssn: str, bname: str, address: str, phone: str = None, card_id: str = None) -> Borrowercreate_librarian(username: str, password: str) -> Usercreate_user(username: str, password: str, group: str) -> Usercreate_book(isbn: str, title: str, authors: List[str] = []) -> Book
Book.authorsis a list of strings (author names).Loan.date_out,Loan.due_date, andLoan.date_inare of typedateorNone.
- Fines are $0.25 per day for late books
update_fines()can be run manually or scheduled- Fine reporting supports paid/unpaid status and borrower summaries
- Fines can be paid per loan or in bulk for a borrower
- Librarians have staff-level access and permissions
- Admins have full system access
- User creation is integrated with librarian and borrower creation as needed
- Default groups ("Librarians") organize permissions
- Install Python 3, MySQL, and clone the repository:
python --version mysql --version git clone https://github.com/Boden-C/phosphorus cd phosphorus - Create and activate a virtual environment:
python -m venv .venv source .venv/bin/activate # On macOS/Linux .venv\Scripts\activate # On Windows
- Install dependencies:
pip install -r requirements.txt
- Enter MySQL and create the database/user:
mysql -u root CREATE DATABASE IF NOT EXISTS phosphorus_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'phosphorus_user'@'localhost' IDENTIFIED BY ''; GRANT ALL PRIVILEGES ON phosphorus_db.* TO 'phosphorus_user'@'localhost'; FLUSH PRIVILEGES; exit
- Setup the database:
mysql -u phosphorus_user phosphorus_db < setup/schema.sql - Update and confirm Django settings:
python manage.py migrate
To normalize the data:
python setup/normalize.pyTo validate the data:
python setup/validate.pyAfter running normalize.py, cleaned data will be saved as book.csv, authors.csv, book_authors.csv, and borrower.csv.
To initialize or reset:
python reset.pyTo run example code:
python main.pyTo start the development server:
python manage.py runserverTo start the Electron development server:
npm run electron:devTo start the general (Next.js or frontend) development server:
npm run dev
It should display this:-
VITE v6.3.2 ready in 580 ms
➜ Local: http://localhost:5173/ (your local URL may vary)
➜ Network: use --host to expose
➜ press h + enter to show helplocalhost:8000/admin
Default admin credentials:
- user: admin
- pass: adminpassword
To manually update fines:
python manage.py update_fines