Slack MCP Server
A comprehensive Slack integration server that enables sending messages, managing channels, uploading files, and running Pomodoro timers through FastMCP v2.
README
Slack MCP Server - Complete Implementation
π νλ‘μ νΈ κ°μ
FastMCP v2λ₯Ό μ¬μ©νμ¬ κ΅¬νν μμ ν Slack API μ°λ MCP μλ²μ λλ€. κ³Όμ κ°μ΄λλΌμΈμ λ°λΌ νμ κΈ°λ₯ 4κ°, μ ν κΈ°λ₯ 4κ°, κ·Έλ¦¬κ³ λ³΄λμ€ λ½λͺ¨λλ‘ νμ΄λ¨Έ κΈ°λ₯ 4κ°λ₯Ό λͺ¨λ ꡬννμ΅λλ€.
π― μ£Όμ νΉμ§
- β μμ ν UTF-8 νκΈ μ§μ - λͺ¨λ λ©μμ§μμ νκΈ μλ²½ μ§μ
- β μ΄μ€ ν ν° μμ€ν - Bot Token + User TokenμΌλ‘ λͺ¨λ κΈ°λ₯ μ§μ
- β μ€λ§νΈ νμΌ μ λ‘λ - ν¬κΈ°λ³ μ΅μ μ λ‘λ λ°©μ μλ μ ν
- β λ½λͺ¨λλ‘ νμ΄λ¨Έ - μλ μλ¦Ό κΈ°λ₯μ΄ ν¬ν¨λ μκ° κ΄λ¦¬ λꡬ
- β λΉλκΈ° μ²λ¦¬ - κ³ μ±λ₯ asyncio κΈ°λ° κ΅¬ν
- β μμΈν μλ¬ νΈλ€λ§ - λͺ¨λ API νΈμΆμ λν μ μ ν μμΈ μ²λ¦¬
π κΈ°λ₯ λͺ©λ‘
π΄ νμ κΈ°λ₯ (Required Features - 4κ°)
-
send_slack_message- λ©μμ§ μ μ‘- μ±λ λλ DMμ λ©μμ§ μ μ‘
- μ€λ λ λ΅κΈ μ§μ
- μμ ν UTF-8 νκΈ μ§μ
-
get_slack_channels- μ±λ λͺ©λ‘ μ‘°ν- 곡κ°/λΉκ³΅κ° μ±λ ꡬλΆ
- λ©€λ²μ μν νμΈ
- 보κ΄λ μ±λ νν°λ§
-
get_slack_channel_history- λ©μμ§ νμ€ν 리 μ‘°ν- μ΅μ λ©μμ§λΆν° μ‘°ν
- μκ° λ²μ μ§μ κ°λ₯
- λ©μμ§ λ©νλ°μ΄ν° ν¬ν¨
-
send_slack_direct_message- DM μ μ‘- νΉμ μ¬μ©μμκ² 1:1 λ©μμ§ μ μ‘
- μλ DM μ±λ μμ±
- λ΄ μ¬μ©μ νν°λ§
π‘ μ ν κΈ°λ₯ (Optional Features - 4κ°)
-
get_slack_users- μ¬μ©μ λͺ©λ‘ μ‘°ν- μ¬μ©μ νμ λ³ λΆλ₯ (κ΄λ¦¬μ, λ©€λ², κ²μ€νΈ, λ΄)
- DM κ°λ₯ μ¬μ©μ νν°λ§
- μμΈν νλ‘ν μ 보
-
search_slack_messages- λ©μμ§ κ²μ (User Token νμ)- ν€μλ κΈ°λ° μ 체 μν¬μ€νμ΄μ€ κ²μ
- μ λ ¬ λ° νν°λ§ μ΅μ
- κ²μ κ²°κ³Ό λ©νλ°μ΄ν°
-
upload_file_to_slack- μ€λ§νΈ νμΌ μ λ‘λ- νμΌ ν¬κΈ°λ³ μ΅μ μ λ‘λ λ°©μ
- λ€μν νμΌ νμ μ§μ
- μλ 미리보기 λ° μ½λ νμ΄λΌμ΄ν
-
add_slack_reaction- λ©μμ§ λ°μ μΆκ°- μ΄λͺ¨μ§ λ°μ μΆκ°
- λ€μν μ΄λͺ¨μ§ νμ μ§μ
π’ 보λμ€ κΈ°λ₯ (Bonus Features - 4κ°)
-
start_pomodoro_timer- λ½λͺ¨λλ‘ νμ΄λ¨Έ μμ- 5κ°μ§ νμ΄λ¨Έ νμ (study, work, break, meeting, custom)
- μλ μμ/μ’ λ£ μλ¦Ό
- μ¬μ©μ μ μ μκ° λ° λ©μμ§
-
cancel_pomodoro_timer- νμ΄λ¨Έ μ·¨μ- μ€ν μ€μΈ νμ΄λ¨Έ μ¦μ μ€λ¨
- μ·¨μ μλ¦Ό μ μ‘
-
list_active_timers- νμ± νμ΄λ¨Έ λͺ©λ‘- νμ¬ μ€ν μ€μΈ λͺ¨λ νμ΄λ¨Έ
- μ§νλ₯ λ° λ¨μ μκ° νμ
-
get_timer_status- νμ΄λ¨Έ μν μ‘°ν- νΉμ νμ΄λ¨Έμ μμΈ μν
- μ€μκ° μ§ν μν©
π οΈ μ νΈλ¦¬ν° κΈ°λ₯
test_slack_connection- μ°κ²° ν μ€νΈget_workspace_info- μν¬μ€νμ΄μ€ μ 보get_file_preview- νμΌ λ―Έλ¦¬λ³΄κΈ°verify_or_create_file- νμΌ νμΈ/μμ±
π¦ μ€μΉ λ° μ€ν λ°©λ²
1. νλ‘μ νΈ μ΄κΈ°ν
# νλ‘μ νΈ ν΄λ‘ λλ λ€μ΄λ‘λ ν
cd slack-mcp
# uv ν¨ν€μ§ λ§€λμ μ€μΉ (μλ κ²½μ°)
curl -LsSf https://astral.sh/uv/install.sh | sh
# κ°μνκ²½ μμ± λ° νμ±ν
uv venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
# μμ‘΄μ± μ€μΉ
uv sync
# λλ
uv pip install -r requirements.txt
2. νκ²½ λ³μ μ€μ
.env νμΌμ μμ±νκ³ λ€μκ³Ό κ°μ΄ μ€μ :
# νμ: Slack Bot Token (xoxb-λ‘ μμ)
SLACK_BOT_TOKEN=xoxb-your-bot-token-here
# μ ν: Slack User Token (xoxp-λ‘ μμ) - κ²μ, νμΌμ
λ‘λμ©
SLACK_USER_TOKEN=xoxp-your-user-token-here
# μ ν: κΈ°λ³Έ μ±λ ID (ν
μ€νΈμ©)
SLACK_TEST_CHANNEL_ID=C08UZKK9Q4R
# μ ν: λ‘κ·Έ λ 벨
LOG_LEVEL=INFO
3. Slack App μ€μ
νμν Bot Token Scopes:
channels:read # μ±λ λͺ©λ‘ μ‘°ν
channels:history # μ±λ λ©μμ§ νμ€ν 리 μ‘°ν
chat:write # λ©μμ§ μ μ‘
im:read # DM μ±λ μ½κΈ°
im:write # DM λ©μμ§ μ μ‘
im:history # DM νμ€ν 리 μ‘°ν
users:read # μ¬μ©μ μ 보 μ‘°ν
reactions:write # λ°μ μΆκ°
μΆκ° User Token Scopes (μ ν κΈ°λ₯μ©):
search:read # λ©μμ§ κ²μ
files:write # νμΌ μ
λ‘λ
4. μλ² μ€ν
# MCP μλ² μ€ν
python slack_mcp_server.py
# λλ μ§μ μ€ν
uv run slack_mcp_server.py
π‘ μ¬μ©λ² λ° μμ
κΈ°λ³Έ λ©μμ§ μ μ‘
# Claude/LLMμ΄ λꡬ νΈμΆ μ
send_slack_message(
channel="C08UZKK9Q4R",
text="μλ
νμΈμ! MCPμμ 보λ΄λ λ©μμ§μ
λλ€! π"
)
νμΌ μ λ‘λ (μ€λ§νΈ μ²λ¦¬)
# λ€μν ν¬κΈ°μ νμΌμ μλμΌλ‘ μ΅μ λ°©μμΌλ‘ μ
λ‘λ
upload_file_to_slack(
file_path="./report.pdf",
channels="C08UZKK9Q4R",
title="λΆμ λ³΄κ³ μ",
comment="μκ° λ°μ΄ν° λΆμ κ²°κ³Όμ
λλ€."
)
λ½λͺ¨λλ‘ νμ΄λ¨Έ μ¬μ©
# μμ
νμ΄λ¨Έ μμ (50λΆ)
start_pomodoro_timer(
timer_type="study",
channel_id="C08UZKK9Q4R",
duration_minutes=50,
custom_name="νμ΄μ¬ κ³ κΈ λ¬Έλ² νμ΅"
)
# νμ± νμ΄λ¨Έ νμΈ
list_active_timers()
# νμ΄λ¨Έ μ·¨μ
cancel_pomodoro_timer("study_20250602_143022_123456")
λ©μμ§ κ²μ (User Token νμ)
# μν¬μ€νμ΄μ€ μ 체μμ λ©μμ§ κ²μ
search_slack_messages(
query="MCP μλ²",
count=10,
sort="timestamp"
)
ποΈ νλ‘μ νΈ κ΅¬μ‘°
slack-mcp/
βββ .env # νκ²½ λ³μ (Git μ μΈ)
βββ .env.example # νκ²½ λ³μ ν
νλ¦Ώ
βββ .gitignore # Git 무μ νμΌ
βββ README.md # μ΄ νμΌ
βββ requirements.txt # μμ‘΄μ± λͺ©λ‘
βββ pyproject.toml # νλ‘μ νΈ μ€μ
βββ slack_api_client.py # Slack API ν΄λΌμ΄μΈνΈ (ν΅μ¬ λͺ¨λ)
βββ pomodoro_timer.py # λ½λͺ¨λλ‘ νμ΄λ¨Έ λͺ¨λ
βββ slack_mcp_server.py # FastMCP μλ² λ©μΈ
π§ κΈ°μ μ ꡬν μΈλΆμ¬ν
μ΄μ€ ν ν° μμ€ν
- Bot Token (xoxb-): μΌλ°μ μΈ λ΄ κΈ°λ₯ (λ©μμ§ μ μ‘, μ±λ μ‘°ν λ±)
- User Token (xoxp-): μ¬μ©μ κΆν νμν κΈ°λ₯ (κ²μ, λμ©λ νμΌ μ λ‘λ)
μ€λ§νΈ νμΌ μ λ‘λ μ λ΅
- μμ ν μ€νΈ νμΌ (< 50KB): λ©μμ§ λ΄μ©μΌλ‘ μ§μ μ μ‘
- μ€κ° νμΌ (50KB - 1MB): μ½λ μ€λν«μΌλ‘ μ λ‘λ
- μΌλ° νμΌ (1MB - 100MB): νμ€ νμΌ μ λ‘λ
- λμ©λ νμΌ (100MB - 1GB): User TokenμΌλ‘ μ λ‘λ
- μ΄λμ©λ νμΌ (> 1GB): νμΌ μ λ³΄λ§ κ³΅μ
λΉλκΈ° μ²λ¦¬ λ° λμμ±
asyncioκΈ°λ° μμ λΉλκΈ° ꡬν- λ½λͺ¨λλ‘ νμ΄λ¨Έμ λ³λ ¬ μ€ν μ§μ
- λ½(Lock)μ ν΅ν ν΄λΌμ΄μΈνΈ μ΄κΈ°ν μμ μ± λ³΄μ₯
UTF-8 νκΈ μ§μ
headers = {
'Content-Type': 'application/json; charset=utf-8'
}
π κ°λ° κ³Όμ μμ κ²ͺμ μ΄λ €μκ³Ό ν΄κ²° λ°©λ²
1. ν¨μλ€ κ°μ Input λ³μλͺ ν΅μΌ μ΄λ €μ
λ¬Έμ : API ν¨μλ§λ€ λ§€κ°λ³μ μ΄λ¦μ΄ λ¬λΌμ μΌκ΄μ± λΆμ‘±
channelvschannel_idvschannelstextvsmessagevscontent
ν΄κ²°μ± :
- Slack API 곡μ λ¬Έμ κΈ°μ€μΌλ‘ λ³μλͺ ν΅μΌ(ν₯ν μ λ°μ΄νΈ μμ )
- λ΄λΆ ν¨μμμλ μΌκ΄λ λ€μ΄λ° 컨벀μ μ μ©
- docstringμ λͺ νν λ§€κ°λ³μ μ€λͺ μΆκ°
async def send_message(
self,
channel: str, # κ°λ₯ν λΆλΆλ€μ channel λ‘ ν΅μΌ μμ
text: str, # ν΅μΌ: text
thread_ts: Optional[str] = None
) -> Dict[str, Any]:
2. Input-Output λ³μλͺ μ°ΎκΈ° μ΄λ €μ
λ¬Έμ : Slack API μλ΅μ 볡μ‘ν μ€μ²© κ΅¬μ‘°λ‘ νμν λ°μ΄ν° μΆμΆ μ΄λ €μ
ν΄κ²°μ± :
- API μλ΅μ λ‘κ·Έλ‘ μΆλ ₯νμ¬ κ΅¬μ‘° νμ
- κ³΅ν΅ λ°μ΄ν° μΆμΆ ν¨μ μμ±
- μλ΅ λ°μ΄ν° μ κ·ν λ° ν¬λ§·ν
# μλ΅ λ°μ΄ν° μ κ·ν μμ
formatted_messages.append({
'text': msg.get('text', ''),
'user': msg.get('user', 'Unknown'),
'timestamp': readable_time,
'ts': msg.get('ts', ''),
# ... νμν νλλ§ μΆμΆ
})
3. Outdated file_upload ν¨μλ₯Ό μ΅μ λ²μ μΌλ‘ μ¬μ©νκΈ°κΉμ§ λ§μ μνμ°©μ€
λ¬Έμ : Slackμ νμΌ μ λ‘λ APIκ° μ¬λ¬ λ² λ³κ²½λμ΄ κΈ°μ‘΄ λ°©μ deprecated
ν΄κ²°μ± :
files.upload(deprecated) βfiles.getUploadURLExternal+files.completeUploadExternal- Slack SDKμ κΈ°μ‘΄ REST APIμ νμ΄λΈλ¦¬λ μ κ·Όλ²
- νμΌ ν¬κΈ°λ³ λ€λ₯Έ μ λ‘λ μ λ΅ κ΅¬ν
# μλ‘μ΄ νμΌ μ
λ‘λ νλ‘μ°
# 1. μ
λ‘λ URL μμ²
upload_response = await self._make_request('files.getUploadURLExternal', 'POST', upload_data)
# 2. μΈλΆ URLλ‘ νμΌ μ
λ‘λ
async with self._session.put(upload_url, data=file_content) as response:
# νμΌ μ
λ‘λ
# 3. μ
λ‘λ μλ£ μ²λ¦¬
complete_response = await self._make_request('files.completeUploadExternal', 'POST', complete_data)
4. User Tokenμ΄ νμν κ²½μ° vs Bot Tokenλ§μΌλ‘ ν΄κ²°λλ κ²½μ°
λ¬Έμ : μ΄λ€ κΈ°λ₯μ μ΄λ€ ν ν°μ΄ νμνμ§ νμ νκΈ° μ΄λ €μ
ν΄κ²°μ± :
- κΈ°λ₯λ³ ν ν° μꡬμ¬ν λͺ νν λΆλ₯
- μ΄μ€ ν ν° μμ€ν μΌλ‘ μλ μ ν
- ν ν° λΆμ‘± μ λͺ νν μλ΄ λ©μμ§
# Bot TokenμΌλ‘ κ°λ₯ν κΈ°λ₯
- λ©μμ§ μ μ‘ (chat.postMessage)
- μ±λ λͺ©λ‘ (conversations.list)
- μ¬μ©μ λͺ©λ‘ (users.list)
- νμΌ μ
λ‘λ (< 100MB)
# User Tokenμ΄ νμν κΈ°λ₯
- λ©μμ§ κ²μ (search.messages)
- λμ©λ νμΌ μ
λ‘λ (> 100MB)
5. GET vs POSTμ μ°¨μ΄
λ¬Έμ : μΈμ GETμ μ°κ³ μΈμ POSTλ₯Ό μ¨μΌ νλμ§ νΌλ
ν΄κ²°μ± :
- Slack API λ¬Έμμ HTTP λ©μλ μ νν νμΈ
- λ°μ΄ν° μ‘°νλ GET, λ°μ΄ν° μμ±/μμ μ POST
- ν΅μΌλ
_make_requestν¨μλ‘ μ²λ¦¬
# GET: λ°μ΄ν° μ‘°ν
await self._make_request('conversations.list', 'GET', params)
await self._make_request('users.list', 'GET', params)
# POST: λ°μ΄ν° μμ±/μμ
await self._make_request('chat.postMessage', 'POST', data)
await self._make_request('files.getUploadURLExternal', 'POST', data)
6. κΈ°ν ν΄κ²°ν μ΄μλ€
- Rate Limiting: μ§μ λ°±μ€νμ μ¬μλ λ‘μ§
- Error Handling: κ° μλ¬ μ½λλ³ λ§μΆ€ν ν΄κ²° μ μ
- UTF-8 Encoding: νκΈ λ©μμ§ μλ²½ μ§μ
- Async Safety: λ½λͺ¨λλ‘ νμ΄λ¨Έμ λμ μ€ν μ²λ¦¬
π μ±λ₯ λ° μ νμ¬ν
νμΌ μ λ‘λ μ ν
- λ¬΄λ£ νλ: μ΅λ 5GB μν¬μ€νμ΄μ€ μ€ν 리μ§
- κ°λ³ νμΌ: μ΅λ 1GB (μ λ£ νλμμ)
- Bot Token: μ΅λ 100MB νμΌ μ λ‘λ
- User Token: μ΅λ 1GB νμΌ μ λ‘λ
API Rate Limits
- Tier 1 λ©μλ: 1+ per minute
- Tier 2 λ©μλ: 20+ per minute
- Tier 3 λ©μλ: 50+ per minute
- Tier 4 λ©μλ: 100+ per minute
π ν μ€νΈ λ°©λ²
1. μ°κ²° ν μ€νΈ
# μλ² μ€ν ν Claudeμμ ν
μ€νΈ
test_slack_connection()
2. κΈ°λ³Έ κΈ°λ₯ ν μ€νΈ
# μ±λ λͺ©λ‘ μ‘°ν
get_slack_channels()
# λ©μμ§ μ μ‘ ν
μ€νΈ
send_slack_message("C08UZKK9Q4R", "ν
μ€νΈ λ©μμ§μ
λλ€! π")
3. κ³ κΈ κΈ°λ₯ ν μ€νΈ
# νμΌ μ
λ‘λ ν
μ€νΈ
upload_file_to_slack("./test.txt", title="ν
μ€νΈ νμΌ")
# λ½λͺ¨λλ‘ νμ΄λ¨Έ ν
μ€νΈ
start_pomodoro_timer("work", duration_minutes=25, custom_name="ν
μ€νΈ μμ
")
π€ κΈ°μ¬ λ°©λ²
- μ΄μ μ 보: GitHub Issues μ¬μ©
- κΈ°λ₯ μ μ: Feature Request ν νλ¦Ώ μ¬μ©
- μ½λ κΈ°μ¬: Pull Request νμ
- λ¬Έμ κ°μ : README λ° docstring κ°μ
π λΌμ΄μ μ€
μ΄ νλ‘μ νΈλ MIT λΌμ΄μ μ€λ₯Ό λ°λ¦ λλ€.
πββοΈ λ¬Έμ λ° μ§μ
- κ°λ°μ: JunHyuck Kwon
- λ²μ : 8.5.2 (Complete Implementation)
- μ΅μ’ μ λ°μ΄νΈ: 2025-06-04
κ³Όμ μμ±λ: β νμ 4κ° + β μ ν 4κ° + β 보λμ€ 4κ° + β μ νΈλ¦¬ν° 4κ° = μ΄ 16κ° κΈ°λ₯ μμ ꡬν
μ΄ νλ‘μ νΈλ₯Ό ν΅ν΄ μ€μ μ 무μμ νμ©ν μ μλ κ³ νμ§ Slack μ°λ λꡬλ₯Ό ꡬμΆν μ μμ΅λλ€! π
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
E2B
Using MCP to run code via e2b.