Skip to main content
Glama
ITSWProj

code-bridge

by ITSWProj

claude-dispatch

Server MCP che espone Claude Code a Claude Desktop, per lavorare su un progetto senza copiare e incollare prompt tra le due applicazioni.

Si ragiona su un problema nella chat di Claude Desktop, e da lì si delega l'esecuzione a Claude Code sul progetto reale. I lavori lunghi girano in background: si avviano, si continua a fare altro, si recupera il risultato quando è pronto.

⚠️ Prima di installarlo

Questo server permette a un modello di eseguire Claude Code sulla tua macchina, con accesso al filesystem. È una superficie di rischio reale e va capita prima di usarlo.

Cosa fa e cosa non fa:

  • Gira solo in locale. Il trasporto è stdio: Claude Desktop lancia il server come processo figlio e ci parla via stdin/stdout. Nessuna porta in ascolto, nessun endpoint pubblico, niente che entri dal firewall.

  • Non limita cosa Claude Code può fare. Il server passa il prompt e basta. I veri freni sono i permessi in .claude/settings.json del progetto: se lì è consentita la scrittura, l'agente scrive.

  • Non c'è allowlist di directory. Qualunque percorso esistente passato come cwd viene accettato. Se ti serve un vincolo più stretto, aggiungi il controllo in avviaClaude ed eseguiClaude.

  • Ogni chiamata a strumento passa dalla conferma di Claude Desktop. Il client chiede l'approvazione prima di invocare il server — a meno che non l'abbia disattivata.

La raccomandazione: configura permessi restrittivi nei progetti su cui lo usi, in particolare per le operazioni irreversibili (migration, cancellazioni, deploy). Un agente che deve chiedere prima di fare danni è più utile di uno veloce.

Related MCP server: Claude MCP

Requisiti

  • Windows, Linux o macOS — testato su Windows 10/11 e Debian/Kali

  • Node.js 18+ — testato su 22

  • Claude Code installato e autenticato

  • Claude Desktop

Installazione

git clone https://github.com/ITSWProj/claude-dispatch.git
cd claude-dispatch
npm install

Verifica che parta:

node server.js

Deve restare appeso in silenzio, senza stampare nulla: sta aspettando input su stdin. È il comportamento corretto. Esci con Ctrl+C.

Configurazione

Il file di configurazione di Claude Desktop è:

Sistema

Percorso

Windows

%APPDATA%\Claude\claude_desktop_config.json

macOS

~/Library/Application Support/Claude/claude_desktop_config.json

Linux

~/.config/Claude/claude_desktop_config.json

Windows:

{
  "mcpServers": {
    "claude-dispatch": {
      "command": "C:\\percorso\\a\\node.exe",
      "args": ["C:\\percorso\\a\\claude-dispatch\\server.js"]
    }
  }
}

macOS / Linux:

{
  "mcpServers": {
    "claude-dispatch": {
      "command": "/percorso/assoluto/a/node",
      "args": ["/percorso/assoluto/a/claude-dispatch/server.js"]
    }
  }
}

Tre punti dove si sbaglia facilmente:

  • Percorso assoluto all'eseguibile di Node, non la parola node. Claude Desktop non eredita il PATH della shell. Se usi nvm, punta all'eseguibile della versione specifica (C:\nvm4w\v22.20.0\node.exe su Windows, ~/.nvm/versions/node/v22.20.0/bin/node su Unix), non alla junction o al symlink current, che cambiano a ogni nvm use. Per trovarlo: where node su Windows, which node su Unix.

  • Su Windows, backslash raddoppiati nel JSON, oppure slash normali (C:/percorso/...), che Node accetta anche lì.

  • Percorso assoluto anche in args: il processo viene avviato con una working directory indefinita, quindi ./server.js non risolve. Su Unix nemmeno ~ viene espanso — quella è una funzione della shell, e qui la shell non c'è.

Poi chiudi Claude Desktop completamente — su Windows anche dall'area di notifica, su macOS con Cmd+Q e non con la X — e riavvialo. La configurazione si legge solo all'avvio.

Se non compare nulla, il sospetto numero uno è il JSON: una virgola di troppo disattiva silenziosamente tutti i server, senza messaggi. Passalo da un validatore.

Lo stderr del server (dove finiscono i console.error()) è nel file mcp-server-claude-dispatch.log, nella cartella logs/ accanto al file di configurazione. Se il processo muore all'avvio, il motivo è scritto lì.

Strumenti

Strumento

Uso

claude_run

Esegue un prompt e attende la risposta. Per compiti brevi.

claude_start

Avvia un lavoro in background, ritorna subito un job_id.

claude_wait

Attende un job avviato; se non è pronto entro hold_ms (default 30s, massimo 60s) riporta "in corso".

claude_status

Elenca le istanze attive, diagnostica quelle bloccate, mostra la credenziale in uso.

claude_kill

Termina un job e tutti i suoi processi figli.

claude_kill_all

Pulizia di emergenza: termina tutte le istanze. Richiede conferma esplicita.

Quale usare

Il discriminante è il tempo. Una domanda circoscritta — "leggi questi file e spiegami come funziona X" — sta bene in claude_run. Un lavoro vero — refactoring, implementazione, esplorazione di un'area sconosciuta — va con claude_start, poi claude_wait finché non è pronto.

claude_run ha un timeout (default 120s) perché una chiamata sincrona che non ritorna blocca la conversazione. claude_start non ne ha: il tetto sta sull'attesa, non sul lavoro.

Anche quell'attesa però è limitata: hold_ms viene tagliato a 60 secondi. Passare valori più alti non allunga l'attesa — semplicemente si richiama claude_wait con lo stesso job_id finché il lavoro non è concluso. È un vincolo voluto: hold_ms lo sceglie il modello, e senza tetto una singola chiamata potrebbe bloccare la conversazione per minuti.

Il limite di istanze contemporanee

Ogni istanza di Claude Code è un processo Node con un contesto in memoria: costa centinaia di MB. Il modello, se una chiamata gli sembra fallita, tende a riprovare — e senza un freno ogni tentativo apre un'istanza nuova. Quattro o cinque tentativi bastano a esaurire la RAM e a congelare la macchina.

Da qui una difesa a tre strati, dal più affidabile al meno:

  1. Tetto rigido. MAX_CONCORRENTI istanze al massimo, sommando claude_start e claude_run, più una soglia minima di RAM libera. È deterministico: non dipende da nessuna decisione del modello né dell'utente, ed è l'unico strato che regge anche durante un loop di retry.

  2. Guard per progetto. Se sullo stesso progetto c'è già un lavoro vivo, non se ne avvia un secondo: lo strumento restituisce DECISIONE RICHIESTA e la scelta torna all'utente.

  3. Le description degli strumenti, che dicono al modello di guardare claude_status prima di avviare e di non ritentare dopo un rifiuto. È persuasione, non applicazione — riduce la frequenza con cui i primi due strati devono intervenire, ma non ci si fa affidamento da sola.

I due valori stanno in cima a server.js:

const MAX_CONCORRENTI = 2;   // istanze contemporanee, start + run
const SOGLIA_RAM_MB = 2000;  // RAM libera sotto cui non si avvia più nulla

Il default è deliberatamente basso. Il costo di tenerlo basso è un'attesa; il costo di tenerlo alto è una macchina congelata. Se ti servono davvero tre lavori in parallelo, cambia la costante.

Le due domande, che sono diverse

Quando claude_start trova un conflitto restituisce DECISIONE RICHIESTA con delle opzioni, e la chiamata va ripetuta con il parametro mode scelto. I casi sono due e vale la pena non confonderli.

C'è un lavoro vivo sul progetto. Le opzioni sono wait (attendere quel job_id) o restart (terminarlo e ripartire). Non esiste una terza via: un processo headless ha già lo stdin chiuso, quindi non c'è modo di infilargli dentro un secondo prompt. O si aspetta, o si interrompe.

Non c'è nessun processo, ma esiste una sessione precedente sul disco. Le opzioni sono resume (riprendere quel contesto) o fresh (ripartire pulito). Qui non si sta riusando un processo — non ce n'è nessuno — ma il contesto salvato da Claude Code, tramite --resume.

Passando mode fin dalla prima chiamata, il guard non chiede nulla e si va dritti.

Il session_id conta

Ogni risposta restituisce un session_id. Riprendere una sessione fa ripartire il lavoro con il contesto già caricato, invece di riesplorare il progetto da zero.

Non è un dettaglio: la prima invocazione su un progetto di medie dimensioni può costare qualche decina di centesimi. Riusare la sessione riduce il costo dei giri successivi di un ordine di grandezza.

Dalla 0.3.0 il server tiene traccia da solo dell'ultima sessione riuscita per ogni progetto e la riprende in automatico. Non serve più ripassare il session_id a mano da una chat all'altra, anche se resta possibile. Per forzare una sessione nuova: mode: "fresh" su claude_start, fresh: true su claude_run.

La mappa è indicizzata per progetto, con il percorso normalizzato (path.resolve, più lowercase su Windows). Senza quella normalizzazione C:\progetti\app e C:/progetti/app/ sarebbero due progetti distinti, e né il resume né il guard scatterebbero.

Da non confondere con il token di autenticazione: il session_id identifica una conversazione con Claude Code, il token identifica te. Vedi Autenticazione.

Autenticazione

Il server non sceglie come autenticarti: si limita a osservare quale credenziale è presente. Ne supporta due, e la differenza non è solo di comodità.

Login salvato

Il caso normale: hai eseguito claude da terminale e completato l'accesso. Il token OAuth ha una scadenza, e la prima invocazione dopo una pausa lunga lo rinnova riscrivendo il file di credenziali. È osservabile: quel file resta intoccato per un'intera giornata di lavoro e cambia solo al primo comando del mattino.

Quella finestra di rinnovo è il punto debole. Lanciando in parallelo, il dispatch può mandare due processi a freddo sullo stesso rinnovo: uno ruota il token, l'altro resta con quello vecchio. Un utente al terminale apre una sessione per volta e non incontra mai questa corsa.

Da qui il lock di riscaldamento: se non gira niente da mezz'ora, la prima invocazione prende un lock e le altre aspettano. Il rilascio avviene alla fine del lavoro o dopo 45 secondi, quello che viene prima — un lavoro lungo non deve tenere fermi gli altri — con un salvagente che apre comunque il lock, perché un lock senza scadenza è un deadlock in attesa di succedere.

Token a vita lunga

Consigliato per questo server, perché elimina il problema invece di gestirlo: chi non usa il login salvato non attraversa mai il rinnovo automatico, e il lock di riscaldamento si disattiva da solo.

claude setup-token

Poi nel claude_desktop_config.json, accanto a command e args:

"env": { "CLAUDE_CODE_OAUTH_TOKEN": "il-token" }

Il campo env non è opzionale: una variabile esportata nella shell non arriva qui. Claude Desktop non lancia il server da una shell, quindi né lui né i suoi figli la ereditano — è lo stesso meccanismo per cui serve il percorso assoluto a Node. Vale identico per ANTHROPIC_API_KEY, che il server riconosce allo stesso modo.

La trappola della precedenza

Le credenziali d'ambiente prevalgono sul login salvato. Quindi se CLAUDE_CODE_OAUTH_TOKEN o ANTHROPIC_API_KEY sono nel campo env e vengono rifiutate, rifare il login non serve a niente: il login salvato non viene nemmeno consultato. Si rifà l'accesso, si rivede lo stesso errore e non si capisce perché.

Per questo il server rileva quale credenziale è in uso e adatta il messaggio: con un token in ambiente dice di rigenerare quello, non di fare il login.

Il rilevamento resta un'inferenza dall'esterno — il server vede il proprio process.env e l'esistenza del file di credenziali, niente di più. Su macOS il login può stare nel portachiavi senza che il file esista, quindi l'assenza del file è etichettata incerto e non "nessun login". La risposta autorevole la dà /status dentro una sessione interattiva di claude.

Il modo rilevato compare in claude_status e in una riga di diagnostica su stderr all'avvio, nel file di log accanto alla configurazione. Se il server non parte, è la prima cosa da leggere.

Quando gli avvii si bloccano

Un errore di autenticazione o di quota, riportato come fallimento generico, somiglia a un guasto passeggero: il modello riprova, e ogni tentativo è un processo che costa secondi e memoria per fallire in modo identico.

Il server riconosce questi fallimenti e apre un circuito che fa fallire i successivi in un millisecondo, con un messaggio che dice cosa fare. Il riconoscimento usa i codici strutturati di Claude Code quando ci sono (authentication_failed, oauth_org_not_allowed) e altrimenti le formulazioni note dei messaggi.

Il circuito si riapre sempre, a velocità diverse: un minuto per i fallimenti che un comando esterno può risolvere, cinque per quelli che richiedono un intervento e per i limiti di quota.

Perché anche i casi apparentemente definitivi si riaprono: la corsa sul rinnovo descritta sopra non ha un messaggio suo, e può presentarsi con le stesse parole di un login davvero scaduto. Un blocco fino all'intervento manuale punirebbe una condizione che si sarebbe risolta da sola. Il compromesso è concedere un tentativo di verifica ogni cinque minuti: se il problema è reale quel tentativo fallisce e richiude il circuito, al costo di un processo ogni cinque minuti; se era spurio, il servizio riprende da solo.

Per riabilitare subito, quando sai di aver risolto:

claude_status(riprova_auth: true)

Diagnosticare un lavoro che sembra bloccato

A un processo headless non si può chiedere "sei ancora attivo?". Non è un demone, non ha un socket di controllo, e il suo stdin è già stato chiuso passandogli il prompt: non esiste un canale per interrogarlo.

claude_status aggira il problema incrociando tre segnali indiretti:

  • il processo esiste (kill(pid, 0), che non uccide: è una sonda);

  • il tempo CPU si muove, misurato su due campioni a distanza di poco meno di un secondo;

  • il file di sessione cresce — Claude Code appende ogni turno a un .jsonl sotto ~/.claude/projects/, quindi il suo mtime dice quando ha prodotto l'ultimo turno.

Nessuno dei tre basta da solo. Insieme distinguono i tre casi che contano: morto, piantato, o semplicemente lento dentro un'operazione lunga. Con dettaglio: true lo strumento riporta anche RAM occupata e secondi dall'ultimo turno.

claude_status mostra due liste separate: le istanze avviate da questo server, su cui può agire, e le altre presenti nel sistema — lanciate a mano in un terminale, o rimaste orfane da un riavvio di Claude Desktop. Queste ultime sono solo informative: la RAM la consumano esattamente come le altre, ma un processo che il server non ha generato non viene mai terminato di iniziativa. Per farlo serve claude_kill_all con include_altri: true, che è esplicito e va chiesto.

Limiti noti

  • Lo stato vive in memoria. Riavviando Claude Desktop mentre un lavoro gira, il processo continua ma il job_id diventa irraggiungibile. Da questa versione quei processi restano almeno visibili: compaiono in claude_status tra le istanze esterne, e claude_kill_all li chiude. Un registro persistito su disco richiederebbe di confermare l'identità del pid contro il riuso, e non c'è ancora.

  • I job in background sopravvivono alla chiusura del client. Su tutte le piattaforme: se hai chiuso Claude Desktop con lavori in corso, quei processi restano vivi. Vanno terminati dal claude_kill_all del server ripartito, oppure a mano (Gestione attività su Windows, pkill -f "claude -p" su Unix).

  • restart interrompe un lavoro a metà. Non è un annullamento pulito: l'agente può aver già scritto parte dei file previsti. Se il progetto è sotto git, conviene passare da git status subito dopo.

  • Il timeout di claude_run uccide l'intero albero di processi, agente incluso, e il lavoro parziale non è recuperabile. Se il compito potrebbe essere lungo, usa claude_start: lì il tempo non è un vincolo.

  • La prima invocazione su un progetto è la più lenta. Sembra un blocco, non lo è.

  • L'identificazione delle istanze esterne è approssimativa. Si cerca la stringa claude nella command line dei processi, quindi è un'euristica. Serve a mostrarle, mai a ucciderle senza conferma.

  • Il riconoscimento dei fallimenti di autenticazione dipende dalle formulazioni dei messaggi. I codici strutturati sono stabili, il testo no: se una versione di Claude Code cambia il fraseggio, un errore può sfuggire al circuito e tornare a essere ritentato. Nessun falso blocco, però — la classificazione gira solo sui rami di fallimento, mai su un esito riuscito che parla di autenticazione.

  • Il rilevamento della credenziale è un'inferenza. Il server legge il proprio process.env e verifica l'esistenza del file di login, niente di più. Su macOS un login nel portachiavi non produce quel file.

  • Su Windows le misure di RAM e CPU sono poco significative. Passando da shell: true, il pid che il server conosce è quello di cmd.exe, non dell'agente: va bene per sapere se il lavoro è vivo e per terminarlo, meno per pesarlo. Su Unix il pid è direttamente claude e i numeri sono reali.

  • Nessun limite di spesa. Il server non impone tetti di costo o di turni. Se servono, si passano a Claude Code con --max-turns.

Come funziona

Un server MCP stdio non è un servizio in ascolto: è un processo figlio. Claude Desktop lo lancia e ci scambia messaggi JSON-RPC via stdin/stdout.

Da qui discende la regola più importante per chi mette mano al codice: mai console.log(). Ogni byte su stdout finisce nel canale del protocollo e corrompe il messaggio. Per il debug si usa console.error(), che scrive su stderr.

L'asincronia è gestita con Promise.race tra la fine del lavoro e un timer: nessun polling, nessuna euristica sul "sembra fermo". I job vivono in una Map con pulizia opportunistica dei conclusi da oltre dieci minuti.

Il prompt viaggia su stdin, non come argomento della riga di comando: è testo lungo e pieno di caratteri speciali, e qualunque escaping per la shell sarebbe fragile.

I processi di claude_run hanno un registro proprio, separato da quello dei job. Non serve a riprenderli — claude_run attende il risultato dentro la propria chiamata — ma a farli esistere agli occhi del tetto di concorrenza: fino alla 0.2.0 erano istanze vive e completamente invisibili al server, cioè metà dei processi generati non veniva contata.

Le differenze di piattaforma

Il file è unico: le differenze sono decise a runtime da process.platform e concentrate in poche costanti, in uccidiAlbero() e nelle funzioni che ispezionano i processi.

Il nodo è che il processo restituito da spawn() non è mai l'agente, ma il primo anello di una catena — cmd.exe → claude.cmd → node → agente su Windows, claude → node → agente su Unix. Terminare solo quello lascerebbe l'agente vivo a consumare token senza più essere raggiungibile.

Su Windows serve shell: true perché claude.cmd è uno script batch che solo cmd.exe sa interpretare, e da lì taskkill /T /F per abbattere l'albero. Su Unix la shell non serve — un guadagno anche di sicurezza — e si usa detached: true, che rende il figlio capostipite di un process group: da quel momento process.kill(-pid) raggiunge l'intero gruppo con un solo segnale. Le due opzioni vanno insieme: senza detached, il PID negativo colpirebbe il gruppo del server stesso.

Per l'ispezione dei processi si usa ps su Unix e PowerShell su Windows — non tasklist, che non espone il tempo CPU, né wmic, deprecato.

Il codice è commentato in dettaglio, con il perché di ogni scelta non ovvia.

Entrambi i rami sono stati verificati: su Unix con ps -eo pid,pgid (il figlio deve avere PGID uguale al proprio PID, cioè essere capostipite del suo gruppo) e controllando che il kill abbatta l'albero senza toccare il server. macOS non è stato provato direttamente, ma usa lo stesso ramo.

Licenza

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    An MCP server that bridges Claude Desktop and Claude Code by letting Desktop read and interact with Claude Code Remote Control sessions, enabling cross-agent coordination.
    6
    3
    MIT
  • A
    license
    -
    quality
    A
    maintenance
    A cross-platform desktop MCP server that allows Codex and other MCP clients to execute tasks via the Claude Agent SDK, providing tools for code generation, file editing, and task management with session continuation.
    14
    MIT

View all related MCP servers

Related MCP Connectors

  • Augments MCP Server - A comprehensive framework documentation provider for Claude Code

  • Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer

  • A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ITSWProj/claude-dispatch'

If you have feedback or need assistance with the MCP directory API, please join our Discord server