diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a52c053..2de29b0 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1,15 +1,25 @@ { "name": "connector-hub", - "version": "2.1.0", - "tagline": "One hub for every external service — 24 providers, 301 operations, spec-driven and auditable.", - "tags": [ - "connectors", - "api", - "mcp", - "automation", - "devops" - ], - "icon": "plug", - "homepage": "https://github.com/CodeWithJuber/connector-hub", - "repository": "https://github.com/CodeWithJuber/connector-hub" + "version": "2.2.0", + "description": "Spec-driven connector orchestration — 24 providers, 301 operations, type-safe execution contract with audit ledger.", + "owner": { + "name": "Connector Hub contributors", + "url": "https://github.com/CodeWithJuber" + }, + "plugins": [ + { + "name": "connector-hub", + "source": "./", + "version": "2.2.0", + "description": "Spec-driven connector orchestration — 24 providers, 301 operations, type-safe execution contract with audit ledger.", + "homepage": "https://github.com/CodeWithJuber/connector-hub", + "keywords": [ + "connectors", + "api", + "mcp", + "automation", + "devops" + ] + } + ] } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 5b67f46..11027da 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "connector-hub", - "version": "2.1.0", + "version": "2.2.0", "description": "Spec-driven connector orchestration — 24 providers, 301 operations, type-safe execution contract with audit ledger.", "author": { "name": "Connector Hub contributors", diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 5b67f46..11027da 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "connector-hub", - "version": "2.1.0", + "version": "2.2.0", "description": "Spec-driven connector orchestration — 24 providers, 301 operations, type-safe execution contract with audit ledger.", "author": { "name": "Connector Hub contributors", diff --git a/.mcp.json b/.mcp.json index 9c98404..ab91b1b 100644 --- a/.mcp.json +++ b/.mcp.json @@ -1,7 +1,7 @@ { "mcpServers": { "connector-hub": { - "command": "${CLAUDE_PLUGIN_ROOT}/crates/target/release/connector-hub", + "command": "${CLAUDE_PLUGIN_ROOT}/bin/connector-hub-mcp", "args": [ "mcp" ], diff --git a/README.md b/README.md index 7c4fbb4..9a470c7 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,26 @@ connector-hub audit-verify audit.jsonl See `docs/adr/0004-audit-ledger-format.md` for the format specification. +## Credentials + +Connectors read credentials from the environment. MCP hosts launch stdio +servers with a bare environment, so `bin/connector-hub-mcp` sources +`~/.config/connector-hub/env` (override with `CONNECTOR_HUB_ENV`) before exec. +One file, shared by every agent on the machine: + +```sh +mkdir -p ~/.config/connector-hub +cat > ~/.config/connector-hub/env <<'EOF' +GITHUB_TOKEN="ghp_..." +HETZNER_API_TOKEN="..." +EOF +chmod 600 ~/.config/connector-hub/env +``` + +Leave unused variables commented out rather than set to `""` — an empty string +reads as configured, which turns a clean `ConfigurationRequired` into a 401 +from the provider. + ## Security model - Credentials live in environment variables or an encrypted store. Never in diff --git a/bin/connector-hub-mcp b/bin/connector-hub-mcp new file mode 100755 index 0000000..d2c4ab6 --- /dev/null +++ b/bin/connector-hub-mcp @@ -0,0 +1,48 @@ +#!/bin/sh +# Locate and run the connector-hub binary. +# +# Plugin hosts (Claude Code, Codex, Kimi) install this repo by cloning it, so +# there is no compiled binary at install time. This resolves one in the places +# it is actually likely to be, and fails with an actionable message otherwise. +# +# Order: $CONNECTOR_HUB_BIN, release build, debug build, $PATH. +ROOT="${CLAUDE_PLUGIN_ROOT:-$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)}" + +# Credentials. MCP hosts launch servers with a bare environment, so provider +# keys have to come from somewhere other than the user's shell profile. One +# file, shared by every host on the machine, keeps a key in a single place +# rather than duplicated across each agent's config. +ENV_FILE="${CONNECTOR_HUB_ENV:-${XDG_CONFIG_HOME:-$HOME/.config}/connector-hub/env}" +if [ -f "$ENV_FILE" ]; then + set -a + . "$ENV_FILE" + set +a +fi + +if [ -n "$CONNECTOR_HUB_BIN" ] && [ -x "$CONNECTOR_HUB_BIN" ]; then + BIN="$CONNECTOR_HUB_BIN" +elif [ -x "$ROOT/crates/target/release/connector-hub" ]; then + BIN="$ROOT/crates/target/release/connector-hub" +elif [ -x "$ROOT/crates/target/debug/connector-hub" ]; then + BIN="$ROOT/crates/target/debug/connector-hub" +elif command -v connector-hub >/dev/null 2>&1; then + BIN="$(command -v connector-hub)" +else + echo "connector-hub: no binary found." >&2 + echo " Build it: cd $ROOT/crates && cargo build --release" >&2 + echo " Or point CONNECTOR_HUB_BIN at an existing build." >&2 + exit 1 +fi + +# The catalogue is data, not code — make sure this checkout's specs are used +# even when the binary came from somewhere else on the filesystem. +if [ -z "$CONNECTOR_HUB_SPECS_DIR" ] && [ -d "$ROOT/specs" ]; then + CONNECTOR_HUB_SPECS_DIR="$ROOT/specs" + export CONNECTOR_HUB_SPECS_DIR +fi + +if [ $# -eq 0 ]; then + exec "$BIN" mcp +else + exec "$BIN" "$@" +fi diff --git a/kimi.plugin.json b/kimi.plugin.json index f12d967..56502a1 100644 --- a/kimi.plugin.json +++ b/kimi.plugin.json @@ -1,6 +1,6 @@ { "name": "connector-hub", - "version": "2.1.0", + "version": "2.2.0", "description": "Spec-driven connector orchestration — 24 providers, 301 operations, type-safe execution contract with audit ledger.", "author": { "name": "Connector Hub contributors",