PluginWorld
Af

afterhours-mcp-public

MCP

Enables a single owner to run a self-hosted authenticated MCP server that adds Slack reading and replying, Outlook inbox and calendar lookup, signed Slack event capture, restricted KakaoTalk Windows-agent tasks, appointment tracking, and morning briefings to an existing MCP setup.

@deploy103 · MIT License · updated today

SECURITY

B

SCORE

60

STARS

▲ 0

PLUG IN

git clone https://github.com/deploy103/afterhours-mcp-public.git

See the README to configure this MCP server

README

After-hours Vooy MCP

기존 인증 MCP에 퇴근 후 처리 도구를 추가하는 통합 구현이다. 단일 소유자용이며 익명 접근이나 다중 사용자 데이터 분리는 제공하지 않는다. 주소·경로·unit은 일반 예시이며 실제 운영 토폴로지가 아니다. 실제 HTTPS origin은 Git 밖의 MCP_PUBLIC_ORIGIN으로 공급하고 프록시 Host와 일치시킨다. 기본은 https://mcp.example.com이며 경로·URL 자격증명 없이 Host/Origin을 exact 검증한다. 예제 loopback bind·credential/state 경로를 기존 운영 설정에 그대로 덮어쓰지 않는다.

새 사용자의 빠른 시작

Linux/Python 3.11+용 통합 도구와 레시피 예제다. 시스템 IANA 시간대 데이터베이스 (tzdata, Asia/Seoul 포함)가 필요하다. 최소 컨테이너 이미지에는 별도로 설치한다. 새 연결은 개별 Slack, Kakao, Outlook, Telegram 서버를 권장한다. 이 통합 서버의 Outlook은 자동 갱신 없는 기존 access-token 방식이다. Gmail은 Vooy의 기존 연결을 사용한다. 어느 서버도 계정 인증이나 자동 감시를 대신 완료해 주지는 않으며, 다중 사용자 공용 서버로 사용하면 안 된다.

git clone https://github.com/deploy103/afterhours-mcp-public.git
cd afterhours-mcp-public
python3 -m venv .venv
.venv/bin/python -m pip install --require-hashes -r requirements.lock
.venv/bin/python configure.py --directory "$HOME/afterhours-private"
"$HOME/afterhours-private/run.sh"

설정기는 소스 밖의 새 디렉터리에만 0700 디렉터리/0600 토큰·설정을 생성한다. 기존 경로를 덮어쓰지 않고 전송은 OFF, 방 목록은 빈 값이다. run.sh는 localhost8000만 수신한다. 로컬 MCP 주소는 http://127.0.0.1:8000/mcp이며 클라이언트의 비밀 입력에 private 디렉터리의 credentials/mcp-token을 Authorization: Bearer로 설정한다. 토큰을 Git·명령행·공유 채팅에 넣지 않는다. curl http://127.0.0.1:8000/healthz는 프로세스 생존 확인뿐이며 메신저 연결 검사가 아니다. 미인증 /mcp는 401이어야 한다.

원격 사용은 --public-origin https://mcp.example.com의 예시를 자기 도메인으로 바꾸고 새 private 디렉터리를 생성한다. TLS reverse proxy에서 /mcp 및 /afterhours/를 loopback8000의 같은 경로로 전달하고 Host와 인증 헤더를 보존한다. 내부 포트를 직접 인터넷에 노출하지 않는다. 서버 설정은 private config.json에서 관리하고 재시작한다. Slack 앱/허용방 설정은 아래를, Windows 에이전트의 설치·TLS·테스트방 절차는 Kakao 서버 안내를 따른다. 이 저장소에도 동일한 windows_setup.ps1과 검토된 vendor/ 소스가 포함된다. 미연결 제공자는 실패/미설정으로 표시되며 다른 사용자의 인증정보를 공유하지 않는다.

자체 코드는 MIT 라이선스이며 vendored 원본은 vendor/kakaotalk-mcp/LICENSE를 유지한다.

구성

  • afterhours.py: Slack Web API 읽기/답장, Windows 작업 큐, 근거 기반 분류 기록, 약속 저장/완료 및 출근 브리핑. SQLite는 systemd StateDirectory에 저장한다.
  • afterhours_app.py: 기존 MCP와 별도 토큰으로 Windows 에이전트 REST를 제공한다.
  • outlook.py: Microsoft Graph의 본인 받은편지함·기본 캘린더 조회 전용 도구.
  • triggers.py: 서명된 Slack 이벤트 중 본인 멘션 또는 지정 방의 수신 메시지를 중복 없이 보관한다. Vooy 레시피를 자동 실행하는 기능은 아니다.
  • windows_agent.py, windows_setup.ps1: Windows host 대화형 세션에서 실행하는 제한된 KakaoTalk 어댑터. 임의 프로그램 실행·파일 조회·방 검색·일괄 전송은 없다.
  • RECIPE.md: Vooy 레시피 지침과 Gmail 조회 전용·캘린더/태스크 확인 후 등록 계획.

자격증명과 설정

MCP 토큰과 Windows 에이전트 토큰은 별도다. 로컬 시작은 설정기가 만든 private 파일을 사용한다. systemd 배포는 LoadCredential로 전달하며 /etc/afterhours-mcp/mcp-token, /etc/afterhours-mcp/windows-agent-token 원본 파일을 root 전용으로 보호한다. Windows 토큰은 에이전트 설치 폴더 token.txt로만 전달하며 채팅·URL·Git에 넣지 않는다. Slack 연결 시 OAuth 앱 토큰을 별도 slack-token credential로 설정해야 한다. 브라우저 세션 쿠키를 복사하지 않는다.

Slack Events URL은 https://mcp.example.com/afterhours/slack/events다. 앱의 slack-signing-secret credential과 slack_team_id, slack_owner_id를 설정한다. 앱이 참여한 채널의 message 이벤트를 구독한다. 본인 메시지·봇·수정 이벤트는 제외한다. pending_message_events 조회 후 실제 처리가 끝나면 acknowledge_message_event로 표시한다. 멘션으로 수집된 미허용 방은 읽기·답장 권한이 자동 확대되지 않는다. 소유자가 방을 허용해야 대화 맥락을 더 읽거나 답장할 수 있다. KakaoTalk 전체 방의 네이티브 멘션 감지는 아직 제공하지 않는다.

Outlook은 소유자 자신의 Entra 앱에서 위임된 Mail.Read, Calendars.ReadBasic을 승인한 outlook-access-token credential이 필요하다. 브라우저 토큰 추출이나 타사 앱 ID를 사용하지 않는다. 현재 자동 갱신은 없으며 만료/취소 시 재연결해야 한다. 메일 발송·답장·일정 생성 도구는 없다. 받은편지함/캘린더는 제한된 한 페이지이며 전체 메일 스캔이나 완전한 가용시간 보고서가 아니다. Gmail은 Vooy 기존 연결을 쓴다. 선택 credential은 준비된 경우에만 systemd LoadCredential로 추가한다.

/etc/afterhours-mcp/afterhours.json은 afterhours.example.json 형식이다. 대화방은 기본 빈 목록, 전송은 OFF다. Slack 채널 ID와 KakaoTalk 정확한 방 제목을 소유자가 정한 뒤 서버 및 Windows 양쪽에서 허용해야 한다. 서버 설정 변경 후 해당 서비스만 재시작한다. Windows는 allowed_rooms, send_enabled 필드를 사용한다. 에이전트 시작 전 KAKAO_AGENT_ENDPOINT에 실제 HTTPS /afterhours/agent/jobs URL을 비공개 실행 환경으로 설정한다. 기본 주소는 예시이며 HTTP·URL 자격증명·다른 경로·query/fragment는 거부한다.

Slack 공식 MCP도 있으나 고정 Slack 앱 ID와 OAuth가 필요하며 Dynamic Client Registration을 지원하지 않는다. 현재 Vooy 테스트에는 읽기/답장 두 기능만 가진 Slack OAuth 앱을 사용한다. 필요한 bot scopes: channels:history, groups:history, im:history, mpim:history, chat:write 중 테스트에 실제 필요한 범위만 선택한다. 봇이 참여한 테스트 채널에만 접근할 수 있으며 사용자 본인으로 위장하지 않는다. Slack 워크스페이스 가입/초대 링크와 앱 설치는 계정 인증 후 완료해야 한다.

검증

development VM에서 .venv/bin/python -m unittest -v test_afterhours test_windows_agent test_outlook. 서버 설치: Python 3.11+ 가상환경에서 pip install --require-hashes -r requirements.lock. Windows 테스트는 포함된 vendor/kakaotalk-mcp의 hash 고정된 원본을 사용한다. 옆 디렉터리나 비공개 reference checkout은 필요하지 않다. 모든 데이터와 자격증명은 폐기 가능한 임시 값이다. 실제 Slack/KakaoTalk 송수신은 계정 연결과 허용 테스트 방을 준비한 후 별도로 검증한다. HTTP/단위 테스트 통과는 네이티브 GUI·메신저·긴급 알림 성공을 뜻하지 않는다.

운영 제약

서버 자체는 분류용 모델이나 상시 메시지 감시 스케줄러가 아니다. Vooy가 도구를 호출할 때 실행되며, 자동화하려면 Vooy 트리거 및 본인 알림 수단을 별도로 설정한다. 기본 근무표는 월금 0918시, Asia/Seoul이고 공휴일·휴가는 미지원이다. 긴급 분류는 모델이 근거를 읽고 선택하며 서버는 영향/기한 조건만 검사한다. Gmail 조회 전용 및 Calendar/Tasks 확인 요구는 레시피 지침이다. 기존 Google 연결 자체의 OAuth 권한을 축소한 것은 아니다.

전송 성공은 Windows UI 입력 완료일 수 있으며 상대방 수신 확인이 아니다. 불명확한 전송은 자동 재시도하지 않는다. Windows journal.json은 임의 삭제하지 않는다. 서버 작업 기록의 오래된 데이터는 새 작업 생성 시 정리한다. 약속/분류는 소유자가 관리할 영속 기록이다.

복구: 새 systemd drop-in afterhours.conf만 제거하고 daemon-reload 후 서비스를 재시작하면 원래 두 도구로 돌아간다. SQLite나 토큰은 삭제하지 않는다. 이는 복구 절차이며 별도 운영 변경을 자동으로 승인하지 않는다.

참고: https://github.com/kronenz/kakaotalk-mcp (MIT, 검토한 버전은 setup에 고정), https://github.com/silver-flight-group/kakaocli (macOS 전용), https://docs.slack.dev/ai/slack-mcp-server . 기존 구현이 있어 REA 분석은 하지 않았다.

SIMILAR PLUGINS