github_activity_set_thread_subscription
Subscribe or unsubscribe to a GitHub thread (issue or pull request) to manage email notifications for that conversation.
Instructions
Set a thread subscription
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| thread_id | Yes | thread_id | |
| body | No | Request body (JSON object) |
Implementation Reference
- src/tools/activity.ts:103-112 (handler)The handler function for the 'github_activity_set_thread_subscription' tool. It sends a PUT request to `/notifications/threads/{thread_id}/subscription` with an optional request body. This sets the authenticated user's subscription to a thread (ignored, subscribed, etc.).
{ name: "github_activity_set_thread_subscription", description: "Set a thread subscription", inputSchema: z.object({ thread_id: z.string().describe("thread_id"), body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON object)") }), handler: async (args: Record<string, any>) => { return githubRequest("PUT", `/notifications/threads/${args.thread_id}/subscription`, args.body, undefined); }, - src/tools/activity.ts:106-109 (schema)The input schema (Zod) for the tool, defining: thread_id (required string) and body (optional record).
inputSchema: z.object({ thread_id: z.string().describe("thread_id"), body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON object)") }), - src/index.ts:110-129 (registration)The tool is registered via server.tool() in the MCP server loop. All tools from activityTools array are iterated and registered by name, description, inputSchema, and handler.
for (const tool of allTools) { server.tool( tool.name, tool.description, tool.inputSchema.shape as any, async (args: any) => { try { const result = await tool.handler(args as any); return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }], }; } catch (err) { const message = err instanceof Error ? err.message : String(err); return { content: [{ type: "text" as const, text: `Error: ${message}` }], isError: true, }; } } ); - src/tools/index.ts:2-3 (registration)The activityTools array is re-exported from the tools index barrel file, so it can be imported by src/index.ts.
export { actionsTools } from "./actions.js"; export { activityTools } from "./activity.js"; - src/client.ts:9-59 (helper)The githubRequest helper function used by the handler to make authenticated HTTP requests to the GitHub REST API.
export async function githubRequest<T>( method: string, path: string, body?: Record<string, unknown>, params?: Record<string, string | number | boolean | string[] | undefined> ): Promise<T> { const url = new URL(`${BASE_URL}${path}`); if (params) { for (const [key, value] of Object.entries(params)) { if (value === undefined || value === null || value === "") continue; if (Array.isArray(value)) { url.searchParams.set(key, value.join(",")); } else { url.searchParams.set(key, String(value)); } } } const headers: Record<string, string> = { Authorization: `Bearer ${getToken()}`, Accept: "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28", "User-Agent": "github-mcp/1.0.0", }; if (body) { headers["Content-Type"] = "application/json"; } const res = await fetch(url.toString(), { method, headers, body: body ? JSON.stringify(body) : undefined, }); if (!res.ok) { const text = await res.text().catch(() => ""); let detail = text; try { const json = JSON.parse(text); detail = json.message || text; if (json.errors) detail += ` -- ${JSON.stringify(json.errors)}`; } catch {} throw new Error(`GitHub API error ${res.status}: ${detail}`); } if (res.status === 204) return {} as T; return res.json() as Promise<T>; }