Skip to content

Chore: Smithery build metadata (smithery.yaml) and docs/tests alignment#17

Merged
cloudbring merged 10 commits into
masterfrom
chore/smithery-cli-docs-and-env-tests
Aug 9, 2025
Merged

Chore: Smithery build metadata (smithery.yaml) and docs/tests alignment#17
cloudbring merged 10 commits into
masterfrom
chore/smithery-cli-docs-and-env-tests

Conversation

@cloudbring
Copy link
Copy Markdown
Owner

@cloudbring cloudbring commented Aug 9, 2025

Add explicit Smithery build metadata (entry/start) and align docs/tests with tool discovery behavior.

  • Add entry and start.command to smithery.yaml so the Smithery CLI can find the entry point and start command.
  • Update README with Smithery CLI guidance and prefer TypeScript runtime.
  • Align server env-validation tests to allow construction without NEW_RELIC_API_KEY (tool-discovery).

CI: lint + tests pass locally.

Summary by CodeRabbit

  • Chores
    • Updated configuration to specify the application entry point, start command, and port number.
    • Added new scripts for running coverage and integration tests.
    • Improved test reliability by managing environment variables and type handling.
    • Refined test runner configuration for better directory exclusions and coverage settings.
    • Enhanced CI workflow with coverage thresholds, artifact uploads, and coverage summaries.
  • Tests
    • Added comprehensive tests for HTTP request methods in the REST client.
    • Extended alert tool tests to cover pagination behavior and tool definition retrieval.
    • Introduced extensive tests for server tool execution covering multiple tool interactions and error handling.
    • Added new test suites for NerdGraph tool and REST tools including APM and Metrics with detailed parameter and pagination coverage.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 9, 2025

Warning

Rate limit exceeded

@cloudbring has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 48 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 50a5bab and ccbc155.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml (2 hunks)
  • test/server/server-execute-tools.test.ts (1 hunks)
  • test/tools/rest/metrics.test.ts (2 hunks)

Walkthrough

The configuration file smithery.yaml was updated to specify an explicit application entry point, add a start section with the start command and port number, and retain the existing NODE_ENV environment variable setting. Two new npm scripts for AI-related test coverage and integration testing were added to package.json. Tests in test/server/server.test.ts were adjusted for environment variable handling and type casting. A new test suite was added for NewRelicRestClient HTTP methods. Additional tests were added to the REST Alerts Tool suite. The Vitest configuration was modified to change exclude patterns by adding trailing slashes and to refine coverage inclusion and exclusion patterns. The CI workflow was updated to run the new coverage script with thresholds, upload coverage reports as artifacts, and append coverage summaries to the GitHub Actions job summary. Several new test suites were added for server tool execution, NerdGraph tool, REST APM, REST Metrics, and REST Alerts tools to increase coverage and validate behavior including pagination and input validation.

Changes

Cohort / File(s) Change Summary
Configuration Update
smithery.yaml
Added entry key for application entry point, introduced start section with command and port, retained NODE_ENV.
NPM Script Additions
package.json
Added new npm scripts ai:test:coverage (Vitest with coverage) and ai:test:integration (Vitest with USE_REAL_ENV=true).
Server Tests Update
test/server/server.test.ts
Updated tests to set and restore NEW_RELIC_API_KEY env var, mocked validateCredentials, and added type casts for tools.
NewRelicRestClient Tests
test/client/rest-client/rest-client-requests.test.ts
Added new test suite for NewRelicRestClient covering GET, POST, and DELETE HTTP methods with mocked fetch and response checks.
REST Alerts Tool Tests
test/tools/rest/alerts.test.ts
Added tests for pagination behavior without auto-pagination and for tool definition retrieval.
Vitest Configuration Update
vitest.config.ts
Modified Vitest exclude patterns by adding trailing slashes; refined coverage include and exclude arrays with TypeScript files; added coverage thresholds.
CI Workflow Update
.github/workflows/ci.yml
Replaced coverage step to run new coverage script with thresholds, renamed coverage upload step, added artifact upload for HTML report, and appended coverage summary to job.
Server Tool Execution Tests
test/server/server-execute-tools.test.ts
Added comprehensive tests for NewRelicMCPServer.executeTool covering multiple tools, input validation, and error handling.
NerdGraph Tool Tests
test/tools/nerdgraph.test.ts
Added tests for NerdGraphTool verifying query tool schema, execution, and error on empty query.
REST APM Tool Tests
test/tools/rest/apm.test.ts
Added tests for listApplications verifying query parameter mapping, pagination control, and empty filter handling.
REST Metrics Tool Tests
test/tools/rest/metrics.test.ts
Added tests for listMetricNames and getMetricData verifying pagination, query parameters, and auto-pagination behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • REST v2: list_apm_applications tool #6: This PR adds tests for the list_apm_applications tool verifying query parameter mapping and pagination behavior, directly addressing the design and requirements described in this issue.

Poem

A config set, a script to run,
Tests expanded, one by one.
Fetch is mocked, alerts in sight,
Coverage shines with clearer light.
CI reports and summaries too,
Rabbit hops with joy anew,
“Code grows strong and tests come through!” 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/smithery-cli-docs-and-env-tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
smithery.yaml (1)

4-4: Add Node source maps for better TS stack traces (optional)

Consider enabling source maps at runtime for readable production traces, provided you emit source maps in the build.

-  command: ["node", "dist/server.js"]
+  command: ["node", "--enable-source-maps", "dist/server.js"]

If you haven’t already, ensure sourceMap: true (or equivalent) in your TS/bundler config.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc5d635 and bad135b.

📒 Files selected for processing (1)
  • smithery.yaml (1 hunks)
🔇 Additional comments (2)
smithery.yaml (2)

2-2: Entry configuration verified

All checks pass—src/server.ts exists, tsconfig.json outputs to ./dist from ./src, and package.json scripts and main/bin fields point to dist/server.js. No changes needed.


5-5: Ensure smithery.yaml port matches your server’s actual listen port

I didn’t find any process.env.PORT usage or app.listen (or similar) calls binding to port 8000 in the codebase. If your server doesn’t bind to 8000, health checks and startup may fail.

• No occurrences of process.env.PORT or .listen( in src/
• No hard-coded 8000, 3000 or 8080 found in the code

Please verify that your server startup code uses port 8000 (or update smithery.yaml to the port your app actually listens on).

…y setting NEW_RELIC_API_KEY during server.start(); fix tool schema assertions for type-safety; vitest: tweak exclude globs; package: add ai:test:integration script
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
vitest.config.ts (1)

13-13: Harden test.exclude globs; verify coverage exclusion removal is intentional

  • Globs like 'node_modules/' and 'dist/' may not consistently exclude nested files across engines. Prefer '/node_modules/' and 'dist/**' (or rely on Vitest defaults, which already exclude node_modules).
  • Also double-check that dropping coverage.exclude is intentional; it can pull test files and configs into coverage and skew metrics.

Suggested tweak:

-    exclude: ['node_modules/', 'dist/'],
+    exclude: ['**/node_modules/**', 'dist/**'],
test/server/server.test.ts (6)

58-65: Avoid env bleed; prefer vi.stubEnv when available

Setting process.env directly works, but Vitest offers helpers that sandbox and auto-restore. Consider:

If your Vitest version supports it:

-      const originalApiKey = process.env.NEW_RELIC_API_KEY;
-      process.env.NEW_RELIC_API_KEY = 'test-key';
-      try {
-        await server.start();
-        expect(mockClient.validateCredentials).toHaveBeenCalled();
-      } finally {
-        process.env.NEW_RELIC_API_KEY = originalApiKey;
-      }
+      vi.stubEnv('NEW_RELIC_API_KEY', 'test-key');
+      await server.start();
+      expect(mockClient.validateCredentials).toHaveBeenCalled();
+      vi.unstubAllEnvs?.();

Fallback to your current try/finally if vi.stubEnv isn’t available in your version.


69-76: Use vi.spyOn instead of reassigning mock method; also consider vi.stubEnv

Reassigning the mock is fine but vi.spyOn is more idiomatic and restores cleanly.

-      const originalApiKey = process.env.NEW_RELIC_API_KEY;
-      process.env.NEW_RELIC_API_KEY = 'test-key';
-      try {
-        mockClient.validateCredentials = vi.fn().mockResolvedValue(false);
-        await expect(server.start()).rejects.toThrow('Invalid New Relic API credentials');
-      } finally {
-        process.env.NEW_RELIC_API_KEY = originalApiKey;
-      }
+      vi.stubEnv?.('NEW_RELIC_API_KEY', 'test-key');
+      vi.spyOn(mockClient, 'validateCredentials').mockResolvedValue(false);
+      await expect(server.start()).rejects.toThrow('Invalid New Relic API credentials');
+      vi.unstubAllEnvs?.();

If vi.stubEnv is unavailable, keep your try/finally env restoration but still prefer vi.spyOn.


82-82: Narrow casts: replace as any with a tiny test-only type

Casting the entire tool to any loses type safety. Prefer a minimal test interface for the properties you assert.

Add once at the top of this test file:

// Test-only type to keep assertions type-safe
type TestTool = {
  name: string;
  description: string;
  inputSchema: {
    properties?: Record<string, any>;
    required?: string[];
  };
};

Then change here:

-      const tool = server.getTool('run_nrql_query') as any;
+      const tool = server.getTool('run_nrql_query') as TestTool;

87-87: Optional: localize the unsafe cast to just the schema property

You already assert the property exists; keep the cast tight:

-      expect((tool.inputSchema as any).properties.nrql.type).toBe('string');
+      expect((tool.inputSchema as any).properties.nrql.type).toBe('string'); // OK

Note: This line is fine; the main improvement is avoiding as any on the whole tool (see prior comment).


92-92: Apply the same typed cast pattern to APM tool

-      const tool = server.getTool('list_apm_applications') as any;
+      const tool = server.getTool('list_apm_applications') as TestTool;

100-100: Apply the same typed cast pattern to entity search tool

-      const tool = server.getTool('search_entities') as any;
+      const tool = server.getTool('search_entities') as TestTool;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bad135b and 6347bc2.

📒 Files selected for processing (3)
  • package.json (1 hunks)
  • test/server/server.test.ts (1 hunks)
  • vitest.config.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • package.json

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (6)
test/tools/rest/alerts.test.ts (2)

45-56: Assert single request when auto_paginate is false

To lock in the intent that pagination is disabled, assert the client was called only once.

   const out = await tool.listIncidents({ auto_paginate: false });
   expect(Array.isArray((out as any).items)).toBeTruthy();
   expect((out as any).items).toHaveLength(1);
   expect((out as any).items[0].id).toBe(10);
+  expect(get).toHaveBeenCalledTimes(1);

58-64: Strengthen tool-definition assertions (description + schema presence)

Names are good; also assert descriptions and a schema-like object exist to better cover the definitions.

   const tool = new RestAlertsTool();
   const policiesTool = tool.getListPoliciesTool();
   const incidentsTool = tool.getListIncidentsTool();
-  expect(policiesTool.name).toBe('list_alert_policies_rest');
-  expect(incidentsTool.name).toBe('list_open_incidents_rest');
+  expect(policiesTool.name).toBe('list_alert_policies_rest');
+  expect(typeof (policiesTool as any).description).toBe('string');
+  const policiesSchema =
+    (policiesTool as any).parameters ??
+    (policiesTool as any).schema ??
+    (policiesTool as any).inputSchema;
+  expect(policiesSchema).toBeDefined();
+
+  expect(incidentsTool.name).toBe('list_open_incidents_rest');
+  expect(typeof (incidentsTool as any).description).toBe('string');
+  const incidentsSchema =
+    (incidentsTool as any).parameters ??
+    (incidentsTool as any).schema ??
+    (incidentsTool as any).inputSchema;
+  expect(incidentsSchema).toBeDefined();
test/client/rest-client/rest-client-requests.test.ts (4)

8-15: Use vi.stubGlobal/vi.unstubAllGlobals for fetch stubbing and cleanup

Avoid manual global mutation and ts-expect-error by leveraging Vitest’s globals stubbing.

-  let originalFetch: typeof global.fetch;
-
-  beforeEach(() => {
-    originalFetch = global.fetch;
-  });
+  // No need to capture original fetch when using vi.stubGlobal

   afterEach(() => {
-    global.fetch = originalFetch;
-    vi.restoreAllMocks();
+    vi.unstubAllGlobals(); // restores any vi.stubGlobal calls
+    vi.restoreAllMocks();
   });
@@
-    // @ts-expect-error: assign to global in tests
-    global.fetch = mockFetch;
+    vi.stubGlobal('fetch', mockFetch);
@@
-    // @ts-expect-error: assign to global in tests
-    global.fetch = mockFetch;
+    vi.stubGlobal('fetch', mockFetch);
@@
-    // @ts-expect-error: assign to global in tests
-    global.fetch = mockFetch;
+    vi.stubGlobal('fetch', mockFetch);

Also applies to: 32-34, 58-60, 85-86


39-45: Add header assertions for GET

Also verify the Accept header is sent (and implicitly that we don’t set Content-Type on GET).

     expect(mockFetch).toHaveBeenCalledWith(
       expect.stringContaining('/applications.json?page=1'),
       expect.objectContaining({
         method: 'GET',
         headers: expect.objectContaining({ 'Api-Key': apiKey }),
       })
     );
+    const init = (mockFetch.mock.calls[0]?.[1] ?? {}) as RequestInit;
+    expect((init.headers as any)).toEqual(
+      expect.objectContaining({ 'Api-Key': apiKey, Accept: 'application/json' })
+    );

66-72: Assert JSON headers for POST

Confirm Content-Type and Accept headers accompany the JSON body.

   expect(mockFetch).toHaveBeenCalledWith(
     expect.any(String),
     expect.objectContaining({
       method: 'POST',
       body: JSON.stringify(payload),
     })
   );
+  const init = (mockFetch.mock.calls[0]?.[1] ?? {}) as RequestInit;
+  expect((init.headers as any)).toEqual(
+    expect.objectContaining({
+      'Api-Key': apiKey,
+      'Content-Type': 'application/json',
+      Accept: 'application/json',
+    })
+  );

87-90: Also assert DELETE request shape (method, URL, headers)

Strengthen this test by checking the request construction alongside error handling.

   await expect(client.delete('/applications/1/deployments/2')).rejects.toThrow(
     'REST API error: 404 Not Found'
   );
+  expect(mockFetch).toHaveBeenCalledWith(
+    expect.stringContaining('https://api.newrelic.com/v2/applications/1/deployments/2.json'),
+    expect.objectContaining({
+      method: 'DELETE',
+      headers: expect.objectContaining({ 'Api-Key': apiKey }),
+    })
+  );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 933cbbc and 2b8cbf2.

📒 Files selected for processing (3)
  • test/client/rest-client/rest-client-requests.test.ts (1 hunks)
  • test/tools/rest/alerts.test.ts (1 hunks)
  • vitest.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • vitest.config.ts

…n coverage in CI; upload HTML report artifact; add markdown summary to PR job
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
.github/workflows/ci.yml (1)

47-55: Codecov action input name is incorrect; use “files” (and consider upgrading to v4).

codecov/codecov-action@v3 expects “files” (comma-separated), not “file”. With “file” nothing may upload.

Minimal fix for v3:

-      - name: Upload coverage reports to Codecov
+      - name: Upload coverage reports to Codecov
         if: matrix.node-version == '20.x'
-        uses: codecov/codecov-action@v3
+        uses: codecov/codecov-action@v3
         with:
-          file: ./coverage/coverage-final.json
+          files: ./coverage/coverage-final.json
           flags: unittests
           name: codecov-umbrella
           fail_ci_if_error: false

Optional: upgrade to v4 (recommended by Codecov). Inputs slightly differ; example:

-        uses: codecov/codecov-action@v3
+        uses: codecov/codecov-action@v4
         with:
-          files: ./coverage/coverage-final.json
+          files: ./coverage/coverage-final.json
           flags: unittests
-          name: codecov-umbrella
-          fail_ci_if_error: false
+          name: codecov-umbrella
+          token: ${{ secrets.CODECOV_TOKEN }} # required for private repos; omit if public
+          fail_ci_if_error: false
🧹 Nitpick comments (2)
.github/workflows/ci.yml (2)

44-46: Propagate env vars to the coverage run for parity with tests.

The coverage step likely re-runs tests; mirror env to avoid divergent behavior between “Run tests” and “Check test coverage”.

-      - name: Check test coverage (with thresholds)
-        run: npm run ai:test:coverage
+      - name: Check test coverage (with thresholds)
+        env:
+          USE_REAL_ENV: ${{ vars.USE_REAL_ENV }}
+          NEW_RELIC_API_KEY: ${{ secrets.NEW_RELIC_API_KEY }}
+          NEW_RELIC_ACCOUNT_ID: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
+        run: npm run ai:test:coverage

56-63: Make artifact upload resilient to missing coverage.

Add if-no-files-found to avoid failing the job when the coverage directory is absent (e.g., on early failures).

       - name: Upload HTML coverage as artifact
         if: always()
         uses: actions/upload-artifact@v4
         with:
           name: coverage-html
           path: coverage
+          if-no-files-found: warn
           retention-days: 7
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b8cbf2 and a4eac41.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml (2 hunks)
  • vitest.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • vitest.config.ts

Comment thread .github/workflows/ci.yml
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba0e04a and 50a5bab.

📒 Files selected for processing (4)
  • test/server/server-execute-tools.test.ts (1 hunks)
  • test/tools/nerdgraph.test.ts (1 hunks)
  • test/tools/rest/apm.test.ts (1 hunks)
  • test/tools/rest/metrics.test.ts (2 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
test/server/server-execute-tools.test.ts

[error] 1-1: Test failure in NewRelicMCPServer.executeTool coverage > validates search_entities inputs: expected function to throw error including 'query' but got 'Account ID must be provided'.

🔇 Additional comments (4)
test/tools/nerdgraph.test.ts (1)

5-12: Looks good – solid mocking & isolation.
The mock client pattern combined with beforeEach reset keeps tests independent and readable.

test/tools/rest/apm.test.ts (1)

34-59: Tests read well and assert the right things.
No issues noted; coverage for non-paginate branch and filter_ids=[] is valuable.

test/tools/rest/metrics.test.ts (2)

34-43: Make the “no auto_paginate” intent explicit.

Pass auto_paginate: false in the listMetricNames call to guard against future default-value changes and keep the assertion deterministic.

-const out = await tool.listMetricNames({ application_id: 1, host_id: 2, page: 3 });
+const out = await tool.listMetricNames({
+  application_id: 1,
+  host_id: 2,
+  page: 3,
+  auto_paginate: false,
+});

64-87: Nice parameter-serialization assertions – LGTM.
Covers optional params & pagination off path well.

Comment thread test/server/server-execute-tools.test.ts Outdated
@cloudbring cloudbring merged commit 98dffc2 into master Aug 9, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant