From 0311d44b770ba105cee8ab815f3a5eb09b64ec07 Mon Sep 17 00:00:00 2001 From: Kousha Talebian Date: Thu, 22 May 2025 14:37:37 -0700 Subject: [PATCH 1/3] add tracking header --- packages/openapi-mcp-server/src/utils/http.ts | 21 +++++++++++- .../tests/utils/http.spec.ts | 32 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/packages/openapi-mcp-server/src/utils/http.ts b/packages/openapi-mcp-server/src/utils/http.ts index 39ac759..b72edd3 100644 --- a/packages/openapi-mcp-server/src/utils/http.ts +++ b/packages/openapi-mcp-server/src/utils/http.ts @@ -1,11 +1,25 @@ import fetch, { Response } from 'node-fetch'; import FormData from 'form-data'; import qs from 'qs'; +import * as fs from 'fs'; +import * as path from 'path'; import { HttpMethod } from '@app/types'; import logger from './logger'; +function getPackageVersion(): string { + try { + const packageJsonPath = path.resolve(__dirname, '../../package.json'); + const packageJsonData = fs.readFileSync(packageJsonPath, 'utf8'); + const packageJson = JSON.parse(packageJsonData); + return packageJson.version; + } catch (error) { + logger.error(`Failed to read package.json: ${error}`); + return 'unknown'; + } +} + type SuccessResponse = { ok: true; statusCode: number; @@ -106,15 +120,20 @@ export default class Http { private readonly logger; + private readonly version: string; + constructor(config: Configuration) { this.defaultRequest = { headers: { 'Content-Type': 'application/json', ...getAuthorization(config.authorization), + 'x-mcp-client-id': `twilio-openapi-mcp-server/${this.version}`, + 'user-agent': `twilio-openapi-mcp-server/${this.version}`, }, }; this.logger = logger.child({ module: 'Http' }); + this.version = getPackageVersion(); } /** @@ -123,11 +142,11 @@ export default class Http { private async make(request: HttpRequest): Promise> { try { logger.debug(`request object: ${JSON.stringify(request)}`); - const options: RequestInit = { ...this.defaultRequest, method: request.method, }; + if (request.headers) { // @ts-ignore options.headers = { diff --git a/packages/openapi-mcp-server/tests/utils/http.spec.ts b/packages/openapi-mcp-server/tests/utils/http.spec.ts index 6512f65..40b6765 100644 --- a/packages/openapi-mcp-server/tests/utils/http.spec.ts +++ b/packages/openapi-mcp-server/tests/utils/http.spec.ts @@ -47,6 +47,10 @@ describe('Http', () => { headers: expect.objectContaining({ Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', 'Content-Type': 'application/json', + 'x-mcp-client-id': expect.stringMatching( + 'twilio-openapi-mcp-server', + ), + 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), }), }), ); @@ -139,6 +143,10 @@ describe('Http', () => { method: 'POST', headers: expect.objectContaining({ 'Content-Type': 'application/x-www-form-urlencoded', + 'x-mcp-client-id': expect.stringMatching( + 'twilio-openapi-mcp-server', + ), + 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), }), body: expect.any(String), // We're not testing the exact encoding, just that it's a string }), @@ -193,6 +201,10 @@ describe('Http', () => { headers: expect.objectContaining({ Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', 'Content-Type': 'application/json', + 'x-mcp-client-id': expect.stringMatching( + 'twilio-openapi-mcp-server', + ), + 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), }), body: JSON.stringify(requestBody), }), @@ -229,6 +241,10 @@ describe('Http', () => { method: 'PUT', headers: expect.objectContaining({ 'Content-Type': 'application/x-www-form-urlencoded', + 'x-mcp-client-id': expect.stringMatching( + 'twilio-openapi-mcp-server', + ), + 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), }), body: expect.any(String), }), @@ -278,6 +294,10 @@ describe('Http', () => { method: 'DELETE', headers: expect.objectContaining({ 'Content-Type': 'application/json', + 'x-mcp-client-id': expect.stringMatching( + 'twilio-openapi-mcp-server', + ), + 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), }), }), ); @@ -454,6 +474,10 @@ describe('Http', () => { headers: expect.objectContaining({ 'content-type': 'multipart/form-data; boundary=---boundary', Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', + 'x-mcp-client-id': expect.stringMatching( + 'twilio-openapi-mcp-server', + ), + 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), }), body: formData, }), @@ -522,6 +546,10 @@ describe('Http', () => { 'content-type': 'multipart/form-data; boundary=---boundary', 'X-Custom-Header': 'custom-value', Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', + 'x-mcp-client-id': expect.stringMatching( + 'twilio-openapi-mcp-server', + ), + 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), }), body: formData, }), @@ -558,6 +586,10 @@ describe('Http', () => { method: 'POST', headers: expect.objectContaining({ Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', + 'x-mcp-client-id': expect.stringMatching( + 'twilio-openapi-mcp-server', + ), + 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), }), body: formData, }), From d3cde9bbd956bfbbb572be12bd8efadf491cbd4a Mon Sep 17 00:00:00 2001 From: Kousha Talebian Date: Thu, 22 May 2025 14:42:33 -0700 Subject: [PATCH 2/3] add tracking header --- packages/openapi-mcp-server/src/utils/http.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/openapi-mcp-server/src/utils/http.ts b/packages/openapi-mcp-server/src/utils/http.ts index b72edd3..36a0fa3 100644 --- a/packages/openapi-mcp-server/src/utils/http.ts +++ b/packages/openapi-mcp-server/src/utils/http.ts @@ -123,6 +123,7 @@ export default class Http { private readonly version: string; constructor(config: Configuration) { + this.version = getPackageVersion(); this.defaultRequest = { headers: { 'Content-Type': 'application/json', @@ -133,7 +134,6 @@ export default class Http { }; this.logger = logger.child({ module: 'Http' }); - this.version = getPackageVersion(); } /** From 1960b45b86f50e46549871739ffb48b8c33cea25 Mon Sep 17 00:00:00 2001 From: Kousha Talebian Date: Thu, 22 May 2025 14:43:26 -0700 Subject: [PATCH 3/3] rename client to server --- packages/openapi-mcp-server/src/utils/http.ts | 2 +- .../openapi-mcp-server/tests/utils/http.spec.ts | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/openapi-mcp-server/src/utils/http.ts b/packages/openapi-mcp-server/src/utils/http.ts index 36a0fa3..b322bdd 100644 --- a/packages/openapi-mcp-server/src/utils/http.ts +++ b/packages/openapi-mcp-server/src/utils/http.ts @@ -128,7 +128,7 @@ export default class Http { headers: { 'Content-Type': 'application/json', ...getAuthorization(config.authorization), - 'x-mcp-client-id': `twilio-openapi-mcp-server/${this.version}`, + 'x-mcp-server-id': `twilio-openapi-mcp-server/${this.version}`, 'user-agent': `twilio-openapi-mcp-server/${this.version}`, }, }; diff --git a/packages/openapi-mcp-server/tests/utils/http.spec.ts b/packages/openapi-mcp-server/tests/utils/http.spec.ts index 40b6765..8158797 100644 --- a/packages/openapi-mcp-server/tests/utils/http.spec.ts +++ b/packages/openapi-mcp-server/tests/utils/http.spec.ts @@ -47,7 +47,7 @@ describe('Http', () => { headers: expect.objectContaining({ Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', 'Content-Type': 'application/json', - 'x-mcp-client-id': expect.stringMatching( + 'x-mcp-server-id': expect.stringMatching( 'twilio-openapi-mcp-server', ), 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), @@ -143,7 +143,7 @@ describe('Http', () => { method: 'POST', headers: expect.objectContaining({ 'Content-Type': 'application/x-www-form-urlencoded', - 'x-mcp-client-id': expect.stringMatching( + 'x-mcp-server-id': expect.stringMatching( 'twilio-openapi-mcp-server', ), 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), @@ -201,7 +201,7 @@ describe('Http', () => { headers: expect.objectContaining({ Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', 'Content-Type': 'application/json', - 'x-mcp-client-id': expect.stringMatching( + 'x-mcp-server-id': expect.stringMatching( 'twilio-openapi-mcp-server', ), 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), @@ -241,7 +241,7 @@ describe('Http', () => { method: 'PUT', headers: expect.objectContaining({ 'Content-Type': 'application/x-www-form-urlencoded', - 'x-mcp-client-id': expect.stringMatching( + 'x-mcp-server-id': expect.stringMatching( 'twilio-openapi-mcp-server', ), 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), @@ -294,7 +294,7 @@ describe('Http', () => { method: 'DELETE', headers: expect.objectContaining({ 'Content-Type': 'application/json', - 'x-mcp-client-id': expect.stringMatching( + 'x-mcp-server-id': expect.stringMatching( 'twilio-openapi-mcp-server', ), 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), @@ -474,7 +474,7 @@ describe('Http', () => { headers: expect.objectContaining({ 'content-type': 'multipart/form-data; boundary=---boundary', Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', - 'x-mcp-client-id': expect.stringMatching( + 'x-mcp-server-id': expect.stringMatching( 'twilio-openapi-mcp-server', ), 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), @@ -546,7 +546,7 @@ describe('Http', () => { 'content-type': 'multipart/form-data; boundary=---boundary', 'X-Custom-Header': 'custom-value', Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', - 'x-mcp-client-id': expect.stringMatching( + 'x-mcp-server-id': expect.stringMatching( 'twilio-openapi-mcp-server', ), 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'), @@ -586,7 +586,7 @@ describe('Http', () => { method: 'POST', headers: expect.objectContaining({ Authorization: 'Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk', - 'x-mcp-client-id': expect.stringMatching( + 'x-mcp-server-id': expect.stringMatching( 'twilio-openapi-mcp-server', ), 'user-agent': expect.stringMatching('twilio-openapi-mcp-server'),