AuthdogVerifier from @authdog/mcp-sdk verifies the bearer token an MCP client presents to your Node.js MCP server. It calls GET {baseUrl}/v1/userinfo with the token and returns an AuthInfo (subject, username, email, expiry, full user). Source is `node/` in authdog/mcp-sdk. The package is ESM, uses axios, and declares node >=16.
This is the MCP token verifier, not the runtime package of the same name used inside the Authdog platform. See MCP SDK for how the language SDKs relate.
Availability
These packages are source-available in github.com/authdog/mcp-sdk and may not resolve from registries yet. At the time of writing @authdog/mcp-sdk returns 404 on npm, and the repository has no release tags. The package version in package.json is 0.1.0. Install from source until a release is published.
The name @authdog/mcp-sdk also belongs to a separate private runtime package inside the Authdog platform monorepo (trust store, AuthZEN, telemetry). That package is not this verifier. See MCP SDK.
Install
From source:
git clone https://github.com/authdog/mcp-sdk.git
cd mcp-sdk/node
npm install
npm run buildnpm run build runs tsc and writes dist/, which is what main and types point at. Then add the built directory to your server project:
npm install /path/to/mcp-sdk/nodeOnce a release is published, the README gives these commands:
deno add npm:@authdog/mcp-sdk
npm install @authdog/mcp-sdkConfigure
import { AuthdogVerifier } from "@authdog/mcp-sdk"
const verifier = new AuthdogVerifier({
baseUrl: "https://api.authdog.com",
timeout: 10000,
})| Option | Type | Default | Behavior |
|---|---|---|---|
baseUrl |
string |
required | Authdog API base URL. Trailing slashes are stripped. A missing or blank value throws TypeError. |
timeout |
number |
10000 |
Request timeout in milliseconds. A falsy value (including 0) falls back to 10000. |
Each request sends Content-Type: application/json and User-Agent: authdog-mcp-node-sdk/0.1.0.
Verify a token
import { AuthdogVerifier, AuthenticationError, APIError } from "@authdog/mcp-sdk"
const authInfo = await verifier.verifyToken("the-access-token")
console.log(authInfo.subject, authInfo.username, authInfo.email)verifyToken(accessToken: string, signal?: AbortSignal): Promise<AuthInfo> sends Authorization: Bearer <accessToken>. Pass an AbortSignal to cancel the in-flight request, for example when the incoming MCP request is cancelled. An empty or whitespace-only token throws AuthenticationError before any request is made.
AuthInfo:
| Field | Type | Value |
|---|---|---|
token |
string |
The token you passed in |
subject |
string |
user.id |
username |
string |
user.userName |
email |
string | null |
First user.emails[].value, or null |
scopes |
string[] |
Always [] |
expiresAt |
Date | null |
Now plus session.remainingSeconds, only when that value is a number greater than 0. Otherwise null. |
user |
UserInfoResponse["user"] |
Full user object from the response |
scopes is empty because the userinfo endpoint does not return scopes; the SDK hard-codes []. Do not use it for scope-based authorization. Authentication identifies the caller; apply authorization separately.
Types AuthInfo, AuthdogVerifierConfig, and UserInfoResponse are exported alongside AuthdogVerifier.
Wire into an MCP server
The MCP TypeScript SDK protects HTTP transports with requireBearerAuth, which delegates to a token verifier. Adapt AuthdogVerifier in a few lines:
import express from "express"
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js"
import type { OAuthTokenVerifier } from "@modelcontextprotocol/sdk/server/auth/provider.js"
import type { AuthInfo as McpAuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js"
import { AuthdogVerifier } from "@authdog/mcp-sdk"
const authdog = new AuthdogVerifier({ baseUrl: "https://api.authdog.com" })
// Adapt the Authdog verifier to MCP's TokenVerifier interface
const verifier: OAuthTokenVerifier = {
async verifyAccessToken(token: string): Promise<McpAuthInfo> {
const info = await authdog.verifyToken(token)
return {
token: info.token,
clientId: info.subject,
scopes: info.scopes,
expiresAt: info.expiresAt
? Math.floor(info.expiresAt.getTime() / 1000) // MCP expects epoch seconds
: undefined,
extra: { username: info.username, email: info.email },
}
},
}
const app = express()
// Protect your MCP HTTP endpoint with Authdog-backed bearer auth
app.use("/mcp", requireBearerAuth({ verifier }))When the token is missing, invalid, or expired, verifyToken throws AuthenticationError, which requireBearerAuth surfaces to the client as HTTP 401.
Errors
All three classes are exported and extend Error. name is set to the class name.
| Class | Thrown when |
|---|---|
AuthdogError |
Base class for the others |
AuthenticationError |
Empty or blank token, or HTTP 401 (Unauthorized - invalid or expired token) |
APIError |
Timeout (Request timed out: ...), other non-2xx (HTTP error <status>: <body>), network failure (Request failed: ...), or a 2xx response with no user (Invalid response: missing user in userinfo payload) |
try {
await verifier.verifyToken(token)
} catch (error) {
if (error instanceof AuthenticationError) {
// reject with 401
} else if (error instanceof APIError) {
// upstream or transport failure
} else {
throw error
}
}Related
- MCP SDK: language overview and the name collision
- MCP authentication: how MCP clients obtain tokens
- Python and Go verifiers