MCP server that exposes Apify Actors as tools for AI assistants.
The codebase is built with TypeScript using ES modules and follows a modular architecture with clear separation of concerns.
The server can run in multiple modes:
- Standard Input/Output (stdio): For local integrations and command-line tools like Claude Desktop
- HTTP Streamable: For hosted deployments and web-based MCP clients
- Legacy SSE over HTTP: Legacy version of the protocol for hosted deployments and web-based clients (deprecated and will be removed in the future)
- Simple is better than complex
- If the implementation is hard to explain, it's (usually) a bad idea.
- Ruthlessly minimal: Only implement what's explicitly in scope
- Lightweight: Measure complexity by lines of code, not abstractions
- No over-engineering: Solve the current problem, not hypothetical future ones
- No unsolicited features: Don't add anything not explicitly requested by the human operator
THIS IS NON-NEGOTIABLE. DO NOT SKIP.
After completing ANY code change (feature, fix, refactor), you MUST:
-
Type check:
npm run type-check- Fix ALL TypeScript errors before proceeding
- Zero tolerance for type errors
-
Lint:
npm run lint- Fix ALL lint errors before proceeding
- Use
npm run lint:fixfor auto-fixable issues
-
Unit tests:
npm run test:unit- ALL tests must pass
- If a test fails, fix it before moving on
What to do if verification fails:
- DO NOT proceed to the next task
- Fix the issue immediately
- Re-run verification until green
- Only then continue
- Do NOT use
npm run buildfor type-checking. Usenpm run type-check— it is faster and skips JavaScript output generation. Only usenpm run buildwhen compiled output is explicitly needed (e.g., before integration tests or deployment). - Do NOT run integration tests as an agent. They require a valid
APIFY_TOKEN, which only humans have access to.
- Unit tests:
npm run test:unit(runsvitest run tests/unit) - Integration tests:
npm run test:integration(requires build first, requiresAPIFY_TOKEN— humans only)
tests/unit/— unit tests for individual modulestests/integration/— integration tests for MCP server functionalitytests/integration/suite.ts— main integration test suite where all test cases should be added- Other files in this directory set up different transport modes (stdio, SSE, streamable-http) that all use
suite.ts
tests/helpers.ts— shared test utilitiestests/const.ts— test constants
- Write tests for new features and bug fixes
- Use descriptive test names that explain what is being tested
- Follow existing test patterns in the codebase
- Ensure all tests pass before submitting a PR
IMPORTANT: Add integration test cases to tests/integration/suite.ts, NOT as separate test files.
suite.ts exports createIntegrationTestsSuite(), used by all transport modes (stdio, SSE, streamable-http). Adding tests here ensures they run across all transport types.
How to add a test case:
- Open
tests/integration/suite.ts - Add your test case inside the
describeblock - Use
it()orit.runIf()for conditional tests - Use
client = await createClientFn(options)to create the test client - Always call
await client.close()when done
Example:
it('should do something awesome', async () => {
client = await createClientFn({ tools: ['actors'] });
const result = await client.callTool({
name: HelperTools.SOME_TOOL,
arguments: { /* ... */ },
});
expect(result.content).toBeDefined();
await client.close();
});IMPORTANT: This package (@apify/actors-mcp-server) is used in the private apify-mcp-server-internal repository for the hosted server. Changes here may affect that server. Breaking changes must be coordinated; check whether updates are needed in apify-mcp-server-internal before submitting a PR. See README.md for canary (beta) releases via pkg.pr.new.
- CONTRIBUTING.md — coding standards, patterns, anti-patterns, commit format, PR guidelines, design system rules
- DEVELOPMENT.md — project structure, setup, build system, hot-reload workflow, manual MCP testing
- DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md — UI widget design system rules (read this when doing any UI/widget work)