@joe-broadhead/opencode-granola 0.0.2 → 0.0.4

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/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
+ ## [0.0.4] - 2026-11-04
6
+
7
+ ### Added
8
+
9
+ - Jelly shows the plugin's one-line summary and icon. The package declares them in its `jelly` section and ships the
10
+ icon as `assets/icon.svg`.
11
+
12
+ ## [0.0.3] - 2026-11-04
13
+
14
+ ### Added
15
+
16
+ - A `jelly` section in `package.json`, which [Jelly](https://heyjelly.ai) reads without loading the plugin:
17
+ - Granola's 10 reads (they run), its 7 writes and `export_markdown` (they ask), each with its permission and
18
+ whether it only reads, so that Jelly's agents, which have no base allow rule for the plugin's default rules to
19
+ follow, still ask before a write;
20
+ - the skill ids, the name Jelly shows on the plugin's card, and the `granola` server's sign-in.
21
+
22
+ [docs/jelly.md](https://github.com/joe-broadhead/opencode-granola/blob/HEAD/docs/jelly.md) explains each part.
23
+
5
24
  ## [0.0.2] - 2026-11-04
6
25
 
7
26
  ### Added
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48"><rect width="48" height="48" rx="12" fill="#3E6B2F"/><path d="M24 25a2 2 0 0 1 4 0a4 4 0 0 1 -8 0a6 6 0 0 1 12 0a8 8 0 0 1 -16 0a10 10 0 0 1 20 0" fill="none" stroke="#D8F0A6" stroke-width="3" stroke-linecap="round"/></svg>
package/dist/index.js CHANGED
@@ -505,6 +505,7 @@ var DESCRIBED = object(
505
505
  description: STRING,
506
506
  available: { type: "boolean" },
507
507
  reason: STRING,
508
+ detail: STRING,
508
509
  input: ANY_OBJECT,
509
510
  output: ANY_OBJECT
510
511
  },
@@ -638,12 +639,15 @@ async function registerToolsRpc(ctx, options) {
638
639
  const rules = [...agent.data.permissions, ...info.permissions ?? []];
639
640
  return { agent: info.agent, rules };
640
641
  };
642
+ const notRegistered = (server) => mcp?.notRegistered?.(server);
641
643
  const unavailable = async (server, tool, connected) => {
642
644
  const status = (await ctx.mcp.list()).data.find((entry) => entry.name === server)?.status.status;
643
645
  const code2 = connection(status) ?? connected;
644
646
  if (code2 === "TOOL_UNAVAILABLE") return fail(code2, `OpenCode does not list ${tool} on the connected "${server}" server`);
645
647
  if (status === "connected") return fail(code2, `the "${server}" server was reconnecting when ${tool} ran`);
646
- return fail(code2, `the "${server}" server ${STATUS_TEXT[code2] ?? "is unavailable"}`);
648
+ const what = `the "${server}" server ${STATUS_TEXT[code2] ?? "is unavailable"}`;
649
+ const own = code2 === "NOT_REGISTERED" ? notRegistered(server) : void 0;
650
+ return own ? new ScriptError({ code: own.code, what, next: own.next }) : fail(code2, what);
647
651
  };
648
652
  const denied = (action, error, asked = action) => {
649
653
  const reason = upstreamText(record2(error) && typeof error["message"] === "string" ? error["message"] : String(error));
@@ -675,11 +679,15 @@ async function registerToolsRpc(ctx, options) {
675
679
  }
676
680
  };
677
681
  };
678
- const ownedTarget = (spec, envelope2) => ({
679
- action: spec.action,
680
- mcp: false,
681
- run: async (call) => await spec.run(envelope2.input, call) ?? null
682
- });
682
+ const ownedTarget = (spec, envelope2) => {
683
+ if (accounts) serverOf(envelope2.account);
684
+ const account = accounts && envelope2.account !== void 0 ? { account: envelope2.account } : {};
685
+ return {
686
+ action: spec.action,
687
+ mcp: false,
688
+ run: async (call) => await spec.run(envelope2.input, { ...call, ...account }) ?? null
689
+ };
690
+ };
683
691
  const invoke = async (target, raw, context) => {
684
692
  const envelope2 = raw;
685
693
  let method;
@@ -732,7 +740,9 @@ async function registerToolsRpc(ctx, options) {
732
740
  for (const name of KNOWN_READS) {
733
741
  const id = `${server}_${name}`;
734
742
  const tool = managed ? tools.find((entry) => entry.id === id) : void 0;
735
- const reason = !managed ? "SERVER_CONFLICT" : tool ? void 0 : connection(status) ?? "TOOL_UNAVAILABLE";
743
+ const code2 = !managed ? "SERVER_CONFLICT" : tool ? void 0 : connection(status) ?? "TOOL_UNAVAILABLE";
744
+ const reason = code2 === "NOT_REGISTERED" ? notRegistered(server)?.code ?? code2 : code2;
745
+ const detail = code2 === void 0 ? void 0 : mcp.unavailableDetail?.(name, code2);
736
746
  const input = jsonSchema(tool?.input) ?? ANY_OBJECT;
737
747
  const output = jsonSchema(tool?.output);
738
748
  methods.push({
@@ -743,6 +753,7 @@ async function registerToolsRpc(ctx, options) {
743
753
  description: tool?.description ?? "",
744
754
  available: reason === void 0,
745
755
  ...reason ? { reason } : {},
756
+ ...detail === void 0 ? {} : { detail },
746
757
  input,
747
758
  output: mcpOutput(output)
748
759
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joe-broadhead/opencode-granola",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Unofficial OpenCode plugin for Granola meeting notes, through Granola's official MCP server",
5
5
  "keywords": [
6
6
  "opencode",
@@ -23,6 +23,7 @@
23
23
  },
24
24
  "files": [
25
25
  "dist",
26
+ "assets/icon.svg",
26
27
  "skills",
27
28
  "README.md",
28
29
  "LICENSE",
@@ -55,5 +56,139 @@
55
56
  "typescript": "5.9.3",
56
57
  "vitest": "5.0.5",
57
58
  "web-tree-sitter": "0.25.10"
59
+ },
60
+ "jelly": {
61
+ "title": "Granola",
62
+ "summary": "Your Granola meetings and notes.",
63
+ "icon": "assets/icon.svg",
64
+ "tools": [
65
+ {
66
+ "name": "granola.get_account_info",
67
+ "permission": "granola_get_account_info",
68
+ "effect": "allow",
69
+ "readOnly": true
70
+ },
71
+ {
72
+ "name": "granola.list_meeting_folders",
73
+ "permission": "granola_list_meeting_folders",
74
+ "effect": "allow",
75
+ "readOnly": true
76
+ },
77
+ {
78
+ "name": "granola.list_meetings",
79
+ "permission": "granola_list_meetings",
80
+ "effect": "allow",
81
+ "readOnly": true
82
+ },
83
+ {
84
+ "name": "granola.search_meetings",
85
+ "permission": "granola_search_meetings",
86
+ "effect": "allow",
87
+ "readOnly": true
88
+ },
89
+ {
90
+ "name": "granola.get_meetings",
91
+ "permission": "granola_get_meetings",
92
+ "effect": "allow",
93
+ "readOnly": true
94
+ },
95
+ {
96
+ "name": "granola.get_meeting_transcript",
97
+ "permission": "granola_get_meeting_transcript",
98
+ "effect": "allow",
99
+ "readOnly": true
100
+ },
101
+ {
102
+ "name": "granola.query_granola_meetings",
103
+ "permission": "granola_query_granola_meetings",
104
+ "effect": "allow",
105
+ "readOnly": true
106
+ },
107
+ {
108
+ "name": "granola.get_meeting_attachment",
109
+ "permission": "granola_get_meeting_attachment",
110
+ "effect": "allow",
111
+ "readOnly": true
112
+ },
113
+ {
114
+ "name": "granola.list_templates",
115
+ "permission": "granola_list_templates",
116
+ "effect": "allow",
117
+ "readOnly": true
118
+ },
119
+ {
120
+ "name": "granola.search_transcripts",
121
+ "permission": "granola_search_transcripts",
122
+ "effect": "allow",
123
+ "readOnly": true
124
+ },
125
+ {
126
+ "name": "granola.create_folder",
127
+ "permission": "granola_create_folder",
128
+ "effect": "ask",
129
+ "readOnly": false
130
+ },
131
+ {
132
+ "name": "granola.update_folder",
133
+ "permission": "granola_update_folder",
134
+ "effect": "ask",
135
+ "readOnly": false
136
+ },
137
+ {
138
+ "name": "granola.add_note_to_folder",
139
+ "permission": "granola_add_note_to_folder",
140
+ "effect": "ask",
141
+ "readOnly": false
142
+ },
143
+ {
144
+ "name": "granola.remove_note_from_folder",
145
+ "permission": "granola_remove_note_from_folder",
146
+ "effect": "ask",
147
+ "readOnly": false
148
+ },
149
+ {
150
+ "name": "granola.update_private_notes",
151
+ "permission": "granola_update_private_notes",
152
+ "effect": "ask",
153
+ "readOnly": false
154
+ },
155
+ {
156
+ "name": "granola.generate_summary",
157
+ "permission": "granola_generate_summary",
158
+ "effect": "ask",
159
+ "readOnly": false
160
+ },
161
+ {
162
+ "name": "granola.give_feedback",
163
+ "permission": "granola_give_feedback",
164
+ "effect": "ask",
165
+ "readOnly": false
166
+ },
167
+ {
168
+ "name": "granola.export_markdown",
169
+ "permission": "granola_export_markdown",
170
+ "effect": "ask",
171
+ "readOnly": false
172
+ }
173
+ ],
174
+ "skills": [
175
+ "granola",
176
+ "granola-meeting-brief"
177
+ ],
178
+ "rpc": [],
179
+ "views": [],
180
+ "signIns": [
181
+ {
182
+ "id": "granola",
183
+ "label": "Granola",
184
+ "server": "granola"
185
+ }
186
+ ],
187
+ "contributes": {
188
+ "homeFeeds": [],
189
+ "homeWidgets": [],
190
+ "workKinds": [],
191
+ "settings": []
192
+ }
58
193
  }
59
194
  }