agentleFS
taurgistaurgis/sfcc-dev-mcp/.github/skills/mcp-programmatic-testing/SKILL.md

mcp-programmatic-testing

Skill27 starsChanged 10 months agoMITView on GitHub

Guide for writing JavaScript programmatic MCP server tests using Node.js test runner. Use this when asked to create complex multi-step MCP tests or debug programmatic test files (*.programmatic.test.js).

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use this skill when writing or debugging *.programmatic.test.js files for Model Context Protocol servers.

    line 8
  2. Distinctive:

    If timing validation is required, use lenient thresholds:

    line 124
  3. Distinctive:

    Use aegis query to discover response formats before writing tests:

    line 136

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

MCP Programmatic Testing Skill

Use this skill when writing or debugging *.programmatic.test.js files for Model Context Protocol servers.

When to Use Programmatic Tests

  • Complex business logic requiring code execution
  • Multi-step workflows with state management
  • Dynamic test case generation
  • Integration with existing JavaScript test suites

For basic functional testing, prefer YAML tests (see mcp-yaml-testing skill).

Basic Test Structure

import { test, describe, before, after, beforeEach } from 'node:test';
import { strict as assert } from 'node:assert';
import { connect } from 'mcp-aegis';

describe('[SERVER_NAME] Programmatic Tests', () => {
  let client;

  before(async () => {
    client = await connect('./aegis.config.docs-only.json');
  });

  after(async () => {
    if (client?.connected) {
      await client.disconnect();
    }
  });

  beforeEach(() => {
    // CRITICAL: Clear buffers to prevent test interference
    client.clearAllBuffers();
  });

  test('should list available tools', async () => {
    const tools = await client.listTools();
    assert.ok(Array.isArray(tools), 'Tools should be array');
    assert.ok(tools.length > 0, 'Should have at least one tool');
  });

  test('should execute tool successfully', async () => {
    const result = await client.callTool('[TOOL_NAME]', { param: 'value' });
    assert.ok(result.content, 'Should return content');
    assert.equal(result.isError, false, 'Should not be error');
  });
});

Critical: Buffer Management

Always include beforeEach with buffer clearing to prevent test flakiness:

beforeEach(() => {
  client.clearAllBuffers();  // Recommended - comprehensive
  // OR: client.clearStderr();  // Minimum - stderr only
});

Without this, stderr from one test can leak into subsequent tests, causing random failures.

Critical: No Concurrent Requests

Never use Promise.all() with MCP requests. MCP uses single stdio with shared buffers:

// ❌ NEVER DO THIS
const results = await Promise.all(tools.map(t => client.callTool(t.name, {})));

// ✅ ALWAYS DO THIS
const results = [];
for (const tool of tools) {
  const result = await client.callTool(tool.name, {});
  results.push(result);
}

Test Execution Commands

# Run individual MCP programmatic test
node --test tests/mcp/node/specific-test.programmatic.test.js

# Run all MCP programmatic tests
npm run test:mcp:node

# Watch mode for development
node --test --watch tests/mcp/node/*.programmatic.test.js

# ❌ WRONG: Don't use npm test with individual files
# npm test -- tests/mcp/node/specific-test.programmatic.test.js  # Runs Jest!

API Reference

// Connection
const client = await connect('./aegis.config.json');
await client.disconnect();

// Tool operations
const tools = await client.listTools();
const result = await client.callTool(name, arguments);

// Debugging
const stderr = client.getStderr();
client.clearStderr();
client.clearAllBuffers();

Performance Testing Guidelines

Performance testing is discouraged in programmatic tests due to CI variability.

If timing validation is required, use lenient thresholds:

// ❌ Too strict for CI
assert.ok(duration < 50, 'Should be under 50ms');

// ✅ CI-friendly
assert.ok(duration < 500, 'Should be under 500ms');

Discovery Before Testing

Use aegis query to discover response formats before writing tests:

npx aegis query search_sfcc_classes 'query:catalog' --config ./aegis.config.docs-only.json

Then use the discovered format to write assertions.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.