Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .github/workflows/publish-mcp-registry.yml
Original file line number Diff line number Diff line change
@@ -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: .}'
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
20 changes: 8 additions & 12 deletions server.json
Original file line number Diff line number Diff line change
@@ -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"
}
]
}
Loading