fdf8fb5cda
The sidecar that isolates all MCP wire complexity from the soul. Binds
loopback 127.0.0.1:7771 only. The soul reaches it over flat HTTP; the bridge
owns stdio/streamable-HTTP transports, OAuth (PKCE), Keychain secrets, server
lifecycle, config, and a tool-schema-hash poisoning guard.
HTTP contract: GET /mcp/tools, /mcp/servers, /mcp/auto-approved, /healthz;
POST /mcp/call, /mcp/oauth/start, /mcp/servers/{add,toggle,auto-approve,
remove,secret}; GET /mcp/oauth/callback.
Config: ~/.neuron/connectors.json (servers, no secrets). Secrets in macOS
Keychain (service ai.neuron.connect, account = serverId). Spec:
docs/research/mcp-connectors-adoption-spec.md.
Phases 1-3 verified end to end (stdio + HTTP transport, Keychain token auth,
OAuth round-trip); Phase 4/5 (CRUD + auto-approve + schema-hash) added for the
ConnectorsView UI.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
21 lines
825 B
JavaScript
21 lines
825 B
JavaScript
import { loadConfig } from "./config.js";
|
|
import { ConnectorBridge } from "./bridge.js";
|
|
import { startServer } from "./server.js";
|
|
// neuron-connectd — the MCP-connector Accessor.
|
|
//
|
|
// Isolates the MCP wire protocol behind a flat loopback HTTP contract the El soul
|
|
// consumes via curl/exec_capture. The soul stays El-simple; this process absorbs
|
|
// stdio framing, (Phase 3) SSE + OAuth, and per-server lifecycle.
|
|
async function main() {
|
|
const config = loadConfig();
|
|
const bridge = new ConnectorBridge();
|
|
await bridge.start(config);
|
|
const total = bridge.allTools().length;
|
|
console.error(`[connectd] ready — ${total} tool(s) across ${bridge.serverStatuses().length} server(s)`);
|
|
startServer(bridge);
|
|
}
|
|
main().catch((err) => {
|
|
console.error("[connectd] fatal:", err);
|
|
process.exit(1);
|
|
});
|