jules-mcp 1.0.1

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/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Jules MCP Server
2
+
3
+ An MCP server implementation for [Jules API](https://developers.google.com/jules/api), allowing LLMs to interact directly with your automated Jules workflows.
4
+
5
+ ## Prerequisites
6
+
7
+ 1. **Jules API Key**: Get your API Key from the Jules [Settings page](https://jules.google.com/settings#api).
8
+ * *Note: Currently, Jules is migrating its authentication methods. If you receive a `401 Unauthorized` indicating "API keys are not supported by this API," you may need to wait for further updates from the Jules platform or supply an OAuth2 Token in place of the API key if supported.*
9
+
10
+ ## Installation & Usage
11
+
12
+ You can use the server directly via `npx` without installing it globally:
13
+
14
+ ```bash
15
+ npx jules-mcp
16
+ ```
17
+
18
+ ### Environment Variables
19
+
20
+ The server requires the following environment variables:
21
+
22
+ - `JULES_API_KEY`: Your Jules API Key or Authentication Token.
23
+
24
+ ## Configuration for Claude Desktop
25
+
26
+ To use this server with the Claude Desktop app, you need to add it to your configuration file.
27
+
28
+ **Config file locations:**
29
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
30
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
31
+
32
+ Add the following to your configuration, replacing `<YOUR_API_KEY>` with your actual Jules API key:
33
+
34
+ ```json
35
+ {
36
+ "mcpServers": {
37
+ "jules": {
38
+ "command": "npx",
39
+ "args": [
40
+ "-y",
41
+ "jules-mcp"
42
+ ],
43
+ "env": {
44
+ "JULES_API_KEY": "<YOUR_API_KEY>"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## Available Tools
52
+
53
+ The server implements the following tools:
54
+
55
+ - `jules_list_sources`: Find the IDs of sources (e.g., connected GitHub repos) you can interact with.
56
+ - `jules_create_session`: Start a new Jules coding session with a specific prompt and source context.
57
+ - `jules_list_sessions`: Check the status and output links (e.g., Pull Requests) of your sessions.
58
+ - `jules_approve_plan`: Approve a session's execution plan (if it was created with `requirePlanApproval=true`).
59
+
60
+ ## Development
61
+
62
+ ```bash
63
+ # Install dependencies
64
+ npm install
65
+
66
+ # Build the project
67
+ npm run build
68
+
69
+ # Run via MCP Inspector for testing
70
+ npm run inspector
71
+ ```
@@ -0,0 +1,3 @@
1
+ export declare const API_BASE_URL = "https://jules.googleapis.com";
2
+ export declare const CHARACTER_LIMIT = 25000;
3
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,iCAAiC,CAAC;AAC3D,eAAO,MAAM,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export const API_BASE_URL = "https://jules.googleapis.com";
2
+ export const CHARACTER_LIMIT = 25000;
3
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,8BAA8B,CAAC;AAC3D,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { registerListSourcesTool } from "./tools/listSources.js";
5
+ import { registerCreateSessionTool } from "./tools/createSession.js";
6
+ import { registerListSessionsTool } from "./tools/listSessions.js";
7
+ import { registerApprovePlanTool } from "./tools/approvePlan.js";
8
+ const server = new McpServer({
9
+ name: "jules-mcp-server",
10
+ version: "1.0.0",
11
+ });
12
+ // Register all tools
13
+ registerListSourcesTool(server);
14
+ registerCreateSessionTool(server);
15
+ registerListSessionsTool(server);
16
+ registerApprovePlanTool(server);
17
+ async function runStdio() {
18
+ if (!process.env.JULES_API_KEY) {
19
+ console.error("ERROR: JULES_API_KEY environment variable is required to authenticate with the Jules API.");
20
+ process.exit(1);
21
+ }
22
+ const transport = new StdioServerTransport();
23
+ await server.connect(transport);
24
+ console.error("Jules MCP server running via stdio");
25
+ }
26
+ runStdio().catch((error) => {
27
+ console.error("Server error:", error);
28
+ process.exit(1);
29
+ });
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IACzB,IAAI,EAAE,kBAAkB;IACxB,OAAO,EAAE,OAAO;CACnB,CAAC,CAAC;AAEH,qBAAqB;AACrB,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAChC,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAClC,wBAAwB,CAAC,MAAM,CAAC,CAAC;AACjC,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAEhC,KAAK,UAAU,QAAQ;IACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,2FAA2F,CAAC,CAAC;QAC3G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACxD,CAAC;AAED,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACvB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ export declare enum ResponseFormat {
3
+ MARKDOWN = "markdown",
4
+ JSON = "json"
5
+ }
6
+ export declare const PaginationSchema: z.ZodObject<{
7
+ pageSize: z.ZodDefault<z.ZodNumber>;
8
+ pageToken: z.ZodOptional<z.ZodString>;
9
+ response_format: z.ZodDefault<z.ZodEnum<typeof ResponseFormat>>;
10
+ }, z.core.$strip>;
11
+ export declare const ListSourcesInputSchema: z.ZodObject<{
12
+ pageSize: z.ZodDefault<z.ZodNumber>;
13
+ pageToken: z.ZodOptional<z.ZodString>;
14
+ response_format: z.ZodDefault<z.ZodEnum<typeof ResponseFormat>>;
15
+ }, z.core.$strip>;
16
+ export type ListSourcesInput = z.infer<typeof ListSourcesInputSchema>;
17
+ export declare const CreateSessionInputSchema: z.ZodObject<{
18
+ prompt: z.ZodString;
19
+ source: z.ZodString;
20
+ startingBranch: z.ZodDefault<z.ZodString>;
21
+ automationMode: z.ZodDefault<z.ZodEnum<{
22
+ AUTO_CREATE_PR: "AUTO_CREATE_PR";
23
+ NONE: "NONE";
24
+ }>>;
25
+ title: z.ZodString;
26
+ requirePlanApproval: z.ZodDefault<z.ZodBoolean>;
27
+ response_format: z.ZodDefault<z.ZodEnum<typeof ResponseFormat>>;
28
+ }, z.core.$strip>;
29
+ export type CreateSessionInput = z.infer<typeof CreateSessionInputSchema>;
30
+ export declare const ListSessionsInputSchema: z.ZodObject<{
31
+ pageSize: z.ZodDefault<z.ZodNumber>;
32
+ pageToken: z.ZodOptional<z.ZodString>;
33
+ response_format: z.ZodDefault<z.ZodEnum<typeof ResponseFormat>>;
34
+ }, z.core.$strip>;
35
+ export type ListSessionsInput = z.infer<typeof ListSessionsInputSchema>;
36
+ export declare const ApprovePlanInputSchema: z.ZodObject<{
37
+ sessionId: z.ZodString;
38
+ response_format: z.ZodDefault<z.ZodEnum<typeof ResponseFormat>>;
39
+ }, z.core.$strip>;
40
+ export type ApprovePlanInput = z.infer<typeof ApprovePlanInputSchema>;
41
+ //# sourceMappingURL=julesSchemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"julesSchemas.d.ts","sourceRoot":"","sources":["../../src/schemas/julesSchemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,oBAAY,cAAc;IACtB,QAAQ,aAAa;IACrB,IAAI,SAAS;CAChB;AAGD,eAAO,MAAM,gBAAgB;;;;iBAI3B,CAAC;AAGH,eAAO,MAAM,sBAAsB;;;;iBAAmB,CAAC;AACvD,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAGtE,eAAO,MAAM,wBAAwB;;;;;;;;;;;iBAQnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAG1E,eAAO,MAAM,uBAAuB;;;;iBAAmB,CAAC;AACxD,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAGxE,eAAO,MAAM,sBAAsB;;;iBAGjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ // --- Enums ---
3
+ export var ResponseFormat;
4
+ (function (ResponseFormat) {
5
+ ResponseFormat["MARKDOWN"] = "markdown";
6
+ ResponseFormat["JSON"] = "json";
7
+ })(ResponseFormat || (ResponseFormat = {}));
8
+ // --- Common ---
9
+ export const PaginationSchema = z.object({
10
+ pageSize: z.number().int().min(1).max(100).default(20).describe("Maximum results to return"),
11
+ pageToken: z.string().optional().describe("Page token for retrieving the next page"),
12
+ response_format: z.nativeEnum(ResponseFormat).default(ResponseFormat.MARKDOWN).describe("Output format: 'markdown' or 'json'"),
13
+ });
14
+ // --- jules_list_sources ---
15
+ export const ListSourcesInputSchema = PaginationSchema;
16
+ // --- jules_create_session ---
17
+ export const CreateSessionInputSchema = z.object({
18
+ prompt: z.string().describe("The user's goal or prompt for the session."),
19
+ source: z.string().describe("The name of the source resource (e.g., 'sources/github/owner/repo')."),
20
+ startingBranch: z.string().default("main").describe("The starting branch for the repository."),
21
+ automationMode: z.enum(["AUTO_CREATE_PR", "NONE"]).default("NONE").describe("Whether to automatically create a PR ('AUTO_CREATE_PR' or 'NONE')."),
22
+ title: z.string().describe("The title of the session."),
23
+ requirePlanApproval: z.boolean().default(false).describe("If true, requires an explicit call to approve_plan to proceed."),
24
+ response_format: z.nativeEnum(ResponseFormat).default(ResponseFormat.MARKDOWN).describe("Output format: 'markdown' or 'json'"),
25
+ });
26
+ // --- jules_list_sessions ---
27
+ export const ListSessionsInputSchema = PaginationSchema;
28
+ // --- jules_approve_plan ---
29
+ export const ApprovePlanInputSchema = z.object({
30
+ sessionId: z.string().describe("The session ID or resource name (e.g., 'sessions/12345')."),
31
+ response_format: z.nativeEnum(ResponseFormat).default(ResponseFormat.MARKDOWN).describe("Output format: 'markdown' or 'json'"),
32
+ });
33
+ //# sourceMappingURL=julesSchemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"julesSchemas.js","sourceRoot":"","sources":["../../src/schemas/julesSchemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gBAAgB;AAChB,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACtB,uCAAqB,CAAA;IACrB,+BAAa,CAAA;AACjB,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB;AAED,iBAAiB;AACjB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC;IAC5F,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;IACpF,eAAe,EAAE,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,qCAAqC,CAAC;CACjI,CAAC,CAAC;AAEH,6BAA6B;AAC7B,MAAM,CAAC,MAAM,sBAAsB,GAAG,gBAAgB,CAAC;AAGvD,+BAA+B;AAC/B,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;IACzE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sEAAsE,CAAC;IACnG,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,yCAAyC,CAAC;IAC9F,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,oEAAoE,CAAC;IACjJ,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;IACvD,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,gEAAgE,CAAC;IAC1H,eAAe,EAAE,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,qCAAqC,CAAC;CACjI,CAAC,CAAC;AAGH,8BAA8B;AAC9B,MAAM,CAAC,MAAM,uBAAuB,GAAG,gBAAgB,CAAC;AAGxD,6BAA6B;AAC7B,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;IAC3F,eAAe,EAAE,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,qCAAqC,CAAC;CACjI,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Make an authenticated request to the Jules API.
3
+ */
4
+ export declare function julesApiRequest<T>(endpoint: string, method?: "GET" | "POST" | "PUT" | "DELETE", data?: any, params?: any): Promise<T>;
5
+ /**
6
+ * Helper to extract an actionable error message.
7
+ */
8
+ export declare function handleApiError(error: unknown): string;
9
+ //# sourceMappingURL=julesApiClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"julesApiClient.d.ts","sourceRoot":"","sources":["../../src/services/julesApiClient.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACnC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAgB,EACjD,IAAI,CAAC,EAAE,GAAG,EACV,MAAM,CAAC,EAAE,GAAG,GACb,OAAO,CAAC,CAAC,CAAC,CAuBZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CA4BrD"}
@@ -0,0 +1,63 @@
1
+ import axios, { AxiosError } from "axios";
2
+ import { API_BASE_URL } from "../constants.js";
3
+ /**
4
+ * Make an authenticated request to the Jules API.
5
+ */
6
+ export async function julesApiRequest(endpoint, method = "GET", data, params) {
7
+ const apiKey = process.env.JULES_API_KEY;
8
+ if (!apiKey) {
9
+ throw new Error("JULES_API_KEY environment variable is missing.");
10
+ }
11
+ try {
12
+ const response = await axios({
13
+ method,
14
+ url: `${API_BASE_URL}${endpoint.startsWith("/") ? endpoint : `/${endpoint}`}`,
15
+ data,
16
+ params,
17
+ timeout: 30000,
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ "Accept": "application/json",
21
+ "X-Goog-Api-Key": apiKey,
22
+ },
23
+ });
24
+ return response.data;
25
+ }
26
+ catch (error) {
27
+ throw error;
28
+ }
29
+ }
30
+ /**
31
+ * Helper to extract an actionable error message.
32
+ */
33
+ export function handleApiError(error) {
34
+ if (error instanceof Error && error.message.includes("JULES_API_KEY")) {
35
+ return error.message;
36
+ }
37
+ if (error instanceof AxiosError) {
38
+ if (error.response) {
39
+ const status = error.response.status;
40
+ const data = error.response.data;
41
+ const detail = data?.error?.message || JSON.stringify(data) || "No additional error info from server.";
42
+ switch (status) {
43
+ case 400:
44
+ return `Error: Bad Request (400). Check the parameters. Detail: ${detail}`;
45
+ case 401:
46
+ return `Error: Unauthorized (401). Ensure JULES_API_KEY is correct. Detail: ${detail}`;
47
+ case 403:
48
+ return `Error: Forbidden (403). You don't have access to this resource. Detail: ${detail}`;
49
+ case 404:
50
+ return `Error: Not Found (404). The requested resource doesn't exist. Detail: ${detail}`;
51
+ case 429:
52
+ return `Error: Rate limit exceeded (429). Please wait before making more requests. Detail: ${detail}`;
53
+ default:
54
+ return `Error: API request failed with status ${status}. Detail: ${detail}`;
55
+ }
56
+ }
57
+ else if (error.code === "ECONNABORTED") {
58
+ return "Error: Request timed out. Please try again.";
59
+ }
60
+ }
61
+ return `Error: Unexpected error occurred: ${error instanceof Error ? error.message : String(error)}`;
62
+ }
63
+ //# sourceMappingURL=julesApiClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"julesApiClient.js","sourceRoot":"","sources":["../../src/services/julesApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACjC,QAAgB,EAChB,SAA4C,KAAK,EACjD,IAAU,EACV,MAAY;IAEZ,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC;YACzB,MAAM;YACN,GAAG,EAAE,GAAG,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,EAAE;YAC7E,IAAI;YACJ,MAAM;YACN,OAAO,EAAE,KAAK;YACd,OAAO,EAAE;gBACL,cAAc,EAAE,kBAAkB;gBAClC,QAAQ,EAAE,kBAAkB;gBAC5B,gBAAgB,EAAE,MAAM;aAC3B;SACJ,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IACzC,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACpE,OAAO,KAAK,CAAC,OAAO,CAAC;IACzB,CAAC;IACD,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAC9B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YACrC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,uCAAuC,CAAC;YACvG,QAAQ,MAAM,EAAE,CAAC;gBACb,KAAK,GAAG;oBACJ,OAAO,2DAA2D,MAAM,EAAE,CAAC;gBAC/E,KAAK,GAAG;oBACJ,OAAO,uEAAuE,MAAM,EAAE,CAAC;gBAC3F,KAAK,GAAG;oBACJ,OAAO,2EAA2E,MAAM,EAAE,CAAC;gBAC/F,KAAK,GAAG;oBACJ,OAAO,yEAAyE,MAAM,EAAE,CAAC;gBAC7F,KAAK,GAAG;oBACJ,OAAO,sFAAsF,MAAM,EAAE,CAAC;gBAC1G;oBACI,OAAO,yCAAyC,MAAM,aAAa,MAAM,EAAE,CAAC;YACpF,CAAC;QACL,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACvC,OAAO,6CAA6C,CAAC;QACzD,CAAC;IACL,CAAC;IACD,OAAO,qCAAqC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACzG,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Registers the jules_approve_plan tool with the given MCP server.
4
+ */
5
+ export declare function registerApprovePlanTool(server: McpServer): void;
6
+ //# sourceMappingURL=approvePlan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvePlan.d.ts","sourceRoot":"","sources":["../../src/tools/approvePlan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,QAkDxD"}
@@ -0,0 +1,52 @@
1
+ import { handleApiError, julesApiRequest } from "../services/julesApiClient.js";
2
+ import { ApprovePlanInputSchema, ResponseFormat } from "../schemas/julesSchemas.js";
3
+ /**
4
+ * Registers the jules_approve_plan tool with the given MCP server.
5
+ */
6
+ export function registerApprovePlanTool(server) {
7
+ server.registerTool("jules_approve_plan", {
8
+ title: "Approve Jules Session Plan",
9
+ description: `Approve the plan for a session that requires explicit approval.
10
+
11
+ If you created a session with requirePlanApproval: true, Jules will pause and wait for approval. Call this tool to allow it to proceed.
12
+
13
+ Args:
14
+ - sessionId (string): The session ID or name (e.g., "sessions/12345" or "12345").
15
+ - response_format ('markdown' | 'json'): Output format (default: 'markdown').
16
+
17
+ Returns:
18
+ Status of the approval.`,
19
+ inputSchema: ApprovePlanInputSchema,
20
+ annotations: {
21
+ readOnlyHint: false,
22
+ destructiveHint: true, // Approving a plan kicks off mutations in the source repo
23
+ idempotentHint: false,
24
+ openWorldHint: false,
25
+ },
26
+ }, async (params) => {
27
+ try {
28
+ const endpoint = params.sessionId.includes("/")
29
+ ? `/${params.sessionId}:approvePlan`
30
+ : `/v1alpha/sessions/${params.sessionId}:approvePlan`;
31
+ const data = await julesApiRequest(endpoint, "POST", {});
32
+ let textContent;
33
+ if (params.response_format === ResponseFormat.MARKDOWN) {
34
+ textContent = `# Plan Approved\n\nSuccessfully approved plan for session \`${params.sessionId}\`.\n\nYou can use \`jules_list_sessions\` to monitor its progress.`;
35
+ }
36
+ else {
37
+ textContent = JSON.stringify({ success: true, session: params.sessionId, data }, null, 2);
38
+ }
39
+ return {
40
+ content: [{ type: "text", text: textContent }],
41
+ structuredContent: { success: true, session: params.sessionId, data },
42
+ };
43
+ }
44
+ catch (error) {
45
+ return {
46
+ content: [{ type: "text", text: handleApiError(error) }],
47
+ isError: true,
48
+ };
49
+ }
50
+ });
51
+ }
52
+ //# sourceMappingURL=approvePlan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvePlan.js","sourceRoot":"","sources":["../../src/tools/approvePlan.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAoB,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGtG;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACrD,MAAM,CAAC,YAAY,CACf,oBAAoB,EACpB;QACI,KAAK,EAAE,4BAA4B;QACnC,WAAW,EAAE;;;;;;;;;0BASC;QACd,WAAW,EAAE,sBAAsB;QACnC,WAAW,EAAE;YACT,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,IAAI,EAAE,0DAA0D;YACjF,cAAc,EAAE,KAAK;YACrB,aAAa,EAAE,KAAK;SACvB;KACJ,EACD,KAAK,EAAE,MAAwB,EAAE,EAAE;QAC/B,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAC3C,CAAC,CAAC,IAAI,MAAM,CAAC,SAAS,cAAc;gBACpC,CAAC,CAAC,qBAAqB,MAAM,CAAC,SAAS,cAAc,CAAC;YAE1D,MAAM,IAAI,GAAG,MAAM,eAAe,CAAM,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;YAE9D,IAAI,WAAmB,CAAC;YACxB,IAAI,MAAM,CAAC,eAAe,KAAK,cAAc,CAAC,QAAQ,EAAE,CAAC;gBACrD,WAAW,GAAG,+DAA+D,MAAM,CAAC,SAAS,qEAAqE,CAAC;YACvK,CAAC;iBAAM,CAAC;gBACJ,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC9F,CAAC;YAED,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;gBAC9C,iBAAiB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE;aACxE,CAAC;QACN,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxD,OAAO,EAAE,IAAI;aAChB,CAAC;QACN,CAAC;IACL,CAAC,CACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Registers the jules_create_session tool with the given MCP server.
4
+ */
5
+ export declare function registerCreateSessionTool(server: McpServer): void;
6
+ //# sourceMappingURL=createSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSession.d.ts","sourceRoot":"","sources":["../../src/tools/createSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,QA8E1D"}
@@ -0,0 +1,80 @@
1
+ import { handleApiError, julesApiRequest } from "../services/julesApiClient.js";
2
+ import { CreateSessionInputSchema, ResponseFormat } from "../schemas/julesSchemas.js";
3
+ import { CHARACTER_LIMIT } from "../constants.js";
4
+ /**
5
+ * Registers the jules_create_session tool with the given MCP server.
6
+ */
7
+ export function registerCreateSessionTool(server) {
8
+ server.registerTool("jules_create_session", {
9
+ title: "Create Jules Session",
10
+ description: `Starts a new automated coding session with Jules.
11
+
12
+ Use this after identifying a target source (e.g. from jules_list_sources).
13
+ This creates a session where Jules will work on the given prompt.
14
+
15
+ Args:
16
+ - prompt (string): The user's goal or instructions.
17
+ - source (string): The full name of the source (e.g., "sources/github/owner/repo").
18
+ - startingBranch (string): The starting branch for the repository (default: "main").
19
+ - automationMode ("AUTO_CREATE_PR" | "NONE"): Whether to automatically create a PR (default: "NONE").
20
+ - title (string): The title of the session.
21
+ - requirePlanApproval (boolean): If true, implicitly requires an approve_plan call to proceed.
22
+ - response_format ('markdown' | 'json'): Output format (default: 'markdown').
23
+
24
+ Returns:
25
+ The created session details.`,
26
+ inputSchema: CreateSessionInputSchema,
27
+ annotations: {
28
+ readOnlyHint: false,
29
+ destructiveHint: false, // Creating a session itself isn't completely destructive
30
+ idempotentHint: false,
31
+ openWorldHint: false,
32
+ },
33
+ }, async (params) => {
34
+ try {
35
+ const payload = {
36
+ prompt: params.prompt,
37
+ sourceContext: {
38
+ source: params.source,
39
+ githubRepoContext: {
40
+ startingBranch: params.startingBranch,
41
+ },
42
+ },
43
+ automationMode: params.automationMode,
44
+ title: params.title,
45
+ requirePlanApproval: params.requirePlanApproval,
46
+ };
47
+ const data = await julesApiRequest("/v1alpha/sessions", "POST", payload);
48
+ let textContent;
49
+ if (params.response_format === ResponseFormat.MARKDOWN) {
50
+ const lines = [
51
+ `# Created Session: ${data.title || "Untitled"}`,
52
+ "",
53
+ `- **Name/ID**: ${data.name || data.id}`,
54
+ `- **Prompt**: ${data.prompt}`,
55
+ `- **Status**: ${data.state || "PENDING"}`,
56
+ "",
57
+ `You can check the progress of this session using the \`jules_list_sessions\` tool.`,
58
+ ];
59
+ textContent = lines.join("\n");
60
+ }
61
+ else {
62
+ textContent = JSON.stringify(data, null, 2);
63
+ }
64
+ if (textContent.length > CHARACTER_LIMIT) {
65
+ textContent = textContent.slice(0, CHARACTER_LIMIT) + "\n...[truncated]";
66
+ }
67
+ return {
68
+ content: [{ type: "text", text: textContent }],
69
+ structuredContent: data,
70
+ };
71
+ }
72
+ catch (error) {
73
+ return {
74
+ content: [{ type: "text", text: handleApiError(error) }],
75
+ isError: true,
76
+ };
77
+ }
78
+ });
79
+ }
80
+ //# sourceMappingURL=createSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSession.js","sourceRoot":"","sources":["../../src/tools/createSession.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAsB,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC1G,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACvD,MAAM,CAAC,YAAY,CACf,sBAAsB,EACtB;QACI,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE;;;;;;;;;;;;;;;+BAeM;QACnB,WAAW,EAAE,wBAAwB;QACrC,WAAW,EAAE;YACT,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,KAAK,EAAE,yDAAyD;YACjF,cAAc,EAAE,KAAK;YACrB,aAAa,EAAE,KAAK;SACvB;KACJ,EACD,KAAK,EAAE,MAA0B,EAAE,EAAE;QACjC,IAAI,CAAC;YACD,MAAM,OAAO,GAAG;gBACZ,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,aAAa,EAAE;oBACX,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,iBAAiB,EAAE;wBACf,cAAc,EAAE,MAAM,CAAC,cAAc;qBACxC;iBACJ;gBACD,cAAc,EAAE,MAAM,CAAC,cAAc;gBACrC,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;aAClD,CAAC;YAEF,MAAM,IAAI,GAAG,MAAM,eAAe,CAAM,mBAAmB,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAE9E,IAAI,WAAmB,CAAC;YACxB,IAAI,MAAM,CAAC,eAAe,KAAK,cAAc,CAAC,QAAQ,EAAE,CAAC;gBACrD,MAAM,KAAK,GAAG;oBACV,sBAAsB,IAAI,CAAC,KAAK,IAAI,UAAU,EAAE;oBAChD,EAAE;oBACF,kBAAkB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE;oBACxC,iBAAiB,IAAI,CAAC,MAAM,EAAE;oBAC9B,iBAAiB,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE;oBAC1C,EAAE;oBACF,oFAAoF;iBACvF,CAAC;gBACF,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACJ,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAChD,CAAC;YAED,IAAI,WAAW,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;gBACvC,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,kBAAkB,CAAC;YAC7E,CAAC;YAED,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;gBAC9C,iBAAiB,EAAE,IAAI;aAC1B,CAAC;QACN,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxD,OAAO,EAAE,IAAI;aAChB,CAAC;QACN,CAAC;IACL,CAAC,CACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Registers the jules_list_sessions tool with the given MCP server.
4
+ */
5
+ export declare function registerListSessionsTool(server: McpServer): void;
6
+ //# sourceMappingURL=listSessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listSessions.d.ts","sourceRoot":"","sources":["../../src/tools/listSessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,QAgGzD"}
@@ -0,0 +1,95 @@
1
+ import { handleApiError, julesApiRequest } from "../services/julesApiClient.js";
2
+ import { ListSessionsInputSchema, ResponseFormat } from "../schemas/julesSchemas.js";
3
+ import { CHARACTER_LIMIT } from "../constants.js";
4
+ /**
5
+ * Registers the jules_list_sessions tool with the given MCP server.
6
+ */
7
+ export function registerListSessionsTool(server) {
8
+ server.registerTool("jules_list_sessions", {
9
+ title: "List Jules Sessions",
10
+ description: `List your Jules sessions to check their status or view outputs (e.g. PR links).
11
+
12
+ Use this to poll for the completion of a session or to find an active session ID.
13
+
14
+ Args:
15
+ - pageSize (number): Maximum results to return (default: 20)
16
+ - pageToken (string): Page token for retrieving the next page
17
+ - response_format ('markdown' | 'json'): Output format (default: 'markdown')
18
+
19
+ Returns:
20
+ A list of sessions, including their state and any outputs.`,
21
+ inputSchema: ListSessionsInputSchema,
22
+ annotations: {
23
+ readOnlyHint: true,
24
+ destructiveHint: false,
25
+ idempotentHint: true,
26
+ openWorldHint: false,
27
+ },
28
+ }, async (params) => {
29
+ try {
30
+ const queryParams = {
31
+ pageSize: params.pageSize,
32
+ };
33
+ if (params.pageToken) {
34
+ queryParams.pageToken = params.pageToken;
35
+ }
36
+ const data = await julesApiRequest("/v1alpha/sessions", "GET", undefined, queryParams);
37
+ const sessions = data?.sessions || [];
38
+ const nextPageToken = data?.nextPageToken;
39
+ if (!sessions.length) {
40
+ return {
41
+ content: [{ type: "text", text: "No sessions found." }],
42
+ };
43
+ }
44
+ const output = {
45
+ sessions,
46
+ nextPageToken,
47
+ };
48
+ let textContent;
49
+ if (params.response_format === ResponseFormat.MARKDOWN) {
50
+ const lines = [`# Jules Sessions`, ""];
51
+ for (const session of sessions) {
52
+ lines.push(`## ${session.title || 'Untitled'} (${session.name || session.id})`);
53
+ lines.push(`- **State**: ${session.state || "UNKNOWN"}`);
54
+ lines.push(`- **Prompt**: ${session.prompt}`);
55
+ if (session.outputs && session.outputs.length > 0) {
56
+ lines.push(`- **Outputs**:`);
57
+ for (const out of session.outputs) {
58
+ if (out.pullRequest) {
59
+ lines.push(` - Pull Request: [${out.pullRequest.title}](${out.pullRequest.url})`);
60
+ }
61
+ else {
62
+ lines.push(` - ${JSON.stringify(out)}`);
63
+ }
64
+ }
65
+ }
66
+ if (session.pendingPlanApproval) {
67
+ lines.push(`- ⚠️ **Requires Plan Approval**: Use \`jules_approve_plan\` to approve.`);
68
+ }
69
+ lines.push("");
70
+ }
71
+ if (nextPageToken) {
72
+ lines.push(`**Next Page Token**: ${nextPageToken}`);
73
+ }
74
+ textContent = lines.join("\n");
75
+ }
76
+ else {
77
+ textContent = JSON.stringify(output, null, 2);
78
+ }
79
+ if (textContent.length > CHARACTER_LIMIT) {
80
+ textContent = textContent.slice(0, CHARACTER_LIMIT) + "\n...[truncated]";
81
+ }
82
+ return {
83
+ content: [{ type: "text", text: textContent }],
84
+ structuredContent: output,
85
+ };
86
+ }
87
+ catch (error) {
88
+ return {
89
+ content: [{ type: "text", text: handleApiError(error) }],
90
+ isError: true,
91
+ };
92
+ }
93
+ });
94
+ }
95
+ //# sourceMappingURL=listSessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listSessions.js","sourceRoot":"","sources":["../../src/tools/listSessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Registers the jules_list_sources tool with the given MCP server.
4
+ */
5
+ export declare function registerListSourcesTool(server: McpServer): void;
6
+ //# sourceMappingURL=listSources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listSources.d.ts","sourceRoot":"","sources":["../../src/tools/listSources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,QAoFxD"}
@@ -0,0 +1,83 @@
1
+ import { handleApiError, julesApiRequest } from "../services/julesApiClient.js";
2
+ import { ListSourcesInputSchema, ResponseFormat } from "../schemas/julesSchemas.js";
3
+ import { CHARACTER_LIMIT } from "../constants.js";
4
+ /**
5
+ * Registers the jules_list_sources tool with the given MCP server.
6
+ */
7
+ export function registerListSourcesTool(server) {
8
+ server.registerTool("jules_list_sources", {
9
+ title: "List Jules Sources",
10
+ description: `List your available sources connected to Jules (e.g., GitHub repositories).
11
+
12
+ Use this to find the name of the source you want to work with before creating a session.
13
+
14
+ Args:
15
+ - pageSize (number): Maximum results to return (default: 20)
16
+ - pageToken (string): Page token for retrieving the next page
17
+ - response_format ('markdown' | 'json'): Output format (default: 'markdown')
18
+
19
+ Returns:
20
+ A list of sources available to the user.`,
21
+ inputSchema: ListSourcesInputSchema,
22
+ annotations: {
23
+ readOnlyHint: true,
24
+ destructiveHint: false,
25
+ idempotentHint: true,
26
+ openWorldHint: false,
27
+ },
28
+ }, async (params) => {
29
+ try {
30
+ const queryParams = {
31
+ pageSize: params.pageSize,
32
+ };
33
+ if (params.pageToken) {
34
+ queryParams.pageToken = params.pageToken;
35
+ }
36
+ const data = await julesApiRequest("/v1alpha/sources", "GET", undefined, queryParams);
37
+ const sources = data?.sources || [];
38
+ const nextPageToken = data?.nextPageToken;
39
+ if (!sources.length) {
40
+ return {
41
+ content: [{ type: "text", text: "No sources found." }],
42
+ };
43
+ }
44
+ const output = {
45
+ sources,
46
+ nextPageToken,
47
+ };
48
+ let textContent;
49
+ if (params.response_format === ResponseFormat.MARKDOWN) {
50
+ const lines = [`# Jules Sources`, ""];
51
+ for (const source of sources) {
52
+ lines.push(`## ${source.name}`);
53
+ lines.push(`- **ID**: ${source.id}`);
54
+ if (source.githubRepo) {
55
+ lines.push(`- **GitHub Repo**: ${source.githubRepo.owner}/${source.githubRepo.repo}`);
56
+ }
57
+ lines.push("");
58
+ }
59
+ if (nextPageToken) {
60
+ lines.push(`**Next Page Token**: ${nextPageToken}`);
61
+ }
62
+ textContent = lines.join("\n");
63
+ }
64
+ else {
65
+ textContent = JSON.stringify(output, null, 2);
66
+ }
67
+ if (textContent.length > CHARACTER_LIMIT) {
68
+ textContent = textContent.slice(0, CHARACTER_LIMIT) + "\n...[truncated]";
69
+ }
70
+ return {
71
+ content: [{ type: "text", text: textContent }],
72
+ structuredContent: output,
73
+ };
74
+ }
75
+ catch (error) {
76
+ return {
77
+ content: [{ type: "text", text: handleApiError(error) }],
78
+ isError: true,
79
+ };
80
+ }
81
+ });
82
+ }
83
+ //# sourceMappingURL=listSources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listSources.js","sourceRoot":"","sources":["../../src/tools/listSources.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "jules-mcp",
3
+ "version": "1.0.1",
4
+ "description": "MCP server for Jules API integration",
5
+ "type": "module",
6
+ "bin": {
7
+ "jules-mcp": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "main": "dist/index.js",
13
+ "scripts": {
14
+ "start": "node dist/index.js",
15
+ "dev": "tsx watch src/index.ts",
16
+ "build": "tsc",
17
+ "inspector": "npx @modelcontextprotocol/inspector node dist/index.js",
18
+ "clean": "rm -rf dist"
19
+ },
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "dependencies": {
24
+ "@modelcontextprotocol/sdk": "^1.6.1",
25
+ "axios": "^1.7.9",
26
+ "zod": "^3.23.8"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^22.10.0",
30
+ "tsx": "^4.19.2",
31
+ "typescript": "^5.7.2"
32
+ }
33
+ }