npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

mcpcodeserver

v1.0.14

Published

MCP proxy server that translates tool calls into TypeScript code generation

Readme

mcpcodeserver

A Model Context Protocol (MCP) proxy server that translates tool calls into TypeScript code generation. Instead of making multiple tool calls back and forth, LLMs can write TypeScript code that calls multiple tools naturally, reducing token overhead and leveraging the LLM's superior code generation capabilities.

Overview

mcpcodeserver is a unique MCP server that:

  • Acts as an MCP client to connect to one or more child MCP servers
  • Discovers all tools from child servers
  • Exposes three powerful tools to parent LLM clients:
    1. list_servers - Lists all available sub-servers connected to this MCP server
    2. get_tool_definitions - Returns TypeScript type definitions for discovered tools (optionally filtered by server)
    3. generate_and_execute_code - Generates and executes TypeScript code that calls those tools in a sandbox

This architecture allows LLMs to orchestrate complex multi-tool workflows by writing code instead of making sequential tool calls, which is often more efficient and natural for modern language models.

Type Conflict Detection

When multiple MCP servers expose tools with the same name but different parameter schemas, mcpcodeserver automatically detects these conflicts and resolves them by adding server prefixes to the generated TypeScript interfaces.

Example:

  • filesystem.read_fileReadFileParams (no conflict)
  • memory.read_fileMemoryReadFileParams (conflict detected, server prefix added)

This ensures TypeScript compilation succeeds and prevents runtime errors from parameter mismatches.

Related Work & Research

This approach is inspired by recent research showing that LLMs perform better when generating executable code rather than making direct tool calls:

  • CodeAct: Your LLM Agent Acts Better when Generating Code (Apple, ICML 2024) - Demonstrates that LLM agents achieve up to 20% higher success rates when using executable Python code as a unified action space instead of pre-defined tool calling formats.

  • Cloudflare Code Mode - A similar implementation that converts MCP tools into TypeScript APIs, showing that "LLMs are better at writing code to call MCP, than at calling MCP directly."

The key insight from this research is that LLMs have extensive training on real-world code but limited exposure to synthetic tool-calling formats, making code generation a more natural and effective approach for complex agent workflows.

Why Use This?

Traditional Tool Calling Problems

  • Multiple round-trips between LLM and tools burn tokens
  • LLMs often struggle with complex tool calling sequences
  • Each tool call requires JSON schema understanding and formatting
  • Data cannot easily be passed between tools without going through the LLM

Code Generation Solution

  • Write TypeScript code to call multiple tools in sequence
  • Use variables, loops, and conditionals naturally
  • Better error handling with try/catch
  • Reduce token usage by combining operations
  • Leverage LLM's strong code generation capabilities

Dynamic Tool Discovery

mcpcodeserver automatically monitors child MCP servers for tool changes and notifies parent clients when tools are added, removed, or modified:

  • Automatic Refresh: Checks for tool changes every 30 seconds
  • Real-time Notifications: Sends notifications/tools/list_changed to parent clients
  • Dynamic Updates: Tool definitions and summaries update automatically
  • No Manual Refresh: Parent LLMs receive notifications to refresh their tool knowledge

This ensures that parent LLMs always have the most current tool definitions without requiring manual intervention.

Server Filtering

To reduce context window usage and improve focus, mcpcodeserver supports filtering tool definitions by specific servers:

  • List Available Servers: Use list_servers to see all connected sub-servers
  • Filtered Tool Definitions: Use get_tool_definitions with server_names parameter to get tools from specific servers only
  • Reduced Verbosity: Get focused TypeScript definitions without overwhelming the LLM's context window
  • Method Namespacing: All generated functions are prefixed with server names (e.g., pizzashop_create_pizza, filesystem_read_file)

Example usage:

// List available servers
const servers = await list_servers({});
// Returns: ["pizzashop", "filesystem", "memory"]

// Get all tool definitions
const allTools = await get_tool_definitions({});

// Get only pizzashop tools
const pizzashopTools = await get_tool_definitions({
  server_names: ["pizzashop"]
});

Advanced MCP Features

mcpcodeserver supports pass-through of advanced MCP protocol features when both parent and child servers support them:

  • Elicitation: Child servers can request user input during tool execution, which is passed through to parent clients
  • Roots: Lists and aggregates roots from all child servers, providing a unified view of available resources
  • Sampling: Enables LLM sampling requests to be passed through to child servers for advanced AI capabilities

These features are automatically advertised to parent clients and work seamlessly when supported by the underlying child MCP servers.

Quick Start

Try it immediately with npx (no installation required):

# From GitHub
npx github:zbowling/mcpcodeserver --help

# Or when published to npm
npx mcpcodeserver --help

Installation for Development

# Install dependencies (using Bun for faster performance)
bun install

# Or with npm
npm install

# Build the project
bun run build

# Test the built server
bun dist/index.js --help

Note: This project uses Bun for better performance, but npm/node also work fine.

Running Modes

Stdio Mode (Default)

The server runs in stdio mode by default, which is perfect for integration with MCP clients like Claude Desktop:

# Run in stdio mode
npx mcpcodeserver --config mcp.json

# Or with custom config path
npx mcpcodeserver --config /path/to/your/mcp.json

HTTP Mode

For debugging, testing, or integration with web-based MCP clients, you can run the server in HTTP mode:

# Run in HTTP mode on default port 3000
npx mcpcodeserver --http --config mcp.json

# Run on custom port and host
npx mcpcodeserver --http --port 8080 --host 0.0.0.0 --config mcp.json

When running in HTTP mode, the server will be available at:

  • Server URL: http://localhost:3000/mcp (or your custom host:port)
  • MCP Inspector: Use npx @modelcontextprotocol/inspector http://localhost:3000/mcp to debug and test

MCP Inspector Integration

The MCP Inspector is a powerful tool for debugging and testing MCP servers. When running in HTTP mode, you can use it to:

  • Inspect available tools and their schemas
  • Test tool calls interactively
  • Debug resource access and prompts
  • Monitor real-time notifications
# Start the server in HTTP mode
npx mcpcodeserver --http --config mcp.json

# In another terminal, start the MCP Inspector
npx @modelcontextprotocol/inspector http://localhost:3000/mcp

# Or use the shorthand script (includes all example servers)
npm run inspector

The inspector will open in your browser and provide a full interface for exploring and testing your MCP server.

Note: The npm run inspector command uses mcp-test.json which includes 8 MCP servers (67 tools total) from the official examples, including both TypeScript (npx) and Python (uvx) based servers.

Configuration

Create an mcp.json file that defines which child MCP servers to connect to. This follows the standard MCP client configuration format:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
      "env": {
        "DEBUG": "false"
      }
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your-token-here"
      }
    },
    "weather": {
      "url": "http://localhost:3000/mcp",
      "transport": "sse"
    }
  }
}

Configuration Options

Each server entry supports:

For stdio transport:

  • command (required) - The command to execute (e.g., "node", "python", "npx")
  • args (optional) - Array of arguments to pass to the command
  • env (optional) - Environment variables for the child process

For HTTP/SSE transport:

  • url (required) - The HTTP endpoint URL
  • transport - Set to "sse" for Server-Sent Events

Usage

Starting the Server

# Use default config (./mcp.json)
mcpcodeserver

# Use custom config location
mcpcodeserver --config /path/to/custom-mcp.json

# Show help
mcpcodeserver --help

Using as an MCP Server

Configure mcpcodeserver in your MCP client (like Claude Desktop, Claude Code, Cline, etc.):

With npx (recommended - no installation needed):

{
  "mcpServers": {
    "codeserver": {
      "command": "npx",
      "args": ["-y", "mcpcodeserver", "--config", "/path/to/mcp.json"]
    }
  }
}

From GitHub (works immediately):

{
  "mcpServers": {
    "codeserver": {
      "command": "npx",
      "args": ["-y", "github:zbowling/mcpcodeserver", "--config", "/path/to/mcp.json"]
    }
  }
}

With other package managers:

// yarn
{ "command": "yarn", "args": ["dlx", "mcpcodeserver", "--config", "/path/to/mcp.json"] }

// pnpm
{ "command": "pnpm", "args": ["dlx", "mcpcodeserver", "--config", "/path/to/mcp.json"] }

// bun
{ "command": "bunx", "args": ["mcpcodeserver", "--config", "/path/to/mcp.json"] }

See examples/ for more configuration examples and MCP client-specific setups.

Tool 1: get_tool_definitions

This tool returns TypeScript type definitions for all discovered tools from child servers.

Input:

  • include_examples (optional boolean) - Whether to include usage examples

Example:

// Call the tool (in your MCP client)
get_tool_definitions({ include_examples: true })

Output: Returns TypeScript code with interfaces and function declarations:

/**
 * Auto-generated TypeScript definitions for MCP tools
 */

interface ToolResult {
  content: Array<{
    type: string;
    text?: string;
    // ...
  }>;
  isError?: boolean;
}

/**
 * Read contents of a file
 * Server: filesystem
 * Tool: read_file
 */
interface ReadFileParams {
  path: string;
}

declare function filesystem_read_file(params: ReadFileParams): Promise<ToolResult>;

// ... more tool definitions

Tool 2: generate_and_execute_code

This tool executes TypeScript code in a sandbox with access to all discovered tool functions.

Input:

  • code (required string) - TypeScript/JavaScript code to execute
  • timeout (optional number) - Max execution time in milliseconds (default: 30000, max: 300000)

Example:

// Call the tool with TypeScript code
generate_and_execute_code({
  code: `
    // Read multiple files and combine them
    const file1 = await filesystem_read_file({ path: "/tmp/file1.txt" });
    const file2 = await filesystem_read_file({ path: "/tmp/file2.txt" });

    const text1 = file1.content[0].text;
    const text2 = file2.content[0].text;

    console.log("File 1 length:", text1.length);
    console.log("File 2 length:", text2.length);

    return {
      combined: text1 + text2,
      totalLength: text1.length + text2.length
    };
  `
})

Output:

=== Console Output ===
File 1 length: 42
File 2 length: 38

=== Result ===
{
  "combined": "...",
  "totalLength": 80
}

Sandbox Environment

The TypeScript execution sandbox provides:

Available:

  • All discovered tool functions (as async functions)
  • Console methods: console.log(), console.error(), console.warn(), console.info()
  • Basic JavaScript globals: Math, JSON, Date, Array, Object, String, Number, Boolean
  • Promise and async/await support
  • Error handling with try/catch
  • Timers: setTimeout, setInterval, clearTimeout, clearInterval

Not Available:

  • Node.js modules (fs, http, child_process, etc.)
  • File system access (except via MCP tools)
  • Network access (except via MCP tools)
  • Process information

Security Note: This is not a fully secure sandbox. The VM context provides isolation but is not bulletproof. Only execute trusted code.

Error Handling

Errors in the sandbox are caught and returned with stack traces:

generate_and_execute_code({
  code: `
    try {
      const result = await filesystem_read_file({ path: "/nonexistent" });
      return result;
    } catch (error) {
      console.error("Failed to read file:", error.message);
      throw error; // Re-throw to surface to parent
    }
  `
})

Testing with Claude Code

Want to try mcpcodeserver with Claude Code? Use the one-command setup:

./setup-claude-code-test.sh

This will build the project, install test dependencies, and show you exactly what to add to your Claude Code configuration. See TESTING_WITH_CLAUDE.md for detailed instructions.

Development

# Install dependencies
bun install

# Build the project
bun run build

# Watch mode for development
bun run dev

# Run the server
bun start

# Run tests
bun test                # All tests
bun run test:unit       # Unit tests only
bun run test:integration # Integration tests (requires Python)

# Code quality
bun run lint            # Check linting
bun run format          # Format code
bun run typecheck       # Type checking

Project Structure

See AGENTS.md for detailed project structure and component documentation.

Use Cases

Multi-File Operations

Instead of making multiple tool calls through the LLM, write code:

const files = ["/tmp/a.txt", "/tmp/b.txt", "/tmp/c.txt"];
const contents = await Promise.all(
  files.map(path => filesystem_read_file({ path }))
);
return contents.map(r => r.content[0].text);

Data Transformation

Process data between tool calls without LLM intervention:

const data = await api_fetch({ url: "https://api.example.com/data" });
const json = JSON.parse(data.content[0].text);
const filtered = json.items.filter(item => item.active);
return filtered.length;

Conditional Logic

Make decisions based on tool results:

const exists = await filesystem_read_file({ path: "/tmp/config.json" });
if (exists.isError) {
  console.log("Config doesn't exist, using defaults");
  return { source: "defaults" };
} else {
  return { source: "file", config: JSON.parse(exists.content[0].text) };
}

Error Recovery

Handle errors gracefully without aborting the entire workflow:

const results = [];
for (const path of ["/tmp/a.txt", "/tmp/b.txt", "/tmp/c.txt"]) {
  try {
    const content = await filesystem_read_file({ path });
    results.push({ path, success: true, data: content });
  } catch (error) {
    results.push({ path, success: false, error: error.message });
  }
}
return results;

Upstream MCP Servers Integration

mcpcodeserver can integrate with official upstream MCP servers from the Model Context Protocol servers repository. This allows you to use real, production-ready MCP servers alongside your custom tools.

Supported Upstream Servers

  • filesystem: File system operations (read, write, list directories)
  • memory: In-memory key-value storage
  • sqlite: SQLite database operations
  • github: GitHub API integration
  • brave-search: Web search capabilities
  • fetch: HTTP request capabilities

Example Configuration

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    },
    "memory": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-memory"]
    },
    "sqlite": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sqlite", "--db-path", "/tmp/test.db"]
    }
  }
}

Testing Upstream Integration

The project includes comprehensive tests for upstream server integration:

# Run upstream servers integration tests
bun tests/integration/run-upstream-tests.ts

# Or manually test with upstream config
npx mcpcodeserver --config tests/integration/upstream-test-config.json

Cross-Server Workflows

With upstream servers, you can create powerful cross-server workflows:

// Store database query results in memory and write to file
const queryResult = await sqlite_execute_sql({
  sql: "SELECT COUNT(*) as count FROM users"
});
const count = queryResult.content[0].text;

await memory_create({
  key: "user-count",
  value: count
});

await filesystem_write_file({
  path: "/tmp/user-count.txt",
  content: `Total users: ${count}`
});

Limitations

  • Execution timeout: Maximum 5 minutes (configurable, default 30 seconds)
  • Memory: Limited by Node.js VM context
  • No persistent state between executions
  • Cannot require/import external modules
  • Not a security sandbox - don't run untrusted code

Contributing

Contributions welcome! This project is built with:

  • TypeScript 5.7+
  • Node.js 18+
  • MCP TypeScript SDK 1.20+
  • Zod for validation

See CONTRIBUTING.md for detailed contribution guidelines.

Support

If you find this project helpful, consider buying me a coffee!

Buy Me A Coffee

License

MIT

Resources