Skip to content

Commit a4e31af

Browse files
authored
fix: capture only axios 500 errors (#106)
- [x] Do not log and send non-500 Axios errors to Sentry - [x] Use default trace created by sentry for per API call
1 parent 776c7ea commit a4e31af

File tree

4 files changed

+80
-50
lines changed

4 files changed

+80
-50
lines changed

bun.lock

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"@segment/analytics-node": "2.2.1",
1313
"@sentry/node": "9.19.0",
1414
"@tailwindcss/postcss": "4.1.10",
15+
"axios": "1.11.0",
1516
"body-parser": "2.2.0",
1617
"chalk": "5.3.0",
1718
"class-variance-authority": "0.7.1",
@@ -549,7 +550,7 @@
549550

550551
"autoevals": ["autoevals@0.0.111", "", { "dependencies": { "@braintrust/core": "0.0.71", "ajv": "^8.13.0", "compute-cosine-similarity": "^1.1.0", "js-levenshtein": "^1.1.6", "js-yaml": "^4.1.0", "linear-sum-assignment": "^1.0.7", "mustache": "^4.2.0", "openai": "4.47.1", "zod": "^3.22.4", "zod-to-json-schema": "^3.22.5" } }, "sha512-H38avDrcWU6w7aP0CwCansc/Um/3Bm8yvjMX6g8TR4FIJeyY84poimdNK3GDRk+hhoiY1DovdZoEJILWC6OmgQ=="],
551552

552-
"axios": ["axios@1.9.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg=="],
553+
"axios": ["axios@1.11.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA=="],
553554

554555
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
555556

@@ -1367,6 +1368,8 @@
13671368

13681369
"@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
13691370

1371+
"@neondatabase/api-client/axios": ["axios@1.9.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg=="],
1372+
13701373
"@neondatabase/serverless/@types/node": ["@types/node@22.15.18", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg=="],
13711374

13721375
"@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="],
@@ -1413,6 +1416,8 @@
14131416

14141417
"ai/@ai-sdk/provider": ["@ai-sdk/provider@0.0.26", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-dQkfBDs2lTYpKM8389oopPdQgIU007GQyCbuPPrV+K6MtSII3HBfE0stUIMXUb44L+LK1t6GXPP7wjSzjO6uKg=="],
14151418

1419+
"axios/form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
1420+
14161421
"basic-auth/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
14171422

14181423
"braintrust/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
@@ -1505,6 +1510,8 @@
15051510

15061511
"@types/tedious/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
15071512

1513+
"axios/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
1514+
15081515
"colorspace/color/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
15091516

15101517
"eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
@@ -1525,6 +1532,8 @@
15251532

15261533
"@opentelemetry/instrumentation-pg/@types/pg/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
15271534

1535+
"axios/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
1536+
15281537
"colorspace/color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
15291538

15301539
"oauth2-server/type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],

package-lock.json

Lines changed: 11 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"@segment/analytics-node": "2.2.1",
4242
"@sentry/node": "9.19.0",
4343
"@tailwindcss/postcss": "4.1.10",
44+
"axios": "1.11.0",
4445
"body-parser": "2.2.0",
4546
"chalk": "5.3.0",
4647
"class-variance-authority": "0.7.1",

src/server/index.ts

Lines changed: 58 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env node
22

33
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4+
import { isAxiosError } from 'axios';
45
import { NEON_RESOURCES } from '../resources.js';
56
import {
67
NEON_HANDLERS,
@@ -10,7 +11,7 @@ import {
1011
import { logger } from '../utils/logger.js';
1112
import { createNeonClient, getPackageJson } from './api.js';
1213
import { track } from '../analytics/analytics.js';
13-
import { captureException, startNewTrace, startSpan } from '@sentry/node';
14+
import { captureException, setHttpStatus, startSpan } from '@sentry/node';
1415
import { ServerContext } from '../types/context.js';
1516
import { setSentryTags } from '../sentry/utils.js';
1617
import { ToolHandlerExtraParams } from '../tools/types.js';
@@ -47,51 +48,66 @@ export const createMcpServer = (context: ServerContext) => {
4748
tool.description,
4849
{ params: tool.inputSchema },
4950
async (args, extra) => {
50-
return await startNewTrace(async () => {
51-
return await startSpan(
52-
{
53-
name: 'tool_call',
54-
attributes: {
55-
tool_name: tool.name,
56-
},
51+
return await startSpan(
52+
{
53+
name: 'tool_call',
54+
attributes: {
55+
tool_name: tool.name,
5756
},
58-
async (span) => {
59-
const properties = { tool_name: tool.name };
60-
logger.info('tool call:', properties);
61-
setSentryTags(context);
62-
track({
63-
userId: context.account.id,
64-
event: 'tool_call',
65-
properties,
66-
context: { client: context.client, app: context.app },
57+
},
58+
async (span) => {
59+
const properties = { tool_name: tool.name };
60+
logger.info('tool call:', properties);
61+
setSentryTags(context);
62+
track({
63+
userId: context.account.id,
64+
event: 'tool_call',
65+
properties,
66+
context: { client: context.client, app: context.app },
67+
});
68+
const extraArgs: ToolHandlerExtraParams = {
69+
...extra,
70+
account: context.account,
71+
};
72+
try {
73+
return await toolHandler(args, neonClient, extraArgs);
74+
} catch (error) {
75+
span.setStatus({
76+
code: 2,
6777
});
68-
const extraArgs: ToolHandlerExtraParams = {
69-
...extra,
70-
account: context.account,
71-
};
72-
try {
73-
return await toolHandler(args, neonClient, extraArgs);
74-
} catch (error) {
75-
span.setStatus({
76-
code: 2,
77-
});
78-
if (error instanceof NeonDbError) {
79-
return handleNeonDbError(error);
80-
} else {
81-
logger.error('Tool call error:', {
82-
error:
83-
error instanceof Error ? error.message : 'Unknown error',
84-
properties,
85-
});
86-
captureException(error, {
87-
extra: properties,
88-
});
89-
throw error;
78+
if (error instanceof NeonDbError) {
79+
return handleNeonDbError(error);
80+
} else {
81+
if (
82+
isAxiosError(error) &&
83+
error.response?.status &&
84+
error.response?.status < 500
85+
) {
86+
setHttpStatus(span, error.response.status);
87+
return {
88+
isError: true,
89+
content: [
90+
{
91+
type: 'text',
92+
text: error.response?.data.message || error.message,
93+
},
94+
],
95+
};
9096
}
97+
98+
logger.error('Tool call error:', {
99+
error:
100+
error instanceof Error ? error.message : 'Unknown error',
101+
properties,
102+
});
103+
captureException(error, {
104+
extra: properties,
105+
});
106+
throw error;
91107
}
92-
},
93-
);
94-
});
108+
}
109+
},
110+
);
95111
},
96112
);
97113
});

0 commit comments

Comments
 (0)