splitwise-mcp 1.0.3 → 1.2.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 CHANGED
@@ -27,7 +27,7 @@ for (const tool of expenseTools)
27
27
  handlers[tool.name] = (n, a) => handleExpenses(n, a, client);
28
28
  for (const tool of utilityTools)
29
29
  handlers[tool.name] = (n, a) => handleUtilities(n, a, client);
30
- const server = new Server({ name: 'splitwise-mcp', version: '1.0.0' }, { capabilities: { tools: {} } });
30
+ const server = new Server({ name: 'splitwise-mcp', version: '1.2.0' }, { capabilities: { tools: {} } });
31
31
  server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: allTools }));
32
32
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
33
33
  const { name, arguments: args = {} } = request.params;
@@ -118,7 +118,7 @@ export const toolDefinitions = [
118
118
  },
119
119
  {
120
120
  name: 'sw_delete_expense',
121
- description: 'Soft-delete a Splitwise expense by id. Returns {success: true} on success. Note: restoring deleted expenses requires sw_undelete_expense (not yet implemented).',
121
+ description: 'Soft-delete a Splitwise expense by id. Returns {success: true} on success. Use sw_undelete_expense to restore.',
122
122
  annotations: { destructiveHint: true },
123
123
  inputSchema: {
124
124
  type: 'object',
@@ -128,7 +128,17 @@ export const toolDefinitions = [
128
128
  required: ['id'],
129
129
  },
130
130
  },
131
- // TODO: sw_undelete_expense — POST /undelete_expense/{id} — restore a soft-deleted expense
131
+ {
132
+ name: 'sw_undelete_expense',
133
+ description: 'Restore a soft-deleted Splitwise expense.',
134
+ inputSchema: {
135
+ type: 'object',
136
+ properties: {
137
+ id: { type: 'integer', description: 'Expense ID to restore' },
138
+ },
139
+ required: ['id'],
140
+ },
141
+ },
132
142
  ];
133
143
  export async function handleTool(name, args, client) {
134
144
  switch (name) {
@@ -164,6 +174,11 @@ export async function handleTool(name, args, client) {
164
174
  const data = await client.request('POST', `/delete_expense/${id}`);
165
175
  return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
166
176
  }
177
+ case 'sw_undelete_expense': {
178
+ const { id } = args;
179
+ const data = await client.request('POST', `/undelete_expense/${id}`);
180
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
181
+ }
167
182
  default:
168
183
  throw new Error(`Unknown tool: ${name}`);
169
184
  }
@@ -5,15 +5,53 @@ export const toolDefinitions = [
5
5
  annotations: { readOnlyHint: true },
6
6
  inputSchema: { type: 'object', properties: {}, required: [] },
7
7
  },
8
- // TODO: sw_create_friend — POST /create_friend — add a friend by email (user_email, user_first_name, user_last_name)
9
- // TODO: sw_delete_friend — POST /delete_friend/{id} — remove a friendship
8
+ {
9
+ name: 'sw_create_friend',
10
+ description: 'Add a Splitwise friend by email.',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {
14
+ user_email: { type: 'string', description: 'Email of the user to add as a friend' },
15
+ user_first_name: { type: 'string', description: 'First name of the user' },
16
+ user_last_name: { type: 'string', description: 'Last name of the user' },
17
+ },
18
+ required: ['user_email'],
19
+ },
20
+ },
21
+ {
22
+ name: 'sw_delete_friend',
23
+ description: 'Remove a Splitwise friendship by user id.',
24
+ annotations: { destructiveHint: true },
25
+ inputSchema: {
26
+ type: 'object',
27
+ properties: {
28
+ id: { type: 'integer', description: 'User ID of the friend to remove' },
29
+ },
30
+ required: ['id'],
31
+ },
32
+ },
10
33
  ];
11
- export async function handleTool(name, _args, client) {
34
+ export async function handleTool(name, args, client) {
12
35
  switch (name) {
13
36
  case 'sw_list_friends': {
14
37
  const data = await client.request('GET', '/get_friends');
15
38
  return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
16
39
  }
40
+ case 'sw_create_friend': {
41
+ const { user_email, user_first_name, user_last_name } = args;
42
+ const body = { user_email };
43
+ if (user_first_name !== undefined)
44
+ body.user_first_name = user_first_name;
45
+ if (user_last_name !== undefined)
46
+ body.user_last_name = user_last_name;
47
+ const data = await client.request('POST', '/create_friend', body);
48
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
49
+ }
50
+ case 'sw_delete_friend': {
51
+ const { id } = args;
52
+ const data = await client.request('POST', `/delete_friend/${id}`);
53
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
54
+ }
17
55
  default:
18
56
  throw new Error(`Unknown tool: ${name}`);
19
57
  }
@@ -61,8 +61,29 @@ export const toolDefinitions = [
61
61
  required: ['group_id', 'user_id'],
62
62
  },
63
63
  },
64
- // TODO: sw_delete_group — POST /delete_group/{id} — soft-delete a group
65
- // TODO: sw_undelete_group — POST /undelete_group/{id} — restore a soft-deleted group
64
+ {
65
+ name: 'sw_delete_group',
66
+ description: 'Soft-delete a Splitwise group.',
67
+ annotations: { destructiveHint: true },
68
+ inputSchema: {
69
+ type: 'object',
70
+ properties: {
71
+ id: { type: 'integer', description: 'Group ID to delete' },
72
+ },
73
+ required: ['id'],
74
+ },
75
+ },
76
+ {
77
+ name: 'sw_undelete_group',
78
+ description: 'Restore a soft-deleted Splitwise group.',
79
+ inputSchema: {
80
+ type: 'object',
81
+ properties: {
82
+ id: { type: 'integer', description: 'Group ID to restore' },
83
+ },
84
+ required: ['id'],
85
+ },
86
+ },
66
87
  ];
67
88
  export async function handleTool(name, args, client) {
68
89
  switch (name) {
@@ -105,6 +126,16 @@ export async function handleTool(name, args, client) {
105
126
  const data = await client.request('POST', '/remove_user_from_group', { group_id, user_id });
106
127
  return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
107
128
  }
129
+ case 'sw_delete_group': {
130
+ const { id } = args;
131
+ const data = await client.request('POST', `/delete_group/${id}`);
132
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
133
+ }
134
+ case 'sw_undelete_group': {
135
+ const { id } = args;
136
+ const data = await client.request('POST', `/undelete_group/${id}`);
137
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
138
+ }
108
139
  default:
109
140
  throw new Error(`Unknown tool: ${name}`);
110
141
  }
@@ -5,15 +5,65 @@ export const toolDefinitions = [
5
5
  annotations: { readOnlyHint: true },
6
6
  inputSchema: { type: 'object', properties: {}, required: [] },
7
7
  },
8
- // TODO: sw_get_user — GET /get_user/{id} — get another user's profile by id
9
- // TODO: sw_update_user — POST /update_user/{id} — update current user's profile (first_name, last_name, email, password, locale, default_currency)
8
+ {
9
+ name: 'sw_get_user',
10
+ description: 'Get another Splitwise user\'s profile by id.',
11
+ annotations: { readOnlyHint: true },
12
+ inputSchema: {
13
+ type: 'object',
14
+ properties: {
15
+ id: { type: 'integer', description: 'User ID' },
16
+ },
17
+ required: ['id'],
18
+ },
19
+ },
20
+ {
21
+ name: 'sw_update_user',
22
+ description: 'Update the current user\'s profile fields. id must be the current user\'s id.',
23
+ inputSchema: {
24
+ type: 'object',
25
+ properties: {
26
+ id: { type: 'integer', description: 'User ID (must be the current user\'s id)' },
27
+ first_name: { type: 'string' },
28
+ last_name: { type: 'string' },
29
+ email: { type: 'string' },
30
+ password: { type: 'string' },
31
+ locale: { type: 'string' },
32
+ default_currency: { type: 'string' },
33
+ },
34
+ required: ['id'],
35
+ },
36
+ },
10
37
  ];
11
- export async function handleTool(name, _args, client) {
38
+ export async function handleTool(name, args, client) {
12
39
  switch (name) {
13
40
  case 'sw_get_current_user': {
14
41
  const data = await client.request('GET', '/get_current_user');
15
42
  return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
16
43
  }
44
+ case 'sw_get_user': {
45
+ const { id } = args;
46
+ const data = await client.request('GET', `/get_user/${id}`);
47
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
48
+ }
49
+ case 'sw_update_user': {
50
+ const { id, first_name, last_name, email, password, locale, default_currency } = args;
51
+ const body = {};
52
+ if (first_name !== undefined)
53
+ body.first_name = first_name;
54
+ if (last_name !== undefined)
55
+ body.last_name = last_name;
56
+ if (email !== undefined)
57
+ body.email = email;
58
+ if (password !== undefined)
59
+ body.password = password;
60
+ if (locale !== undefined)
61
+ body.locale = locale;
62
+ if (default_currency !== undefined)
63
+ body.default_currency = default_currency;
64
+ const data = await client.request('POST', `/update_user/${id}`, body);
65
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
66
+ }
17
67
  default:
18
68
  throw new Error(`Unknown tool: ${name}`);
19
69
  }
@@ -17,11 +17,44 @@ export const toolDefinitions = [
17
17
  annotations: { readOnlyHint: true },
18
18
  inputSchema: { type: 'object', properties: {}, required: [] },
19
19
  },
20
- // TODO: sw_get_comments — GET /get_comments?expense_id= — get comments on an expense
21
- // TODO: sw_create_comment — POST /create_comment — add a comment to an expense (expense_id, content)
22
- // TODO: sw_delete_comment POST /delete_comment/{id} delete a comment
20
+ {
21
+ name: 'sw_get_comments',
22
+ description: 'Get all comments on a Splitwise expense.',
23
+ annotations: { readOnlyHint: true },
24
+ inputSchema: {
25
+ type: 'object',
26
+ properties: {
27
+ expense_id: { type: 'integer', description: 'Expense ID to get comments for' },
28
+ },
29
+ required: ['expense_id'],
30
+ },
31
+ },
32
+ {
33
+ name: 'sw_create_comment',
34
+ description: 'Add a comment to a Splitwise expense.',
35
+ inputSchema: {
36
+ type: 'object',
37
+ properties: {
38
+ expense_id: { type: 'integer', description: 'Expense ID to comment on' },
39
+ content: { type: 'string', description: 'Comment text' },
40
+ },
41
+ required: ['expense_id', 'content'],
42
+ },
43
+ },
44
+ {
45
+ name: 'sw_delete_comment',
46
+ description: 'Delete a comment by id.',
47
+ annotations: { destructiveHint: true },
48
+ inputSchema: {
49
+ type: 'object',
50
+ properties: {
51
+ id: { type: 'integer', description: 'Comment ID to delete' },
52
+ },
53
+ required: ['id'],
54
+ },
55
+ },
23
56
  ];
24
- export async function handleTool(name, _args, client) {
57
+ export async function handleTool(name, args, client) {
25
58
  switch (name) {
26
59
  case 'sw_get_notifications': {
27
60
  const data = await client.request('GET', '/get_notifications');
@@ -35,6 +68,21 @@ export async function handleTool(name, _args, client) {
35
68
  const data = await client.request('GET', '/get_currencies');
36
69
  return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
37
70
  }
71
+ case 'sw_get_comments': {
72
+ const { expense_id } = args;
73
+ const data = await client.request('GET', `/get_comments?expense_id=${expense_id}`);
74
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
75
+ }
76
+ case 'sw_create_comment': {
77
+ const { expense_id, content } = args;
78
+ const data = await client.request('POST', '/create_comment', { expense_id, content });
79
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
80
+ }
81
+ case 'sw_delete_comment': {
82
+ const { id } = args;
83
+ const data = await client.request('POST', `/delete_comment/${id}`);
84
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
85
+ }
38
86
  default:
39
87
  throw new Error(`Unknown tool: ${name}`);
40
88
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "splitwise-mcp",
3
- "version": "1.0.3",
3
+ "version": "1.2.0",
4
4
  "description": "Splitwise MCP server for Claude — developed and maintained by AI (Claude Sonnet 4.6)",
5
5
  "author": "Claude Sonnet 4.6 (AI) <https://www.anthropic.com/claude>",
6
6
  "repository": {