diff --git a/.github/workflows/publish-mcp-registry.yml b/.github/workflows/publish-mcp-registry.yml new file mode 100644 index 0000000..bc9c84f --- /dev/null +++ b/.github/workflows/publish-mcp-registry.yml @@ -0,0 +1,74 @@ +name: Publish MCP Registry + +on: + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish: + name: Publish ai.exa/exa to MCP Registry + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + + steps: + - uses: actions/checkout@v4 + + - name: Verify server.json shape + run: | + NAME=$(jq -r .name server.json) + VERSION=$(jq -r .version server.json) + PKG_VERSION=$(jq -r .version package.json) + MCP_NAME=$(jq -r .mcpName package.json) + REMOTE_TYPE=$(jq -r '.remotes[0].type' server.json) + REMOTE_URL=$(jq -r '.remotes[0].url' server.json) + HAS_PACKAGES=$(jq 'has("packages")' server.json) + + if [ "$NAME" != "ai.exa/exa" ] || [ "$MCP_NAME" != "ai.exa/exa" ]; then + echo "::error::expected ai.exa/exa, got server.json=$NAME mcpName=$MCP_NAME" + exit 1 + fi + if [ "$VERSION" != "$PKG_VERSION" ]; then + echo "::error::version mismatch: server.json=$VERSION package.json=$PKG_VERSION" + exit 1 + fi + if [ "$HAS_PACKAGES" != "false" ]; then + echo "::error::server.json must be remote-only (no packages)" + exit 1 + fi + if [ "$REMOTE_TYPE" != "streamable-http" ] || [ "$REMOTE_URL" != "https://mcp.exa.ai/mcp" ]; then + echo "::error::unexpected remote: type=$REMOTE_TYPE url=$REMOTE_URL" + exit 1 + fi + + echo "Name: $NAME" + echo "Version: $VERSION" + echo "Remote: $REMOTE_TYPE $REMOTE_URL" + + - name: Install mcp-publisher + run: | + curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher + sudo mv mcp-publisher /usr/local/bin/ + mcp-publisher --help + + - name: Authenticate via DNS + env: + MCP_REGISTRY_DNS_PRIVATE_KEY: ${{ secrets.MCP_REGISTRY_DNS_PRIVATE_KEY }} + run: | + if [ -z "$MCP_REGISTRY_DNS_PRIVATE_KEY" ]; then + echo "::error::Missing secret MCP_REGISTRY_DNS_PRIVATE_KEY" + exit 1 + fi + mcp-publisher login dns --domain exa.ai --private-key "$MCP_REGISTRY_DNS_PRIVATE_KEY" + + - name: Publish server to MCP Registry + run: mcp-publisher publish + + - name: Verify on registry + run: | + NAME=$(jq -r .name server.json) + VERSION=$(jq -r .version server.json) + sleep 5 + curl -sS "https://registry.modelcontextprotocol.io/v0.1/servers?search=${NAME}" \ + | jq --arg name "$NAME" --arg version "$VERSION" '{name: $name, version: $version, response: .}' diff --git a/package.json b/package.json index a512f96..3aef4f4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "exa-mcp-server", "version": "3.4.1", "description": "Connect AI agents to Exa for web search, content fetching, and multi-step research.", - "mcpName": "io.github.exa-labs/exa-mcp-server", + "mcpName": "ai.exa/exa", "type": "module", "module": "./src/stdio.ts", "repository": { diff --git a/server.json b/server.json index cf888b2..38968f4 100644 --- a/server.json +++ b/server.json @@ -1,20 +1,16 @@ { - "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json", - "name": "io.github.exa-labs/exa-mcp-server", + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "ai.exa/exa", "description": "Connect AI agents to Exa for web search, content fetching, and multi-step research.", + "repository": { + "url": "https://github.com/exa-labs/exa-mcp-server", + "source": "github" + }, "version": "3.4.1", - "packages": [ - { - "registryType": "npm", - "identifier": "exa-mcp-server", - "version": "3.4.1" - } - ], "remotes": [ { - "type": "sse", - "url": "https://mcp.exa.ai/mcp", - "description": "Hosted Exa MCP. Optional API key: https://dashboard.exa.ai/api-keys. Use ?tools= to enable tools." + "type": "streamable-http", + "url": "https://mcp.exa.ai/mcp" } ] }