standup-mr 0.7.0 → 1.0.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/CHANGELOG.md +31 -0
- package/README.md +56 -3
- package/dist/{chunk-J5LAGA3U.js → chunk-S7DAKN36.js} +4 -1
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp/server.js +46 -21
- package/llms-install.md +5 -0
- package/mcp/README.md +6 -1
- package/package.json +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,37 @@ All notable changes to standup-mr are recorded here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
5
|
[semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.0.0] - 2026-10-12
|
|
8
|
+
|
|
9
|
+
First stable release. From here on the CLI commands and flags, the JSON that
|
|
10
|
+
`fetch` and `get_standup_data` return, the MCP tool names and arguments, and
|
|
11
|
+
the environment variables follow semantic versioning: anything that would
|
|
12
|
+
break an existing setup waits for 2.0.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Remote MCP server for claude.ai.** Add
|
|
17
|
+
`https://standup.ilkerbalcilar.com/mcp` as a custom connector, sign in with
|
|
18
|
+
GitHub or gitlab.com — or paste a token for a self-hosted host — and use
|
|
19
|
+
standup-mr from claude.ai on the web and on mobile, with no environment
|
|
20
|
+
variables. One connector can hold several accounts and an optional chat
|
|
21
|
+
webhook. The server lives in `remote/` and is not part of the npm package.
|
|
22
|
+
- **Sign in to your company's GitLab or GitHub Enterprise.** On the connect
|
|
23
|
+
page, type the host: if someone there already set up sign-in, use it;
|
|
24
|
+
otherwise register an OAuth application once, following the exact redirect
|
|
25
|
+
URI and scopes the page shows, and everyone at that host can sign in from
|
|
26
|
+
then on.
|
|
27
|
+
- `server.json` lists the remote endpoint, so registries show both the npm
|
|
28
|
+
package and the hosted server.
|
|
29
|
+
- Both servers declare the project icon in `serverInfo.icons`.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- GitLab requests send the token as `Authorization: Bearer` instead of
|
|
34
|
+
`PRIVATE-TOKEN`. Personal access tokens work either way, but OAuth tokens —
|
|
35
|
+
from `glab`'s browser login or from the remote server's sign-in — were
|
|
36
|
+
rejected with 401.
|
|
37
|
+
|
|
7
38
|
## [0.7.0] - 2026-10-10
|
|
8
39
|
|
|
9
40
|
### Added
|
package/README.md
CHANGED
|
@@ -66,12 +66,55 @@ So if you already use `gh` or `glab`, there is nothing to configure.
|
|
|
66
66
|
npx standup-mr fetch --markdown | npx standup-mr post --slack "$SLACK_WEBHOOK_URL"
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
##
|
|
69
|
+
## claude.ai (web and mobile)
|
|
70
|
+
|
|
71
|
+
No token, no config file — sign in instead. In claude.ai open **Settings →
|
|
72
|
+
Connectors → Add custom connector** and paste:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
https://standup.ilkerbalcilar.com/mcp
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Press **Connect**. A page opens where you link the accounts the note should
|
|
79
|
+
read:
|
|
80
|
+
|
|
81
|
+
- **GitHub** — sign in through the standup-mr GitHub App. It only sees the
|
|
82
|
+
repositories it is installed on, so install it on your org too; if the org
|
|
83
|
+
won't approve it, add github.com with a fine-grained token instead.
|
|
84
|
+
- **gitlab.com** — sign in with GitLab.
|
|
85
|
+
- **Your company's GitLab or GitHub Enterprise** — type the host. If someone
|
|
86
|
+
at your company already set up sign-in, you get a "Sign in with …" button.
|
|
87
|
+
Otherwise set it up once: the page shows the exact redirect URI and scopes
|
|
88
|
+
for an OAuth application on your host, you paste its ID and secret, and
|
|
89
|
+
everyone at that host can sign in from then on. A read-only token works too.
|
|
90
|
+
- **Chat webhook** _(optional)_ — Slack, Discord or Google Chat, so Claude can
|
|
91
|
+
post the finished note when you ask it to.
|
|
92
|
+
|
|
93
|
+
Link as many as you like — say, GitHub for side projects and your company's
|
|
94
|
+
GitLab for work — then ask for "my standup" or "my work standup". With
|
|
95
|
+
several accounts linked, Claude asks which one you mean.
|
|
96
|
+
|
|
97
|
+
The connector then works from the claude.ai mobile app as well.
|
|
98
|
+
|
|
99
|
+
**What is stored.** Your provider tokens and webhook URL, encrypted with
|
|
100
|
+
AES-256-GCM, and only to read your merge requests and post your note. The
|
|
101
|
+
access tokens Claude holds are stored as hashes. Disconnecting the connector
|
|
102
|
+
deletes everything; connections unused for 30 days are deleted. The server is
|
|
103
|
+
the code in [`remote/`](remote/).
|
|
104
|
+
|
|
105
|
+
**When to use the local server instead.** A GitLab behind a VPN or on a
|
|
106
|
+
private network is out of reach of a hosted server. Run the stdio server
|
|
107
|
+
below on your own machine — the token never leaves it.
|
|
108
|
+
|
|
109
|
+
## The four surfaces
|
|
70
110
|
|
|
71
111
|
**CLI** — the core. Emits JSON; zero runtime dependencies.
|
|
72
112
|
|
|
73
|
-
**MCP server** (`mcp/`) —
|
|
74
|
-
|
|
113
|
+
**MCP server** (`mcp/`) — three tools for Claude Desktop, Claude Code, Cursor,
|
|
114
|
+
or any MCP client that runs a local process. See [`mcp/README.md`](mcp/README.md).
|
|
115
|
+
|
|
116
|
+
**Remote MCP server** (`remote/`) — the same tools over HTTPS with sign-in, for
|
|
117
|
+
claude.ai on the web and on mobile. See [above](#claudeai-web-and-mobile).
|
|
75
118
|
|
|
76
119
|
**Claude Code plugin** — the note-writing playbook, shipped as the `standup`
|
|
77
120
|
skill. From inside Claude Code:
|
|
@@ -205,6 +248,16 @@ that pipeline is red; this one opens the failed job's log and shows you the
|
|
|
205
248
|
404 — and a 404 rather than a 403 usually means the token's scope is wrong, not
|
|
206
249
|
that the package is missing.
|
|
207
250
|
|
|
251
|
+
## Stability
|
|
252
|
+
|
|
253
|
+
Since 1.0.0 the CLI commands and flags, the JSON that `fetch` and
|
|
254
|
+
`get_standup_data` return, the MCP tool names and arguments, and the
|
|
255
|
+
environment variables follow [semantic versioning](https://semver.org/): a
|
|
256
|
+
change that would break an existing setup waits for a major release. New
|
|
257
|
+
fields in the JSON may appear in minor releases, so read it by name rather
|
|
258
|
+
than by position. The hosted server at `standup.ilkerbalcilar.com` is
|
|
259
|
+
updated continuously and is not tied to the npm version.
|
|
260
|
+
|
|
208
261
|
## Known limits
|
|
209
262
|
|
|
210
263
|
- **GitHub's events feed is shallow.** It is capped at roughly 300 events over
|
|
@@ -810,7 +810,10 @@ var GitLabProvider = class {
|
|
|
810
810
|
const response = await sendWithRetry(
|
|
811
811
|
this.fetchImpl,
|
|
812
812
|
url,
|
|
813
|
-
|
|
813
|
+
// Bearer, not PRIVATE-TOKEN: GitLab accepts personal access tokens
|
|
814
|
+
// either way, but OAuth tokens — glab's browser login, and the
|
|
815
|
+
// remote server's sign-in — only as a bearer.
|
|
816
|
+
{ headers: { Authorization: `Bearer ${this.token}` } },
|
|
814
817
|
this.host
|
|
815
818
|
);
|
|
816
819
|
assertUsable(response, this.host);
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/dist/mcp/server.js
CHANGED
|
@@ -842,7 +842,10 @@ var GitLabProvider = class {
|
|
|
842
842
|
const response = await sendWithRetry(
|
|
843
843
|
this.fetchImpl,
|
|
844
844
|
url,
|
|
845
|
-
|
|
845
|
+
// Bearer, not PRIVATE-TOKEN: GitLab accepts personal access tokens
|
|
846
|
+
// either way, but OAuth tokens — glab's browser login, and the
|
|
847
|
+
// remote server's sign-in — only as a bearer.
|
|
848
|
+
{ headers: { Authorization: `Bearer ${this.token}` } },
|
|
846
849
|
this.host
|
|
847
850
|
);
|
|
848
851
|
assertUsable(response, this.host);
|
|
@@ -1277,22 +1280,48 @@ async function runPostTool(args, deps = {}) {
|
|
|
1277
1280
|
async function runInstructionsTool() {
|
|
1278
1281
|
return text(readStandupSkillBody());
|
|
1279
1282
|
}
|
|
1283
|
+
var STANDUP_TOOL_ANNOTATIONS = {
|
|
1284
|
+
readOnlyHint: true,
|
|
1285
|
+
destructiveHint: false,
|
|
1286
|
+
idempotentHint: true,
|
|
1287
|
+
openWorldHint: true
|
|
1288
|
+
};
|
|
1289
|
+
var POST_TOOL_ANNOTATIONS = {
|
|
1290
|
+
readOnlyHint: false,
|
|
1291
|
+
destructiveHint: false,
|
|
1292
|
+
idempotentHint: false,
|
|
1293
|
+
openWorldHint: true
|
|
1294
|
+
};
|
|
1295
|
+
var INSTRUCTIONS_TOOL_ANNOTATIONS = {
|
|
1296
|
+
readOnlyHint: true,
|
|
1297
|
+
destructiveHint: false,
|
|
1298
|
+
idempotentHint: true,
|
|
1299
|
+
openWorldHint: false
|
|
1300
|
+
};
|
|
1301
|
+
var SERVER_ICONS = [
|
|
1302
|
+
{
|
|
1303
|
+
src: "https://raw.githubusercontent.com/Jubstaaa/standup-mr/main/assets/icon-512.png",
|
|
1304
|
+
mimeType: "image/png",
|
|
1305
|
+
sizes: ["512x512"]
|
|
1306
|
+
},
|
|
1307
|
+
{
|
|
1308
|
+
src: "https://raw.githubusercontent.com/Jubstaaa/standup-mr/main/assets/icon.svg",
|
|
1309
|
+
mimeType: "image/svg+xml",
|
|
1310
|
+
sizes: ["any"]
|
|
1311
|
+
}
|
|
1312
|
+
];
|
|
1280
1313
|
function createServer() {
|
|
1281
1314
|
const server = new McpServer({
|
|
1282
1315
|
name: "standup-mr",
|
|
1283
|
-
version: packageVersion(import.meta.url)
|
|
1316
|
+
version: packageVersion(import.meta.url),
|
|
1317
|
+
icons: SERVER_ICONS
|
|
1284
1318
|
});
|
|
1285
1319
|
server.registerTool(
|
|
1286
1320
|
"get_standup_data",
|
|
1287
1321
|
{
|
|
1288
1322
|
description: STANDUP_TOOL_DESCRIPTION,
|
|
1289
1323
|
inputSchema: STANDUP_TOOL_SCHEMA,
|
|
1290
|
-
annotations:
|
|
1291
|
-
readOnlyHint: true,
|
|
1292
|
-
destructiveHint: false,
|
|
1293
|
-
idempotentHint: true,
|
|
1294
|
-
openWorldHint: true
|
|
1295
|
-
}
|
|
1324
|
+
annotations: STANDUP_TOOL_ANNOTATIONS
|
|
1296
1325
|
},
|
|
1297
1326
|
async (args) => await runStandupTool(args)
|
|
1298
1327
|
);
|
|
@@ -1301,12 +1330,7 @@ function createServer() {
|
|
|
1301
1330
|
{
|
|
1302
1331
|
description: POST_TOOL_DESCRIPTION,
|
|
1303
1332
|
inputSchema: POST_TOOL_SCHEMA,
|
|
1304
|
-
annotations:
|
|
1305
|
-
readOnlyHint: false,
|
|
1306
|
-
destructiveHint: false,
|
|
1307
|
-
idempotentHint: false,
|
|
1308
|
-
openWorldHint: true
|
|
1309
|
-
}
|
|
1333
|
+
annotations: POST_TOOL_ANNOTATIONS
|
|
1310
1334
|
},
|
|
1311
1335
|
async (args) => await runPostTool(args)
|
|
1312
1336
|
);
|
|
@@ -1314,12 +1338,7 @@ function createServer() {
|
|
|
1314
1338
|
"get_note_instructions",
|
|
1315
1339
|
{
|
|
1316
1340
|
description: INSTRUCTIONS_TOOL_DESCRIPTION,
|
|
1317
|
-
annotations:
|
|
1318
|
-
readOnlyHint: true,
|
|
1319
|
-
destructiveHint: false,
|
|
1320
|
-
idempotentHint: true,
|
|
1321
|
-
openWorldHint: false
|
|
1322
|
-
}
|
|
1341
|
+
annotations: INSTRUCTIONS_TOOL_ANNOTATIONS
|
|
1323
1342
|
},
|
|
1324
1343
|
async () => await runInstructionsTool()
|
|
1325
1344
|
);
|
|
@@ -1345,16 +1364,22 @@ if (entryUrl && import.meta.url === entryUrl) {
|
|
|
1345
1364
|
});
|
|
1346
1365
|
}
|
|
1347
1366
|
export {
|
|
1367
|
+
INSTRUCTIONS_TOOL_ANNOTATIONS,
|
|
1348
1368
|
INSTRUCTIONS_TOOL_DESCRIPTION,
|
|
1369
|
+
POST_TOOL_ANNOTATIONS,
|
|
1349
1370
|
POST_TOOL_DESCRIPTION,
|
|
1350
1371
|
POST_TOOL_SCHEMA,
|
|
1372
|
+
SERVER_ICONS,
|
|
1373
|
+
STANDUP_TOOL_ANNOTATIONS,
|
|
1351
1374
|
STANDUP_TOOL_DESCRIPTION,
|
|
1352
1375
|
STANDUP_TOOL_SCHEMA,
|
|
1353
1376
|
WEBHOOK_URL_ENV,
|
|
1354
1377
|
collect,
|
|
1355
1378
|
createServer,
|
|
1379
|
+
failure,
|
|
1356
1380
|
main,
|
|
1357
1381
|
runInstructionsTool,
|
|
1358
1382
|
runPostTool,
|
|
1359
|
-
runStandupTool
|
|
1383
|
+
runStandupTool,
|
|
1384
|
+
text
|
|
1360
1385
|
};
|
package/llms-install.md
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
Instructions for an AI assistant setting this MCP server up on a user's
|
|
4
4
|
machine. Everything here is verified against the published package.
|
|
5
5
|
|
|
6
|
+
If the user is on claude.ai (web or mobile) rather than a client that runs
|
|
7
|
+
local processes, none of this applies: tell them to add
|
|
8
|
+
`https://standup.ilkerbalcilar.com/mcp` under Settings → Connectors → Add custom
|
|
9
|
+
connector and sign in on the page that opens.
|
|
10
|
+
|
|
6
11
|
## What it needs
|
|
7
12
|
|
|
8
13
|
- Node.js 20 or newer. Nothing to clone, nothing to build — the server runs
|
package/mcp/README.md
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
# MCP server
|
|
2
2
|
|
|
3
|
-
Exposes
|
|
3
|
+
Exposes three tools — `get_standup_data`, `get_note_instructions` and
|
|
4
|
+
`post_standup_note` — for either GitLab or GitHub. `get_standup_data` returns
|
|
4
5
|
the same JSON as `standup fetch`.
|
|
5
6
|
|
|
7
|
+
This is the local, stdio server: it runs on your machine and reads tokens from
|
|
8
|
+
its environment. On claude.ai (web or mobile), use the hosted connector instead
|
|
9
|
+
— see [claude.ai (web and mobile)](../README.md#claudeai-web-and-mobile).
|
|
10
|
+
|
|
6
11
|
## Configure
|
|
7
12
|
|
|
8
13
|
GitLab:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "standup-mr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"mcpName": "io.github.Jubstaaa/standup-mr",
|
|
5
5
|
"description": "Standup notes from merge request state, not commit logs.",
|
|
6
6
|
"keywords": [
|
|
@@ -53,6 +53,9 @@
|
|
|
53
53
|
"CHANGELOG.md",
|
|
54
54
|
"LICENSE"
|
|
55
55
|
],
|
|
56
|
+
"workspaces": [
|
|
57
|
+
"remote"
|
|
58
|
+
],
|
|
56
59
|
"scripts": {
|
|
57
60
|
"build": "tsup",
|
|
58
61
|
"lint": "eslint .",
|
|
@@ -64,8 +67,8 @@
|
|
|
64
67
|
"prepublishOnly": "tsup"
|
|
65
68
|
},
|
|
66
69
|
"dependencies": {
|
|
67
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
68
|
-
"zod": "^4.
|
|
70
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
71
|
+
"zod": "^4.6.6"
|
|
69
72
|
},
|
|
70
73
|
"devDependencies": {
|
|
71
74
|
"@eslint/js": "^9.39.1",
|