Skip to content

Commit acebcfd

Browse files
committed
Address PR review comments: json.dumps, .env.sample, date shadowing, localhost binding
1 parent e0cb876 commit acebcfd

6 files changed

Lines changed: 145 additions & 9 deletions

File tree

.env.sample

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# API_HOST can be either azure, openai, or github:
22
API_HOST=azure
33
# Configure for Azure:
4-
AZURE_OPENAI_ENDPOINT=https://YOUR-AZURE-OPENAI-SERVICE-NAME.openai.azure.com/openai/v1
4+
AZURE_OPENAI_ENDPOINT=https://YOUR-AZURE-OPENAI-SERVICE-NAME.openai.azure.com
55
AZURE_OPENAI_CHAT_DEPLOYMENT=YOUR-AZURE-DEPLOYMENT-NAME
66
# Configure for OpenAI.com:
77
OPENAI_API_KEY=YOUR-OPENAI-KEY
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
---
2+
name: review_pr_comments
3+
description: This prompt is used to review comments on an active pull request and decide whether to accept, iterate, or reject the changes suggested in each comment.
4+
---
5+
We have received comments on the current active pull request. Together, we will go through each comment one by one and discuss whether to accept the change, iterate on it, or reject the change.
6+
7+
## Steps to follow:
8+
9+
1. Fetch the active pull request: If available, use the `activePullRequest` tool from the `GitHub Pull Requests` toolset to get the details of the active pull request including the comments. If not, use the GitHub MCP server or GitHub CLI to get the details of the active pull request. Fetch both top level comments and inline comments.
10+
2. Present a list of the comments with a one-sentence summary of each.
11+
3. One at a time, present each comment in full detail and ask me whether to accept, iterate, or reject the change. Provide your recommendation for each comment based on best practices, code quality, and project guidelines. Await user's decision before proceeding to the next comment. DO NOT make any changes to the code or files until I have responded with my decision for each comment.
12+
4. If the decision is to accept or iterate, make the necessary code changes to address the comment. If the decision is to reject, provide a brief explanation of why the change was not made.
13+
5. Wait for user to affirm completion of any code changes made before moving to the next comment.
14+
6. Reply to each comment on the pull request with the outcome of our discussion (accepted, iterated, or rejected) along with any relevant explanations.
15+
16+
17+
## How to reply to PR review comments
18+
19+
This guide explains how to reply directly to inline review comments on GitHub pull requests.
20+
21+
### API Endpoint
22+
23+
To reply to an inline PR comment, use:
24+
25+
```http
26+
POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies
27+
```
28+
29+
With body:
30+
31+
```json
32+
{
33+
"body": "Your reply message"
34+
}
35+
```
36+
37+
### Using gh CLI
38+
39+
```bash
40+
gh api repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies \
41+
-X POST \
42+
-f body="Your reply message"
43+
```
44+
45+
### Workflow
46+
47+
1. **Get PR comments**: First fetch the PR review comments to get their IDs:
48+
49+
```bash
50+
gh api repos/{owner}/{repo}/pulls/{pull_number}/comments
51+
```
52+
53+
2. **Identify comment IDs**: Each comment has an `id` field. For threaded comments, use the root comment's `id`.
54+
55+
3. **Post replies**: For each comment you want to reply to:
56+
57+
```bash
58+
gh api repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies \
59+
-X POST \
60+
-f body="Fixed in commit abc123"
61+
```
62+
63+
### Example Replies
64+
65+
For accepted changes:
66+
67+
- "Fixed in {commit_sha}"
68+
- "Accepted - fixed in {commit_sha}"
69+
70+
For rejected changes:
71+
72+
- "Rejected - {reason}"
73+
- "Won't fix - {explanation}"
74+
75+
For questions:
76+
77+
- "Good catch, addressed in {commit_sha}"
78+
79+
## Notes
80+
81+
- The `comment_id` is the numeric ID from the comment object, NOT the `node_id`
82+
- Replies appear as threaded responses under the original comment
83+
- You can reply to any comment, including bot comments (like Copilot reviews)
84+
85+
### Resolving Conversations
86+
87+
To resolve (mark as resolved) PR review threads, use the GraphQL API:
88+
89+
1. **Get thread IDs**: Query for unresolved threads:
90+
91+
```bash
92+
gh api graphql -f query='
93+
query {
94+
repository(owner: "{owner}", name: "{repo}") {
95+
pullRequest(number: {pull_number}) {
96+
reviewThreads(first: 50) {
97+
nodes {
98+
id
99+
isResolved
100+
comments(first: 1) {
101+
nodes { body path }
102+
}
103+
}
104+
}
105+
}
106+
}
107+
}'
108+
```
109+
110+
2. **Resolve threads**: Use the `resolveReviewThread` mutation:
111+
112+
```bash
113+
gh api graphql -f query='
114+
mutation {
115+
resolveReviewThread(input: {threadId: "PRRT_xxx"}) {
116+
thread { isResolved }
117+
}
118+
}'
119+
```
120+
121+
3. **Resolve multiple threads at once**:
122+
123+
```bash
124+
gh api graphql -f query='
125+
mutation {
126+
t1: resolveReviewThread(input: {threadId: "PRRT_xxx"}) { thread { isResolved } }
127+
t2: resolveReviewThread(input: {threadId: "PRRT_yyy"}) { thread { isResolved } }
128+
}'
129+
```
130+
131+
The thread ID starts with `PRRT_` and can be found in the GraphQL query response.
132+
133+
Note: This skill can be removed once the GitHub MCP server has added built-in support for replying to PR review comments and resolving threads.
134+
See:
135+
https://github.com/github/github-mcp-server/issues/1323
136+
https://github.com/github/github-mcp-server/issues/1768

examples/mcp_server.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Category(Enum):
4646

4747
@mcp.tool
4848
async def add_expense(
49-
date: Annotated[date, "Date of the expense in YYYY-MM-DD format"],
49+
expense_date: Annotated[date, "Date of the expense in YYYY-MM-DD format"],
5050
amount: Annotated[float, "Positive numeric amount of the expense"],
5151
category: Annotated[Category, "Category label"],
5252
description: Annotated[str, "Human-readable description of the expense"],
@@ -56,7 +56,7 @@ async def add_expense(
5656
if amount <= 0:
5757
return "Error: Amount must be positive"
5858

59-
date_iso = date.isoformat()
59+
date_iso = expense_date.isoformat()
6060
logger.info(f"Adding expense: ${amount} for {description} on {date_iso}")
6161

6262
try:
@@ -106,4 +106,4 @@ async def get_expenses_data() -> str:
106106

107107
if __name__ == "__main__":
108108
logger.info("MCP Expenses server starting (HTTP mode on port 8000)")
109-
mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
109+
mcp.run(transport="streamable-http", host="127.0.0.1", port=8000)

examples/openai_tool_calling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,6 @@ def lookup_weather(city_name: str | None = None, zip_code: str | None = None) ->
8484
if function_name == "lookup_weather":
8585
messages.append(response.choices[0].message)
8686
result = lookup_weather(**arguments)
87-
messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": str(result)})
87+
messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)})
8888
response = client.chat.completions.create(model=MODEL_NAME, messages=messages, tools=tools)
8989
print(response.choices[0].message.content)

examples/spanish/mcp_server.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Categoria(Enum):
4646

4747
@mcp.tool
4848
async def agregar_gasto(
49-
date: Annotated[date, "Fecha del gasto en formato AAAA-MM-DD"],
49+
fecha_gasto: Annotated[date, "Fecha del gasto en formato AAAA-MM-DD"],
5050
amount: Annotated[float, "Monto numérico positivo del gasto"],
5151
category: Annotated[Categoria, "Etiqueta de categoría"],
5252
description: Annotated[str, "Descripción legible del gasto"],
@@ -56,7 +56,7 @@ async def agregar_gasto(
5656
if amount <= 0:
5757
return "Error: El monto debe ser positivo"
5858

59-
date_iso = date.isoformat()
59+
date_iso = fecha_gasto.isoformat()
6060
logger.info(f"Agregando gasto: ${amount} por {description} el {date_iso}")
6161

6262
try:
@@ -106,4 +106,4 @@ async def obtener_datos_gastos() -> str:
106106

107107
if __name__ == "__main__":
108108
logger.info("Servidor MCP de Gastos iniciando (modo HTTP en puerto 8000)")
109-
mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
109+
mcp.run(transport="streamable-http", host="127.0.0.1", port=8000)

examples/spanish/openai_tool_calling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,6 @@ def lookup_weather(city_name: str | None = None, zip_code: str | None = None) ->
8484
if function_name == "lookup_weather":
8585
messages.append(response.choices[0].message)
8686
result = lookup_weather(**arguments)
87-
messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": str(result)})
87+
messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)})
8888
response = client.chat.completions.create(model=MODEL_NAME, messages=messages, tools=tools)
8989
print(response.choices[0].message.content)

0 commit comments

Comments
 (0)