@bragduck/mcp 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/dist/index.js ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { loginTool, handleLogin } from './tools/login.js';
6
+ import { logBragTool, handleLogBrag } from './tools/log-brag.js';
7
+ import { listBragsTool, handleListBrags } from './tools/list-brags.js';
8
+ import { listObjectivesTool, handleListObjectives } from './tools/list-objectives.js';
9
+ import { linkBragToGoalTool, handleLinkBragToGoal } from './tools/link-brag-to-goal.js';
10
+ const server = new Server({
11
+ name: 'bragduck',
12
+ version: '1.0.0',
13
+ }, {
14
+ capabilities: {
15
+ tools: {},
16
+ },
17
+ });
18
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
19
+ return {
20
+ tools: [loginTool, logBragTool, listBragsTool, listObjectivesTool, linkBragToGoalTool],
21
+ };
22
+ });
23
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
24
+ const { name, arguments: args } = request.params;
25
+ switch (name) {
26
+ case 'login':
27
+ return handleLogin(args);
28
+ case 'log_brag':
29
+ return handleLogBrag(args);
30
+ case 'list_brags':
31
+ return handleListBrags(args);
32
+ case 'list_objectives':
33
+ return handleListObjectives();
34
+ case 'link_brag_to_goal':
35
+ return handleLinkBragToGoal(args);
36
+ default:
37
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
38
+ }
39
+ });
40
+ const transport = new StdioServerTransport();
41
+ await server.connect(transport);
42
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,SAAS,EACT,sBAAsB,EACtB,QAAQ,GACT,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAExF,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,EACD;IACE,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;KACV;CACF,CACF,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;IAC1D,OAAO;QACL,KAAK,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;KACvF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAEjD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,WAAW,CAAC,IAAW,CAAC,CAAC;QAClC,KAAK,UAAU;YACb,OAAO,aAAa,CAAC,IAAW,CAAC,CAAC;QACpC,KAAK,YAAY;YACf,OAAO,eAAe,CAAC,IAAW,CAAC,CAAC;QACtC,KAAK,iBAAiB;YACpB,OAAO,oBAAoB,EAAE,CAAC;QAChC,KAAK,mBAAmB;YACtB,OAAO,oBAAoB,CAAC,IAAW,CAAC,CAAC;QAC3C;YACE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,iBAAiB,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ export declare const linkBragToGoalTool: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ bragId: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ goalId: {
12
+ type: string;
13
+ description: string;
14
+ };
15
+ };
16
+ required: string[];
17
+ };
18
+ };
19
+ interface LinkBragInput {
20
+ bragId: string;
21
+ goalId: string;
22
+ }
23
+ export declare function handleLinkBragToGoal(input: LinkBragInput): Promise<{
24
+ content: Array<{
25
+ type: string;
26
+ text: string;
27
+ }>;
28
+ isError?: boolean;
29
+ }>;
30
+ export {};
@@ -0,0 +1,64 @@
1
+ import { apiRequest } from '../api-client.js';
2
+ import { getUserInfo } from '../credentials.js';
3
+ export const linkBragToGoalTool = {
4
+ name: 'link_brag_to_goal',
5
+ description: 'Link an existing brag to a goal/key-result. ' +
6
+ 'Use list_objectives to find goal IDs and list_brags to find brag IDs.',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ bragId: {
11
+ type: 'string',
12
+ description: 'The ID of the brag to update',
13
+ },
14
+ goalId: {
15
+ type: 'string',
16
+ description: 'The ID of the goal to link the brag to',
17
+ },
18
+ },
19
+ required: ['bragId', 'goalId'],
20
+ },
21
+ };
22
+ export async function handleLinkBragToGoal(input) {
23
+ try {
24
+ const userInfo = getUserInfo();
25
+ if (!userInfo) {
26
+ return {
27
+ content: [{
28
+ type: 'text',
29
+ text: 'Not authenticated with BragDuck. Please call the "login" tool first.',
30
+ }],
31
+ isError: true,
32
+ };
33
+ }
34
+ await apiRequest(`/v1/users/${userInfo.id}/brags/${input.bragId}`, {
35
+ method: 'PATCH',
36
+ body: { goalId: input.goalId },
37
+ });
38
+ return {
39
+ content: [{
40
+ type: 'text',
41
+ text: `Brag ${input.bragId} linked to goal ${input.goalId}.`,
42
+ }],
43
+ };
44
+ }
45
+ catch (error) {
46
+ if (error instanceof Error && (error.message === 'NOT_AUTHENTICATED' || error.message === 'TOKEN_EXPIRED')) {
47
+ return {
48
+ content: [{
49
+ type: 'text',
50
+ text: 'Not authenticated with BragDuck. Please call the "login" tool first.',
51
+ }],
52
+ isError: true,
53
+ };
54
+ }
55
+ return {
56
+ content: [{
57
+ type: 'text',
58
+ text: `Failed to link brag to goal: ${error instanceof Error ? error.message : String(error)}`,
59
+ }],
60
+ isError: true,
61
+ };
62
+ }
63
+ }
64
+ //# sourceMappingURL=link-brag-to-goal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-brag-to-goal.js","sourceRoot":"","sources":["../../src/tools/link-brag-to-goal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,8CAA8C;QAC9C,uEAAuE;IACzE,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,8BAA8B;aAC5C;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,wCAAwC;aACtD;SACF;QACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;KAC/B;CACF,CAAC;AAOF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAoB;IAEpB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,sEAAsE;qBAC7E,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,CAAC,aAAa,QAAQ,CAAC,EAAE,UAAU,KAAK,CAAC,MAAM,EAAE,EAAE;YACjE,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;SAC/B,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,QAAQ,KAAK,CAAC,MAAM,mBAAmB,KAAK,CAAC,MAAM,GAAG;iBAC7D,CAAC;SACH,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,mBAAmB,IAAI,KAAK,CAAC,OAAO,KAAK,eAAe,CAAC,EAAE,CAAC;YAC3G,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,sEAAsE;qBAC7E,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;iBAC/F,CAAC;YACF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,37 @@
1
+ export declare const listBragsTool: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ limit: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ search: {
12
+ type: string;
13
+ description: string;
14
+ };
15
+ tags: {
16
+ type: string;
17
+ items: {
18
+ type: string;
19
+ };
20
+ description: string;
21
+ };
22
+ };
23
+ };
24
+ };
25
+ interface ListBragsInput {
26
+ limit?: number;
27
+ search?: string;
28
+ tags?: string[];
29
+ }
30
+ export declare function handleListBrags(input: ListBragsInput): Promise<{
31
+ content: Array<{
32
+ type: string;
33
+ text: string;
34
+ }>;
35
+ isError?: boolean;
36
+ }>;
37
+ export {};
@@ -0,0 +1,71 @@
1
+ import { apiRequest } from '../api-client.js';
2
+ export const listBragsTool = {
3
+ name: 'list_brags',
4
+ description: 'List recent brags (career achievements) from BragDuck. ' +
5
+ 'Use this to review past accomplishments, find brags to link to goals, or check recent entries.',
6
+ inputSchema: {
7
+ type: 'object',
8
+ properties: {
9
+ limit: {
10
+ type: 'number',
11
+ description: 'Number of brags to return (default: 10, max: 50)',
12
+ },
13
+ search: {
14
+ type: 'string',
15
+ description: 'Search term to filter brags by title or description',
16
+ },
17
+ tags: {
18
+ type: 'array',
19
+ items: { type: 'string' },
20
+ description: 'Filter brags by tags',
21
+ },
22
+ },
23
+ },
24
+ };
25
+ export async function handleListBrags(input) {
26
+ try {
27
+ const params = {
28
+ limit: String(input.limit || 10),
29
+ offset: '0',
30
+ };
31
+ if (input.search)
32
+ params.search = input.search;
33
+ if (input.tags && input.tags.length > 0)
34
+ params.tags = input.tags;
35
+ const response = await apiRequest('/v1/brags', { params });
36
+ if (response.brags.length === 0) {
37
+ return {
38
+ content: [{ type: 'text', text: 'No brags found.' }],
39
+ };
40
+ }
41
+ const lines = response.brags.map((brag) => {
42
+ const tags = brag.tags.length > 0 ? ` [${brag.tags.join(', ')}]` : '';
43
+ const date = new Date(brag.date).toLocaleDateString();
44
+ const goal = brag.goalId ? ` (linked to goal: ${brag.goalId})` : '';
45
+ return `- **${brag.title}** (ID: ${brag.id}, ${date})${tags}${goal}\n ${brag.description.slice(0, 150)}${brag.description.length > 150 ? '...' : ''}`;
46
+ });
47
+ const summary = `Found ${response.total} brags (showing ${response.brags.length}):`;
48
+ return {
49
+ content: [{ type: 'text', text: `${summary}\n\n${lines.join('\n\n')}` }],
50
+ };
51
+ }
52
+ catch (error) {
53
+ if (error instanceof Error && (error.message === 'NOT_AUTHENTICATED' || error.message === 'TOKEN_EXPIRED')) {
54
+ return {
55
+ content: [{
56
+ type: 'text',
57
+ text: 'Not authenticated with BragDuck. Please call the "login" tool first.',
58
+ }],
59
+ isError: true,
60
+ };
61
+ }
62
+ return {
63
+ content: [{
64
+ type: 'text',
65
+ text: `Failed to list brags: ${error instanceof Error ? error.message : String(error)}`,
66
+ }],
67
+ isError: true,
68
+ };
69
+ }
70
+ }
71
+ //# sourceMappingURL=list-brags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-brags.js","sourceRoot":"","sources":["../../src/tools/list-brags.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export declare const listObjectivesTool: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {};
7
+ };
8
+ };
9
+ export declare function handleListObjectives(): Promise<{
10
+ content: Array<{
11
+ type: string;
12
+ text: string;
13
+ }>;
14
+ isError?: boolean;
15
+ }>;
@@ -0,0 +1,63 @@
1
+ import { apiRequest } from '../api-client.js';
2
+ import { getUserInfo } from '../credentials.js';
3
+ export const listObjectivesTool = {
4
+ name: 'list_objectives',
5
+ description: 'List OKRs (Objectives and Key Results) from BragDuck. ' +
6
+ 'Use this to see current goals and their IDs, which can be used to link brags to specific goals.',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {},
10
+ },
11
+ };
12
+ export async function handleListObjectives() {
13
+ try {
14
+ const userInfo = getUserInfo();
15
+ if (!userInfo) {
16
+ return {
17
+ content: [{
18
+ type: 'text',
19
+ text: 'Not authenticated with BragDuck. Please call the "login" tool first.',
20
+ }],
21
+ isError: true,
22
+ };
23
+ }
24
+ const response = await apiRequest(`/v1/users/${userInfo.id}/objectives`);
25
+ if (response.items.length === 0) {
26
+ return {
27
+ content: [{ type: 'text', text: 'No objectives found.' }],
28
+ };
29
+ }
30
+ const lines = response.items.map((obj) => {
31
+ const goals = obj.goals
32
+ .map((g) => ` - ${g.label} (Goal ID: ${g.id}, status: ${g.status})`)
33
+ .join('\n');
34
+ const category = obj.category ? ` [${obj.category}]` : '';
35
+ return `- **${obj.title}** (ID: ${obj.id}, status: ${obj.status})${category}\n${goals || ' (no goals)'}`;
36
+ });
37
+ return {
38
+ content: [{
39
+ type: 'text',
40
+ text: `Found ${response.total} objectives:\n\n${lines.join('\n\n')}`,
41
+ }],
42
+ };
43
+ }
44
+ catch (error) {
45
+ if (error instanceof Error && (error.message === 'NOT_AUTHENTICATED' || error.message === 'TOKEN_EXPIRED')) {
46
+ return {
47
+ content: [{
48
+ type: 'text',
49
+ text: 'Not authenticated with BragDuck. Please call the "login" tool first.',
50
+ }],
51
+ isError: true,
52
+ };
53
+ }
54
+ return {
55
+ content: [{
56
+ type: 'text',
57
+ text: `Failed to list objectives: ${error instanceof Error ? error.message : String(error)}`,
58
+ }],
59
+ isError: true,
60
+ };
61
+ }
62
+ }
63
+ //# sourceMappingURL=list-objectives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-objectives.js","sourceRoot":"","sources":["../../src/tools/list-objectives.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,wDAAwD;QACxD,iGAAiG;IACnG,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE,EAAE;KACf;CACF,CAAC;AAuBF,MAAM,CAAC,KAAK,UAAU,oBAAoB;IAIxC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,sEAAsE;qBAC7E,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,UAAU,CAC/B,aAAa,QAAQ,CAAC,EAAE,aAAa,CACtC,CAAC;QAEF,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC;aAC1D,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACvC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK;iBACpB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC;iBACtE,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,OAAO,OAAO,GAAG,CAAC,KAAK,WAAW,GAAG,CAAC,EAAE,aAAa,GAAG,CAAC,MAAM,IAAI,QAAQ,KAAK,KAAK,IAAI,gBAAgB,EAAE,CAAC;QAC9G,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,SAAS,QAAQ,CAAC,KAAK,mBAAmB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;iBACrE,CAAC;SACH,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,mBAAmB,IAAI,KAAK,CAAC,OAAO,KAAK,eAAe,CAAC,EAAE,CAAC;YAC3G,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,sEAAsE;qBAC7E,CAAC;gBACF,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,8BAA8B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;iBAC7F,CAAC;YACF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,69 @@
1
+ export declare const logBragTool: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ title: {
8
+ type: string;
9
+ minLength: number;
10
+ maxLength: number;
11
+ description: string;
12
+ };
13
+ description: {
14
+ type: string;
15
+ minLength: number;
16
+ maxLength: number;
17
+ description: string;
18
+ };
19
+ tags: {
20
+ type: string;
21
+ items: {
22
+ type: string;
23
+ };
24
+ description: string;
25
+ };
26
+ date: {
27
+ type: string;
28
+ description: string;
29
+ };
30
+ impact_level: {
31
+ type: string;
32
+ enum: number[];
33
+ description: string;
34
+ };
35
+ impact_description: {
36
+ type: string;
37
+ description: string;
38
+ };
39
+ type: {
40
+ type: string;
41
+ enum: string[];
42
+ description: string;
43
+ };
44
+ orgId: {
45
+ type: string;
46
+ description: string;
47
+ };
48
+ };
49
+ required: string[];
50
+ };
51
+ };
52
+ interface LogBragInput {
53
+ title: string;
54
+ description: string;
55
+ tags?: string[];
56
+ date?: string;
57
+ impact_level?: number;
58
+ impact_description?: string;
59
+ type?: string;
60
+ orgId?: string;
61
+ }
62
+ export declare function handleLogBrag(input: LogBragInput): Promise<{
63
+ content: Array<{
64
+ type: string;
65
+ text: string;
66
+ }>;
67
+ isError?: boolean;
68
+ }>;
69
+ export {};
@@ -0,0 +1,131 @@
1
+ import { apiRequest } from '../api-client.js';
2
+ export const logBragTool = {
3
+ name: 'log_brag',
4
+ description: 'Log a career achievement (brag) to BragDuck. ' +
5
+ 'Use this to record accomplishments, completed tasks, or notable contributions.',
6
+ inputSchema: {
7
+ type: 'object',
8
+ properties: {
9
+ title: {
10
+ type: 'string',
11
+ minLength: 10,
12
+ maxLength: 200,
13
+ description: 'Short title of the achievement (must be 10-200 characters)',
14
+ },
15
+ description: {
16
+ type: 'string',
17
+ minLength: 50,
18
+ maxLength: 2000,
19
+ description: 'Detailed description of what was accomplished and its impact (must be 50-2000 characters)',
20
+ },
21
+ tags: {
22
+ type: 'array',
23
+ items: { type: 'string' },
24
+ description: 'Tags to categorize the brag (e.g., "performance", "leadership", "backend")',
25
+ },
26
+ date: {
27
+ type: 'string',
28
+ description: 'ISO datetime string for when this happened (defaults to now)',
29
+ },
30
+ impact_level: {
31
+ type: 'number',
32
+ enum: [0, 1, 2, 3],
33
+ description: 'Impact level of the achievement. ' +
34
+ '0 = none (personal learning, routine tasks). ' +
35
+ '1 = low (individual contributor impact, fixed small bug). ' +
36
+ '2 = medium (team-level impact, improved team process, led project). ' +
37
+ '3 = high (organization-level impact, reduced costs, improved key metrics).',
38
+ },
39
+ impact_description: {
40
+ type: 'string',
41
+ description: 'Narrative description of the impact. ' +
42
+ 'Start with scope (Individual/Team/Organization/Company-wide), ' +
43
+ 'then include 1-3 measurable outcomes. ' +
44
+ 'Example: "Team impact: Reduced deploy time by 60%, unblocking 4 engineers"',
45
+ },
46
+ type: {
47
+ type: 'string',
48
+ enum: [
49
+ 'progress',
50
+ 'achievement',
51
+ 'recognition',
52
+ 'support',
53
+ 'code',
54
+ 'leadership',
55
+ 'learning',
56
+ 'collaboration',
57
+ 'challenge',
58
+ 'innovation',
59
+ 'meeting',
60
+ 'bug',
61
+ 'others',
62
+ ],
63
+ description: 'Type of achievement. Choose the most appropriate category for this brag.',
64
+ },
65
+ orgId: {
66
+ type: 'string',
67
+ description: 'Organisation ID to associate the brag with',
68
+ },
69
+ },
70
+ required: ['title', 'description', 'type', 'impact_level', 'impact_description'],
71
+ },
72
+ };
73
+ export async function handleLogBrag(input) {
74
+ try {
75
+ const brag = {
76
+ title: input.title,
77
+ description: input.description,
78
+ tags: input.tags || [],
79
+ date: input.date || new Date().toISOString(),
80
+ visibility: 'private',
81
+ };
82
+ if (input.impact_level !== undefined)
83
+ brag.impactLevel = input.impact_level;
84
+ if (input.impact_description)
85
+ brag.impact_description = input.impact_description;
86
+ if (input.type)
87
+ brag.typeKey = input.type;
88
+ if (input.orgId)
89
+ brag.orgId = input.orgId;
90
+ const response = await apiRequest('/v1/brags', {
91
+ method: 'POST',
92
+ body: { brags: [brag], source: 'mcp' },
93
+ });
94
+ // The CLI route returns { created, failed, brags, errors }
95
+ const brags = response.brags;
96
+ if (brags && brags.length > 0) {
97
+ return {
98
+ content: [{
99
+ type: 'text',
100
+ text: `Brag created: "${brags[0].title}" (ID: ${brags[0].id})`,
101
+ }],
102
+ };
103
+ }
104
+ // Fallback: brag was created but response shape is unexpected
105
+ return {
106
+ content: [{
107
+ type: 'text',
108
+ text: `Brag created. API response: ${JSON.stringify(response)}`,
109
+ }],
110
+ };
111
+ }
112
+ catch (error) {
113
+ if (error instanceof Error && (error.message === 'NOT_AUTHENTICATED' || error.message === 'TOKEN_EXPIRED')) {
114
+ return {
115
+ content: [{
116
+ type: 'text',
117
+ text: 'Not authenticated with BragDuck. Please call the "login" tool first.',
118
+ }],
119
+ isError: true,
120
+ };
121
+ }
122
+ return {
123
+ content: [{
124
+ type: 'text',
125
+ text: `Failed to create brag: ${error instanceof Error ? error.message : String(error)}`,
126
+ }],
127
+ isError: true,
128
+ };
129
+ }
130
+ }
131
+ //# sourceMappingURL=log-brag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-brag.js","sourceRoot":"","sources":["../../src/tools/log-brag.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export declare const loginTool: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {
5
+ type: "object";
6
+ properties: {
7
+ force: {
8
+ type: string;
9
+ description: string;
10
+ };
11
+ };
12
+ };
13
+ };
14
+ interface LoginInput {
15
+ force?: boolean;
16
+ }
17
+ export declare function handleLogin(input?: LoginInput): Promise<{
18
+ content: Array<{
19
+ type: string;
20
+ text: string;
21
+ }>;
22
+ isError?: boolean;
23
+ }>;
24
+ export {};
@@ -0,0 +1,46 @@
1
+ import { login } from '../auth.js';
2
+ import { getAccessToken } from '../credentials.js';
3
+ export const loginTool = {
4
+ name: 'login',
5
+ description: 'Authenticate with BragDuck. Opens the browser for sign-in/sign-up. ' +
6
+ 'Call this when other tools return an authentication error.',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ force: {
11
+ type: 'boolean',
12
+ description: 'Force re-authentication even if already logged in',
13
+ },
14
+ },
15
+ },
16
+ };
17
+ export async function handleLogin(input) {
18
+ // Check if already authenticated (skip if force=true)
19
+ if (!input?.force) {
20
+ const existingToken = getAccessToken();
21
+ if (existingToken) {
22
+ return {
23
+ content: [{ type: 'text', text: 'Already authenticated with BragDuck.' }],
24
+ };
25
+ }
26
+ }
27
+ try {
28
+ const user = await login();
29
+ return {
30
+ content: [{
31
+ type: 'text',
32
+ text: `Authenticated as ${user.name} (${user.email}). You can now log brags and manage objectives.`,
33
+ }],
34
+ };
35
+ }
36
+ catch (error) {
37
+ return {
38
+ content: [{
39
+ type: 'text',
40
+ text: `Authentication failed: ${error instanceof Error ? error.message : String(error)}`,
41
+ }],
42
+ isError: true,
43
+ };
44
+ }
45
+ }
46
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/tools/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,IAAI,EAAE,OAAO;IACb,WAAW,EACT,qEAAqE;QACrE,4DAA4D;IAC9D,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,mDAAmD;aACjE;SACF;KACF;CACF,CAAC;AAMF,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAkB;IAElB,sDAAsD;IACtD,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;QAClB,MAAM,aAAa,GAAG,cAAc,EAAE,CAAC;QACvC,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sCAAsC,EAAE,CAAC;aAC1E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,EAAE,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,oBAAoB,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,iDAAiD;iBACpG,CAAC;SACH,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;iBACzF,CAAC;YACF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}