@foundation0/git 1.2.4 → 1.3.0

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.
package/mcp/README.md CHANGED
@@ -12,6 +12,20 @@ Each tool is addressed by the full API path (`repo.issue.create`, `search.issues
12
12
  - `args`: array of positional string arguments
13
13
  - `options`: object for request body/query/header customisation
14
14
 
15
+ Tool results are returned as a compact envelope by default:
16
+
17
+ ```json
18
+ { "ok": true, "data": { "...": "..." }, "meta": { "status": 200 } }
19
+ ```
20
+
21
+ If the upstream git API returns `{ ok: false }` or an HTTP status `>= 400`, the MCP tool call is marked as an error (`isError: true`) and a typed error envelope is returned:
22
+
23
+ ```json
24
+ { "ok": false, "error": { "code": "HTTP_NOT_FOUND", "status": 404, "message": "HTTP 404", "retryable": false }, "meta": { "status": 404 } }
25
+ ```
26
+
27
+ To include the full debug payload (mapping/request/response headers), pass `format: "debug"` (either top-level or in `options`).
28
+
15
29
  Use the `batch` tool to run multiple calls in one request. It is the preferred mode when you want to issue multiple MCP calls because it executes them in parallel and returns a combined response.
16
30
 
17
31
  Batch payload format:
@@ -111,6 +125,12 @@ await client.call('repo.issue.create', {
111
125
  })
112
126
  ```
113
127
 
128
+ To return a debug payload for a specific call:
129
+
130
+ ```ts
131
+ await client.call('repo.issue.list', { format: 'debug' })
132
+ ```
133
+
114
134
  ## Using with MCP-compatible agents
115
135
 
116
136
  Create a small server entry file for your agent (for example `packages/git/mcp/server-entry.ts`):
@@ -211,6 +231,36 @@ Tips:
211
231
  `repo.label.listManaged`, `repo.label.getByName`, `repo.label.upsert`, and `repo.label.deleteByName`
212
232
  - Includes Gitea Actions convenience tools exposed from the API object (best-effort helpers):
213
233
  `repo.actions.tasks.list`, `repo.actions.jobs.logs`, `repo.actions.jobs.logsTail`, `repo.actions.jobs.logsForRunTail`,
214
- and `repo.actions.artifacts.downloadZipUrl`
234
+ `repo.actions.diagnoseLatestFailure`, and `repo.actions.artifacts.downloadZipUrl`
215
235
  - Includes a discovery helper:
216
236
  `help.actionsLogs` (also available under `repo.help.actionsLogs`)
237
+
238
+ ## Notes: jobs.logsForRunTail
239
+
240
+ `repo.actions.jobs.logsForRunTail` (and the `help.*` variants) expect a `headSha` and a `runNumber`. Prefer the named form to avoid positional confusion:
241
+
242
+ ```json
243
+ {
244
+ "owner": "F0",
245
+ "repo": "adl",
246
+ "headSha": "6dd4062ec271277e7e83ac6864fec9208559564c",
247
+ "runNumber": 11,
248
+ "maxLines": 250
249
+ }
250
+ ```
251
+
252
+ ## Notes: actions.diagnoseLatestFailure
253
+
254
+ `repo.actions.diagnoseLatestFailure` is a convenience tool that finds the most recent failing Actions task and returns a log tail.
255
+
256
+ ```json
257
+ { "owner": "F0", "repo": "adl", "workflowName": "TypeScript", "maxLines": 250 }
258
+ ```
259
+
260
+ ## Notes: actions.runs.artifacts
261
+
262
+ `repo.actions.runs.artifacts` accepts a named form to avoid legacy positional ordering:
263
+
264
+ ```json
265
+ { "owner": "F0", "repo": "adl", "runId": 11 }
266
+ ```
package/mcp/src/client.ts CHANGED
@@ -12,6 +12,9 @@ type ToolResult = {
12
12
  content?: ToolResultText[]
13
13
  }
14
14
 
15
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
16
+ typeof value === 'object' && value !== null && !Array.isArray(value)
17
+
15
18
  const toText = (result: ToolResult | null): string => {
16
19
  if (!result || !result.content || result.content.length === 0) {
17
20
  return ''
@@ -116,8 +119,14 @@ export class GitMcpClient {
116
119
 
117
120
  const text = toText(response as ToolResult)
118
121
  const parsed = tryParseResult(text)
122
+
123
+ // Back-compat: if a server returns an { ok:false } envelope but forgets to mark MCP isError,
124
+ // treat it as an error on the client side as well.
125
+ const parsedIsError =
126
+ isRecord(parsed.parsed) && typeof parsed.parsed.ok === 'boolean' ? parsed.parsed.ok === false : false
127
+
119
128
  return {
120
- isError: Boolean(response.isError),
129
+ isError: Boolean(response.isError) || parsedIsError,
121
130
  text: parsed.text,
122
131
  data: parsed.parsed,
123
132
  }