Get Started

The recommended path is the one-command installer, which configures Claude Code, Claude Desktop, Cursor, VS Code, and Windsurf automatically. You can also run TDP standalone with Node.js 18+ or Python.

Installation

Terminal (PowerShell)
git clone https://github.com/eddyficial/tdp.git
cd tdp
.\install.ps1

One command. The installer configures all five AI tools, installs dependencies, starts the server manager in the background, and launches the 5 demo servers automatically. No manual terminal windows needed.

Running the Demo

After running install.ps1, everything starts automatically. The server manager launches all 5 demo servers in the background. No manual terminal windows needed.

5 demo servers ship out of the box

servers/
  calculator_server.py   # add, subtract, multiply, divide, sqrt, percentage
  file_server.py         # read_file, list_directory, file_info, file_exists
  system_server.py       # system_info, network_info, disk_usage, current_time
  weather_server.py      # get_weather, get_forecast
  joke_server.py         # get_joke, get_jokes_by_category, list_categories, random_joke

20 tools available immediately

The bridge re-scans every 15 seconds for new servers and uses fresh connections per tool call, so there are no stale connections.

The bridge discovers all servers and exposes their tools:

Adding Your Own Tools

Write a *_server.py script and drop it in the servers/ folder. The server manager picks it up automatically within 15 seconds. No restarts, no config changes.

servers/my_custom_server.py
import asyncio, os, sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "python"))
from tdp_config import SHARED_SECRET
from lib.discovery import TdpServiceProvider, get_local_ip
from lib.connection import start_server
from lib.mcp import McpServer

tools = {
    "my_tool": {
        "description": "Does something useful",
        "args": ["input"],
        "allowedAgents": None,
        "inputSchema": {
            "type": "object",
            "properties": { "input": { "type": "string" } },
            "required": ["input"],
        },
        "handler": lambda args: f"Processed: {args['input']}",
    },
}

async def main():
    mcp = McpServer(tools, server_name="my-custom-server")
    async def on_ready(conn):
        await mcp.attach(conn)
    server = await start_server(41250, SHARED_SECRET, on_ready)
    discovery = TdpServiceProvider("my-custom-server", 41250,
        [{"name": n, "description": t["description"], "args": t["args"]}
         for n, t in tools.items()])
    await discovery.start()
    await asyncio.Future()

asyncio.run(main())

Drop that file into servers/ and the bridge picks it up on its next scan (every 15 seconds). The bridge uses fresh connections per tool call, so there are never stale connections. Your new tools appear in Claude Code, Cursor, VS Code, Claude Desktop, and Windsurf automatically.

Configuration

Edit tdp.config.js or set environment variables.

SettingEnv VarDefaultDescription
sharedSecretTDP_SECRETtdp-prototype-...HMAC auth secret
agentSecrets--nullPer-agent secrets { agentId: secret }
allowedAgents--nullAgent allow list (null = all)
manifestSecret--nullHMAC key to sign broadcasts
trustedManifestSecret--nullOnly accept signed manifests
discoveryPort--41234UDP broadcast port
discoveryInterval--10000Broadcast interval (ms)
dataPort--41235TCP data port
authTimeout--5000Auth timeout (ms)
rpcTimeout--10000RPC timeout (ms)

Security

Each server independently controls its own access. No central authority. All settings default to null (open) for backward compatibility.

Server-side allow lists

Restrict which agents can connect to a server. Set in the provider script.

provider-agent.js
// Only these agents can connect to this server
const allowedAgents = ['claude-agent-01', 'claude-agent-py'];

// Pass to startServer
startServer(port, secret, onReady, { allowedAgents });

// Set to null to allow all authenticated agents
const allowedAgents = null;

Tool-level permissions

Restrict specific tools to specific agents. Agents that are not authorized will not see the tool in tools/list and cannot call it.

provider-agent.js
const tools = {
  read_data: {
    description: 'Read from database',
    allowedAgents: null, // all agents can read
    handler: (args) => { /* ... */ },
  },
  write_data: {
    description: 'Write to database',
    allowedAgents: ['admin-agent'], // only admin can write
    handler: (args) => { /* ... */ },
  },
};

Per-agent secrets (capability tokens)

Give each agent its own HMAC secret instead of sharing one. Agents not in the map fall back to the shared secret.

tdp.config.js
agentSecrets: {
  'claude-agent-01': 'secret-for-claude',
  'admin-agent': 'secret-for-admin',
},

Manifest trust filtering

Sign broadcast manifests so callers can reject rogue servers. Set the same key on provider and caller.

tdp.config.js
// Provider signs manifests
manifestSecret: 'my-manifest-signing-key',

// Caller only accepts signed manifests
trustedManifestSecret: 'my-manifest-signing-key',

Shell bypass protection (command filter)

MCP permissions only gate tool access. An agent with read-only MCP tools can still use PowerShell to run SQL writes directly. TDP includes a command filter that installs as a Claude Code hook and blocks shell commands that violate the security profile.

Four security profiles
read-write  No restrictions. All shell commands allowed.
read-only   SQL reads OK, writes blocked. GET OK, POST/PUT/DELETE blocked.
no-network  All network access via shell blocked (curl, wget, ssh).
strict      Blocks writes, network, and destructive commands.
Install the command filter
py security\install_hook.py                  # read-only profile
py security\install_hook.py --profile strict # strict profile
py security\install_hook.py --remove         # remove the hook

The filter is included in the installer. Edit security/rules.json to customize blocked patterns. All blocked commands are logged to security/blocked.log.

System tray app

The TDP tray app sits in the Windows notification area and gives you real-time visibility into server health. The icon color changes based on status: green when all servers are running, yellow when some are down, red when all are down.

Features
Right-click menu:
  - Live server count and per-server status (port + running/down)
  - Start All / Stop All / Restart Dead Servers
  - Switch security profiles (read-write, read-only, no-network, strict)
  - Open Status Dashboard
  - Open Website

The menu refreshes every time you open it.
The tray app starts automatically on boot via Windows Task Scheduler.
To run manually:  pythonw tdp_tray.py

Web dashboard

A real-time web dashboard for monitoring and managing your TDP servers. Shows server health, security profiles, tool call analytics, and recent activity. Start, stop, and restart servers from the browser. Live updates via WebSocket.

Terminal
py dashboard/server.py    # starts on http://localhost:41200

The dashboard runs locally and talks directly to your TDP servers. No data leaves your machine. You can also open it from the system tray menu.

Status terminal

A lightweight terminal-based status check. Shows all servers, bridge connection, and security profile. Auto-restarts dead servers.

Terminal
py tdp_status.py        # live dashboard (refreshes every 5s)
py tdp_status.py --once # print status once

Multi-Server Mesh

The caller agent uses an AgentMesh that connects to all discovered servers independently. It maintains a unified tool index and routes calls to the correct server automatically.

Auto-discovery

New servers are found automatically via UDP broadcast (Node.js) or mDNS (Python). No config changes needed.

Unified tool routing

The mesh indexes all tools across all servers. callTool('add', {a:1, b:2}) routes to whichever server provides 'add'.

Failover

If a server disconnects, its tools are removed from the index. If multiple servers provide the same tool, the mesh tries the next one.

Health checks

The mesh pings every connected server every 15 seconds. Unreachable servers are marked inactive.

Integrations

TDP is a discovery and connection layer. It sits between your AI agent (Claude, GPT, Cursor, etc.) and your MCP servers. Here is how the pieces connect.

One-Command Install

The installer configures all five supported AI tools, installs Node.js dependencies, and creates a Windows startup task so TDP runs automatically when your machine boots.

Terminal (PowerShell)
git clone https://github.com/eddyficial/tdp.git
cd tdp
.\install.ps1

What it does:

  • +Configures Claude Code as an MCP server in your settings
  • +Adds TDP to Claude Desktop config (claude_desktop_config.json)
  • +Configures Cursor and VS Code MCP settings
  • +Configures Windsurf MCP settings
  • +Installs npm dependencies
  • +Creates Windows Task Scheduler startup tasks for servers and tray app
  • +Launches the system tray app for monitoring and management

How auto-discovery works

When an TDP caller agent starts, it scans the LAN for MCP servers. No URLs to configure. No tokens to distribute. Servers announce themselves, and agents find them.

What happens when the caller starts
1. Caller listens for UDP broadcasts (Node.js)
   and mDNS services (Python) on the LAN

2. Provider broadcasts every 10 seconds:
   { agentId: "sql-server", tools: ["query", "insert"], port: 41235 }

3. Caller receives broadcast, connects via TCP

4. HMAC auth handshake (per-connection)

5. MCP initialize, tools/list, tools/call
   Standard JSON-RPC 2.0 from here on

6. If another server appears, the mesh adds it automatically
   If a server disappears, the mesh removes it

Wrapping an existing MCP server

If you already have an MCP server (file system, database, API wrapper, etc.), you can expose it on the LAN via TDP by writing a thin provider wrapper. The tool logic stays the same. You just add TDP discovery and auth on top.

wrapping-example.js
import config from './tdp.config.js';
import { getLocalIp, startBroadcasting } from './lib/discovery.js';
import { startServer } from './lib/connection.js';
import { McpServer } from './lib/mcp.js';

// Your existing tool logic
const tools = {
  query: {
    description: 'Query the production database',
    args: ['sql'],
    allowedAgents: ['data-agent'],  // restrict access
    inputSchema: {
      type: 'object',
      properties: { sql: { type: 'string' } },
      required: ['sql'],
    },
    handler: async ({ sql }) => {
      // Call your existing DB logic here
      const rows = await db.query(sql);
      return rows;
    },
  },
};

// Wrap it with TDP discovery + auth
const mcpServer = new McpServer(tools, { name: 'db-server' });
const manifest = {
  agentId: 'db-server',
  role: 'provider',
  dataPort: 41237,
  ip: getLocalIp(),
  tools: Object.keys(tools).map(n => ({ name: n })),
};

startServer(41237, config.sharedSecret, (conn) => {
  mcpServer.attach(conn);
}, { allowedAgents: ['data-agent', 'admin-agent'] });

startBroadcasting(manifest, config);

Any agent on the LAN running an TDP caller will discover this server automatically and can call its tools if authorized.

Integration with AI tools

The install.ps1 installer configures all five AI tools automatically. You can also run TDP standalone with Node.js or Python.

Claude Code (CLI)

Available

Configured by install.ps1. TDP registers as an MCP server in Claude Code settings. Claude discovers LAN tools automatically and can call them like any other MCP tool.

VS Code / Cursor

Available

Configured by install.ps1. TDP is added to the MCP settings for both editors. Discovered tools appear without manual config.

Claude Desktop

Available

Configured by install.ps1. TDP is added to claude_desktop_config.json so LAN servers appear in Claude Desktop without editing JSON files.

Windsurf

Available

Configured by install.ps1. TDP is added to Windsurf MCP settings. Discovered tools are available inside Windsurf sessions.

Ollama

Planned

Expose local Ollama models as TDP tools. Other agents on the LAN can call your local LLM for inference.

Python (standalone)

Available

provider_agent.py and caller_agent.py with mDNS discovery. pip install zeroconf, then run.

Node.js (standalone)

Available

provider-agent.js and caller-agent.js with UDP discovery. Zero dependencies, just run with Node.js 18+.

Logging

Since TDP has no central gateway for logging, each agent can independently log events. Enable file logging by setting the file option.

caller-agent.js
const logger = new TdpLogger('my-agent', {
  console: true,
  file: './tdp.log',  // set to null to disable
});

// Events logged: discover, connect, auth,
// tool-call, tool-result, tool-error,
// disconnect, health