@metabob/mcp 0.2.2 → 0.2.3

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.
Files changed (2) hide show
  1. package/dist/cli.js +1 -128
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -35025,110 +35025,6 @@ class AuthService {
35025
35025
  }
35026
35026
  var DEFAULT_IDENTITY_ENDPOINT = "https://identity.metabob.com", RESOLVE_TIMEOUT_MS = 5000, BEARER_REFRESH_MARGIN_MS = 60000;
35027
35027
 
35028
- // src/vessel-heartbeat.ts
35029
- class VesselHeartbeat {
35030
- config;
35031
- intervalHandle;
35032
- running = false;
35033
- failures = 0;
35034
- lastRegistered;
35035
- constructor(config2) {
35036
- const ttl = config2.ttl ?? DEFAULT_TTL_S;
35037
- this.config = {
35038
- ...config2,
35039
- ttl,
35040
- metadata: config2.metadata ?? {},
35041
- heartbeatIntervalMs: config2.heartbeatIntervalMs ?? ttl * 1000 / 2
35042
- };
35043
- }
35044
- async start() {
35045
- if (this.running)
35046
- return;
35047
- await this.register();
35048
- this.intervalHandle = setInterval(() => {
35049
- this.register().catch((err) => {
35050
- console.error(`[vessel-heartbeat] interval error: ${err instanceof Error ? err.message : err}`);
35051
- });
35052
- }, this.config.heartbeatIntervalMs);
35053
- this.running = true;
35054
- console.error(`[vessel-heartbeat] started for ${this.config.vesselId} ` + `(ttl=${this.config.ttl}s interval=${this.config.heartbeatIntervalMs}ms)`);
35055
- }
35056
- stop() {
35057
- if (!this.running)
35058
- return;
35059
- clearInterval(this.intervalHandle);
35060
- this.intervalHandle = undefined;
35061
- this.running = false;
35062
- console.error(`[vessel-heartbeat] stopped for ${this.config.vesselId}`);
35063
- }
35064
- async register() {
35065
- const { activityEndpoint, vesselId, vesselName, endpoint, shapes, metadata, ttl, authService } = this.config;
35066
- const headers = { "Content-Type": "application/json" };
35067
- if (authService.bearerTokenIsStale()) {
35068
- authService.refreshTenant().catch(() => {});
35069
- }
35070
- const bearer = authService.getBearerToken();
35071
- const identityApiKey = authService.getIdentityApiKey();
35072
- if (bearer) {
35073
- headers["Authorization"] = `Bearer ${bearer}`;
35074
- } else if (identityApiKey) {
35075
- headers["Authorization"] = `ApiKey ${identityApiKey}`;
35076
- }
35077
- const body = {
35078
- vesselId,
35079
- vesselName,
35080
- endpoint,
35081
- shapes,
35082
- metadata,
35083
- ttl,
35084
- resolve_endpoint: "/v2/impulses/resolve",
35085
- resolve_request_format: "pointer",
35086
- auth_scheme: "ApiKey",
35087
- resolve_timeout_ms: 30000,
35088
- auth_token_source: "header",
35089
- auth_delegation_mode: "direct"
35090
- };
35091
- try {
35092
- const res = await fetch(`${activityEndpoint}/v2/vessels/register`, {
35093
- method: "POST",
35094
- headers,
35095
- body: JSON.stringify(body),
35096
- signal: AbortSignal.timeout(1e4)
35097
- });
35098
- if (!res.ok) {
35099
- const text = await res.text().catch(() => "");
35100
- console.error(`[vessel-heartbeat] registration HTTP ${res.status}: ${text.slice(0, 120)}`);
35101
- this.onFailure();
35102
- return false;
35103
- }
35104
- this.lastRegistered = new Date;
35105
- this.failures = 0;
35106
- console.error(`[vessel-heartbeat] registered ${vesselId} shapes=[${shapes.join(", ")}]`);
35107
- return true;
35108
- } catch (err) {
35109
- console.error(`[vessel-heartbeat] registration error: ${err instanceof Error ? err.message : err}`);
35110
- this.onFailure();
35111
- return false;
35112
- }
35113
- }
35114
- onFailure() {
35115
- this.failures++;
35116
- if (this.failures >= MAX_FAILURES) {
35117
- console.error(`[vessel-heartbeat] ${MAX_FAILURES} consecutive failures — stopping`);
35118
- this.stop();
35119
- }
35120
- }
35121
- status() {
35122
- return {
35123
- running: this.running,
35124
- lastRegistered: this.lastRegistered,
35125
- consecutiveFailures: this.failures,
35126
- vesselId: this.config.vesselId
35127
- };
35128
- }
35129
- }
35130
- var MAX_FAILURES = 3, DEFAULT_TTL_S = 300;
35131
-
35132
35028
  // src/index.ts
35133
35029
  var exports_src = {};
35134
35030
  function log(level, message, data) {
@@ -35210,15 +35106,11 @@ Authentication failed: ${err.message}`);
35210
35106
  log("warn", "Continuing without connection slot. Some features may be limited.");
35211
35107
  }
35212
35108
  }
35213
- vesselHeartbeat.start().catch((err) => {
35214
- log("warn", "Discovery registration failed (continuing without discovery)", { error: err.message });
35215
- });
35216
35109
  const transport = new StdioServerTransport;
35217
35110
  await server.connect(transport);
35218
35111
  log("info", "MCP server ready");
35219
35112
  process.on("SIGINT", async () => {
35220
35113
  log("info", "Shutting down...");
35221
- vesselHeartbeat.stop();
35222
35114
  authService.stopKeyHeartbeat();
35223
35115
  await apiClient.shutdown();
35224
35116
  await vesselServer.stop();
@@ -35228,7 +35120,6 @@ Authentication failed: ${err.message}`);
35228
35120
  });
35229
35121
  process.on("SIGTERM", async () => {
35230
35122
  log("info", "Shutting down...");
35231
- vesselHeartbeat.stop();
35232
35123
  authService.stopKeyHeartbeat();
35233
35124
  await apiClient.shutdown();
35234
35125
  await vesselServer.stop();
@@ -35237,7 +35128,7 @@ Authentication failed: ${err.message}`);
35237
35128
  process.exit(0);
35238
35129
  });
35239
35130
  }
35240
- var ANALYSIS_API_URL, ACTIVITY_API_URL, SESSION_ID, LOG_LEVEL, MAX_REQUESTS_PER_MINUTE, HEALTH_PORT, METABOB_API_KEY, SESSION_TOKEN, USE_CONNECTION_SLOTS, IDENTITY_ENDPOINT, ACTIVITY_ENDPOINT, VESSEL_ID, VESSEL_ENDPOINT, apiClient, sessionManager, rateLimiter, circuitBreaker, authService, identityApiKey, vesselServer, vesselHeartbeat, server;
35131
+ var ANALYSIS_API_URL, ACTIVITY_API_URL, SESSION_ID, LOG_LEVEL, MAX_REQUESTS_PER_MINUTE, HEALTH_PORT, METABOB_API_KEY, SESSION_TOKEN, USE_CONNECTION_SLOTS, IDENTITY_ENDPOINT, apiClient, sessionManager, rateLimiter, circuitBreaker, authService, identityApiKey, vesselServer, server;
35241
35132
  var init_src = __esm(() => {
35242
35133
  init_server2();
35243
35134
  init_stdio2();
@@ -35257,9 +35148,6 @@ var init_src = __esm(() => {
35257
35148
  SESSION_TOKEN = process.env.SESSION_TOKEN;
35258
35149
  USE_CONNECTION_SLOTS = process.env.USE_CONNECTION_SLOTS === "true";
35259
35150
  IDENTITY_ENDPOINT = process.env.IDENTITY_ENDPOINT || "https://identity.metabob.com";
35260
- ACTIVITY_ENDPOINT = process.env.ACTIVITY_ENDPOINT || "https://activity.metabob.com";
35261
- VESSEL_ID = process.env.VESSEL_ID || "metabob_mcp";
35262
- VESSEL_ENDPOINT = process.env.VESSEL_ENDPOINT || `http://localhost:${HEALTH_PORT}`;
35263
35151
  apiClient = new AnalysisAPIClient({
35264
35152
  baseURL: ANALYSIS_API_URL,
35265
35153
  activityApiUrl: ACTIVITY_API_URL,
@@ -35298,21 +35186,6 @@ var init_src = __esm(() => {
35298
35186
  apiKey: METABOB_API_KEY,
35299
35187
  authService
35300
35188
  });
35301
- vesselHeartbeat = new VesselHeartbeat({
35302
- activityEndpoint: ACTIVITY_ENDPOINT,
35303
- vesselId: VESSEL_ID,
35304
- vesselName: "Metabob MCP",
35305
- endpoint: VESSEL_ENDPOINT,
35306
- shapes: [
35307
- "mcp:tool_call",
35308
- "code:cochange_prediction",
35309
- "code:impact_analysis",
35310
- "code:git_change_assignment",
35311
- "code:analysis_context"
35312
- ],
35313
- metadata: { version: "0.2.0" },
35314
- authService
35315
- });
35316
35189
  server = new Server({
35317
35190
  name: "metabob-mcp",
35318
35191
  version: "0.2.0"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metabob/mcp",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "MCP server exposing Metabob analysis capabilities to AI agents",
5
5
  "type": "module",
6
6
  "bin": {