atlassian-sdk-py 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: atlassian-sdk-py
3
+ Version: 0.1.0
4
+ Summary: Python async SDK for Atlassian REST API (Jira + Confluence)
5
+ Author: kknaks
6
+ Requires-Python: >=3.11,<4.0
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Provides-Extra: dev
13
+ Requires-Dist: httpx (>=0.27,<1.0)
14
+ Requires-Dist: mcp (>=1.0,<2.0)
15
+ Requires-Dist: pydantic (>=2.0,<3.0)
16
+ Requires-Dist: pytest (>=9.0) ; extra == "dev"
17
+ Requires-Dist: pytest-asyncio (>=1.3) ; extra == "dev"
18
+ Requires-Dist: respx (>=0.22) ; extra == "dev"
19
+ Description-Content-Type: text/markdown
20
+
21
+ # atlassian-sdk-py
22
+
23
+ Atlassian REST API를 직접 호출하는 Python async SDK. Jira + Confluence를 하나의 패키지로 지원합니다.
24
+
25
+ > acli 바이너리 불필요 — httpx로 REST API 직접 호출
26
+
27
+ ## 설치
28
+
29
+ ```bash
30
+ pip install atlassian-sdk-py
31
+ ```
32
+
33
+ ## 환경변수
34
+
35
+ ```env
36
+ ATLASSIAN_SITE=your-site.atlassian.net
37
+ ATLASSIAN_EMAIL=user@example.com
38
+ ATLASSIAN_API_TOKEN=your-api-token
39
+ PYACLI_DEFAULT_PROJECT=WNVO
40
+ PYACLI_EPIC_MAP=frontend:WNVO-9,backend:WNVO-23,ai:WNVO-24
41
+ ```
42
+
43
+ ## Jira 사용법
44
+
45
+ ```python
46
+ import asyncio
47
+ from atlassian_sdk import JiraClient
48
+
49
+ async def main():
50
+ client = JiraClient()
51
+
52
+ # 프로젝트 목록 조회
53
+ projects = await client.list_projects()
54
+
55
+ # 에픽 이름으로 이슈 생성 (epic map 사용)
56
+ issue = await client.create_issue(
57
+ summary="로그인 에러 수정",
58
+ epic="frontend", # → WNVO-9 밑에 생성
59
+ labels=["bug", "backend"],
60
+ )
61
+ print(issue.key) # WNVO-111
62
+ print(issue.url) # https://site.atlassian.net/browse/WNVO-111
63
+
64
+ # 이슈 조회
65
+ issue = await client.get_issue("WNVO-111")
66
+
67
+ # JQL 검색
68
+ issues = await client.search_issues(
69
+ jql="project = WNVO AND status = 'To Do'",
70
+ )
71
+
72
+ # 상태 변경
73
+ await client.transition_issue("WNVO-111", status="완료")
74
+
75
+ # 댓글
76
+ await client.add_comment("WNVO-111", body="수정 완료")
77
+ comments = await client.list_comments("WNVO-111")
78
+
79
+ asyncio.run(main())
80
+ ```
81
+
82
+ ## Confluence 사용법
83
+
84
+ ```python
85
+ from atlassian_sdk import ConfluenceClient
86
+
87
+ async def main():
88
+ client = ConfluenceClient()
89
+
90
+ # 스페이스 목록
91
+ spaces = await client.list_spaces()
92
+
93
+ # 페이지 생성
94
+ page = await client.create_page(
95
+ space_id="12345",
96
+ title="회의록 2024-01-15",
97
+ body="<h1>회의 내용</h1><p>안건 논의</p>",
98
+ )
99
+
100
+ # 페이지 조회 / 수정
101
+ page = await client.get_page("67890")
102
+ updated = await client.update_page(
103
+ "67890",
104
+ title="회의록 (수정)",
105
+ body="<p>수정된 내용</p>",
106
+ version_number=2,
107
+ )
108
+
109
+ # 하위 페이지 / 댓글
110
+ children = await client.get_child_pages("67890")
111
+ await client.add_footer_comment("67890", body="확인했습니다")
112
+
113
+ # CQL 검색
114
+ results = await client.search(cql="type=page AND space=DEV")
115
+ ```
116
+
117
+ ## Jira 계층 구조
118
+
119
+ ```
120
+ Project (WNVO)
121
+ ├── [에픽] 기능구현-프론트 1차 ← parent 없이 생성
122
+ │ ├── [작업] 로그인 에러 수정 ← parent = 에픽 키
123
+ │ │ ├── [하위작업] UI 구현 ← parent = 작업 키
124
+ │ │ └── [하위작업] API 연동
125
+ │ └── [작업] 회원가입 구현
126
+ └── [에픽] 기능구현-백엔드 1차
127
+ ```
128
+
129
+ ## Pydantic 입력 모델
130
+
131
+ 파라미터가 많을 때 Request 모델을 사용할 수 있습니다:
132
+
133
+ ```python
134
+ from atlassian_sdk import JiraClient, CreateIssueRequest
135
+
136
+ client = JiraClient(project="WNVO")
137
+
138
+ req = CreateIssueRequest(
139
+ summary="복잡한 이슈",
140
+ description="상세 설명",
141
+ type="Bug",
142
+ assignee="user-account-id",
143
+ labels=["bug", "urgent"],
144
+ parent="WNVO-9",
145
+ )
146
+ issue = await client.create_issue(request=req)
147
+ ```
148
+
149
+ ## FastAPI 에러 자동 보고
150
+
151
+ ```python
152
+ from fastapi import FastAPI, Request
153
+ from fastapi.responses import JSONResponse
154
+ from atlassian_sdk import JiraClient
155
+ import traceback
156
+
157
+ app = FastAPI()
158
+ client = JiraClient()
159
+
160
+ @app.middleware("http")
161
+ async def error_reporting(request: Request, call_next):
162
+ try:
163
+ return await call_next(request)
164
+ except Exception as exc:
165
+ tb = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))
166
+ issue = await client.create_issue(
167
+ summary=f"[AUTO-BUG] {type(exc).__name__}: {exc}",
168
+ description=f"Endpoint: {request.method} {request.url.path}",
169
+ issue_type="버그",
170
+ epic="backend",
171
+ )
172
+ await client.add_comment(issue.key, body=tb)
173
+ return JSONResponse(status_code=500, content={"jira": issue.key})
174
+ ```
175
+
176
+ ## MCP 서버
177
+
178
+ Claude Desktop/Claude Code에서 Jira + Confluence를 사용할 수 있는 MCP 서버가 포함되어 있습니다.
179
+
180
+ ```json
181
+ {
182
+ "mcpServers": {
183
+ "atlassian-sdk": {
184
+ "command": "python",
185
+ "args": ["-m", "atlassian_sdk.mcp"]
186
+ }
187
+ }
188
+ }
189
+ ```
190
+
191
+ 제공 도구 (20개):
192
+ - **Schema 도구**: `list_methods`, `get_method_info`, `get_models`
193
+ - **Jira 도구**: `list_projects`, `list_issue_types`, `get_issue`, `search_issues`, `create_issue`, `transition_issue`, `add_comment`, `list_comments`
194
+ - **Confluence 도구**: `create_page`, `get_page`, `update_page`, `list_spaces`, `get_pages_in_space`, `get_child_pages`, `get_footer_comments`, `add_footer_comment`, `search_confluence`
195
+
196
+ ## 인증
197
+
198
+ | 환경 | 방식 |
199
+ |------|------|
200
+ | 로컬 개발 | `.env` 파일에 환경변수 설정 |
201
+ | Docker / CI | 환경변수 직접 주입 |
202
+
203
+ Basic Auth: `email + API token` → `Authorization: Basic base64(email:token)`
204
+
205
+ ## 기술 스택
206
+
207
+ - Python 3.11+
208
+ - httpx (async HTTP)
209
+ - Pydantic v2
210
+ - MCP SDK
211
+ - Poetry
212
+
213
+ ## 라이선스
214
+
215
+ MIT
216
+
@@ -0,0 +1,195 @@
1
+ # atlassian-sdk-py
2
+
3
+ Atlassian REST API를 직접 호출하는 Python async SDK. Jira + Confluence를 하나의 패키지로 지원합니다.
4
+
5
+ > acli 바이너리 불필요 — httpx로 REST API 직접 호출
6
+
7
+ ## 설치
8
+
9
+ ```bash
10
+ pip install atlassian-sdk-py
11
+ ```
12
+
13
+ ## 환경변수
14
+
15
+ ```env
16
+ ATLASSIAN_SITE=your-site.atlassian.net
17
+ ATLASSIAN_EMAIL=user@example.com
18
+ ATLASSIAN_API_TOKEN=your-api-token
19
+ PYACLI_DEFAULT_PROJECT=WNVO
20
+ PYACLI_EPIC_MAP=frontend:WNVO-9,backend:WNVO-23,ai:WNVO-24
21
+ ```
22
+
23
+ ## Jira 사용법
24
+
25
+ ```python
26
+ import asyncio
27
+ from atlassian_sdk import JiraClient
28
+
29
+ async def main():
30
+ client = JiraClient()
31
+
32
+ # 프로젝트 목록 조회
33
+ projects = await client.list_projects()
34
+
35
+ # 에픽 이름으로 이슈 생성 (epic map 사용)
36
+ issue = await client.create_issue(
37
+ summary="로그인 에러 수정",
38
+ epic="frontend", # → WNVO-9 밑에 생성
39
+ labels=["bug", "backend"],
40
+ )
41
+ print(issue.key) # WNVO-111
42
+ print(issue.url) # https://site.atlassian.net/browse/WNVO-111
43
+
44
+ # 이슈 조회
45
+ issue = await client.get_issue("WNVO-111")
46
+
47
+ # JQL 검색
48
+ issues = await client.search_issues(
49
+ jql="project = WNVO AND status = 'To Do'",
50
+ )
51
+
52
+ # 상태 변경
53
+ await client.transition_issue("WNVO-111", status="완료")
54
+
55
+ # 댓글
56
+ await client.add_comment("WNVO-111", body="수정 완료")
57
+ comments = await client.list_comments("WNVO-111")
58
+
59
+ asyncio.run(main())
60
+ ```
61
+
62
+ ## Confluence 사용법
63
+
64
+ ```python
65
+ from atlassian_sdk import ConfluenceClient
66
+
67
+ async def main():
68
+ client = ConfluenceClient()
69
+
70
+ # 스페이스 목록
71
+ spaces = await client.list_spaces()
72
+
73
+ # 페이지 생성
74
+ page = await client.create_page(
75
+ space_id="12345",
76
+ title="회의록 2024-01-15",
77
+ body="<h1>회의 내용</h1><p>안건 논의</p>",
78
+ )
79
+
80
+ # 페이지 조회 / 수정
81
+ page = await client.get_page("67890")
82
+ updated = await client.update_page(
83
+ "67890",
84
+ title="회의록 (수정)",
85
+ body="<p>수정된 내용</p>",
86
+ version_number=2,
87
+ )
88
+
89
+ # 하위 페이지 / 댓글
90
+ children = await client.get_child_pages("67890")
91
+ await client.add_footer_comment("67890", body="확인했습니다")
92
+
93
+ # CQL 검색
94
+ results = await client.search(cql="type=page AND space=DEV")
95
+ ```
96
+
97
+ ## Jira 계층 구조
98
+
99
+ ```
100
+ Project (WNVO)
101
+ ├── [에픽] 기능구현-프론트 1차 ← parent 없이 생성
102
+ │ ├── [작업] 로그인 에러 수정 ← parent = 에픽 키
103
+ │ │ ├── [하위작업] UI 구현 ← parent = 작업 키
104
+ │ │ └── [하위작업] API 연동
105
+ │ └── [작업] 회원가입 구현
106
+ └── [에픽] 기능구현-백엔드 1차
107
+ ```
108
+
109
+ ## Pydantic 입력 모델
110
+
111
+ 파라미터가 많을 때 Request 모델을 사용할 수 있습니다:
112
+
113
+ ```python
114
+ from atlassian_sdk import JiraClient, CreateIssueRequest
115
+
116
+ client = JiraClient(project="WNVO")
117
+
118
+ req = CreateIssueRequest(
119
+ summary="복잡한 이슈",
120
+ description="상세 설명",
121
+ type="Bug",
122
+ assignee="user-account-id",
123
+ labels=["bug", "urgent"],
124
+ parent="WNVO-9",
125
+ )
126
+ issue = await client.create_issue(request=req)
127
+ ```
128
+
129
+ ## FastAPI 에러 자동 보고
130
+
131
+ ```python
132
+ from fastapi import FastAPI, Request
133
+ from fastapi.responses import JSONResponse
134
+ from atlassian_sdk import JiraClient
135
+ import traceback
136
+
137
+ app = FastAPI()
138
+ client = JiraClient()
139
+
140
+ @app.middleware("http")
141
+ async def error_reporting(request: Request, call_next):
142
+ try:
143
+ return await call_next(request)
144
+ except Exception as exc:
145
+ tb = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))
146
+ issue = await client.create_issue(
147
+ summary=f"[AUTO-BUG] {type(exc).__name__}: {exc}",
148
+ description=f"Endpoint: {request.method} {request.url.path}",
149
+ issue_type="버그",
150
+ epic="backend",
151
+ )
152
+ await client.add_comment(issue.key, body=tb)
153
+ return JSONResponse(status_code=500, content={"jira": issue.key})
154
+ ```
155
+
156
+ ## MCP 서버
157
+
158
+ Claude Desktop/Claude Code에서 Jira + Confluence를 사용할 수 있는 MCP 서버가 포함되어 있습니다.
159
+
160
+ ```json
161
+ {
162
+ "mcpServers": {
163
+ "atlassian-sdk": {
164
+ "command": "python",
165
+ "args": ["-m", "atlassian_sdk.mcp"]
166
+ }
167
+ }
168
+ }
169
+ ```
170
+
171
+ 제공 도구 (20개):
172
+ - **Schema 도구**: `list_methods`, `get_method_info`, `get_models`
173
+ - **Jira 도구**: `list_projects`, `list_issue_types`, `get_issue`, `search_issues`, `create_issue`, `transition_issue`, `add_comment`, `list_comments`
174
+ - **Confluence 도구**: `create_page`, `get_page`, `update_page`, `list_spaces`, `get_pages_in_space`, `get_child_pages`, `get_footer_comments`, `add_footer_comment`, `search_confluence`
175
+
176
+ ## 인증
177
+
178
+ | 환경 | 방식 |
179
+ |------|------|
180
+ | 로컬 개발 | `.env` 파일에 환경변수 설정 |
181
+ | Docker / CI | 환경변수 직접 주입 |
182
+
183
+ Basic Auth: `email + API token` → `Authorization: Basic base64(email:token)`
184
+
185
+ ## 기술 스택
186
+
187
+ - Python 3.11+
188
+ - httpx (async HTTP)
189
+ - Pydantic v2
190
+ - MCP SDK
191
+ - Poetry
192
+
193
+ ## 라이선스
194
+
195
+ MIT
@@ -0,0 +1,42 @@
1
+ [project]
2
+ name = "atlassian-sdk-py"
3
+ version = "0.1.0"
4
+ description = "Python async SDK for Atlassian REST API (Jira + Confluence)"
5
+ authors = [
6
+ {name = "kknaks"}
7
+ ]
8
+ readme = "README.md"
9
+ requires-python = ">=3.11,<4.0"
10
+ dependencies = [
11
+ "pydantic>=2.0,<3.0",
12
+ "httpx>=0.27,<1.0",
13
+ "mcp>=1.0,<2.0",
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ dev = [
18
+ "pytest>=9.0",
19
+ "pytest-asyncio>=1.3",
20
+ "respx>=0.22",
21
+ ]
22
+
23
+ [project.scripts]
24
+ atlassian-sdk-mcp = "atlassian_sdk.mcp:run"
25
+
26
+ [build-system]
27
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
28
+ build-backend = "poetry.core.masonry.api"
29
+
30
+ [tool.poetry]
31
+ packages = [{include = "atlassian_sdk", from = "src"}]
32
+
33
+ [tool.pytest.ini_options]
34
+ testpaths = ["tests"]
35
+ asyncio_mode = "auto"
36
+
37
+ [dependency-groups]
38
+ dev = [
39
+ "pytest (>=9.0.0,<10.0.0)",
40
+ "pytest-asyncio (>=1.3.0,<2.0.0)",
41
+ "respx (>=0.22.0,<1.0.0)",
42
+ ]
@@ -0,0 +1,93 @@
1
+ """Atlassian SDK — Python async client for Jira and Confluence REST APIs."""
2
+ from __future__ import annotations
3
+
4
+ __version__ = "0.1.0"
5
+
6
+ from atlassian_sdk.auth import BasicAuth
7
+ from atlassian_sdk.exceptions import (
8
+ ApiError,
9
+ AuthError,
10
+ NotFoundError,
11
+ RateLimitError,
12
+ SdkError,
13
+ TimeoutError,
14
+ ValidationError,
15
+ )
16
+ from atlassian_sdk.http import AsyncHttpClient
17
+ from atlassian_sdk.jira.client import JiraClient
18
+ from atlassian_sdk.jira.models import (
19
+ Comment,
20
+ IssueType,
21
+ JiraIssue,
22
+ JiraProject,
23
+ ParentRef,
24
+ Priority,
25
+ Project,
26
+ Status,
27
+ StatusCategory,
28
+ Transition,
29
+ User,
30
+ )
31
+ from atlassian_sdk.jira.schemas import (
32
+ CreateIssueRequest,
33
+ SearchIssuesRequest,
34
+ TransitionIssueRequest,
35
+ )
36
+ from atlassian_sdk.confluence.client import ConfluenceClient
37
+ from atlassian_sdk.confluence.models import (
38
+ ConfluenceComment,
39
+ Page,
40
+ PageBody,
41
+ PageVersion,
42
+ Space,
43
+ )
44
+ from atlassian_sdk.confluence.schemas import (
45
+ CreateCommentRequest,
46
+ CreatePageRequest,
47
+ SearchConfluenceRequest,
48
+ UpdatePageRequest,
49
+ )
50
+
51
+ __all__ = [
52
+ # Version
53
+ "__version__",
54
+ # Auth
55
+ "BasicAuth",
56
+ # HTTP
57
+ "AsyncHttpClient",
58
+ # Exceptions
59
+ "SdkError",
60
+ "ApiError",
61
+ "AuthError",
62
+ "NotFoundError",
63
+ "RateLimitError",
64
+ "TimeoutError",
65
+ "ValidationError",
66
+ # Jira
67
+ "JiraClient",
68
+ "JiraIssue",
69
+ "JiraProject",
70
+ "IssueType",
71
+ "Status",
72
+ "StatusCategory",
73
+ "Priority",
74
+ "User",
75
+ "Project",
76
+ "ParentRef",
77
+ "Transition",
78
+ "Comment",
79
+ "CreateIssueRequest",
80
+ "SearchIssuesRequest",
81
+ "TransitionIssueRequest",
82
+ # Confluence
83
+ "ConfluenceClient",
84
+ "Space",
85
+ "PageVersion",
86
+ "PageBody",
87
+ "Page",
88
+ "ConfluenceComment",
89
+ "CreatePageRequest",
90
+ "UpdatePageRequest",
91
+ "CreateCommentRequest",
92
+ "SearchConfluenceRequest",
93
+ ]
@@ -0,0 +1,49 @@
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import os
5
+ from dataclasses import dataclass
6
+
7
+ from atlassian_sdk.exceptions import AuthError
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class BasicAuth:
12
+ """Immutable container for Atlassian basic-auth credentials."""
13
+
14
+ email: str
15
+ api_token: str
16
+
17
+ @property
18
+ def header_value(self) -> str:
19
+ """Return the ``Authorization`` header value (``Basic <b64>``)."""
20
+ raw = f"{self.email}:{self.api_token}".encode()
21
+ encoded = base64.b64encode(raw).decode()
22
+ return f"Basic {encoded}"
23
+
24
+ @classmethod
25
+ def from_env(cls) -> BasicAuth:
26
+ """Create a :class:`BasicAuth` from environment variables.
27
+
28
+ Reads ``ATLASSIAN_EMAIL`` and ``ATLASSIAN_API_TOKEN``.
29
+
30
+ Raises:
31
+ AuthError: If either variable is missing.
32
+ """
33
+ email = os.environ.get("ATLASSIAN_EMAIL")
34
+ api_token = os.environ.get("ATLASSIAN_API_TOKEN")
35
+
36
+ missing: list[str] = []
37
+ if not email:
38
+ missing.append("ATLASSIAN_EMAIL")
39
+ if not api_token:
40
+ missing.append("ATLASSIAN_API_TOKEN")
41
+
42
+ if missing:
43
+ raise AuthError(
44
+ f"Missing environment variable(s): {', '.join(missing)}",
45
+ status_code=401,
46
+ response_body="",
47
+ )
48
+
49
+ return cls(email=email, api_token=api_token)
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+ from atlassian_sdk.confluence.client import ConfluenceClient
4
+ from atlassian_sdk.confluence.models import (
5
+ ConfluenceComment,
6
+ Page,
7
+ PageBody,
8
+ PageVersion,
9
+ Space,
10
+ )
11
+ from atlassian_sdk.confluence.schemas import (
12
+ CreateCommentRequest,
13
+ CreatePageRequest,
14
+ SearchConfluenceRequest,
15
+ UpdatePageRequest,
16
+ )
17
+
18
+ __all__ = [
19
+ "ConfluenceClient",
20
+ "ConfluenceComment",
21
+ "CreateCommentRequest",
22
+ "CreatePageRequest",
23
+ "Page",
24
+ "PageBody",
25
+ "PageVersion",
26
+ "SearchConfluenceRequest",
27
+ "Space",
28
+ "UpdatePageRequest",
29
+ ]