JSON Canvas MCP Server
Um servidor para criar, modificar, validar e exportar arquivos JSON Canvas, um formato para dados de canvas infinito.
Documentação
JSON Canvas MCP Server
Um servidor Model Context Protocol (MCP) para trabalhar com
arquivos JSON Canvas — o formato aberto de tela infinita usado
pelo Obsidian. Ele permite que um cliente MCP crie, valide,
leia e liste arquivos .canvas.
Construído sobre o SDK Python oficial mcp (>=1.27), que negocia a revisão do protocolo MCP 2025-11-25. Executa via stdio por padrão e opcionalmente sobre o transporte Streamable HTTP.
Hosts que suportam a extensão de UI MCP Apps renderizam um visualizador de canvas interativo inline ao ler ou criar um canvas — uma pré-visualização com pan/zoom, no estilo do Obsidian, dos nós e arestas. Clientes somente texto não são afetados e continuam recebendo o canvas como saída texto/estruturada.
Componentes
Ferramentas
- create_canvas — Cria um canvas a partir de
nodes(eedgesopcional) e o grava em um arquivo.canvascom prefixo de data emOUTPUT_PATH.- Entrada:
nodes(matriz de objetos de nó JSON Canvas),filename(string, sem extensão),edges(matriz opcional de objetos de aresta). - Retorna (estruturado):
{ path, node_count, edge_count }.
- Entrada:
- validate_canvas — Valida dados de canvas contra a especificação JSON Canvas 1.0.
- Entrada:
canvas(objeto comnodeseedgesopcionais). - Retorna (estruturado):
{ valid, error }.
- Entrada:
- read_canvas — Lê um arquivo
.canvasarmazenado e retorna seus nós e arestas.- Entrada:
filename(string, com ou sem a extensão.canvas). - Retorna (estruturado):
{ nodes, edges }(também renderizado pelo visualizador de canvas; o fallback de texto é o JSON do canvas).
- Entrada:
- list_canvases — Lista os arquivos
.canvasdisponíveis emOUTPUT_PATH.- Retorna: matriz de nomes de arquivo.
- edit_canvas — Adiciona, atualiza e/ou remove nós e arestas em um canvas armazenado em uma única
gravação atômica (uma operação com falha deixa o arquivo inalterado).
- Entrada:
filename, além deadd_nodesopcional,update_nodes(parcial, deve incluirid),remove_node_ids(propaga para arestas conectadas),add_edges,update_edges,remove_edge_ids. - Retorna (estruturado):
{ path, node_count, edge_count, canvas }— o canvas atualizado, para que hosts com capacidade de UI o re-renderizem inline.
- Entrada:
- export_canvas — Exporta um canvas armazenado para outro formato.
- Entrada:
filename,format(markdown|svg). - Retorna (estruturado):
{ format, mime_type, content }. Markdown é um esboço ordenado por arestas; SVG é uma imagem vetorial autônoma (apenas linhas de título de nó — SVG simples não pode renderizar Markdown).
- Entrada:
- search_canvases — Pesquisa de substring sem diferenciar maiúsculas/minúsculas nos canvases armazenados.
- Entrada:
query,filenameopcional para limitar a um canvas. - Retorna (estruturado):
{ matches: [{ filename, kind, id, field, snippet }] }.
- Entrada:
create_canvas, read_canvas e edit_canvas estão vinculados ao visualizador de canvas via
_meta.ui.resourceUri, para que hosts com capacidade de UI renderizem o resultado inline.
Objetos de nó usam a forma JSON Canvas: id, type (text | file | link | group),
x, y, width, height, color opcional, além de campos específicos de tipo (text, file/subpath,
url, label/background/backgroundStyle). Objetos de aresta usam id, fromNode, toNode e
fromSide/toSide/fromEnd/toEnd/color/label opcionais.
Recursos
canvas://schema— JSON Schema para validar arquivos de canvas.canvas://examples/basic— Um canvas de exemplo simples (dois nós de texto unidos por uma aresta).ui://canvas/viewer.html— O visualizador de canvas interativo (UI MCP Apps), servido com tipo MIMEtext/html;profile=mcp-app. Referenciado porcreate_canvaseread_canvas.
Visualizador de canvas interativo (UI MCP Apps)
O visualizador é um único pacote HTML autônomo construído a partir do código-fonte ui/ com Vite
e o cliente oficial @modelcontextprotocol/ext-apps. Ele renderiza nós (com markdown, cores e grupos) e arestas (lados, setas, rótulos)
em uma visualização com pan/zoom, tematizada pelas variáveis CSS do host.
O pacote construído é commitado em jsoncanvas/_ui/viewer.html e incluído no pacote, então
executar o servidor requer apenas Python. Reconstrua-o após alterar ui/:
make build-ui # cd ui && npm install && npm run build (requires Node.js)
Para pré-visualizar o renderizador de forma autônoma (sem host MCP), execute cd ui && npm run dev e abra
/preview.html.
Uso com Claude Desktop
Docker (stdio)
docker build -t mcp/jsoncanvas .
Adicione ao seu claude_desktop_config.json:
{
"mcpServers": {
"jsoncanvas": {
"command": "docker",
"args": ["run", "-i", "--rm", "-v", "canvas-data:/data", "mcp/jsoncanvas"],
"env": { "OUTPUT_PATH": "/data/output" }
}
}
}
uv (stdio)
{
"mcpServers": {
"jsoncanvas": {
"command": "uv",
"args": ["--directory", "/path/to/jsoncanvas", "run", "mcp-server-jsoncanvas"],
"env": { "OUTPUT_PATH": "./output" }
}
}
}
Transporte Streamable HTTP
Para servir via Streamable HTTP em vez de stdio:
mcp-server-jsoncanvas --transport streamable-http --host 127.0.0.1 --port 8000
O endpoint MCP é então http://127.0.0.1:8000/mcp. O transporte vincula-se a localhost e, conforme a
especificação 2025-11-25, valida o cabeçalho Origin com proteção contra DNS-rebinding habilitada
(apenas Origins de localhost por padrão). Para aceitar conexões de fora do host (por exemplo, ao
executar o contêiner com HTTP), vincule --host 0.0.0.0 e configure seus Origins permitidos
de acordo.
Hosts MCP baseados em navegador (o tipo que renderiza o visualizador de canvas) conectam-se entre origens e devem
ler o cabeçalho de resposta mcp-session-id, então o transporte Streamable HTTP serve cabeçalhos
CORS permissivos. Restrinja as origens permitidas com MCP_CORS_ORIGINS (separadas por vírgula; padrão
*).
Nota de segurança. O transporte HTTP é não autenticado — qualquer pessoa que alcance a porta pode ler e gravar arquivos
.canvasemOUTPUT_PATH. O servidor é destinado ao uso local; mantenha-o vinculado a127.0.0.1(o padrão). A proteção DNS-rebinding/Originé fixada em Origins e Hosts de localhost na inicialização, então vincular--host 0.0.0.0expõe a porta na rede, mas ainda rejeita cabeçalhosHost/Originde não-localhost — para expô-lo remotamente com segurança, coloque um proxy reverso autenticador na frente em vez de publicá-lo diretamente, e definaMCP_CORS_ORIGINSpara as origens específicas em que você confia (nunca*).
Configuração
Variáveis de ambiente:
OUTPUT_PATH— Diretório onde os arquivos.canvassão gravados/lidos (padrão./output).MCP_TRANSPORT—stdio(padrão) oustreamable-http.MCP_HOST/MCP_PORT— Host/porta para o transporte Streamable HTTP (padrão127.0.0.1:8000).MCP_CORS_ORIGINS— Origens CORS permitidas, separadas por vírgula, para o transporte HTTP (padrão*).
Desenvolvimento
# Install uv: https://docs.astral.sh/uv/getting-started/installation/
make setup # uv venv && uv sync --extra dev
make build-ui # rebuild the canvas viewer bundle (requires Node.js)
make test # run the test suite
make lint # ruff check + format check
make audit # scan dependencies for known vulnerabilities (pip-audit)
make run # run the server over stdio
Execute o exemplo de biblioteca incluído:
make example # writes example.canvas to OUTPUT_PATH (default ./output)
Exemplo de biblioteca
O pacote jsoncanvas também pode ser usado diretamente:
from jsoncanvas import Canvas, TextNode, Edge
title = TextNode(id="title", x=100, y=100, width=400, height=100,
text="# Hello Canvas", color="#4285F4")
info = TextNode(id="info", x=600, y=100, width=300, height=100,
text="More information here", color="2") # preset color
canvas = Canvas()
canvas.add_node(title)
canvas.add_node(info)
canvas.add_edge(Edge(id="edge1", from_node="title", to_node="info",
from_side="right", to_side="left", label="Connection"))
import json
print(json.dumps(canvas.to_dict(), indent=2))
Licença
MIT. Consulte LICENSE.