mcp server
fam-mcp
π A read-only MCP server for my universityβs student portal (FAM).
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
{
"mcpServers": {
"fam-mcp": {
"command": "uvx",
"args": [
"fam-mcp"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 21, 2026About
TL;DR: a read-only MCP server that gives an AI assistant access to a student's data on the portal of FAM (Faculdade de Americana): grades, absences, assignments, schedule, exams, inbox, forums, finances and complementary hours. The portal has no API, so the server signs in as the student, reads the pages and hands back clean, typed JSON. It does not write anything back.
Why it exists
The portal does its job, but it was built for a browser and a patient person. There is no API, every screen is a full page rendered on the server that takes seconds to load, and the answer to a simple question is usually spread over several of them. What do I have to deliver this week? means the assignments, the forums, the exam calendar and the finance page.
With this server the assistant opens those pages for me, and I just ask. Some things I use it for:
- "What is due this week?" reads the assignments, exams, forums and invoices in one go
- "Can I still miss class in this course?" checks the absences against the allowed maximum
- "What do I need on the last exam to pass?" reads the averages together with the portal's own grading rules
- "How much of the degree is left?" adds up the transcript
How it works
Every tool is a small module. It asks the portal client for one or more pages, parses the HTML into a typed model, and returns it. The portal client keeps a single session for the whole run: it signs in when the server starts, notices when the portal sends it back to the login page, signs in again once and retries the request. Calls that arrive together share that one login.
What it can do
Student
| Tools | What they do |
|---|---|
get_student_profile | Who is signed in: name, RA, class, term and masked contact data |
Academics
| Tools | What they do |
|---|---|
list_coursesget_class_scheduleget_gradesget_term_resultsget_absencesget_transcriptget_degree_progressget_exam_calendar | The courses of a term, with teachers and teaching-plan statusWhat happens on each weekdayScores per evaluation stage: N1, N2 and N3Averages, grading rules and the absences used so farHow many classes can still be missed, month by monthThe full grade history, semester by semesterHow much of the degree is done and what comes nextWhen the exams are |
Assignments
| Tools | What they do |
|---|---|
list_activitiesget_activitydownload_activity_materialget_agenda | Assignments with deadline, status and whether they were deliveredOne assignment in full: instructions, materials and the deliverySaves an attached file so the assistant can read itEverything with a date in the next days, in one sorted list |
Communication
| Tools | What they do |
|---|---|
get_inboxget_inbox_maillist_forumsget_forumlist_surveys | Inbox messages, filtered by unread or senderOne message in full, with its attachmentsThe course forums and whether they are still openA forum's instructions and repliesThe institutional surveys and which ones were answered |
Finance and requests
| Tools | What they do |
|---|---|
get_financial_statuslist_requestsget_complementary_hours | Open and paid invoices, with the bank data to check them againstThe requests opened at the secretariatComplementary activity hours, by status |
Installation
FAM MCP is a local stdio server published on PyPI. It requires Python 3.14 or newer. Most MCP clients can launch it with uvx:
{
"mcpServers": {
"fam": {
"command": "uvx",
"args": ["fam-mcp"],
"env": {
"FAM_USERNAME": "YOUR_CPF",
"FAM_PASSWORD": "YOUR_FAM_PASSWORD"
}
}
}
}
What you will need
uv, which provides theuvxcommand.- Python 3.14 or newer.
- Your FAM portal credentials:
FAM_USERNAMEis your CPF (digits only), andFAM_PASSWORDis your portal password.
Replace the example values with your credentials. Keep populated user configuration files private, and never commit real credentials to a repository.
Client-specific instructions
The examples below cover Claude Code, Claude Desktop, OpenAI Codex, OpenCode, Gemini CLI, Grok Build, DeepSeek Harness, Cursor, VS Code with GitHub Copilot, Zed, Cline, Roo Code, and Continue. Claude.ai and ChatGPT in a browser are covered too; they require a remote MCP server, while FAM MCP currently runs locally over stdio.
Run this in a terminal. The user scope makes FAM available in all your Claude Code projects:
claude mcp add --transport stdio --scope user \
--env "FAM_USERNAME=YOUR_CPF" \
--env "FAM_PASSWORD=YOUR_FAM_PASSWORD" \
fam -- uvx fam-mcp
Check the connection with claude mcp get fam or /mcp inside Claude Code. See the Claude Code MCP guide.
Open Settings β Developer β Edit Config and add this entry inside mcpServers:
{
"mcpServers": {
"fam": {
"command": "uvx",
"args": ["fam-mcp"],
"env": {
"FAM_USERNAME": "YOUR_CPF",
"FAM_PASSWORD": "YOUR_FAM_PASSWORD"
}
}
}
}
Restart Claude Desktop after saving. See Claude Desktop local MCP setup.
Add this to ~/.codex/config.toml. The same user config is used by Codex CLI and its IDE integrations:
[mcp_servers.fam]
command = "uvx"
args = ["fam-mcp"]
env = { FAM_USERNAME = "YOUR_CPF", FAM_PASSWORD = "YOUR_FAM_PASSWORD" }
Restart Codex, then check the server with codex mcp list. See the Codex configuration reference.
Add this server under mcp in your user ~/.config/opencode/opencode.json or project opencode.json:
{
"mcp": {
"fam": {
"type": "local",
"command": ["uvx", "fam-mcp"],
"environment": {
"FAM_USERNAME": "YOUR_CPF",
"FAM_PASSWORD": "YOUR_FAM_PASSWORD"
},
"enabled": true
}
}
}
See the OpenCode MCP server guide.
Run:
gemini mcp add --scope user \
--env "FAM_USERNAME=YOUR_CPF" \
--env "FAM_PASSWORD=YOUR_FAM_PASSWORD" \
fam uvx fam-mcp
Check with gemini mcp list. See the Gemini CLI MCP guide.
Add this to ~/.grok/config.toml:
[mcp_servers.fam]
command = "uvx"
args = ["fam-mcp"]
env = { FAM_USERNAME = "YOUR_CPF", FAM_PASSWORD = "YOUR_FAM_PASSWORD" }
enabled = true
Reload the MCP list in Grok Build after saving. See the Grok Build MCP guide.
Add this MCP client entry to your DeepSeek Harness Cordis profile. Start the harness with FAM_USERNAME and FAM_PASSWORD set in its environment:
- id: mcp-fam
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: fam
transport: stdio
command: uvx
args: [fam-mcp]
env:
FAM_USERNAME: !!js process.env.FAM_USERNAME
FAM_PASSWORD: !!js process.env.FAM_PASSWORD
See the DeepSeek Harness MCP client guide.
Add this entry under mcpServers in .cursor/mcp.json:
{
"mcpServers": {
"fam": {
"command": "uvx",
"args": ["fam-mcp"],
"env": {
"FAM_USERNAME": "YOUR_CPF",
"FAM_PASSWORD": "YOUR_FAM_PASSWORD"
}
}
}
}
See the Cursor MCP guide.
Create or edit .vscode/mcp.json:
{
"servers": {
"fam": {
"type": "stdio",
"command": "uvx",
"args": ["fam-mcp"],
"env": {
"FAM_USERNAME": "YOUR_CPF",
"FAM_PASSWORD": "YOUR_FAM_PASSWORD"
}
}
}
}
Start the server from the MCP Servers view in Copilot Chat. See VS Code MCP setup.
Add this entry under context_servers in Zed's settings.json:
{
"context_servers": {
"fam": {
"command": "uvx",
"args": ["fam-mcp"],
"env": {
"FAM_USERNAME": "YOUR_CPF",
"FAM_PASSWORD": "YOUR_FAM_PASSWORD"
}
}
}
}
See the Zed MCP guide.
In either extension's MCP settings, add a local stdio server with command uvx, argument fam-mcp, and environment variables FAM_USERNAME and FAM_PASSWORD. Both provide an MCP settings editor in the extension UI. See the Cline MCP guide and Roo Code MCP guide.
Create .continue/mcpServers/fam.yaml:
name: FAM MCP
version: 1.0.0
schema: v1
mcpServers:
- name: FAM
command: uvx
args:
- fam-mcp
env:
FAM_USERNAME: YOUR_CPF
FAM_PASSWORD: YOUR_FAM_PASSWORD
See the Continue MCP guide.
These web apps connect to remote MCP servers. FAM MCP currently runs locally over stdio and does not publish a remote endpoint, so you cannot paste uvx fam-mcp into their connector settings. Connecting a web app requires a separately hosted or securely tunneled remote MCP endpoint. See Claude remote connectors and ChatGPT MCP connectors.
Philosophy
Read-only, always.
It never submits, posts or answers anything on the portal. The only side effect comes from the portal itself: opening a message in the inbox marks it as read.
Questions, not screens.
The tools follow what a student actually asks, not how the portal's menu is organized. One question about what's coming up replaces four pages, and finding out how far along the degree is replaces adding up a transcript by hand.
Private by default.
Personal documents like the CPF and the RG come back hidden, other students' names and registration numbers are removed from forum replies, and the login stays in the environment instead of showing up in any answer.
Failures that explain themselves.
When something goes wrong, the assistant gets a clear answer: what happened, whether trying again makes sense and which tool it was. A portal that is down is told apart from a page that changed its layout, and the technical details stay in the log instead of reaching the assistant.
Gentle with a fragile site.
There is one shared session, renewed only when it expires. A call takes from a few seconds to about twenty, and doing several at once barely helps. The server doesn't hide that, and tells the assistant up front.
Shaped for the assistant.
Dates and numbers always come in the same format, and every id the assistant needs comes from a previous answer. The server also says where to start, so the assistant spends its calls on the answer instead of finding its way around.
What's inside
βββ assets/ # the How it works diagram, as an editable Excalidraw file and its SVG
βββ src/fam_mcp
β βββ server.py # the MCP server: instructions, middleware and the login at startup
β βββ portal.py # the session with the portal: login, re-login, retries, decoding
β βββ middleware.py # turns every failure into the JSON error
β βββ errors.py # the error hierarchy, one class per failure
β βββ constants.py # the error codes and their messages
β βββ utils.py # parsing helpers: dates, numbers, masking
β βββ data/ # what the tools return, as dataclasses, one module per area
β βββ tools/ # one file per tool, registered automatically on import
βββ pyproject.toml
Technologies
| Β Β Β Β Β | Technology | Used for |
|---|---|---|
| Model Context Protocol | The protocol that lets an assistant call the tools | |
| FastMCP | The MCP framework: tool registration, input validation, middleware and the startup lifecycle | |
| Python | The language, with asyncio so calls don't block each other | |
| httpx | The async HTTP client behind the portal session | |
| Beautiful Soup | Reads the portal's HTML, which is often malformed | |
| uv | Dependencies and running the project |
Roadmap
What's already in place:
- β A portal client that signs in, survives an expired session and shares one login between parallel calls
- β 21 read-only tools across the student's profile, academics, assignments, communication and finances
- β
Published on PyPI as
fam-mcp, withuvxinstallation instructions above - β Errors as JSON with a code, a retryable flag and the tool that raised them
- β Masked personal data, and forum replies stripped of other students' identifiers
- β Paid invoice history alongside open invoices
- β Every tool checked against the live portal, including its error cases
- β Server instructions that tell the assistant where to start
References
- Model Context Protocol: the specification the server speaks
- FastMCP: the framework the server is built on
- httpx: the HTTP client
- Beautiful Soup: the HTML parser
- uv: how the project is run
- FAM: the portal this server reads
Starred by students
Disclaimer
This project is unofficial. It is not made by, affiliated with or endorsed by FAM.
License
MIT, in LICENSE.md.