sigaa-tools
Friendly CLI and MCP server for SIGAA UFPB and SIPAC public process lookup. Fetch your classes, grades, deadlines, and curriculum all at once without opening the web portal.
Quickstart
Step 1: Install uv (once only):
brew install uv
# or: curl -LsSf https://astral.sh/uv/install.sh | sh
Step 2: Install sigaa:
uv tool install "sigaa-tools[mcp] @ git+https://github.com/PucaVaz/sigaa-tools"
Step 3: Run the setup wizard:
sigaa init
That's it. The wizard prompts for your SIGAA credentials, stores them securely, syncs your data, and optionally sets up MCP for Claude Code or background polling.
What you get
- CLI:
sigaa classes,sigaa news,sigaa grades,sigaa deadlines, etc. Fast, offline-first queries from a local SQLite database. - MCP server: Wire into Claude Code (or any MCP client) to let AI agents fetch your SIGAA data on demand.
- SIPAC lookup:
sigaa sipac process 23074.056437/2026-26— look up public UFPB administrative processes without a browser.
Common commands
sigaa sync # fetch & persist new news, deadlines, grades
sigaa sync --bodies # also fetch full news article text
sigaa classes --schedule # enrolled classes with decoded weekly schedule
sigaa news --class DSCO00022 # news for one class
sigaa news --unread --mark-seen
sigaa grades --semester 2025.1 # grades by semester
sigaa deadlines # assessment/task due dates
sigaa ics --out sigaa.ics # export classes + deadlines as calendar
sigaa curriculum # live progress & required courses
sigaa cra --json # official CRA as JSON
sigaa watch --once --json # sync and report changes as JSON (see Notifications)
Store-backed commands (classes, news, grades, deadlines) are fast and offline. Network commands (sync, watch, curriculum, cra, downloads) need internet.
SIPAC public process lookup
Use this feature to follow UFPB administrative processes without opening each SIPAC page manually. Look up one process by its complete number or find processes by an interested party name or identifier. Process details include the current status, subject, interested parties, public documents, routing movements, status changes, and attached files.
sigaa sipac process 23074.056437/2026-26
sigaa sipac process 23074.056437/2026-26 --json
sigaa sipac search --name "Fulano de Tal"
sigaa sipac search --identifier "12345678901" --page 2 --json
Example summary:
23074.056437/2026-26 [ATIVO]
ANÁLISE DE PROPOSTA DE RESOLUÇÃO SOBRE DISTRIBUIÇÃO DE ENCARGOS DIDÁTICOS
Origin: CI - DIREÇÃO DE CENTRO (11.01.45.01)
Opened: 12/06/2026 17:26
Interested parties: 1 | Documents: 14 | Movements: 6
Agents can call sipac_get_public_process with {"number": "23074.056437/2026-26"}. To search, call sipac_search_public_processes with either name or identifier. Both interfaces use the same schema_version: 1 contracts as the CLI JSON output. Public SIPAC commands do not authenticate, bypass restricted documents, change processes, or persist results. See the SIPAC process guide for fields, use cases, privacy guidance, and error handling.
Headless fallback: export SIGAA_USER=... SIGAA_PASS=....
Optional SIGAA_DB=/path/to/sigaa.db to override the store location.
MCP server (for code agents)
Run sigaa init; it can detect or create .mcp.json and add the sigaa MCP
server without manual absolute-path editing.
Tools: sigaa_list_classes, sigaa_list_news, sigaa_get_news_body,
sigaa_get_schedule, sigaa_list_grades, sigaa_list_deadlines,
sigaa_get_curriculum, sigaa_get_cra, sigaa_export_ics,
sipac_get_public_process, sipac_search_public_processes,
sigaa_download_historico,
sigaa_download_declaracao_vinculo, sigaa_download_atestado_matricula,
sigaa_sync. Store-backed reads are offline; sync, live lookups, and downloads
touch the network.
sipac_get_public_process(number) returns the public process metadata exposed
by UFPB: general data, interested parties, documents and public download links,
movements, status changes, and attached files. It shares schema version 1 with
sigaa sipac process --json and does not require credentials.
sipac_search_public_processes(name?, identifier?, page=1) finds public
processes by one interested-party field. Pass exactly one of name or
identifier. Each response contains at most the 15 results exposed by one
portal page. Results are not retained after the request finishes.
Identifiers such as CPF, registration number, and CNPJ are personal data. Query
them only for a legitimate purpose and avoid copying them into logs.
sigaa_get_curriculum is networked and uses the same normalized contract and
filters as sigaa curriculum: status, required_only, period,
include_requirements, and include_cra. Its default current view contains
enrolled components plus required pending ones. Pending optional components are
choices toward the remaining optional workload, not courses that must all be
completed. sigaa_get_cra is also networked and reads the official CRA from the
academic transcript; a new student may receive source: "unavailable" until
SIGAA reports one. Neither response exposes SIGAA's internal student id.
Every download tool accepts a safe filename (not an arbitrary path), never
overwrites, and writes under the app's private downloads directory. This
covers the three academic documents plus sigaa_download_material and
sigaa_download_tarefa_anexo; on those two the parameter is named filename
and no longer accepts a path. Filenames SIGAA supplies in Content-Disposition
are sanitized rather than trusted. Set
SIGAA_DOWNLOAD_DIR on the MCP server to choose another directory. A successful
call returns both structured metadata (filename, MIME type, and size) and
an opaque MCP ResourceLink. Clients that support resource links can present the
document as an attachment or download; opening it reads the saved file through
MCP without putting its bytes in the original tool response. The resource link is
valid for the current server session, while the local file remains on disk. HTML
certificates are exposed as download-only binary resources so an MCP client does
not execute the report's active SIGAA markup inline.
Tool surface: SIGAA_MODE
SIGAA_MODE picks which tools the MCP server exposes. It defaults to local,
which exposes all 24 tools — nothing is ever removed from a local or
self-hosted install.
SIGAA_MODE=hosted is for a shared, multi-tenant deployment. It withholds the
five tools that write files to the server's disk:
| Withheld in hosted | Why |
|---|---|
sigaa_download_material |
Unbounded file writes; a class can hold hundreds of MB |
sigaa_download_tarefa_anexo |
Same |
sigaa_download_historico |
Needs a per-tenant download directory, which does not exist yet |
sigaa_download_declaracao_vinculo |
Same |
sigaa_download_atestado_matricula |
Same |
Everything else stays, including sigaa_sync — without it a tenant's store is
empty and every store-backed tool returns nothing. Its writes are confined to
SIGAA_DB. No MCP tool mutates SIGAA state in any mode: enrollment
selection and confirmation are deliberately CLI-only.
The mode is applied at import, so it holds whether the server is started via
sigaa-mcp, python -m sigaa.mcp_server, or by importing mcp from
sigaa.mcp_server and mounting it. Withheld tools are removed from the tool
manager, so they are uncallable rather than merely hidden. An unrecognized
SIGAA_MODE raises at startup instead of falling back to local.
A hosted deployment must also set SIGAA_DB and SIGAA_DOWNLOAD_DIR per
tenant. Restoring the three academic-document tools in hosted mode depends on
that isolation existing first.
Scheduled polling
Run sigaa init; it can write the launchd plist on macOS or print the cron
entry for other operating systems.
Notifications
sigaa watch is the integration point for cron, systemd, and chat bridges. It
syncs, then prints what changed since its previous run as JSON events; no LLM is
involved in deciding whether something changed.
sigaa login # password + account into the OS keyring
sigaa sync --bodies --json # expect "ok": true
sigaa watch --once --baseline --json # optional: skip what is already stored
sigaa watch --once --bodies --json --fail-on-error # schedule this
- stdout carries only JSON; human messages go to stderr.
- A run with nothing new reports
"status": "no_changes". - A failed run reports
"status": "failed"pluserrorevents tagged with astage(auth,network,parse,sync) and, with--fail-on-error, exits 1. A failure is never reported asno_changes. - A class page whose news panel cannot be read is a
parseerror, not an empty class. - Unchanged state prints identical bytes, so hash-based monitors are safe.
--jsonl prints one event per line (for --interval 30m loops). Event schema
and a consumer example: docs/notificacoes.mdx.
Credentials
Keyring-first, env-second. Never commit credentials, cookies, downloaded live HTML, SQLite databases, exported PDFs, or .env files.
sigaa init stores your SIGAA password securely in your OS keyring and verifies the login. Public SIPAC queries do not need credentials.
After sigaa login, no environment variables are needed. For headless
environments without a keyring: export SIGAA_USER=username SIGAA_PASS=password
(plaintext password files are not recommended). Optional: SIGAA_DB=/path/to/sigaa.db to override the store location.
Advanced manual configuration
Usually you should run sigaa init. The examples below are for manual setups,
debugging, or custom automation.
Manual MCP
Run with sigaa-mcp (stdio). Wire into Claude Code via .mcp.json:
{
"mcpServers": {
"sigaa": {
"command": "uvx",
"args": [
"--from",
"sigaa-tools[mcp] @ git+https://github.com/PucaVaz/sigaa-tools",
"sigaa-mcp"
]
}
}
}
This form carries no machine-specific path, so the file stays valid when
committed and shared with your team. sigaa init writes it for you. The server
reads the active account from your keyring; add
"env": { "SIGAA_USER": "your_user" } only if keyring is unavailable.
Manual scheduled polling
macOS (launchd) - sync every 30 min. Save as
~/Library/LaunchAgents/ai.sigaa.sync.plist then
launchctl load it:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>Label</key><string>ai.sigaa.sync</string>
<key>ProgramArguments</key>
<array>
<string>/Users/you/.local/bin/sigaa</string>
<string>sync</string>
</array>
<key>EnvironmentVariables</key>
<dict><key>SIGAA_USER</key><string>your_user</string></dict>
<key>StartInterval</key><integer>1800</integer>
</dict></plist>
uv tool install puts sigaa in ~/.local/bin; launchd needs it spelled out in
full, since it does not expand ~. Run which sigaa to confirm yours.
Linux (cron): */30 * * * * $HOME/.local/bin/sigaa watch --once --bodies --jsonl --fail-on-error
(account and password from sigaa login; SIGAA_USER/SIGAA_PASS only where no keyring is reachable).
Architecture
sigaa/
config.py endpoints, JSF constants, slot-time table, creds resolution
http.py session: cookie jar, ViewState, re-login + retry
auth.py login flow
client.py SigaaClient -> domain models
sipac.py unauthenticated public SIPAC process client + JSON contract
models.py Student, Turma, NewsItem, Schedule, CurriculumStatus
parsers/ portal, news, schedule, curriculum, transcript, SIPAC process
store/ SQLite db + repository (dedup, queries)
services/ sync (fetch -> diff -> persist)
cli.py command line
mcp_server.py agent tools
Adding a feature (materials, attendance) = a parser + client method and a
CLI/MCP surface, plus store columns when it is persisted. HTML changes touch
only parsers/. Implemented so far: classes, news (+bodies), grades, deadlines,
curriculum progress, official CRA, academic documents, and ICS export.
Public SIPAC administrative-process consultation is also available live.
exporters/ turns store data into interchange formats (currently ics).
Schedule decoding
6M2345 → Fri (day 6) morning slots 2–5. Days 2=Mon..7=Sat, shift M/T/N.
Clock times in config.SLOT_TIMES_UNCONFIRMED are an unconfirmed default —
verify against a turma's "Plano de Curso" before using them for calendar export.
Tests
pytest # offline: parsers run on fixtures, store on in-memory sqlite
Contributing
Interested in hacking on sigaa-tools? See CONTRIBUTING.md for setup and release instructions.
Security
Single-user, local-first tool. config.py reads credentials from keyring first
and environment variables second. The SQLite db is local and may contain student
data copied from SIGAA. .gitignore excludes *.db, .env, and live HTML
dumps, but review generated files before sharing logs, issues, or screenshots.
The SIPAC process feature is read-only and public; it does not send stored
credentials, but its responses can contain names and identifiers already shown
by the public portal, so handle exported JSON responsibly.
License
MIT. See LICENSE.
Metadata
Release files for sigaa-tools 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sigaa_tools-0.2.0.tar.gz | 118.8 kB | With provenance | Details for sigaa_tools-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sigaa_tools-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for sigaa_tools-0.2.0-py3-none-any.whl |
Total release size: 210.2 kB
Release files / sigaa_tools-0.2.0.tar.gz
| Download URL | sigaa_tools-0.2.0.tar.gz |
|---|---|
| Size | 118.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
51471626235ade23aabd7573a1a651dc96bfefcda9d1aaa5c9c9733e20a37d55
|
|
BLAKE2b-256 checksum How to use checksums |
f3ae38a3d12d5c441fb55d7d4f71820faa8d2bdb5cba51764af0fc63147bf415
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logRelease files / sigaa_tools-0.2.0-py3-none-any.whl
| Download URL | sigaa_tools-0.2.0-py3-none-any.whl |
|---|---|
| Size | 91.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9d7cfbf655f00da8289700c9281f18e7476a7f89bca90d01af786bd6532f5b7b
|
|
BLAKE2b-256 checksum How to use checksums |
99a5d0d8a13986a4201e65eff9841ee08aafba236f179b4c72ad69b83ef011f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logSecurity for sigaa-tools 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for sigaa_tools-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.