Skip to main content
Glama

sigaa-ufrpe-mcp

Servidor MCP (Model Context Protocol) para o SIGAA da UFRPE, com acesso mais profundo do que uma API estruturada tradicional: além de dados já parseados (notas, turmas, currículo...), ele permite ver o HTML cru de qualquer página da sessão, montar e disparar requisições customizadas (reproduzindo ações JSF descobertas no próprio HTML) e baixar arquivos arbitrários (PDFs, anexos de cronograma, etc.), não só os casos pré-definidos.

Implementação standalone em TypeScript: o próprio servidor faz login e mantém a sessão SIGAA (JSESSIONID + javax.faces.ViewState), sem depender de nenhum serviço externo em runtime.

Instalação

npm install
npm run build

Related MCP server: MyAndrews MCP

Uso (Claude Desktop / Claude Code)

Adicione ao seu claude_desktop_config.json (ou equivalente):

{
  "mcpServers": {
    "sigaa-ufrpe": {
      "command": "node",
      "args": ["/caminho/absoluto/para/Sigaa-UFRPE-MCP/dist/index.js"],
      "env": {
        "SIGAA_MCP_DOWNLOAD_DIR": "/caminho/absoluto/para/downloads"
      }
    }
  }
}

SIGAA_MCP_DOWNLOAD_DIR é opcional — por padrão os arquivos baixados vão para ./downloads (relativo ao diretório de onde o processo é iniciado).

Testar com o MCP Inspector

npm run build
npm run inspector

Abra a URL impressa no terminal e chame as tools na ordem sugerida abaixo.

Remoto (HTTP) — Claude.ai (web) e apps mobile

Claude Desktop e Claude Code sabem spawnar um processo local (command/args acima), mas Claude.ai (web) e os apps mobile só conseguem falar com MCP servers remotos, acessíveis via HTTPS. Para isso existe um segundo entrypoint, dist/remote.js, que expõe o mesmo servidor via Streamable HTTP em vez de stdio.

Diferente do modo stdio (uma sessão SIGAA por processo), o modo remoto cria uma SigaaSession isolada por conexão MCP — duas pessoas (ou duas abas da mesma pessoa) nunca compartilham jsessionid/viewState.

Rodar localmente

npm run build
SIGAA_MCP_REMOTE_TOKEN=$(openssl rand -hex 32) PORT=3000 npm run start:remote

Variáveis de ambiente:

Variável

Obrigatória

Descrição

SIGAA_MCP_REMOTE_TOKEN

Não, mas fortemente recomendada

Token de acesso (Authorization: Bearer <token>). Se não definida, o endpoint /mcp fica público — qualquer pessoa com a URL pode usá-lo (ver "Conectar sem token" abaixo, necessário para a tela simplificada de conectores do app/web do Claude, que não tem campo para headers customizados).

PORT

Não (padrão 3000)

Porta HTTP.

SIGAA_MCP_DOWNLOAD_DIR

Não

Mesma variável do modo stdio — pasta onde arquivos baixados são salvos (compartilhada entre todas as conexões).

Testar com curl

curl http://localhost:3000/health
# {"status":"ok"}

curl -i -X POST http://localhost:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $SIGAA_MCP_REMOTE_TOKEN" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
# devolve o header Mcp-Session-Id — use-o nas próximas chamadas dessa sessão

Deploy

Um Dockerfile já vem pronto (build multi-stage, CMD node dist/remote.js, respeita $PORT) — funciona em qualquer plataforma que rode containers (Railway, Fly.io, Render, um VPS com Docker, etc.). Esse processo fala HTTP puro; em produção ele precisa ficar atrás de algo que termine TLS (a própria plataforma de deploy, ou um proxy como Caddy/nginx/Cloudflare na frente) — nunca exponha a porta HTTP direto na internet.

Conectar

Claude Desktop / Claude Code, apontando para o servidor remoto em vez de um processo local:

{
  "mcpServers": {
    "sigaa-ufrpe-remote": {
      "url": "https://seu-host.example.com/mcp",
      "headers": { "Authorization": "Bearer SEU_TOKEN_AQUI" }
    }
  }
}

Claude.ai (web) e apps mobile — "Adicionar conector personalizado": essa tela só tem Nome + URL e um toggle "Requer início de sessão" (para servidores com OAuth) — não tem campo para header customizado, então não dá para mandar Authorization: Bearer <token> por ali. Duas opções:

  1. Deixe SIGAA_MCP_REMOTE_TOKEN sem definir no deploy (endpoint público, sem autenticação) e coloque só a URL (https://seu-host.example.com/mcp), com o toggle "Requer início de sessão" desligado. É o único jeito de usar essa tela hoje, dado que ela não suporta token estático nem faz sentido usar OAuth aqui (não implementamos um authorization server).

  2. Prefira usar Claude Desktop ou Claude Code (config JSON acima) sempre que possível — lá dá pra manter o SIGAA_MCP_REMOTE_TOKEN exigido, já que o campo headers é suportado nativamente.

Limitações / avisos de segurança

  • Se você rodar sem SIGAA_MCP_REMOTE_TOKEN (necessário para o app/web, ver acima): o endpoint fica público. Qualquer pessoa com a URL pode chamar sigaa_login com credenciais próprias, baixar arquivos, etc. — cada conexão tem sua própria SigaaSession isolada (ver seção "Sessão" abaixo), então isso não expõe a sua conta SIGAA a estranhos, mas transforma o servidor num recurso público que qualquer um pode usar/consumir. Se isso for uma preocupação, prefira Desktop/Code com token, ou restrinja o acesso por outra camada (proxy com allowlist de IP, VPN, etc.).

  • Pensado para uso pessoal, não multi-tenant de verdade: mesmo com token, quem o tiver tem acesso completo. Trate-o como uma senha — gere com openssl rand -hex 32, nunca comite, e rotacione (troque a env var e reinicie o processo) se vazar.

  • Downloads de todas as conexões caem na mesma pasta (SIGAA_MCP_DOWNLOAD_DIR), sem isolamento por sessão.

  • Sessões sem atividade por 30 minutos são encerradas e removidas da memória automaticamente.

Sessão

Diferente de uma API REST stateless, este servidor guarda a sessão SIGAA (JSESSIONID + ViewState) em memória, no processo, e a reutiliza automaticamente entre chamadas de tool — não é preciso repassar tokens manualmente. Chame sigaa_login uma vez no início da conversa; as demais tools usam a sessão ativa.

Tools disponíveis

Núcleo genérico (acesso avançado)

Tool

Descrição

sigaa_login

Autentica (usuário/senha), trata o interstitial "Aviso de Logon".

sigaa_get_html

Devolve o HTML bruto de qualquer URL sob sigs.ufrpe.br, sem parsing.

sigaa_raw_request

Monta e dispara uma requisição customizada (método, URL, campos de formulário) — para reproduzir ações JSF sem precisar de uma tool dedicada.

sigaa_download_file

Baixa um arquivo arbitrário (PDF, anexo, etc.), validando que a resposta não é uma página de erro disfarçada. Devolve o conteúdo embutido na resposta da tool (base64, até 8 MiB) — não só um caminho de arquivo, que não seria acessível no modo remoto — e, se for PDF, também o texto extraído.

Paridade com a API REST original

Tool

Descrição

sigaa_main_data

Nome, matrícula, turmas resumidas, índices acadêmicos, carga horária.

sigaa_get_turma

Cronograma, notícia e faltas de uma turma.

sigaa_get_notas

Notas do semestre atual e anteriores.

sigaa_get_curriculo

Estrutura curricular do curso.

sigaa_get_componente

Detalhes de um componente curricular (ementa, pré-requisitos, equivalências).

sigaa_get_matricula

Atestado de matrícula estruturado.

sigaa_get_historico_pdf

Baixa o histórico escolar em PDF (conteúdo embutido na resposta + texto extraído).

sigaa_get_vinculo_pdf

Baixa a declaração de vínculo em PDF (conteúdo embutido na resposta + texto extraído).

Todas as tools que dependem de um ViewState avisam explicitamente quando é preciso chamar sigaa_main_data antes.

Downloads (PDF, anexos, etc.)

As três tools que baixam arquivos (sigaa_download_file, sigaa_get_historico_pdf, sigaa_get_vinculo_pdf) fazem duas coisas com o arquivo baixado:

  1. Salvam uma cópia em disco em SIGAA_MCP_DOWNLOAD_DIR (útil no modo stdio local, onde esse caminho é diretamente acessível).

  2. Embutem o conteúdo na própria resposta da tool — um item resource com o arquivo em base64 (até 8 MiB; acima disso só o aviso + o caminho em disco) — porque no modo remoto (HTTP) não existe filesystem compartilhada entre o servidor e quem chama a tool; só o caminho não serviria de nada.

  3. Quando o arquivo é um PDF, o texto também é extraído no servidor (pdf-parse) e incluído como um item de texto adicional, para o modelo conseguir ler o conteúdo mesmo que o cliente MCP não saiba renderizar o resource binário.

Segurança

sigaa_get_html, sigaa_raw_request e sigaa_download_file só fazem requisições para hosts na allowlist (src/constants.ts, hoje só sigs.ufrpe.br) — isso evita que o servidor vire um proxy aberto para qualquer host arbitrário (SSRF).

Escopo

Não inclui o subsistema de integração com Google Classroom presente na API Go original (/classroom/*) — é um subsistema independente do SIGAA, que exigiria OAuth e banco de dados próprios, fora do escopo de "acesso mais profundo ao SIGAA".

Available Tools

12 tools
sigaa_download_fileBaixar um arquivo arbitrário do SIGAAA

Monta e dispara uma requisição (method + url + campos de formulário) contra sigs.ufrpe.br esperando um arquivo binário como resposta (PDF, anexo de cronograma, etc.) em vez de HTML. Detecta e rejeita páginas de erro/sessão expirada disfarçadas de arquivo (redirect ou Content-Type text/html). Salva o arquivo em disco e devolve o caminho — generaliza os fluxos de download hoje hardcoded na API Go (anexos de cronograma, histórico/vínculo em PDF) para qualquer ação de download do SIGAA.

Inputs: url (required), method (required), referer, formFields.

sigaa_get_componenteDetalhes de um componente curricularA

Ementa, tipo, modalidade, carga horária, pré-requisitos e equivalências de um componente curricular específico. 'idComponente' e 'curriculo' vêm de 'sigaa_get_curriculo' (componentes[].id e estruturaCurricular.codigo, respectivamente).

Inputs: curriculo (required), idComponente (required).

sigaa_get_curriculoEstrutura curricular do cursoA

Lista os componentes curriculares (obrigatórios, optativos, complementares) do curso do aluno, organizados por semestre. Use 'componentes[].id' + 'estruturaCurricular.codigo' para chamar 'sigaa_get_componente' em seguida.

Inputs: no named parameters.

sigaa_get_historico_pdfBaixar histórico escolar (PDF)A

Baixa o histórico escolar do aluno em PDF e salva em disco. Requer um ViewState válido — chame 'sigaa_main_data' antes se ainda não tiver um.

Inputs: no named parameters.

sigaa_get_htmlVer HTML cru de uma página do SIGAAA

Busca uma URL sob sigs.ufrpe.br usando a sessão SIGAA atual (se houver) e devolve o HTML bruto da resposta, sem nenhum parsing — inclusive páginas de erro/sessão expirada, para inspeção. Use 'sigaa_login' antes se a página exigir autenticação.

Inputs: url (required), method, referer.

sigaa_get_matriculaAtestado de matrícula (estruturado)A

Período letivo, vínculo, curso e turmas matriculadas no semestre, extraídos do atestado de matrícula do SIGAA. Requer um ViewState válido — chame 'sigaa_main_data' antes se ainda não tiver um.

Inputs: no named parameters.

sigaa_get_notasRelatório de notasA

Notas do semestre atual e de semestres anteriores. Requer um ViewState válido — chame 'sigaa_main_data' antes se ainda não tiver um.

Inputs: no named parameters.

sigaa_get_turmaDetalhar uma turma (cronograma, notícia, faltas)A

Enriquece uma turma (obtida via sigaa_main_data) com cronograma, notícia e total de faltas. Envie o objeto 'turma' de volta sem alterar os campos 'nome'/'info' — eles são usados para navegar até a turma virtual correta, e a resposta é validada para nunca devolver dados de uma turma diferente da pedida.

Inputs: turma (required).

sigaa_get_vinculo_pdfBaixar declaração de vínculo (PDF)A

Baixa a declaração de vínculo do aluno em PDF e salva em disco. Requer um ViewState válido — chame 'sigaa_main_data' antes se ainda não tiver um.

Inputs: no named parameters.

sigaa_loginLogin no SIGAAA

Autentica no SIGAA UFRPE com usuário e senha, lidando com o eventual interstitial 'Aviso de Logon'. A sessão (JSESSIONID/ViewState) fica guardada em memória neste servidor MCP e é reaproveitada automaticamente pelas demais tools — não é preciso repassar tokens manualmente.

Inputs: password (required), username (required).

sigaa_main_dataDados do portal do discenteA

Ponto de entrada depois do login: nome, matrícula, turmas do semestre (resumidas, sem cronograma/notícia/faltas — use sigaa_get_turma para detalhar cada uma), índices acadêmicos e carga horária pendente.

Inputs: no named parameters.

sigaa_raw_requestMontar e disparar uma requisição customizada ao SIGAAA

Monta e envia uma requisição HTTP arbitrária (method + url + campos de formulário) contra qualquer URL sob sigs.ufrpe.br, anexando automaticamente o cookie JSESSIONID da sessão atual. Use para reproduzir uma ação JSF descoberta ao inspecionar o HTML (ex.: um 'jscook_action' ou 'jsfcljs' visto num atributo onclick) quando não existe uma tool dedicada para essa ação. Devolve o HTML bruto da resposta e, se encontrado, o novo javax.faces.ViewState — atualize seu próximo formFields com esse valor quando a página exigir ViewState.

Inputs: url (required), method (required), referer, formFields, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 12 tools

    Disambiguation4/5

    Most tools map to distinct resources and actions, with explicit cross-references like main_data -> get_turma and curriculo -> componente. The closest overlap is sigaa_get_html vs sigaa_raw_request, and sigaa_download_file vs the specific PDF tools, but the descriptions delineate their use cases well enough.

    Naming Consistency4/5

    The dominant pattern is sigaa_get_<resource>, and all names consistently use snake_case with the sigaa_ prefix. However, sigaa_login, sigaa_main_data, and sigaa_raw_request deviate from the verb_noun pattern, so consistency is good but not perfect.

    Tool Count5/5

    12 tools is squarely within the ideal 3-15 range for a student portal integration. Each tool covers a meaningful action or retrieval, and the generic fallbacks like sigaa_raw_request and sigaa_download_file do not feel like padding.

    Completeness4/5

    The set covers authentication, main dashboard data, grades, class details, curriculum, component details, enrollment, and PDF document downloads, which is solid for a read-only academic portal. A dedicated logout/session reset is absent, but the generic raw_request and download_file tools mitigate many potential gaps.

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      C
      maintenance
      Provides read-only access to Andrews University's MyAndrews Ellucian portal, enabling retrieval of academic profiles, classes, degree progress, advisors, account balances, tasks, notifications, and portal cards via authenticated browser sessions.
      -
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables querying the IFSC SIGAA student portal to retrieve a student's profile, classes, schedules, grades, attendance, assignments, exams, news, and academic documents, and also provides access to the IFSC Moodle for courses, materials, deadlines, grades, forums, and messaging. Includes session management with browser-based login or pasted cookie, and confirmation-gated submission of assignments and forms.
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to log into the SIGAA academic system through its web interface and read a student's data: portal info, enrolled and past classes, course topics, participants, grades, attendance, assignments, exams, news, forums, and course plans. It also lets agents download course files and participant photos on demand.
      7
      MIT