Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit137990e

Browse files
committed
Simplify issues cli and mcp
1 parent37e660e commit137990e

File tree

4 files changed

+134
-17
lines changed

4 files changed

+134
-17
lines changed

‎cli/README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,14 @@ Cursor configuration example (Settings → MCP):
117117

118118
Tools exposed:
119119
- list_issues: returns the same JSON as`pgai issues list`.
120-
-list_issue_comments: list comments for anissue (args: { issue_id, debug? })
120+
-view_issue: view a singleissue with its comments (args: { issue_id, debug? })
121121
- post_issue_comment: post a comment (args: { issue_id, content, parent_comment_id?, debug? })
122122

123123
###Issues management (`issues` group)
124124

125125
```bash
126-
pgai issues list# List issues
127-
pgai issuescomments<issueId># List comments for anissue
126+
pgai issues list# List issues (shows: id, title, status, created_at)
127+
pgai issuesview<issueId># Viewissue details and comments
128128
pgai issues post_comment<issueId><content># Post a comment to an issue
129129
# Options:
130130
# --parent <uuid> Parent comment ID (for replies)
@@ -145,7 +145,7 @@ pgai issues list --json | jq '.[] | {id, title}'
145145
- Rely on auto-detection: when stdout is not a TTY (e.g., piped or redirected), output is JSON automatically:
146146

147147
```bash
148-
pgai issuescomments<issueId>>comments.json
148+
pgai issuesview<issueId>>issue.json
149149
```
150150

151151
####Grafana management

‎cli/bin/postgres-ai.ts‎

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import * as readline from "readline";
1313
import*ashttpfrom"https";
1414
import{URL}from"url";
1515
import{startMcpServer}from"../lib/mcp-server";
16-
import{fetchIssues,fetchIssueComments,createIssueComment}from"../lib/issues";
16+
import{fetchIssues,fetchIssueComments,createIssueComment,fetchIssue}from"../lib/issues";
1717
import{resolveBaseUrls}from"../lib/util";
1818

1919
constexecPromise=promisify(exec);
@@ -1225,7 +1225,15 @@ issues
12251225
const{ apiBaseUrl}=resolveBaseUrls(rootOpts,cfg);
12261226

12271227
constresult=awaitfetchIssues({ apiKey, apiBaseUrl,debug:!!opts.debug});
1228-
printResult(result,opts.json);
1228+
consttrimmed=Array.isArray(result)
1229+
?(resultasany[]).map((r)=>({
1230+
id:(rasany).id,
1231+
title:(rasany).title,
1232+
status:(rasany).status,
1233+
created_at:(rasany).created_at,
1234+
}))
1235+
:result;
1236+
printResult(trimmed,opts.json);
12291237
}catch(err){
12301238
constmessage=errinstanceofError ?err.message :String(err);
12311239
console.error(message);
@@ -1234,8 +1242,8 @@ issues
12341242
});
12351243

12361244
issues
1237-
.command("comments <issueId>")
1238-
.description("list comments for an issue")
1245+
.command("view <issueId>")
1246+
.description("view issue details and comments")
12391247
.option("--debug","enable debug output")
12401248
.option("--json","output raw JSON")
12411249
.action(async(issueId:string,opts:{debug?:boolean;json?:boolean})=>{
@@ -1251,8 +1259,16 @@ issues
12511259

12521260
const{ apiBaseUrl}=resolveBaseUrls(rootOpts,cfg);
12531261

1254-
constresult=awaitfetchIssueComments({ apiKey, apiBaseUrl, issueId,debug:!!opts.debug});
1255-
printResult(result,opts.json);
1262+
constissue=awaitfetchIssue({ apiKey, apiBaseUrl, issueId,debug:!!opts.debug});
1263+
if(!issue){
1264+
console.error("Issue not found");
1265+
process.exitCode=1;
1266+
return;
1267+
}
1268+
1269+
constcomments=awaitfetchIssueComments({ apiKey, apiBaseUrl, issueId,debug:!!opts.debug});
1270+
constcombined={ issue, comments};
1271+
printResult(combined,opts.json);
12561272
}catch(err){
12571273
constmessage=errinstanceofError ?err.message :String(err);
12581274
console.error(message);

‎cli/lib/issues.ts‎

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,94 @@ export async function fetchIssueComments(params: FetchIssueCommentsParams): Prom
163163
});
164164
}
165165

166+
exportinterfaceFetchIssueParams{
167+
apiKey:string;
168+
apiBaseUrl:string;
169+
issueId:string;
170+
debug?:boolean;
171+
}
172+
173+
exportasyncfunctionfetchIssue(params:FetchIssueParams):Promise<unknown>{
174+
const{ apiKey, apiBaseUrl, issueId, debug}=params;
175+
if(!apiKey){
176+
thrownewError("API key is required");
177+
}
178+
if(!issueId){
179+
thrownewError("issueId is required");
180+
}
181+
182+
constbase=normalizeBaseUrl(apiBaseUrl);
183+
consturl=newURL(`${base}/issues`);
184+
url.searchParams.set("id",`eq.${issueId}`);
185+
url.searchParams.set("limit","1");
186+
187+
constheaders:Record<string,string>={
188+
"access-token":apiKey,
189+
"Prefer":"return=representation",
190+
"Content-Type":"application/json",
191+
};
192+
193+
if(debug){
194+
constdebugHeaders:Record<string,string>={ ...headers,"access-token":maskSecret(apiKey)};
195+
// eslint-disable-next-line no-console
196+
console.log(`Debug: Resolved API base URL:${base}`);
197+
// eslint-disable-next-line no-console
198+
console.log(`Debug: GET URL:${url.toString()}`);
199+
// eslint-disable-next-line no-console
200+
console.log(`Debug: Auth scheme: access-token`);
201+
// eslint-disable-next-line no-console
202+
console.log(`Debug: Request headers:${JSON.stringify(debugHeaders)}`);
203+
}
204+
205+
returnnewPromise((resolve,reject)=>{
206+
constreq=https.request(
207+
url,
208+
{
209+
method:"GET",
210+
headers,
211+
},
212+
(res)=>{
213+
letdata="";
214+
res.on("data",(chunk)=>(data+=chunk));
215+
res.on("end",()=>{
216+
if(debug){
217+
// eslint-disable-next-line no-console
218+
console.log(`Debug: Response status:${res.statusCode}`);
219+
// eslint-disable-next-line no-console
220+
console.log(`Debug: Response headers:${JSON.stringify(res.headers)}`);
221+
}
222+
if(res.statusCode&&res.statusCode>=200&&res.statusCode<300){
223+
try{
224+
constparsed=JSON.parse(data);
225+
if(Array.isArray(parsed)){
226+
resolve(parsed[0]??null);
227+
}else{
228+
resolve(parsed);
229+
}
230+
}catch{
231+
resolve(data);
232+
}
233+
}else{
234+
leterrMsg=`Failed to fetch issue: HTTP${res.statusCode}`;
235+
if(data){
236+
try{
237+
consterrObj=JSON.parse(data);
238+
errMsg+=`\n${JSON.stringify(errObj,null,2)}`;
239+
}catch{
240+
errMsg+=`\n${data}`;
241+
}
242+
}
243+
reject(newError(errMsg));
244+
}
245+
});
246+
}
247+
);
248+
249+
req.on("error",(err:Error)=>reject(err));
250+
req.end();
251+
});
252+
}
253+
166254
exportinterfaceCreateIssueCommentParams{
167255
apiKey:string;
168256
apiBaseUrl:string;

‎cli/lib/mcp-server.ts‎

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import*aspkgfrom"../package.json";
22
import*asconfigfrom"./config";
3-
import{fetchIssues,fetchIssueComments,createIssueComment}from"./issues";
3+
import{fetchIssues,fetchIssueComments,createIssueComment,fetchIssue}from"./issues";
44
import{resolveBaseUrls}from"./util";
55

66
// MCP SDK imports
@@ -54,8 +54,8 @@ export async function startMcpServer(rootOpts?: RootOptsLike, extra?: { debug?:
5454
},
5555
},
5656
{
57-
name:"list_issue_comments",
58-
description:"List comments fora specific issue(issue_id UUID)",
57+
name:"view_issue",
58+
description:"Viewa specific issuewith its comments",
5959
inputSchema:{
6060
type:"object",
6161
properties:{
@@ -110,16 +110,29 @@ export async function startMcpServer(rootOpts?: RootOptsLike, extra?: { debug?:
110110
try{
111111
if(toolName==="list_issues"){
112112
constresult=awaitfetchIssues({ apiKey, apiBaseUrl, debug});
113-
return{content:[{type:"text",text:JSON.stringify(result,null,2)}]};
113+
consttrimmed=Array.isArray(result)
114+
?(resultasany[]).map((r)=>({
115+
id:(rasany).id,
116+
title:(rasany).title,
117+
status:(rasany).status,
118+
created_at:(rasany).created_at,
119+
}))
120+
:result;
121+
return{content:[{type:"text",text:JSON.stringify(trimmed,null,2)}]};
114122
}
115123

116-
if(toolName==="list_issue_comments"){
124+
if(toolName==="view_issue"){
117125
constissueId=String(args.issue_id||"").trim();
118126
if(!issueId){
119127
return{content:[{type:"text",text:"issue_id is required"}],isError:true};
120128
}
121-
constresult=awaitfetchIssueComments({ apiKey, apiBaseUrl, issueId, debug});
122-
return{content:[{type:"text",text:JSON.stringify(result,null,2)}]};
129+
constissue=awaitfetchIssue({ apiKey, apiBaseUrl, issueId, debug});
130+
if(!issue){
131+
return{content:[{type:"text",text:"Issue not found"}],isError:true};
132+
}
133+
constcomments=awaitfetchIssueComments({ apiKey, apiBaseUrl, issueId, debug});
134+
constcombined={ issue, comments};
135+
return{content:[{type:"text",text:JSON.stringify(combined,null,2)}]};
123136
}
124137

125138
if(toolName==="post_issue_comment"){

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp