Skip to main content
Glama

sigaa-mcp

Conecte o seu assistente de IA (Claude, Cursor, Copilot, OpenCode...) ao SIGAA e pergunte em linguagem natural sobre a sua vida acadêmica:

"Quanto eu preciso tirar na última unidade de Cálculo para passar?" "Quantas faltas ainda posso ter em cada matéria?" "O que eu tenho para entregar essa semana?"

O sigaa-mcp é um servidor MCP (Model Context Protocol) que roda na sua própria máquina, entra no SIGAA com o seu login e entrega à IA as suas notas, frequência, tarefas, provas, notícias das turmas e o calendário acadêmico, já organizados e com as regras de aprovação da UNEMAT aplicadas.


Sumário


Related MCP server: SGU Academic MCP Server

Instalação passo a passo

1. Pré-requisitos

Você só precisa do uv, o gerenciador de projetos Python. Ele baixa sozinho o Python 3.12 e todas as dependências na primeira execução.

Windows (PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

macOS / Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh

Feche e abra o terminal e confira:

uv --version

Você também precisa de um login ativo no SIGAA da UNEMAT (o mesmo usuário e senha que usa no navegador).

2. Baixar o projeto

Com git:

git clone https://github.com/GallegoSz/sigaa-mcp.git
cd sigaa-mcp

Ou baixe o ZIP pelo botão Code → Download ZIP no GitHub e extraia numa pasta.

Anote o caminho completo dessa pasta, ele vai ser usado na configuração da IA. Exemplos:

  • Windows: C:/Users/maria/Documents/sigaa-mcp

  • macOS: /Users/maria/sigaa-mcp

  • Linux: /home/maria/sigaa-mcp

No Windows, use barras normais (/) ou barras duplas (\\) nos caminhos dentro de arquivos JSON.

Instale as dependências e espere terminar antes de conectar à IA:

uv sync

Na primeira vez o uv baixa o Python e todas as dependências, o que pode levar alguns minutos. Se isso acontecer só quando a IA iniciar o servidor, alguns clientes desistem antes (timeout) e o servidor simplesmente não aparece, sem mensagem de erro.

3. Testar o acesso ao SIGAA

Antes de conectar a IA, vale confirmar que o login funciona. Copie o arquivo de exemplo:

cp .env.example .env        # macOS / Linux
copy .env.example .env      # Windows

Edite o .env com o seu usuário e senha do SIGAA:

SIGAA_USER=seu_login
SIGAA_PASS=sua_senha

E rode o teste:

uv run python testar.py

Se tudo estiver certo, aparecem no terminal o calendário acadêmico, as avaliações, a situação das notas, os alertas de frequência e o resumo da semana, em JSON. Se aparecer Falha no login, confira usuário e senha.

O .env está no .gitignore e só é lido pelo testar.py. O servidor MCP recebe as credenciais pela configuração da IA (próximo passo). Se quiser, apague o .env depois do teste.

4. Conectar à sua IA

O servidor usa o transporte stdio: a IA inicia o processo localmente e conversa com ele. Por isso ele funciona em aplicativos e ferramentas instalados no computador (Claude Desktop, Claude Code, Cursor, VS Code, OpenCode...), mas não nas versões web (claude.ai, chatgpt.com), que só aceitam servidores remotos.

Em todos os casos, troque:

  • CAMINHO/DO/sigaa-mcp pelo caminho da pasta do passo 2;

  • seu_login e sua_senha pelas suas credenciais do SIGAA.

Depois de configurar, reinicie o aplicativo.

  1. Abra o Claude Desktop e vá em Configurações → Desenvolvedor → Editar configuração. Isso abre o arquivo claude_desktop_config.json:

    • Windows: %APPDATA%\Claude\claude_desktop_config.json

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  2. Adicione o servidor dentro de mcpServers (se o arquivo estiver vazio, use o conteúdo inteiro abaixo):

{
  "mcpServers": {
    "sigaa": {
      "command": "uv",
      "args": ["--directory", "CAMINHO/DO/sigaa-mcp", "run", "sigaa-mcp"],
      "env": {
        "SIGAA_USER": "seu_login",
        "SIGAA_PASS": "sua_senha"
      }
    }
  }
}
  1. Feche o Claude Desktop por completo (inclusive na bandeja do sistema) e abra de novo.

  2. Numa conversa nova, clique no ícone de ferramentas: o sigaa deve aparecer com as 13 tools.

Se o servidor não iniciar com erro de uv não encontrado, troque "command": "uv" pelo caminho completo do executável. Descubra com where uv (Windows) ou which uv (macOS/Linux). No Windows costuma ser C:\\Users\\<voce>\\.local\\bin\\uv.exe.

claude mcp add sigaa --scope user \
  -e SIGAA_USER=seu_login -e SIGAA_PASS=sua_senha \
  -- uv --directory CAMINHO/DO/sigaa-mcp run sigaa-mcp

No PowerShell, escreva tudo numa linha só (sem as \).

--scope user deixa o servidor disponível em qualquer pasta. Confira com claude mcp list ou com /mcp dentro do Claude Code.

Em Settings → MCP → Add new global MCP server (arquivo ~/.cursor/mcp.json):

{
  "mcpServers": {
    "sigaa": {
      "command": "uv",
      "args": ["--directory", "CAMINHO/DO/sigaa-mcp", "run", "sigaa-mcp"],
      "env": {
        "SIGAA_USER": "seu_login",
        "SIGAA_PASS": "sua_senha"
      }
    }
  }
}

Crie .vscode/mcp.json no seu workspace (ou use MCP: Add Server na paleta de comandos). Aqui o VS Code pede a senha na hora, sem gravá-la no arquivo:

{
  "inputs": [
    { "type": "promptString", "id": "sigaa-user", "description": "Usuário do SIGAA" },
    { "type": "promptString", "id": "sigaa-pass", "description": "Senha do SIGAA", "password": true }
  ],
  "servers": {
    "sigaa": {
      "type": "stdio",
      "command": "uv",
      "args": ["--directory", "CAMINHO/DO/sigaa-mcp", "run", "sigaa-mcp"],
      "env": {
        "SIGAA_USER": "${input:sigaa-user}",
        "SIGAA_PASS": "${input:sigaa-pass}"
      }
    }
  }
}

O OpenCode é um assistente de terminal que funciona com vários modelos (Claude, GPT, Gemini e outros) e oferece alguns modelos gratuitos para testar, sem precisar de assinatura. A lista de modelos gratuitos muda com o tempo; veja as opções com /models dentro do OpenCode.

Adicione o servidor no opencode.json, global (~/.config/opencode/opencode.json) ou na pasta do projeto:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "sigaa": {
      "type": "local",
      "command": ["uv", "--directory", "CAMINHO/DO/sigaa-mcp", "run", "sigaa-mcp"],
      "enabled": true,
      "environment": {
        "SIGAA_USER": "seu_login",
        "SIGAA_PASS": "sua_senha"
      }
    }
  }
}

Repare que o formato é diferente dos outros clientes: a chave é mcp, o comando e os argumentos vão juntos numa lista em command, e as credenciais ficam em environment.

Se a pasta tiver ao mesmo tempo opencode.json e opencode.jsonc, mantenha a configuração em um só deles. Conteúdo diferente nos dois pode fazer o servidor sumir sem nenhum erro.

Qualquer cliente que suporte servidores MCP locais (stdio) funciona. Os dados são sempre os mesmos:

Campo

Valor

Comando

uv

Argumentos

--directory CAMINHO/DO/sigaa-mcp run sigaa-mcp

Variáveis de ambiente

SIGAA_USER, SIGAA_PASS e, opcionalmente, SIGAA_URL


Exemplos de uso

Depois de conectado, é só conversar. A IA escolhe quais tools chamar.

Você pergunta

A IA usa

"Como estão minhas notas esse semestre?"

get_notas

"Quanto preciso tirar na U3 de Física pra passar direto?"

get_situacao_notas

"Em qual matéria eu tô mais perto de reprovar por falta?"

get_alertas_frequencia

"O que tenho pra fazer nos próximos 10 dias?"

get_resumo_semana(dias=10)

"Tem alguma tarefa de Algoritmos que eu ainda não enviei?"

get_tarefas("algoritmo")

"Quando é a próxima prova de Cálculo?"

get_avaliacoes("calculo")

"O professor de Física postou alguma coisa nova?"

get_noticias("fisica")

"Qual o último dia pra trancar matrícula?"

get_calendario_academico

"Qual meu CRA e quanto falta pra eu me formar?"

get_dados_discente

Exemplo de resposta de get_alertas_frequencia:

[
  {
    "disciplina": "CÁLCULO DIFERENCIAL E INTEGRAL I",
    "faltas": 8,
    "aulas_carga_horaria": 72,
    "percentual_presenca_aulas_ministradas": 83,
    "limite_faltas": 18,
    "faltas_restantes": 10,
    "aulas_por_encontro": 4,
    "encontros_que_ainda_pode_faltar": 2,
    "status": "ok"
  }
]

Tools disponíveis

Dados do portal

Tool

O que retorna

get_notas(semestre?)

Notas por semestre: unidades, recuperação, prova final, resultado, faltas, situação. Filtro opcional no formato 2026.2

get_turmas()

Turmas do semestre atual (componente, local, horário)

get_dados_discente()

Matrícula, curso, status, e-mail, entrada, CRA, carga horária pendente, % integralizado

get_agenda()

Tarefas e avaliações com data e dias restantes (bloco "Minhas atividades" do portal)

get_calendario_academico(semestre?)

Período letivo, consolidação, trancamento, matrícula etc. do calendário do seu curso

Dados das turmas virtuais

Tool

O que retorna

get_frequencia(disciplina?)

Presença/faltas por aula e percentuais de frequência de cada turma

get_tarefas(disciplina?)

Tarefas: prazo, se vale nota, se já foi enviada, se ainda aceita envio, enunciado

get_noticias(disciplina?)

Notícias publicadas pelos professores (título e data)

get_avaliacoes(disciplina?)

Datas e horários das provas marcadas

get_conteudo(disciplina?)

Tópicos de aula (cronograma com datas, descrição e materiais)

O parâmetro disciplina aceita parte do nome, sem diferenciar acentos nem maiúsculas ("calculo" encontra "CÁLCULO DIFERENCIAL E INTEGRAL I"). Sem filtro, a tool percorre todas as turmas, o que pode levar alguns segundos.

Análises

Tool

O que retorna

get_situacao_notas()

Para cada disciplina em andamento: média parcial e quanto precisa tirar nas unidades restantes para aprovar direto ou ir ao exame final

get_alertas_frequencia()

Limite de faltas, faltas restantes, quantos encontros ainda pode faltar e um status (ok, atenção, crítico, REPROVADO POR FALTA)

get_resumo_semana(dias=7)

Agenda dos próximos dias, tarefas abertas ainda não enviadas, notícias recentes e só os alertas de frequência que não estão ok

Em get_notas, o campo faltas só vem preenchido em disciplinas já consolidadas. Enquanto a turma está em andamento ele vem null, porque o relatório do SIGAA mostra 0 até a consolidação. Para o semestre atual, use get_frequencia.


Regras acadêmicas usadas

As análises seguem a Resolução nº 001/2024-CONEPE (Normatização Acadêmica da UNEMAT):

Artigo

Regra

Onde é usada

Art. 61

Média semestral ≥ 6,0 aprova. Com frequência ≥ 75% e média entre 4,0 e 5,9, o aluno vai para o exame final, onde precisa de nota ≥ 5,0

get_situacao_notas

Art. 43

Frequência abaixo de 75% da carga horária presencial reprova, independentemente da nota

get_alertas_frequencia

Art. 40

Faltas não são abonadas

get_alertas_frequencia

Como os cálculos são feitos:

  • Média: média aritmética das unidades (padrão do SIGAA). O plano de curso de uma disciplina pode definir pesos diferentes; nesse caso o resultado é uma estimativa.

  • Nota necessária: (meta × total_de_unidades − soma_das_notas_lançadas) ÷ unidades_restantes, para a meta 6,0 (aprovar) e 4,0 (exame final).

  • Limite de faltas: ⌊ aulas_da_carga_horária × 25% ⌋.

  • Encontros que ainda pode faltar: faltas restantes divididas pelo número de aulas de cada encontro, já que faltar num dia conta todas as aulas daquele dia.

Os números são um apoio. A palavra final é sempre do SIGAA e da coordenação do curso.


Segurança e privacidade

  • Tudo roda no seu computador. O servidor conversa diretamente com sigaa.unemat.br. Nenhum dado passa por servidores de terceiros, exceto o que a própria IA recebe para responder (as respostas das tools vão para o provedor da IA que você usa, como em qualquer conversa).

  • Somente leitura. Nenhuma tool envia, altera ou apaga nada no SIGAA.

  • Sua senha fica no arquivo de configuração do cliente (ex.: claude_desktop_config.json) em texto puro. Não compartilhe esse arquivo nem tire print dele. No VS Code dá para usar inputs para não gravar a senha (veja acima). Em qualquer cliente, outra opção é definir SIGAA_USER e SIGAA_PASS como variáveis de ambiente do sistema e omitir o bloco env (no Windows: setx SIGAA_PASS "sua_senha" e reabra o cliente; no macOS/Linux, export no perfil do shell). O cliente precisa ter sido aberto depois de definir as variáveis.

  • Nunca suba o .env para o GitHub. Ele já está no .gitignore.

  • Não hospede este servidor para outras pessoas. Ele foi feito para um único aluno por instalação: as credenciais vêm de variáveis de ambiente e não há autenticação. Se ele for exposto na internet, quem tiver o endereço acessa os dados de quem o configurou.

  • Conteúdo de terceiros: enunciados de tarefas e notícias são escritos pelos professores e repassados à IA como estão. Trate-os como informação, não como instruções.


Como funciona por dentro

O SIGAA não tem API pública. O servidor se comporta como um navegador: faz login, guarda o cookie de sessão, "clica" nos menus enviando os mesmos formulários que a página enviaria e lê o HTML que volta.

sequenceDiagram
    participant IA as Cliente de IA
    participant MCP as sigaa-mcp (local)
    participant S as sigaa.unemat.br

    IA->>MCP: chama tool (ex.: get_notas)
    MCP->>S: GET /sigaa/verTelaLogin.do
    S-->>MCP: cookie JSESSIONID
    MCP->>S: POST /sigaa/logar.do?dispatch=logOn
    MCP->>S: GET portal do discente
    S-->>MCP: HTML com o menu e o ViewState
    MCP->>S: POST do formulário do menu (jscook_action)
    S-->>MCP: HTML do relatório
    MCP->>MCP: parser (HTML → dados) + análises
    MCP-->>IA: JSON estruturado

Login e sessão

  1. GET /sigaa/verTelaLogin.do cria a sessão (cookie JSESSIONID).

  2. POST /sigaa/logar.do?dispatch=logOn com user.login e user.senha.

  3. Se a resposta ainda for a tela de login, o servidor reporta Falha no login.

O login acontece uma vez e é reaproveitado. Se a sessão expirar, o cliente detecta a tela de login no meio do caminho e entra de novo automaticamente.

Navegação JSF

O SIGAA é feito em JSF (JavaServer Faces). Cada link é, na prática, o envio de um formulário com campos ocultos, e um deles, o javax.faces.ViewState, muda a cada requisição. Por isso o servidor sempre lê os campos da página mais recente antes de "clicar":

  • Menu do portal (menu:form_menu_discente): os itens são montados em JavaScript (JSCookMenu). O valor de jscook_action de cada item ("Consultar Minhas Notas", "Calendário Acadêmico"...) é encontrado pelo texto do item, porque o id gerado pelo JSF muda entre versões do sistema.

  • Links h:commandLink: os parâmetros que o link enviaria ficam no onclick (jsfcljs(form, {...})). O parser extrai esses pares e os adiciona ao formulário.

Turmas virtuais

Para frequência, tarefas, notícias, avaliações e conteúdo, o servidor:

  1. Abre o portal e encontra os formulários form_acessarTurmaVirtual* de cada turma.

  2. Entra na turma (a página inicial já traz o conteúdo/tópicos de aula).

  3. Clica nos itens do menu lateral (formMenu) pelo texto: "Frequência", "Tarefas"...

  4. Volta ao portal e repete para a próxima turma.

Cada item de cada turma fica em cache por 2 minutos, e get_resumo_semana entra uma vez em cada turma e coleta tudo o que precisa em sequência, para não repetir navegação.

As requisições passam por um lock: como a sessão JSF tem estado, duas navegações ao mesmo tempo corromperiam o ViewState, então elas acontecem uma de cada vez.

Calendário acadêmico

A busca de calendários exige filtros. O servidor escolhe a modalidade Presencial e o convênio que aparece no nome do seu curso (ex.: ... - CONTÍNUA - N), já que sem o convênio o SIGAA só lista calendários antigos. Depois seleciona o calendário do semestre pedido (ou o atual).


Estrutura do código

sigaa-mcp/
├── src/sigaa_mcp/
│   ├── server.py    # Definição das tools MCP (o que a IA enxerga)
│   ├── client.py    # Cliente HTTP: login, sessão, navegação JSF, cache e lock
│   ├── parser.py    # HTML do SIGAA → dicionários Python
│   └── analise.py   # Regras da UNEMAT: situação de notas, frequência, resumo
├── tests/           # Testes automatizados (pytest), sem rede e sem login
├── testar.py        # Teste rápido contra o SIGAA real, sem MCP
├── .env.example     # Modelo de credenciais para o testar.py
├── pyproject.toml   # Metadados e dependências
└── uv.lock          # Versões exatas das dependências

As camadas são separadas de propósito:

Arquivo

Responsabilidade

Depende de

server.py

Expõe as tools via MCPServer. Cada tool tem docstring e parâmetros tipados, que viram a descrição que a IA lê para decidir quando usá-la. Cria o cliente sob demanda a partir das variáveis de ambiente

client, analise

client.py

SigaaClient: um httpx.AsyncClient com cookies, que sabe logar, abrir o portal, acionar itens de menu, clicar em commandLinks e varrer as turmas virtuais. Detecta charset (o SIGAA às vezes não declara no header) e reloga quando a sessão cai

parser

parser.py

Funções puras que recebem HTML e devolvem dados: formulários JSF, menus, tabelas de notas, frequência, tarefas, notícias, avaliações, tópicos, calendário. Usa selectolax (parser rápido baseado no Lexbor) e normaliza datas para ISO 8601

—

analise.py

Funções puras de regra de negócio sobre os dados já extraídos. Não faz rede

—

Como parser.py e analise.py não acessam a rede, dá para testá-los com HTML salvo ou dados de exemplo. Os arquivos *.html estão no .gitignore justamente para que páginas salvas durante o desenvolvimento (que contêm dados pessoais) nunca sejam publicadas.

Dependências

Pacote

Para quê

mcp

SDK oficial do Model Context Protocol

httpx

Cliente HTTP assíncrono com cookies e redirecionamentos

selectolax

Parser de HTML rápido com seletores CSS

Adicionando uma nova tool

  1. Se a página ainda não é lida, crie a função parse_* em parser.py.

  2. Exponha a navegação em client.py (um item de menu com _acao_menu, ou um item de turma virtual registrado em _ITENS_TURMA).

  3. Crie a função em server.py com @mcp.tool(), docstring clara e argumentos tipados.

  4. Escreva o teste em tests/ (HTML sintético para o parser) e rode uv run pytest.

  5. Teste pelo testar.py antes de testar pela IA.


Problemas comuns

Sintoma

Causa provável e solução

Defina as variáveis de ambiente SIGAA_USER e SIGAA_PASS

O bloco env não foi configurado no cliente de IA, ou o nome das variáveis está diferente

Falha no login: verifique SIGAA_USER e SIGAA_PASS

Usuário ou senha errados. Teste o mesmo login no navegador

Portal do discente não carregou

O SIGAA está mostrando uma tela intermediária (questionário, aviso, atualização de dados). Entre pelo navegador, resolva a tela e tente de novo

Nenhuma turma corresponde a '...'

O filtro de disciplina não bateu com nenhum nome. A própria mensagem lista as turmas disponíveis. O filtro procura o texto dentro do nome, então prefira um trecho curto ("algoritmo" em vez de "algoritmos")

Calendário de 2026.2 não encontrado

O calendário do semestre ainda não foi publicado. A mensagem lista os disponíveis

O servidor não aparece na IA

Reinicie o aplicativo por completo. Confira se o caminho em --directory existe e se o uv está no PATH (ou use o caminho completo). Rode uv sync antes, para a primeira inicialização não estourar o tempo do cliente. Como alternativa ao uv run, aponte direto para o executável do ambiente: CAMINHO/DO/sigaa-mcp/.venv/Scripts/sigaa-mcp.exe (Windows) ou .venv/bin/sigaa-mcp (macOS/Linux)

A primeira chamada demora

Na primeira execução o uv baixa o Python e as dependências. Tools sem filtro de disciplina também visitam todas as turmas

Dados estranhos ou vazios numa tool

O layout de alguma página do SIGAA pode ter mudado. Abra uma issue dizendo qual tool e o que apareceu (sem dados pessoais)


Limitações

  • Feito e testado para o SIGAA da UNEMAT, no portal do discente. A variável SIGAA_URL permite apontar para outra instituição, mas cada SIGAA tem personalizações e os parsers podem não funcionar.

  • Depende do HTML do SIGAA. Se a universidade mudar o layout, partes podem quebrar até o parser ser ajustado.

  • A média usada nas análises é aritmética; disciplinas com pesos diferentes no plano de curso terão resultados aproximados.

  • Somente leitura: não envia tarefas, não faz matrícula, não altera nada.

  • Um usuário por instalação.

Este é um projeto independente, feito por aluno, sem vínculo com a UNEMAT nem com os desenvolvedores do SIGAA. Use por sua conta e com moderação.


Contribuindo

Issues e pull requests são bem-vindos, principalmente para:

  • ajustes quando o SIGAA mudar alguma página;

  • novas tools (histórico, declarações, horários...);

  • suporte a SIGAAs de outras instituições.

Ao reportar um problema, nunca cole HTML, prints ou JSON com dados pessoais (nome, matrícula, notas). Descreva o que esperava e o que aconteceu.

Para desenvolver:

uv sync
uv run pytest            # testes automatizados, não acessam o SIGAA
cp .env.example .env     # preencha com suas credenciais
uv run python testar.py  # teste contra o SIGAA real

Os testes em tests/ cobrem as quatro camadas: test_parser.py e test_analise.py usam HTML e dados sintéticos; test_client.py roda o SigaaClient contra um SIGAA falso (httpx.MockTransport) que simula login, sessão expirada, troca de ViewState a cada página, turmas virtuais e calendário; test_server.py confere o registro e o schema das tools.

Para testar as tools numa interface visual, use o MCP Inspector:

npx @modelcontextprotocol/inspector uv --directory . run sigaa-mcp

(defina SIGAA_USER e SIGAA_PASS no ambiente ou na tela do Inspector).

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to query the UEx virtual campus (CVUEx/AVUEx) in natural language, including deadlines, grades, announcements, forums, and course materials, using the user's own account with read-only access.
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI assistants to read a student's own university academic data — class timetables, exam schedules, grades, available terms, and empty classrooms — from Qiangzhi (jsxsd) or Zhengfang V9 systems via a session imported from the browser. All access is strictly read-only, never performing course selection, withdrawal, or evaluations.
    6
    1
    MIT